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