1# Media Data Demuxing
2
3You can call the native APIs provided by the AVDemuxer module to demux media data. The demuxing involves extracting media samples such as audio, video, and subtitles from bit stream data, and obtaining information related to Digital Rights Management (DRM).
4
5Currently, two data input types are supported: remote connection (over HTTP) and File Descriptor (FD).
6
7The following demuxing formats are supported:
8
9| Media Format | Muxing Format                     | Stream Format                     |
10| -------- | :----------------------------| :----------------------------|
11| Audio/Video    | mp4                        |<!--RP1-->Video stream: AVC (H.264); audio stream: AAC and MPEG (MP3); subtitle stream: WEBVTT<!--RP1End-->|
12| Audio/Video    | fmp4                       |<!--RP2-->Video stream: AVC (H.264); audio stream: AAC and MPEG (MP3)<!--RP2End-->|
13| Audio/Video    | mkv                        |<!--RP3-->Video stream: AVC (H.264); audio stream: AAC, MPEG (MP3), and OPUS<!--RP3End-->|
14| Audio/Video    | mpeg-ts                    |<!--RP4-->Video stream: AVC (H.264); audio stream: AAC and MPEG (MP3)<!--RP4End-->|
15| Audio/Video    | flv                        |<!--RP5-->Video stream: AVC (H.264); audio stream: AAC<!--RP5End-->|
16| Audio      | m4a                        |<!--RP6-->Audio stream: AAC<!--RP6End-->|
17| Audio      | aac                        |Audio stream: AAC|
18| Audio      | mp3                        |Audio stream: MPEG (MP3)|
19| Audio      | ogg                        |Audio stream: OGG|
20| Audio      | flac                       |Audio stream: FLAC|
21| Audio      | wav                        |Audio stream: PCM and PCM-MULAW|
22| Audio      | amr                        |Audio stream: AMR (AMR-NB and AMR-WB)|
23| Audio      | ape                        |Audio stream: APE|
24| External subtitle  | srt                        |Subtitle stream: SRT|
25| External subtitle  | webvtt                     |Subtitle stream: WEBVTT|
26
27The DRM demuxing capability supports the following formats: <!--RP7-->mp4 (H.264 and AAC) and mpeg-ts (H.264 and AAC)<!--RP7End-->.
28
29**Usage Scenario**
30
31- Audio and video playback
32  
33  Demux media streams, decode the samples obtained through demuxing, and play the samples.
34
35- Audio and video editing
36  
37  Demux media streams, and edit the specified samples.
38
39- Media file format conversion
40
41  Demux media streams, and encapsulate them into a new file format.
42
43## How to Develop
44
45Read [AVDemuxer](../../reference/apis-avcodec-kit/_a_v_demuxer.md) and [AVSource](../../reference/apis-avcodec-kit/_a_v_source.md) for the API reference.
46
47> **NOTE**
48>
49> - To call the demuxer APIs to parse a network playback path, declare the **ohos.permission.INTERNET** permission by following the instructions provided in [Declaring Permissions](../../security/AccessToken/declare-permissions.md).
50> - To call the demuxer APIs to write a local file, request the **ohos.permission.READ_MEDIA** permission by following the instructions provided in [Requesting User Authorization](../../security/AccessToken/request-user-authorization.md).
51> - You can also use **ResourceManager.getRawFd** to obtain the FD of a file packed in the HAP file. For details, see [ResourceManager API Reference](../../reference/apis-localization-kit/js-apis-resource-manager.md#getrawfd9).
52
53### Linking the Dynamic Libraries in the CMake Script
54
55``` cmake
56target_link_libraries(sample PUBLIC libnative_media_codecbase.so)
57target_link_libraries(sample PUBLIC libnative_media_avdemuxer.so)
58target_link_libraries(sample PUBLIC libnative_media_avsource.so)
59target_link_libraries(sample PUBLIC libnative_media_core.so)
60```
61
62> **NOTE**
63>
64> The word 'sample' in the preceding code snippet is only an example. Use the actual project directory name.
65>
66
67### How to Develop
68
691. Add the header files.
70
71   ```c++
72   #include <multimedia/player_framework/native_avdemuxer.h>
73   #include <multimedia/player_framework/native_avsource.h>
74   #include <multimedia/player_framework/native_avcodec_base.h>
75   #include <multimedia/player_framework/native_avformat.h>
76   #include <multimedia/player_framework/native_avbuffer.h>
77   #include <fcntl.h>
78   #include <sys/stat.h>
79   ```
80
812. Create a resource object.
82
83   When using **open** to obtain the FD, convert the value of **filepath** to a [sandbox path](../../file-management/app-sandbox-directory.md#app-sandbox-directory.md#mapping-between-application-sandbox-paths-and-physical-paths) to obtain sandbox resources.
84
85   ```c++
86   // Create the FD. You must have the read permission on the file handle when opening the file. (filePath indicates the path of the file to be demuxed. The file must exist.)
87   std::string filePath = "test.mp4";
88   int fd = open(filePath.c_str(), O_RDONLY);
89   struct stat fileStatus {};
90   size_t fileSize = 0;
91   if (stat(filePath.c_str(), &fileStatus) == 0) {
92      fileSize = static_cast<size_t>(fileStatus.st_size);
93   } else {
94      printf("get stat failed");
95      return;
96   }
97   // Create a source resource object for the FD resource file. If offset is not the start position of the file or size is not the actual file size, the data obtained may be incomplete. Consequently, the source resource object may fail to create or subsequent demuxing may fail.
98   OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, fileSize);
99   if (source == nullptr) {
100      printf("create source failed");
101      return;
102   }
103   // (Optional) Create a source resource object for the URI resource file.
104   // OH_AVSource *source = OH_AVSource_CreateWithURI(uri);
105
106   // (Optional) Create a source resource object for the custom data source. Before the operation, you must implement AVSourceReadAt.
107   // Add g_filePath when OH_AVSource_CreateWithDataSource is used.
108   // g_filePath = filePath ;
109   // OH_AVDataSource dataSource = {fileSize, AVSourceReadAt};
110   // OH_AVSource *source = OH_AVSource_CreateWithDataSource(&dataSource);
111   ```
112
113   Implement the **AVSourceReadAt** API before creating the resource object.
114
115   ```c++
116   // Add the header file.
117   #include <fstream>
118   ```
119
120   ```c++
121   static std::string g_filePath;
122
123   enum MediaDataSourceError : int32_t {
124      SOURCE_ERROR_IO = -2,
125      SOURCE_ERROR_EOF = -1
126   };
127
128   int32_t AVSourceReadAt(OH_AVBuffer *data, int32_t length, int64_t pos)
129   {
130      if (data == nullptr) {
131         printf("AVSourceReadAt : data is nullptr!\n");
132         return MediaDataSourceError::SOURCE_ERROR_IO;
133      }
134
135      std::ifstream infile(g_filePath, std::ofstream::binary);
136      if (!infile.is_open()) {
137         printf("AVSourceReadAt : open file failed! file:%s\n", g_filePath.c_str());
138         return MediaDataSourceError::SOURCE_ERROR_IO; // Failed to open the file.
139      }
140
141      infile.seekg(0, std::ios::end);
142      int64_t fileSize = infile.tellg();
143      if (pos >= fileSize) {
144         printf("AVSourceReadAt : pos over or equals file size!\n");
145         return MediaDataSourceError::SOURCE_ERROR_EOF; // pos is already at the end of the file and cannot be read.
146      }
147
148      if (pos + length > fileSize) {
149         length of length = fileSize - pos; // When the sum of pos and length exceeds the file size, the data from pos to the end of the file is read.
150      }
151
152      infile.seekg(pos, std::ios::beg);
153      if (length <= 0) {
154         printf("AVSourceReadAt : raed length less than zero!\n");
155         return MediaDataSourceError::SOURCE_ERROR_IO;
156      }
157      char* buffer = new char[length];
158      infile.read(buffer, length);
159      infile.close();
160
161      memcpy(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)),
162         buffer, length);
163      delete[] buffer;
164
165      return length;
166   }
167   ```
1683. Create a demuxer instance.
169   ```c++
170   // Create a demuxer for the resource object.
171   OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source);
172   if (demuxer == nullptr) {
173      printf("create demuxer failed");
174      return;
175   }
176   ```
1774. (Optional) Register a [callback to obtain the media key system information](../../reference/apis-drm-kit/_drm.md#drm_mediakeysysteminfocallback). If the stream is not a DRM stream or the [media key system information](../../reference/apis-drm-kit/_drm.md#drm_mediakeysysteminfo) has been obtained, you can skip this step.
178
179   Add the header file.
180   ```c++
181   #include <multimedia/drm_framework/native_drm_common.h>
182   ```
183   Link the dynamic library in the cmake script.
184
185   ``` cmake
186   target_link_libraries(sample PUBLIC libnative_drm.so)
187   ```
188   There are two types of APIs for setting DRM information listeners. The callback function shown in example 1 can return a demuxer instance and therefore is recommended in the scenario where multiple demuxer instances are used. The callback function shown in example 2 does not return a demuxer instance and is applicable to the scenario where a single demuxer instance is used.
189
190   Example 1:
191   ```c++
192   // Implement the OnDrmInfoChangedWithObj callback.
193   static void OnDrmInfoChangedWithObj(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *drmInfo)
194   {
195      // Parse the media key system information, including the quantity, DRM type, and corresponding PSSH.
196   }
197
198   Demuxer_MediaKeySystemInfoCallback callback = &OnDrmInfoChangedWithObj;
199   Drm_ErrCode ret = OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(demuxer, callback);
200
201   ```
202
203   Example 2:
204   ```c++
205   // Implement the OnDrmInfoChanged callback.
206   static void OnDrmInfoChanged(DRM_MediaKeySystemInfo *drmInfo)
207   {
208      // Parse the media key system information, including the quantity, DRM type, and corresponding PSSH.
209   }
210
211   DRM_MediaKeySystemInfoCallback callback = &OnDrmInfoChanged;
212   Drm_ErrCode ret = OH_AVDemuxer_SetMediaKeySystemInfoCallback(demuxer, callback);
213   ```
214
215   After the callback is invoked, you can call the API to proactively obtain the media key system information (UUID and corresponding PSSH).
216   ```c++
217   DRM_MediaKeySystemInfo mediaKeySystemInfo;
218   OH_AVDemuxer_GetMediaKeySystemInfo(demuxer, &mediaKeySystemInfo);
219   ```
220   After obtaining and parsing DRM information, create [MediaKeySystem](../drm/native-drm-mediakeysystem-management.md) and [MediaKeySession](../drm/native-drm-mediakeysession-management.md) instances of the corresponding DRM scheme to obtain a media key. If required, set the audio decryption configuration by following step 4 in [Audio Decoding](./audio-decoding.md#how-to-develop), and set the video decryption configuration by following step 5 [Surface Output in Video Decoding](./video-decoding.md#surface-mode) or step 4 in [Buffer Output in Video Decoding](./video-decoding.md#buffer mode).
221
2225. (Optional) Obtain the number of tracks. If you know the track information, skip this step.
223
224   ```c++
225   // Obtain the number of tracks from the file source information. You can call the API to obtain file-level attributes. For details, see Table 1 in Appendix 1.
226   OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
227   if (sourceFormat == nullptr) {
228      printf("get source format failed");
229      return;
230   }
231   int32_t trackCount = 0;
232   if (!OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount)) {
233      printf("get track count from source format failed");
234      return;
235   }
236   OH_AVFormat_Destroy(sourceFormat);
237   ```
238
2396. (Optional) Obtain the track index and format. If you know the track information, skip this step.
240
241   ```c++
242   uint32_t audioTrackIndex = 0;
243   uint32_t videoTrackIndex = 0;
244   int32_t w = 0;
245   int32_t h = 0;
246   int32_t trackType;
247   for (uint32_t index = 0; index < (static_cast<uint32_t>(trackCount)); index++) {
248      // Obtain the track information. You can call the API to obtain track-level attributes. For details, see Table 2 in Appendix.
249      OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
250      if (trackFormat == nullptr) {
251         printf("get track format failed");
252         return;
253      }
254      if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType)) {
255         printf("get track type from track format failed");
256         return;
257      }
258      static_cast<OH_MediaType>(trackType) == OH_MediaType::MEDIA_TYPE_AUD ? audioTrackIndex = index : videoTrackIndex = index;
259      // Obtain the width and height of the video track.
260      if (trackType == OH_MediaType::MEDIA_TYPE_VID) {
261         if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_WIDTH, &w)) {
262            printf("get track width from track format failed");
263            return;
264         }
265         if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_HEIGHT, &h)) {
266            printf("get track height from track format failed");
267            return;
268         }
269      }
270      OH_AVFormat_Destroy(trackFormat);
271   }
272   ```
273
2747. Select a track, from which the demuxer reads data.
275
276   ```c++
277   if(OH_AVDemuxer_SelectTrackByID(demuxer, audioTrackIndex) != AV_ERR_OK){
278      printf("select audio track failed: %d", audioTrackIndex);
279      return;
280   }
281   if(OH_AVDemuxer_SelectTrackByID(demuxer, videoTrackIndex) != AV_ERR_OK){
282      printf("select video track failed: %d", videoTrackIndex);
283      return;
284   }
285   // (Optional) Deselect the track.
286   // OH_AVDemuxer_UnselectTrackByID(demuxer, audioTrackIndex);
287   ```
288
2898. (Optional) Seek to the specified time for the selected track.
290
291   ```c++
292   // Demuxing is performed from this time.
293   // Note:
294   // 1. If OH_AVDemuxer_SeekToTime is called for an MPEG TS file, the target position may be a non-key frame. You can then call OH_AVDemuxer_ReadSampleBuffer to check whether the current frame is a key frame based on the obtained OH_AVCodecBufferAttr. If it is a non-key frame, which causes display issues on the application side, cyclically read the frames until you reach the first key frame, where you can perform processing such as decoding.
295   // 2. If OH_AVDemuxer_SeekToTime is called for an OGG file, the file seeks to the start of the time interval (second) where the input parameter millisecond is located, which may cause a certain number of frame errors.
296   OH_AVDemuxer_SeekToTime(demuxer, 0, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
297   ```
298
2999. Start demuxing and cyclically obtain samples. The code snippet below uses a file that contains audio and video tracks as an example.
300
301   A **BufferAttr** object contains the following attributes.
302   - **size**: sample size.
303   - **offset**: offset of the data in the AVBuffer. The value is generally 0.
304   - **pts**: timestamp when the file is muxed.
305   - **flags**: sample attributes.
306
307   | flag | Description|
308   | -------- | -------- |
309   | AVCODEC_BUFFER_FLAGS_NONE | Default value.|
310   | AVCODEC_BUFFER_FLAGS_EOS | End of Stream (EOS). The data is empty.|
311   | AVCODEC_BUFFER_FLAGS_SYNC_FRAME | IDR frame or I-frame.|
312   | AVCODEC_BUFFER_FLAGS_INCOMPLETE_FRAME | Incomplete sample. Generally, a complete sample fails to be copied because the buffer is too small.|
313   | AVCODEC_BUFFER_FLAGS_CODEC_DATA | Frame containing parameter set information.|
314   | AVCODEC_BUFFER_FLAGS_DISCARD  | Frames that can be discarded.|
315
316   ```c++
317   // Create a buffer to store the data obtained after demuxing.
318   OH_AVBuffer *buffer = OH_AVBuffer_Create(w * h * 3 >> 1);
319   if (buffer == nullptr) {
320      printf("build buffer failed");
321      return;
322   }
323   OH_AVCodecBufferAttr info;
324   bool videoIsEnd = false;
325   bool audioIsEnd = false;
326   int32_t ret;
327   while (!audioIsEnd || !videoIsEnd) {
328      // Before calling OH_AVDemuxer_ReadSampleBuffer, call OH_AVDemuxer_SelectTrackByID to select the track from which the demuxer reads data.
329      // Obtain the audio sample.
330      if(!audioIsEnd) {
331         ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, audioTrackIndex, buffer);
332         if (ret == AV_ERR_OK) {
333            // Obtain and process the audio sample in the buffer.
334            OH_AVBuffer_GetBufferAttr(buffer, &info);
335            printf("audio info.size: %d\n", info.size);
336            if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
337               audioIsEnd = true;
338            }
339         }
340      }
341      if(!videoIsEnd) {
342         ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, videoTrackIndex, buffer);
343         if (ret == AV_ERR_OK) {
344            // Obtain and process the video sample in the buffer.
345            OH_AVBuffer_GetBufferAttr(buffer, &info);
346            printf("video info.size: %d\n", info.size);
347            if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
348               videoIsEnd = true;
349            }
350         }
351      }
352   }
353   OH_AVBuffer_Destroy(buffer);
354   ```
355
35610. Destroy the demuxer instance.
357      ```c++
358      // Manually set the instance to NULL after OH_AVSource_Destroy is called. Do not call this API repeatedly for the same instance; otherwise, a program error occurs.
359      if (OH_AVSource_Destroy(source) != AV_ERR_OK) {
360         printf("destroy source pointer error");
361      }
362      source = NULL;
363      // Manually set the instance to NULL after OH_AVDemuxer_Destroy is called. Do not call this API repeatedly for the same instance; otherwise, a program error occurs.
364      if (OH_AVDemuxer_Destroy(demuxer) != AV_ERR_OK) {
365         printf("destroy demuxer pointer error");
366      }
367      demuxer = NULL;
368      close(fd);
369      ```
370
371## Appendix
372### Supported File-Level Attributes
373
374> **NOTE**
375>
376> Attribute data can be obtained only when the file is parsed normally. If the file information is incorrect or missing, the parsing is abnormal and the corresponding data cannot be obtained.
377> 
378> For details about the data type and value range, see [Media Data Key-Value Pairs](../../reference/apis-avcodec-kit/_codec_base.md#media-data-key-value-pairs).
379
380**Table 1** Supported file-level attributes
381| Name| Description|
382| -- | -- |
383|OH_MD_KEY_TITLE|Title.|
384|OH_MD_KEY_ARTIST|Artist.|
385|OH_MD_KEY_ALBUM|Album.|
386|OH_MD_KEY_ALBUM_ARTIST|Album artist.|
387|OH_MD_KEY_DATE|Date.|
388|OH_MD_KEY_COMMENT|Comment.|
389|OH_MD_KEY_GENRE|Genre.|
390|OH_MD_KEY_COPYRIGHT|Copyright.|
391|OH_MD_KEY_LANGUAGE|Language.|
392|OH_MD_KEY_DESCRIPTION|Description.|
393|OH_MD_KEY_LYRICS|Lyrics.|
394|OH_MD_KEY_TRACK_COUNT|Track count.|
395|OH_MD_KEY_DURATION|Duration.|
396|OH_MD_KEY_START_TIME|Start time.|
397
398### Supported Track-Level Attributes
399
400> **NOTE**
401>
402> Attribute data can be obtained only when the file is parsed normally. If the file information is incorrect or missing, the parsing is abnormal and the corresponding data cannot be obtained.
403> 
404> For details about the data type and value range, see [Media Data Key-Value Pairs](../../reference/apis-avcodec-kit/_codec_base.md#media-data-key-value-pairs).
405
406**Table 2** Supported track-level attributes
407| Name| Description| Supported by Video Tracks| Supported by Audio Tracks| Supported by Subtitle Tracks|
408| -- | -- | -- | -- | -- |
409|OH_MD_KEY_CODEC_MIME|Stream codec type.|Supported|Supported|Supported|
410|OH_MD_KEY_TRACK_TYPE|Stream track type.|Supported|Supported|Supported|
411|OH_MD_KEY_TRACK_START_TIME|Start time of the stream.|Supported|Supported|Supported|
412|OH_MD_KEY_BITRATE|Stream bit rate.|Supported|Supported|Not supported|
413|OH_MD_KEY_LANGUAGE|Stream language type.|Supported|Supported|Not supported|
414|OH_MD_KEY_CODEC_CONFIG|Codec-specific data. In the case of video, a parameter set is transferred. In the case of audio, parameter configuration information of the decoder is transferred.|Supported|Supported|Not supported|
415|OH_MD_KEY_WIDTH|Video stream width.|Supported|Not supported|Not supported|
416|OH_MD_KEY_HEIGHT|Video stream height.|Supported|Not supported|Not supported|
417|OH_MD_KEY_FRAME_RATE|Video stream frame rate.|Supported|Not supported|Not supported|
418|OH_MD_KEY_ROTATION|Rotation angle of the video stream.|Supported|Not supported|Not supported|
419|OH_MD_KEY_VIDEO_SAR|Aspect ratio of the video stream sample.|Supported|Not supported|Not supported|
420|OH_MD_KEY_PROFILE|Encoding profile of the video stream. This key is valid only for H.265 streams.|Supported|Not supported|Not supported|
421|OH_MD_KEY_RANGE_FLAG|Video YUV value range flag of the video stream. This key is valid only for H.265 streams.|Supported|Not supported|Not supported|
422|OH_MD_KEY_COLOR_PRIMARIES|Video primary color of the video stream. This key is valid only for H.265 streams.|Supported|Not supported|Not supported|
423|OH_MD_KEY_TRANSFER_CHARACTERISTICS|Video transfer characteristics of the video stream. This key is valid only for H.265 streams.|Supported|Not supported|Not supported|
424|OH_MD_KEY_MATRIX_COEFFICIENTS|Video matrix coefficient. This key is valid only for H.265 streams.|Supported|Not supported|Not supported|
425|OH_MD_KEY_VIDEO_IS_HDR_VIVID|Flag indicating whether the video stream is HDR Vivid. This key is valid only for HDR Vivid streams.|Supported|Not supported|Not supported|
426|OH_MD_KEY_AUD_SAMPLE_RATE|Audio stream sampling rate.|Not supported|Supported|Not supported|
427|OH_MD_KEY_AUD_CHANNEL_COUNT|Number of audio stream channels.|Not supported|Supported|Not supported|
428|OH_MD_KEY_CHANNEL_LAYOUT|Encoding channel layout required by the audio stream.|Not supported|Supported|Not supported|
429|OH_MD_KEY_AUDIO_SAMPLE_FORMAT|Audio stream sample format.|Not supported|Supported|Not supported|
430|OH_MD_KEY_AAC_IS_ADTS|AAC format. This key is valid only for AAC streams.|Not supported|Supported|Not supported|
431|OH_MD_KEY_BITS_PER_CODED_SAMPLE|Number of bits per coded sample in the audio stream.|Not supported|Supported|Not supported|
432