1# 媒体数据封装 2 3开发者可以调用本模块的Native API接口,完成音视频封装,即将音频、视频等编码后的媒体数据,按一定的格式存储到文件里。 4 5当前支持的封装能力请参考[AVCodec支持的格式](avcodec-support-formats.md#媒体数据封装)。 6 7<!--RP2--><!--RP2End--> 8 9**适用场景** 10 11- 录像、录音 12 13 保存录像、录音文件时,需要先对音视频流进行编码,再封装为文件。 14 15- 音视频编辑 16 17 完成编辑后的音视频,需要封装为文件。 18 19- 音视频转码 20 21 转码后,保存文件时需要封装。 22 23## 开发指导 24 25详细的API说明请参考[API文档](../../reference/apis-avcodec-kit/_a_v_muxer.md)。 26 27> **说明:** 28> 29> 如果调用封装模块写本地文件,需要[向用户申请授权](../../security/AccessToken/request-user-authorization.md):ohos.permission.READ_MEDIA, ohos.permission.WRITE_MEDIA。 30 31### 在 CMake 脚本中链接动态库 32 33``` cmake 34target_link_libraries(sample PUBLIC libnative_media_avmuxer.so) 35target_link_libraries(sample PUBLIC libnative_media_core.so) 36``` 37 38### 开发步骤 39 40参考以下示例代码,完成音视频封装的全流程。以封装mp4格式的音视频文件为例。 41 42不同的封装格式需要配置的key请参考[AVCodec支持的格式](avcodec-support-formats.md#媒体数据封装)。 43 441. 添加头文件。 45 46 ```c++ 47 #include <multimedia/player_framework/native_avmuxer.h> 48 #include <multimedia/player_framework/native_avcodec_base.h> 49 #include <multimedia/player_framework/native_avformat.h> 50 #include <multimedia/player_framework/native_avbuffer.h> 51 #include <fcntl.h> 52 ``` 53 542. 调用OH_AVMuxer_Create()创建封装器实例对象。 55 56 ```c++ 57 // 设置封装格式为mp4。 58 OH_AVOutputFormat format = AV_OUTPUT_FORMAT_MPEG_4; 59 // 以读写方式创建fd。 60 int32_t fd = open("test.mp4", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 61 OH_AVMuxer *muxer = OH_AVMuxer_Create(fd, format); 62 ``` 63 643. (可选)调用OH_AVMuxer_SetRotation()设置旋转角度。 65 66 ```c++ 67 // 旋转角度,视频画面需要旋转的时候设置。 68 OH_AVMuxer_SetRotation(muxer, 0); 69 ``` 70 714. 添加文件级数据。 72 ```c++ 73 OH_AVFormat *format = OH_AVFormat_Create(); // 用OH_AVFormat_Create创建format。 74 OH_AVFormat_SetStringValue(format, OH_MD_KEY_CREATION_TIME, "2024-12-28T00:00:00:000000Z"); // 设置创建时间(使用ISO 8601标准的时间格式且为UTC时间)。 75 int ret = OH_AVMuxer_SetFormat(muxer, format); // 设置封装的format。 76 if (ret != AV_ERR_OK) { 77 // 设置format失败,未找到有效待写入的key数据。 78 } 79 OH_AVFormat_Destroy(format); // 销毁。 80 ``` 81 825. 添加音频轨。 83 84 **方法一:用OH_AVFormat_Create创建format** 85 86 ```c++ 87 int audioTrackId = -1; 88 uint8_t *buffer = ...; // 编码config data,如果没有可以不传。 89 size_t size = ...; // 编码config data的长度,根据实际情况配置。 90 OH_AVFormat *formatAudio = OH_AVFormat_Create(); // 用OH_AVFormat_Create创建format,这里以封装44100Hz采样率、2声道的AAC-LC音频为例。 91 OH_AVFormat_SetStringValue(formatAudio, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_AAC); // 必填。 92 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_SAMPLE_RATE, 44100); // 必填。 93 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_CHANNEL_COUNT, 2); // 必填。 94 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_PROFILE, AAC_PROFILE_LC); // 选填。 95 OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 选填。 96 97 int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio); 98 if (ret != AV_ERR_OK || audioTrackId < 0) { 99 // 音频轨添加失败。 100 } 101 OH_AVFormat_Destroy(formatAudio); // 销毁。 102 ``` 103 104 **方法二:用OH_AVFormat_CreateAudioFormat创建format** 105 106 ```c++ 107 int audioTrackId = -1; 108 uint8_t *buffer = ...; // 编码config data,如果没有可以不传。 109 size_t size = ...; // 编码config data的长度,根据实际情况配置。 110 OH_AVFormat *formatAudio = OH_AVFormat_CreateAudioFormat(OH_AVCODEC_MIMETYPE_AUDIO_AAC, 44100, 2); 111 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_PROFILE, AAC_PROFILE_LC); // 选填。 112 OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 选填。 113 114 int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio); 115 if (ret != AV_ERR_OK || audioTrackId < 0) { 116 // 音频轨添加失败。 117 } 118 OH_AVFormat_Destroy(formatAudio); // 销毁。 119 ``` 120 1216. 添加视频轨。 122 123 **方法一:用OH_AVFormat_Create创建format** 124 125 ```c++ 126 int videoTrackId = -1; 127 uint8_t *buffer = ...; // 编码config data,如果没有可以不传。 128 size_t size = ...; // 编码config data的长度,根据实际情况配置。 129 OH_AVFormat *formatVideo = OH_AVFormat_Create(); 130 OH_AVFormat_SetStringValue(formatVideo, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_AVC); // 必填。 131 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_WIDTH, 1280); // 必填。 132 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_HEIGHT, 720); // 必填。 133 OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须。 134 135 int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo); 136 if (ret != AV_ERR_OK || videoTrackId < 0) { 137 // 视频轨添加失败。 138 } 139 OH_AVFormat_Destroy(formatVideo); // 销毁。 140 ``` 141 142 **方法二:用OH_AVFormat_CreateVideoFormat创建format** 143 144 ```c++ 145 int videoTrackId = -1; 146 uint8_t *buffer = ...; // 编码config data,如果没有可以不传。 147 size_t size = ...; // 编码config data的长度,根据实际情况配置。 148 OH_AVFormat *formatVideo = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1280, 720); 149 OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须。 150 151 int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo); 152 if (ret != AV_ERR_OK || videoTrackId < 0) { 153 // 视频轨添加失败。 154 } 155 OH_AVFormat_Destroy(formatVideo); // 销毁。 156 ``` 157 1587. 添加辅助轨。 159 > **说明:** 160 > 161 > 设置OH_MD_KEY_TRACK_TYPE时,值为MEDIA_TYPE_AUXILIARY代表添加辅助轨。<br> 162 > 设置OH_MD_KEY_TRACK_REFERENCE_TYPE时,值必须为"hint"、"cdsc"、"font"、"hind"、"vdep"、"vplx"、"subt"、"thmb"、"auxl"、"cdtg"、"shsc"或"aest"其中一项。<br> 163 > 设置OH_MD_KEY_TRACK_DESCRIPTION时,值必须为"com.openharmony."开头且长度不超过256的字符串。<br> 164 > 设置OH_MD_KEY_REFERENCE_TRACK_IDS时,track id值必须大于等于0,且必须是已经存在的track id。 165 166 **添加音频辅助轨** 167 168 ```c++ 169 int32_t audioAuxlTrackId = -1; 170 std::vector<int32_t> audioTrackIDsVector = {0}; // 根据实际情况设置被辅助音频轨的编号,可填写多个值。 171 int32_t *audioAuxlTrackIDs = audioTrackIDsVector.data(); 172 OH_AVFormat *audioAuxlFormat = OH_AVFormat_Create(); 173 OH_AVFormat_SetStringValue(audioAuxlFormat, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_AAC); // 必填。 174 OH_AVFormat_SetIntValue(audioAuxlFormat, OH_MD_KEY_AUD_SAMPLE_RATE, 44100); // 必填。 175 OH_AVFormat_SetIntValue(audioAuxlFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, 2); // 必填。 176 OH_AVFormat_SetIntValue(audioAuxlFormat, OH_MD_KEY_PROFILE, AAC_PROFILE_LC); // 选填。 177 OH_AVFormat_SetIntValue(audioAuxlFormat, OH_MD_KEY_TRACK_TYPE, static_cast<int32_t>(OH_MediaType::MEDIA_TYPE_AUXILIARY)); // 必填。 178 OH_AVFormat_SetStringValue(audioAuxlFormat, OH_MD_KEY_TRACK_REFERENCE_TYPE, "auxl"); // 必填。 179 OH_AVFormat_SetStringValue(audioAuxlFormat, OH_MD_KEY_TRACK_DESCRIPTION, "com.openharmony.audiomode.auxiliary"); // 必填。 180 OH_AVFormat_SetIntBuffer(audioAuxlFormat, OH_MD_KEY_REFERENCE_TRACK_IDS, audioAuxlTrackIDs, audioTrackIDsVector.size()); // 必填。 181 182 int ret = OH_AVMuxer_AddTrack(muxer, &audioAuxlTrackId, audioAuxlFormat); 183 if (ret != AV_ERR_OK || audioAuxlTrackId < 0) { 184 // 音频辅助轨添加失败。 185 } 186 ``` 187 188 **添加视频辅助轨** 189 190 ```c++ 191 int32_t videoAuxlTrackId = -1; 192 std::vector<int32_t> videoTrackIDsVector = {0}; // 根据实际情况设置被辅助视频轨的编号,可填写多个值。 193 int32_t *videoAuxlTrackIDs = videoTrackIDsVector.data(); 194 OH_AVFormat *videoAuxlFormat = OH_AVFormat_Create(); 195 OH_AVFormat_SetStringValue(videoAuxlFormat, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_AVC); // 必填。 196 OH_AVFormat_SetIntValue(videoAuxlFormat, OH_MD_KEY_WIDTH, 1280); // 必填。 197 OH_AVFormat_SetIntValue(videoAuxlFormat, OH_MD_KEY_HEIGHT, 720); // 必填。 198 OH_AVFormat_SetIntValue(videoAuxlFormat, OH_MD_KEY_TRACK_TYPE, static_cast<int32_t>(OH_MediaType::MEDIA_TYPE_AUXILIARY)); // 必填。 199 OH_AVFormat_SetStringValue(videoAuxlFormat, OH_MD_KEY_TRACK_REFERENCE_TYPE, "vdep"); // 必填。 200 OH_AVFormat_SetStringValue(videoAuxlFormat, OH_MD_KEY_TRACK_DESCRIPTION, "com.openharmony.moviemode.depth"); // 必填。 201 OH_AVFormat_SetIntBuffer(videoAuxlFormat, OH_MD_KEY_REFERENCE_TRACK_IDS, videoAuxlTrackIDs, videoTrackIDsVector.size()); // 必填。 202 203 int ret = OH_AVMuxer_AddTrack(muxer, &videoAuxlTrackId, videoAuxlFormat); 204 if (ret != AV_ERR_OK || videoAuxlTrackId < 0) { 205 // 视频辅助轨添加失败。 206 } 207 ``` 208 2098. 添加封面轨。 210 211 **方法一:用OH_AVFormat_Create创建format** 212 213 ```c++ 214 int coverTrackId = -1; 215 OH_AVFormat *formatCover = OH_AVFormat_Create(); 216 OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_IMAGE_JPG); 217 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, 1280); 218 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, 720); 219 220 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 221 if (ret != AV_ERR_OK || coverTrackId < 0) { 222 // 添加封面失败。 223 } 224 OH_AVFormat_Destroy(formatCover); // 销毁。 225 ``` 226 227 **方法二:用OH_AVFormat_CreateVideoFormat创建format** 228 229 ```c++ 230 int coverTrackId = -1; 231 OH_AVFormat *formatCover = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_IMAGE_JPG, 1280, 720); 232 233 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 234 if (ret != AV_ERR_OK || coverTrackId < 0) { 235 // 添加封面失败。 236 } 237 OH_AVFormat_Destroy(formatCover); // 销毁。 238 ``` 239 2409. 调用OH_AVMuxer_Start()开始封装。 241 242 ```c++ 243 // 调用start,写封装文件头。start后,不能设置媒体参数、不能添加音视频轨。 244 if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) { 245 // 异常处理。 246 } 247 ``` 248 24910. 调用OH_AVMuxer_WriteSampleBuffer(),写入封装数据。 250 251 封装数据包括视频、音频、封面等数据。 252 253 ```c++ 254 // start后,才能开始写入数据。 255 int size = ...; 256 OH_AVBuffer *sample = OH_AVBuffer_Create(size); // 创建AVBuffer。 257 // 通过OH_AVBuffer_GetAddr(sample)往sampleBuffer里写入数据参考OH_AVBuffer的使用方法。 258 // 封装封面,必须一次写完一张图片。 259 260 // 创建buffer info。 261 OH_AVCodecBufferAttr info = {0}; 262 info.pts = ...; // 当前数据的开始播放的时间,单位微秒,相对时间。 263 info.size = size; // 当前数据的长度。 264 info.offset = 0; // 偏移,一般为0。 265 info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME; // 当前数据的标志。具体参考OH_AVCodecBufferFlags。 266 info.flags |= AVCODEC_BUFFER_FLAGS_CODEC_DATA; // 当annex-b格式的avc包含codec config的标志。 267 OH_AVBuffer_SetBufferAttr(sample, &info); // 设置buffer的属性。 268 int trackId = audioTrackId; // 选择写的音视频轨。 269 270 int ret = OH_AVMuxer_WriteSampleBuffer(muxer, trackId, sample); 271 if (ret != AV_ERR_OK) { 272 // 异常处理。 273 } 274 ``` 275 27611. 调用OH_AVMuxer_Stop(),停止封装。 277 278 ```c++ 279 // 调用stop,写封装文件尾。stop后不能写入媒体数据。 280 if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) { 281 // 异常处理。 282 } 283 ``` 284 28512. 调用OH_AVMuxer_Destroy()销毁实例,释放资源。 286 287 注意不能重复销毁,否则将会导致程序崩溃。 288 289 ```c++ 290 if (OH_AVMuxer_Destroy(muxer) != AV_ERR_OK) { 291 // 异常处理。 292 } 293 muxer = NULL; 294 close(fd); // 关闭文件描述符。 295 ``` 296