1# 音视频封装 2 3开发者可以调用本模块的Native API接口,完成音视频封装,即将音频、视频等编码后的媒体数据,按一定的格式存储到文件里。 4 5当前支持的封装能力如下: 6 7| 封装格式 | 视频编解码类型 | 音频编解码类型 | 封面类型 | 8| -------- | --------------------- | ---------------- | -------------- | 9| mp4 | MPEG-4、 AVC(H.264) | AAC、MPEG(MP3) | jpeg、png、bmp | 10| m4a | MPEG-4、 AVC(H.264) | AAC | jpeg、png、bmp | 11 12**适用场景** 13 14- 录像、录音 15 16 保存录像、录音文件时,需要先对音视频流进行编码,再封装为文件。 17 18- 音视频编辑 19 20 完成编辑后的音视频,需要封装为文件。 21 22- 音视频转码 23 24 转码后,保存文件时需要封装。 25 26## 开发指导 27 28详细的API说明请参考[API文档](../reference/native-apis/_a_v_muxer.md)。 29 30> **说明:** 31> 32> 如果调用封装能力写本地文件,需要[申请相关权限](../security/accesstoken-guidelines.md):ohos.permission.READ_MEDIA, ohos.permission.WRITE_MEDIA 33 34### 在 CMake 脚本中链接动态库 35``` cmake 36target_link_libraries(sample PUBLIC libnative_media_avmuxer.so) 37``` 38 39### 开发步骤 40 41参考以下示例代码,完成音视频封装的全流程。以封装mp4格式的音视频文件为例。 42 431. 调用OH_AVMuxer_Create()创建封装器实例对象。 44 45 ``` c++ 46 // 设置封装格式为mp4 47 OH_AVOutputFormat format = AV_OUTPUT_FORMAT_MPEG_4; 48 // 以读写方式创建fd 49 int32_t fd = open("test.mp4", O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 50 OH_AVMuxer *muxer = OH_AVMuxer_Create(fd, format); 51 ``` 52 532. (可选)调用OH_AVMuxer_SetRotation()设置旋转角度。 54 55 ``` c++ 56 // 旋转角度,视频画面需要旋转的时候设置 57 OH_AVMuxer_SetRotation(muxer, 0); 58 ``` 59 603. 添加音频轨。 61 62 **方法一:用OH_AVFormat_Create创建format** 63 64 ``` c++ 65 int audioTrackId = -1; 66 OH_AVFormat *formatAudio = OH_AVFormat_Create(); 67 OH_AVFormat_SetStringValue(formatAudio, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_AAC); // 必填 68 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_SAMPLE_RATE, 44100); // 必填 69 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_CHANNEL_COUNT, 2); // 必填 70 71 int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio); 72 if (ret != AV_ERR_OK || audioTrackId < 0) { 73 // 音频轨添加失败 74 } 75 OH_AVFormat_Destroy(formatAudio); // 销毁 76 ``` 77 78 **方法二:用OH_AVFormat_CreateAudioFormat创建format** 79 80 ``` c++ 81 int audioTrackId = -1; 82 OH_AVFormat *formatAudio = OH_AVFormat_CreateAudioFormat(OH_AVCODEC_MIMETYPE_AUDIO_AAC, 44100, 2); 83 84 int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio); 85 if (ret != AV_ERR_OK || audioTrackId < 0) { 86 // 音频轨添加失败 87 } 88 OH_AVFormat_Destroy(formatAudio); // 销毁 89 ``` 90 914. 添加视频轨。 92 93 **方法一:用OH_AVFormat_Create创建format** 94 95 ``` c++ 96 int videoTrackId = -1; 97 uint8_t *buffer = ...; // 编码config data,如果没有可以不传 98 size_t size = ...; // 编码config data的长度,根据实际情况配置 99 OH_AVFormat *formatVideo = OH_AVFormat_Create(); 100 OH_AVFormat_SetStringValue(formatVideo, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_MPEG4); // 必填 101 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_WIDTH, 1280); // 必填 102 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_HEIGHT, 720); // 必填 103 OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须 104 105 int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo); 106 if (ret != AV_ERR_OK || videoTrackId < 0) { 107 // 视频轨添加失败 108 } 109 OH_AVFormat_Destroy(formatVideo); // 销毁 110 ``` 111 112 **方法二:用OH_AVFormat_CreateVideoFormat创建format** 113 114 ``` c++ 115 int videoTrackId = -1; 116 uint8_t *buffer = ...; // 编码config data,如果没有可以不传 117 size_t size = ...; // 编码config data的长度,根据实际情况配置 118 OH_AVFormat *formatVideo = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_MPEG4, 1280, 720); 119 OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须 120 121 int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo); 122 if (ret != AV_ERR_OK || videoTrackId < 0) { 123 // 视频轨添加失败 124 } 125 OH_AVFormat_Destroy(formatVideo); // 销毁 126 ``` 127 1285. 添加封面轨。 129 130 **方法一:用OH_AVFormat_Create创建format** 131 132 ``` c++ 133 int coverTrackId = -1; 134 OH_AVFormat *formatCover = OH_AVFormat_Create(); 135 OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_IMAGE_JPG); 136 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, 1280); 137 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, 720); 138 139 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 140 if (ret != AV_ERR_OK || coverTrackId < 0) { 141 // 添加封面失败 142 } 143 OH_AVFormat_Destroy(formatCover); // 销毁 144 ``` 145 146 **方法二:用OH_AVFormat_CreateVideoFormat创建format** 147 148 ``` c++ 149 int coverTrackId = -1; 150 OH_AVFormat *formatCover = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_IMAGE_JPG, 1280, 720); 151 152 int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover); 153 if (ret != AV_ERR_OK || coverTrackId < 0) { 154 // 添加封面失败 155 } 156 OH_AVFormat_Destroy(formatCover); // 销毁 157 ``` 158 1596. 调用OH_AVMuxer_Start()开始封装。 160 161 ``` c++ 162 // 调用start,写封装文件头。start后,不能设置媒体参数、不能添加媒体轨 163 if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) { 164 // 异常处理 165 } 166 ``` 167 1687. 调用OH_AVMuxer_WriteSample(),写入封装数据。 169 170 包括视频、音频、封面数据。 171 172 ``` c++ 173 // start后,才能开始写入数据 174 int size = ...; 175 OH_AVMemory *sample = OH_AVMemory_Create(size); // 创建AVMemory 176 // 往sampleBuffer里写入数据参考OH_AVMemory的使用方法 177 // 封装封面,必须一次写完一张图片 178 179 // 创建buffer info 180 OH_AVCodecBufferAttr info; 181 info.pts = ...; // 当前数据的开始播放的时间,单位微秒 182 info.size = size; // 当前数据的长度 183 info.offset = 0; // 偏移,一般为0 184 info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME; // 当前数据的标志。具体参考OH_AVCodecBufferFlags 185 int trackId = audioTrackId; // 选择写的媒体轨 186 187 int ret = OH_AVMuxer_WriteSample(muxer, trackId, sample, info); 188 if (ret != AV_ERR_OK) { 189 // 异常处理 190 } 191 ``` 192 1938. 调用OH_AVMuxer_Stop(),停止封装。 194 195 ``` c++ 196 // 调用stop,写封装文件尾。stop后不能写入媒体数据 197 if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) { 198 // 异常处理 199 } 200 ``` 201 2029. 调用OH_AVMuxer_Destroy()销毁实例,释放资源。 203 204 ``` c++ 205 if (OH_AVMuxer_Destroy(muxer) != AV_ERR_OK) { 206 // 异常处理 207 } 208 muxer = NULL; 209 close(fd); // 关闭文件描述符 210 ```