1# 媒体数据封装 2 3开发者可以调用本模块的Native API接口,完成音视频封装,即将音频、视频等编码后的媒体数据,按一定的格式存储到文件里。 4 5当前支持的封装能力如下: 6 7| 封装格式 | 视频编解码类型 | 音频编解码类型 | 封面类型 | 8| -------- | --------------------- | ---------------- | -------------- | 9| mp4 | AVC(H.264)<!--RP1--><!--RP1End--> | AAC、MPEG(MP3) | jpeg、png、bmp | 10| m4a | - | AAC | jpeg、png、bmp | 11| mp3 | - | MPEG(MP3) | - | 12| amr | - | AMR(amrnb、amrwb) | - | 13| wav | - | G711mu(pcm-mulaw) | - | 14 15> **说明:** 16> 17> - 封装格式为mp4,音频编解码类型为MPEG(MP3)时采样率需大于等于16000Hz。 18> - 封装格式为mp4/m4a,音频编解码类型为AAC时声道数范围为1~7。 19 20<!--RP2--><!--RP2End--> 21 22**适用场景** 23 24- 录像、录音 25 26 保存录像、录音文件时,需要先对音视频流进行编码,再封装为文件。 27 28- 音视频编辑 29 30 完成编辑后的音视频,需要封装为文件。 31 32- 音视频转码 33 34 转码后,保存文件时需要封装。 35 36## 开发指导 37 38详细的API说明请参考[API文档](../../reference/apis-avcodec-kit/_a_v_muxer.md)。 39 40> **说明:** 41> 42> 如果调用封装模块写本地文件,需要[向用户申请授权](../../security/AccessToken/request-user-authorization.md):ohos.permission.READ_MEDIA, ohos.permission.WRITE_MEDIA 43 44### 在 CMake 脚本中链接动态库 45 46``` cmake 47target_link_libraries(sample PUBLIC libnative_media_avmuxer.so) 48target_link_libraries(sample PUBLIC libnative_media_core.so) 49``` 50 51### 开发步骤 52 53参考以下示例代码,完成音视频封装的全流程。以封装mp4格式的音视频文件为例。 54 551. 添加头文件。 56 57 ```c++ 58 #include <multimedia/player_framework/native_avmuxer.h> 59 #include <multimedia/player_framework/native_avcodec_base.h> 60 #include <multimedia/player_framework/native_avformat.h> 61 #include <multimedia/player_framework/native_avbuffer.h> 62 #include <fcntl.h> 63 ``` 64 652. 调用OH_AVMuxer_Create()创建封装器实例对象。 66 67 ```c++ 68 // 设置封装格式为mp4 69 OH_AVOutputFormat format = AV_OUTPUT_FORMAT_MPEG_4; 70 // 以读写方式创建fd 71 int32_t fd = open("test.mp4", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 72 OH_AVMuxer *muxer = OH_AVMuxer_Create(fd, format); 73 ``` 74 753. (可选)调用OH_AVMuxer_SetRotation()设置旋转角度。 76 77 ```c++ 78 // 旋转角度,视频画面需要旋转的时候设置 79 OH_AVMuxer_SetRotation(muxer, 0); 80 ``` 81 824. 添加音频轨。 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 1215. 添加视频轨。 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 1586. 添加封面轨。 159 160 **方法一:用OH_AVFormat_Create创建format** 161 162 ```c++ 163 int coverTrackId = -1; 164 OH_AVFormat *formatCover = OH_AVFormat_Create(); 165 OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_IMAGE_JPG); 166 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, 1280); 167 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, 720); 168 169 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 170 if (ret != AV_ERR_OK || coverTrackId < 0) { 171 // 添加封面失败 172 } 173 OH_AVFormat_Destroy(formatCover); // 销毁 174 ``` 175 176 **方法二:用OH_AVFormat_CreateVideoFormat创建format** 177 178 ```c++ 179 int coverTrackId = -1; 180 OH_AVFormat *formatCover = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_IMAGE_JPG, 1280, 720); 181 182 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 183 if (ret != AV_ERR_OK || coverTrackId < 0) { 184 // 添加封面失败 185 } 186 OH_AVFormat_Destroy(formatCover); // 销毁 187 ``` 188 1897. 调用OH_AVMuxer_Start()开始封装。 190 191 ```c++ 192 // 调用start,写封装文件头。start后,不能设置媒体参数、不能添加音视频轨 193 if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) { 194 // 异常处理 195 } 196 ``` 197 1988. 调用OH_AVMuxer_WriteSampleBuffer(),写入封装数据。封装数据包括视频、音频、封面等数据。 199 200 ```c++ 201 // start后,才能开始写入数据 202 int size = ...; 203 OH_AVBuffer *sample = OH_AVBuffer_Create(size); // 创建AVBuffer 204 // 通过OH_AVBuffer_GetAddr(sample)往sampleBuffer里写入数据参考OH_AVBuffer的使用方法 205 // 封装封面,必须一次写完一张图片 206 207 // 创建buffer info 208 OH_AVCodecBufferAttr info = {0}; 209 info.pts = ...; // 当前数据的开始播放的时间,单位微秒,相对时间 210 info.size = size; // 当前数据的长度 211 info.offset = 0; // 偏移,一般为0 212 info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME; // 当前数据的标志。具体参考OH_AVCodecBufferFlags 213 info.flags |= AVCODEC_BUFFER_FLAGS_CODEC_DATA; // 当annex-b格式的avc包含codec config的标志。 214 OH_AVBuffer_SetBufferAttr(sample, &info); // 设置buffer的属性. 215 int trackId = audioTrackId; // 选择写的音视频轨 216 217 int ret = OH_AVMuxer_WriteSampleBuffer(muxer, trackId, sample); 218 if (ret != AV_ERR_OK) { 219 // 异常处理 220 } 221 ``` 222 2239. 调用OH_AVMuxer_Stop(),停止封装。 224 225 ```c++ 226 // 调用stop,写封装文件尾。stop后不能写入媒体数据 227 if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) { 228 // 异常处理 229 } 230 ``` 231 23210. 调用OH_AVMuxer_Destroy()销毁实例,释放资源。注意不能重复销毁,会导致程序崩溃。 233 234 ```c++ 235 if (OH_AVMuxer_Destroy(muxer) != AV_ERR_OK) { 236 // 异常处理 237 } 238 muxer = NULL; 239 close(fd); // 关闭文件描述符 240 ``` 241