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