• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Audio and Video Decapsulation
2
3You can call the native APIs provided by the **AVDemuxer** module to decapsulate audio and video, that is, to extract audio and video frame data from bit stream data.
4
5Currently, two data input types are supported: remote connection (over HTTP) and File Descriptor (FD).
6
7The following decapsulation formats are supported:
8
9| Media Format | Encapsulation Format                     |
10| -------- | :----------------------------|
11| Video    | MP4, MPEG TS                 |
12| Audio     | M4A, AAC, MP3, OGG, FLAC, WAV|
13
14
15
16**Usage Scenario**
17
18- Audio and video playback
19
20  Decapsulate audio and video streams, decode the frame data obtained through decapsulation, and play the decoded data.
21
22- Audio and video editing
23
24  Decapsulate audio and video streams, and edit the specified frames.
25
26- Media file format conversion
27
28  Decapsulate audio and video streams, and encapsulate them into a new file format.
29
30## How to Develop
31Read [AVDemuxer](../reference/native-apis/_a_v_demuxer.md) and [AVSource](../reference/native-apis/_a_v_source.md) for the API reference.
32
33> **NOTE**
34>
35> - To call the decapsulation APIs to parse a network playback path, request the **ohos.permission.INTERNET** permission by following the instructions provided in [Applying for Permissions](../security/accesstoken-guidelines.md).
36> - To call the decapsulation APIs to parse a local file, request the **ohos.permission.READ_MEDIA** permission by following the instructions provided in [Applying for Permissions](../security/accesstoken-guidelines.md).
37> - 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/js-apis-resource-manager.md#getrawfd9).
38
39### Linking the Dynamic Library in the CMake Script
40``` cmake
41target_link_libraries(sample PUBLIC libnative_media_avdemuxer.so)
42target_link_libraries(sample PUBLIC libnative_media_avsource.so)
43```
44
45### How to Develop
46
471. Create a demuxer instance.
48
49   ``` c++
50   // Create the FD. You must have the read permission on the file handle when opening the file.
51   std::string fileName = "test.mp4";
52   int fd = open(fileName.c_str(), O_RDONLY);
53   struct stat fileStatus {};
54   size_t fileSize = 0;
55   if (stat(fileName.c_str(), &fileStatus) == 0) {
56      fileSize = static_cast<size_t>(fileStatus.st_size);
57   } else {
58      printf("get stat failed");
59      return;
60   }
61   // 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 decapsulation may fail.
62   OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, fileSize);
63   if (source == nullptr) {
64      printf("create source failed");
65      return;
66   }
67   // (Optional) Create a source resource object for the URI resource file.
68   // OH_AVSource *source = OH_AVSource_CreateWithURI(uri);
69   ```
70   ```c++
71   // Create a demuxer for the resource object.
72   OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source);
73   if (demuxer == nullptr) {
74      printf("create demuxer failed");
75      return;
76   }
77   ```
78
79
80
812. (Optional) Obtain the number of tracks. If you know the track information, skip this step.
82
83   ``` c++
84   // Obtain the number of tracks from the file source information.
85   OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source);
86   if (sourceFormat == nullptr) {
87      printf("get source format failed");
88      return;
89   }
90   int32_t trackCount = 0;
91   OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount);
92   OH_AVFormat_Destroy(sourceFormat);
93   ```
94
95
96
973. (Optional) Obtain the track index and format. If you know the track information, skip this step.
98
99   ``` c++
100   uint32_t audioTrackIndex = 0;
101   uint32_t videoTrackIndex = 0;
102   int32_t w = 0;
103   int32_t h = 0;
104   int32_t trackType;
105   for (uint32_t index = 0; index < (static_cast<uint32_t>(trackCount)); index++) {
106      // Obtain the track format.
107      OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index);
108      if (trackFormat == nullptr) {
109         printf("get track format failed");
110         return;
111      }
112      OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType);
113      static_cast<OH_MediaType>(trackType) == OH_MediaType::MEDIA_TYPE_AUD ? audioTrackIndex = index : videoTrackIndex = index;
114      // Obtain the width and height of the video track.
115      if (trackType == OH_MediaType::MEDIA_TYPE_VID) {
116         OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_WIDTH, &w);
117         OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_HEIGHT, &h);
118      }
119      OH_AVFormat_Destroy(trackFormat);
120   }
121   ```
122
123
124
1254. Select a track, from which the demuxer reads data.
126
127   ``` c++
128   if(OH_AVDemuxer_SelectTrackByID(demuxer, audioTrackIndex) != AV_ERR_OK){
129      printf("select audio track failed: %d", audioTrackIndex);
130      return;
131   }
132   if(OH_AVDemuxer_SelectTrackByID(demuxer, videoTrackIndex) != AV_ERR_OK){
133      printf("select video track failed: %d", videoTrackIndex);
134      return;
135   }
136   // (Optional) Deselect the track.
137   // OH_AVDemuxer_UnselectTrackByID(demuxer, audioTrackIndex);
138   ```
139
140
141
1425. (Optional) Seek to the specified time for the selected track.
143
144   ``` c++
145   // Decapsulation is performed from this time.
146   // Note:
147   // 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_ReadSample 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.
148   // 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.
149   OH_AVDemuxer_SeekToTime(demuxer, 0, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
150   ```
151
1526. Start decapsulation and cyclically obtain frame data. The code snippet below uses a file that contains audio and video tracks as an example.
153
154   ``` c++
155   // Create a buffer to store the data obtained after decapsulation.
156   OH_AVMemory *buffer = OH_AVMemory_Create(w * h * 3 >> 1);
157   if (buffer == nullptr) {
158      printf("build buffer failed");
159      return;
160   }
161   OH_AVCodecBufferAttr info;
162   bool videoIsEnd = false;
163   bool audioIsEnd = false;
164   int32_t ret;
165   while (!audioIsEnd || !videoIsEnd) {
166      // Before calling OH_AVDemuxer_ReadSample, call OH_AVDemuxer_SelectTrackByID to select the track from which the demuxer reads data.
167      // Obtain audio frame data.
168      if(!audioIsEnd) {
169         ret = OH_AVDemuxer_ReadSample(demuxer, audioTrackIndex, buffer, &info);
170         if (ret == AV_ERR_OK) {
171            // Obtain the process the audio frame data in the buffer.
172            printf("audio info.size: %d\n", info.size);
173            if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
174               audioIsEnd = true;
175            }
176         }
177      }
178      if(!videoIsEnd) {
179         ret = OH_AVDemuxer_ReadSample(demuxer, videoTrackIndex, buffer, &info);
180         if (ret == AV_ERR_OK) {
181            // Obtain the process the video frame data in the buffer.
182            printf("video info.size: %d\n", info.size);
183            if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) {
184               videoIsEnd = true;
185            }
186         }
187      }
188   }
189   OH_AVMemory_Destroy(buffer);
190   ```
191
192
193
1947. Destroy the demuxer instance.
195
196   ``` c++
197   // 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.
198   if (OH_AVSource_Destroy(source) != AV_ERR_OK) {
199      printf("destroy source pointer error");
200   }
201   source = NULL;
202   // 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.
203   if (OH_AVDemuxer_Destroy(demuxer) != AV_ERR_OK) {
204      printf("destroy demuxer pointer error");
205   }
206   demuxer = NULL;
207   close(fd);
208   ```
209