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