• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_MEDIA30
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