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
73   **方法一:用OH_AVFormat_Create创建format**
74
75   ```c++
76   int audioTrackId = -1;
77   uint8_t *buffer = ...; // 编码config data,如果没有可以不传
78   size_t size = ...;  // 编码config data的长度,根据实际情况配置
79   OH_AVFormat *formatAudio = OH_AVFormat_Create(); // 用OH_AVFormat_Create创建format, 这里以封装44100Hz采样率、2声道的AAC-LC音频为例。
80   OH_AVFormat_SetStringValue(formatAudio, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_AAC); // 必填
81   OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_SAMPLE_RATE, 44100); // 必填
82   OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUD_CHANNEL_COUNT, 2); // 必填
83   OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_PROFILE, AAC_PROFILE_LC); // 选填
84   OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 选填
85
86   int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio);
87   if (ret != AV_ERR_OK || audioTrackId < 0) {
88       // 音频轨添加失败
89   }
90   OH_AVFormat_Destroy(formatAudio); // 销毁
91   ```
92
93   **方法二:用OH_AVFormat_CreateAudioFormat创建format**
94
95   ```c++
96   int audioTrackId = -1;
97   uint8_t *buffer = ...; // 编码config data,如果没有可以不传
98   size_t size = ...;  // 编码config data的长度,根据实际情况配置
99   OH_AVFormat *formatAudio = OH_AVFormat_CreateAudioFormat(OH_AVCODEC_MIMETYPE_AUDIO_AAC, 44100, 2);
100   OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_PROFILE, AAC_PROFILE_LC); // 选填
101   OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 选填
102
103   int ret = OH_AVMuxer_AddTrack(muxer, &audioTrackId, formatAudio);
104   if (ret != AV_ERR_OK || audioTrackId < 0) {
105       // 音频轨添加失败
106   }
107   OH_AVFormat_Destroy(formatAudio); // 销毁
108   ```
109
1105. 添加视频轨。
111
112   **方法一:用OH_AVFormat_Create创建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_Create();
119   OH_AVFormat_SetStringValue(formatVideo, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_VIDEO_AVC); // 必填
120   OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_WIDTH, 1280); // 必填
121   OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_HEIGHT, 720); // 必填
122   OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须
123
124   int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo);
125   if (ret != AV_ERR_OK || videoTrackId < 0) {
126       // 视频轨添加失败
127   }
128   OH_AVFormat_Destroy(formatVideo); // 销毁
129   ```
130
131   **方法二:用OH_AVFormat_CreateVideoFormat创建format**
132
133   ```c++
134   int videoTrackId = -1;
135   uint8_t *buffer = ...; // 编码config data,如果没有可以不传
136   size_t size = ...;  // 编码config data的长度,根据实际情况配置
137   OH_AVFormat *formatVideo = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_VIDEO_AVC, 1280, 720);
138   OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, size); // 非必须
139
140   int ret = OH_AVMuxer_AddTrack(muxer, &videoTrackId, formatVideo);
141   if (ret != AV_ERR_OK || videoTrackId < 0) {
142       // 视频轨添加失败
143   }
144   OH_AVFormat_Destroy(formatVideo); // 销毁
145   ```
146
1476. 添加封面轨。
148
149   **方法一:用OH_AVFormat_Create创建format**
150
151   ```c++
152   int coverTrackId = -1;
153   OH_AVFormat *formatCover = OH_AVFormat_Create();
154   OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_IMAGE_JPG);
155   OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, 1280);
156   OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, 720);
157
158   int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover);
159   if (ret != AV_ERR_OK || coverTrackId < 0) {
160       // 添加封面失败
161   }
162   OH_AVFormat_Destroy(formatCover); // 销毁
163   ```
164
165   **方法二:用OH_AVFormat_CreateVideoFormat创建format**
166
167   ```c++
168   int coverTrackId = -1;
169   OH_AVFormat *formatCover = OH_AVFormat_CreateVideoFormat(OH_AVCODEC_MIMETYPE_IMAGE_JPG, 1280, 720);
170
171   int ret = OH_AVMuxer_AddTrack(muxer, &coverTrackId, formatCover);
172   if (ret != AV_ERR_OK || coverTrackId < 0) {
173       // 添加封面失败
174   }
175   OH_AVFormat_Destroy(formatCover); // 销毁
176   ```
177
1787. 调用OH_AVMuxer_Start()开始封装。
179
180   ```c++
181   // 调用start,写封装文件头。start后,不能设置媒体参数、不能添加音视频轨
182   if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) {
183       // 异常处理
184   }
185   ```
186
1878. 调用OH_AVMuxer_WriteSampleBuffer(),写入封装数据。封装数据包括视频、音频、封面等数据。
188
189   ```c++
190   // start后,才能开始写入数据
191   int size = ...;
192   OH_AVBuffer *sample = OH_AVBuffer_Create(size); // 创建AVBuffer
193   // 通过OH_AVBuffer_GetAddr(sample)往sampleBuffer里写入数据参考OH_AVBuffer的使用方法
194   // 封装封面,必须一次写完一张图片
195
196   // 创建buffer info
197   OH_AVCodecBufferAttr info = {0};
198   info.pts = ...; // 当前数据的开始播放的时间,单位微秒,相对时间
199   info.size = size; // 当前数据的长度
200   info.offset = 0; // 偏移,一般为0
201   info.flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME; // 当前数据的标志。具体参考OH_AVCodecBufferFlags
202   info.flags |= AVCODEC_BUFFER_FLAGS_CODEC_DATA; // 当annex-b格式的avc包含codec config的标志。
203   OH_AVBuffer_SetBufferAttr(sample, &info); // 设置buffer的属性.
204   int trackId = audioTrackId; // 选择写的音视频轨
205
206   int ret = OH_AVMuxer_WriteSampleBuffer(muxer, trackId, sample);
207   if (ret != AV_ERR_OK) {
208       // 异常处理
209   }
210   ```
211
2129. 调用OH_AVMuxer_Stop(),停止封装。
213
214   ```c++
215   // 调用stop,写封装文件尾。stop后不能写入媒体数据
216   if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) {
217       // 异常处理
218   }
219   ```
220
22110. 调用OH_AVMuxer_Destroy()销毁实例,释放资源。注意不能重复销毁,会导致程序崩溃。
222
223    ```c++
224    if (OH_AVMuxer_Destroy(muxer) != AV_ERR_OK) {
225        // 异常处理
226    }
227    muxer = NULL;
228    close(fd); // 关闭文件描述符
229    ```
230