1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "audio_muxer_demo.h"
17 #include <iostream>
18 #include <cstdio>
19 #include <unistd.h>
20 #include <dlfcn.h>
21 #include <sys/stat.h>
22
23 #include "avcodec_common.h"
24 #include "avcodec_errors.h"
25 #include "media_description.h"
26 #include "native_avformat.h"
27 #include "demo_log.h"
28 #include "avcodec_codec_name.h"
29 #include "native_avbuffer.h"
30 #include "ffmpeg_converter.h"
31
32 using namespace OHOS;
33 using namespace OHOS::MediaAVCodec;
34 using namespace OHOS::MediaAVCodec::AudioBufferDemo;
35
36 constexpr int32_t WIDTH_720 = 720;
37 constexpr int32_t HEIGHT_480 = 480;
38 constexpr int32_t WIDTH_3840 = 3840;
39 constexpr int32_t HEIGHT_2160 = 2160;
40 constexpr int32_t COLOR_TRANSFER_2 = 2;
41 constexpr int32_t COLOR_TRANSFER_18 = 18;
42 constexpr int32_t FRAME_RATE_30 = 30;
43 constexpr int32_t FRAME_RATE_60 = 60;
44 constexpr int32_t FRAME_SIZE_1024 = 1024;
45 constexpr int32_t COLOR_PRIMARIES_2 = 2;
46 constexpr int32_t COLOR_PRIMARIES_9 = 9;
47 constexpr int32_t COLOR_MATRIXCIEFF_2 = 2;
48 constexpr int32_t COLOR_MATRIXCIEFF_9 = 9;
49 constexpr int32_t VIDEO_DELAY_2 = 2;
50
51 constexpr int32_t CHANNELS_2 = 2;
52
53 constexpr int32_t INFO_PTS_100 = 100;
54 constexpr int32_t INFO_SIZE_1024 = 1024;
55
56 constexpr int32_t SAMPLE_RATE_8000 = 8000;
57 constexpr int32_t SAMPLE_RATE_16000 = 16000;
58 constexpr int32_t SAMPLE_RATE_44100 = 44100;
59
60 constexpr const char* MP4_OUTPUT_FILE_PATH = "/data/test/media/muxer_MP4_outputfile.mp4";
61 constexpr const char* AMRNB_OUTPUT_FILE_PATH = "/data/test/media/muxer_AMRNB_outputfile.amr";
62 constexpr const char* AMRWB_OUTPUT_FILE_PATH = "/data/test/media/muxer_AMRWB_outputfile.amr";
63 constexpr const char* M4A_OUTPUT_FILE_PATH = "/data/test/media/muxer_M4A_outputfile.m4a";
64 constexpr const char* MP3_OUTPUT_FILE_PATH = "/data/test/media/muxer_MP3_outputfile.mp3";
65
AVMuxerDemo()66 AVMuxerDemo::AVMuxerDemo()
67 {
68 }
~AVMuxerDemo()69 AVMuxerDemo::~AVMuxerDemo()
70 {
71 if (avmuxer_) {
72 OH_AVMuxer_Destroy(avmuxer_);
73 avmuxer_ = nullptr;
74 }
75 if (avbuffer) {
76 OH_AVBuffer_Destroy(avbuffer);
77 avbuffer = nullptr;
78 }
79 if (outputFd_ > -1) {
80 close(outputFd_);
81 outputFd_ = -1;
82 }
83 }
84
InitFile(const std::string & inputFile)85 bool AVMuxerDemo::InitFile(const std::string& inputFile)
86 {
87 if (inputFile.find("aac") != std::string::npos) {
88 audioType_ = AudioMuxerFormatType::TYPE_AAC;
89 output_path_ = MP4_OUTPUT_FILE_PATH;
90 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_M4A;
91 } else if (inputFile.find("h264") != std::string::npos) {
92 audioType_ = AudioMuxerFormatType::TYPE_H264;
93 output_path_ = MP4_OUTPUT_FILE_PATH;
94 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
95 } else if (inputFile.find("h265") != std::string::npos) {
96 audioType_ = AudioMuxerFormatType::TYPE_H265;
97 output_path_ = MP4_OUTPUT_FILE_PATH;
98 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
99 } else if (inputFile.find("mpeg4") != std::string::npos) {
100 audioType_ = AudioMuxerFormatType::TYPE_MPEG4;
101 output_path_ = MP4_OUTPUT_FILE_PATH;
102 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
103 } else if (inputFile.find("hdr") != std::string::npos) {
104 audioType_ = AudioMuxerFormatType::TYPE_HDR;
105 output_path_ = MP4_OUTPUT_FILE_PATH;
106 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
107 } else if (inputFile.find("jpg") != std::string::npos) {
108 audioType_ = AudioMuxerFormatType::TYPE_JPG;
109 output_path_ = M4A_OUTPUT_FILE_PATH;
110 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
111 } else if (inputFile.find("amrwb") != std::string::npos) {
112 audioType_ = AudioMuxerFormatType::TYPE_AMRWB;
113 output_path_ = AMRWB_OUTPUT_FILE_PATH;
114 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_AMR;
115 } else if (inputFile.find("amrnb") != std::string::npos) {
116 audioType_ = AudioMuxerFormatType::TYPE_AMRNB;
117 output_path_ = AMRNB_OUTPUT_FILE_PATH;
118 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_AMR;
119 } else if (inputFile.find("mpeg3") != std::string::npos) {
120 audioType_ = AudioMuxerFormatType::TYPE_MPEG3;
121 output_path_ = MP3_OUTPUT_FILE_PATH;
122 output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MP3;
123 }
124 return true;
125 }
RunCase(const uint8_t * data,size_t size)126 bool AVMuxerDemo::RunCase(const uint8_t *data, size_t size)
127 {
128 std::string codecdata(reinterpret_cast<const char *>(data), size);
129 inputdata = codecdata;
130 inputdatasize = size;
131 std::string outputFile(output_path_);
132 //Create
133 avmuxer_ = Create();
134 DEMO_CHECK_AND_RETURN_RET_LOG(avmuxer_ != nullptr, false, "Fatal: Create fail");
135 DEMO_CHECK_AND_RETURN_RET_LOG(SetRotation(avmuxer_, 0) == AVCS_ERR_OK, false, "Fatal: SetRotation fail");
136 //获取param
137 AudioTrackParam param = InitFormatParam(audioType_);
138 int32_t trackIndex = -1;
139 //添加轨
140 int32_t res = 0;
141 if (param.isNeedCover) {
142 res = AddCoverTrack(avmuxer_, trackIndex, param);
143 DEMO_CHECK_AND_RETURN_RET_LOG(res == AVCS_ERR_OK, false, "Fatal: AddTrack fail");
144 } else {
145 res = AddTrack(avmuxer_, trackIndex, param);
146 DEMO_CHECK_AND_RETURN_RET_LOG(res == AVCS_ERR_OK, false, "Fatal: AddTrack fail");
147 }
148 //Start
149 DEMO_CHECK_AND_RETURN_RET_LOG(Start() == AVCS_ERR_OK, false, "Fatal: Start fail");
150 //写数据
151 if (param.isNeedCover) {
152 WriteTrackCover(avmuxer_, trackIndex);
153 } else {
154 WriteSingleTrackSampleAVBuffer(avmuxer_, trackIndex);
155 }
156 //Stop
157 DEMO_CHECK_AND_RETURN_RET_LOG(Stop() == AVCS_ERR_OK, false, "Fatal: Stop fail");
158 //Destroy
159 DEMO_CHECK_AND_RETURN_RET_LOG(Destroy() == AVCS_ERR_OK, false, "Fatal: Destroy fail");
160 return true;
161 }
162
InitFormatParam(AudioMuxerFormatType type)163 AudioTrackParam AVMuxerDemo::InitFormatParam(AudioMuxerFormatType type)
164 {
165 AudioTrackParam param;
166 param.sampleRate = SAMPLE_RATE_44100;
167 param.channels = CHANNELS_2;
168 param.frameSize = FRAME_SIZE_1024;
169 param.width = WIDTH_720;
170 param.height = HEIGHT_480;
171 param.isNeedCover = false;
172 param.frameRate = FRAME_RATE_60;
173 param.videoDelay = 0;
174 param.colorPrimaries = COLOR_PRIMARIES_2;
175 param.colorTransfer = COLOR_TRANSFER_2;
176 param.colorMatrixCoeff = COLOR_MATRIXCIEFF_2;
177 param.colorRange = 0;
178 param.isHdrVivid = 0;
179 param.isNeedVideo = false;
180 if (audioType_ == AudioMuxerFormatType::TYPE_AAC) {
181 param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AAC;
182 } else if (audioType_ == AudioMuxerFormatType::TYPE_H264) {
183 param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_AVC;
184 } else if (audioType_ == AudioMuxerFormatType::TYPE_H265) {
185 param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_HEVC;
186 param.videoDelay = VIDEO_DELAY_2;
187 } else if (audioType_ == AudioMuxerFormatType::TYPE_MPEG3 || audioType_ == AudioMuxerFormatType::TYPE_MPEG4) {
188 param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_MPEG;
189 } else if (audioType_ == AudioMuxerFormatType::TYPE_HDR) {
190 param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_HEVC;
191 param.width = WIDTH_3840;
192 param.height = HEIGHT_2160;
193 param.frameRate = FRAME_RATE_30;
194 param.colorPrimaries = COLOR_PRIMARIES_9;
195 param.colorTransfer = COLOR_TRANSFER_18;
196 param.colorMatrixCoeff = COLOR_MATRIXCIEFF_9;
197 param.isHdrVivid = 1;
198 } else if (audioType_ == AudioMuxerFormatType::TYPE_JPG) {
199 param.mimeType = OH_AVCODEC_MIMETYPE_IMAGE_JPG;
200 param.isNeedCover = true;
201 } else if (audioType_ == AudioMuxerFormatType::TYPE_AMRNB) {
202 param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AMR_NB;
203 param.sampleRate = SAMPLE_RATE_8000;
204 param.channels = 1;
205 } else if (audioType_ == AudioMuxerFormatType::TYPE_AMRWB) {
206 param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AMR_WB;
207 param.sampleRate = SAMPLE_RATE_16000;
208 param.channels = 1;
209 }
210 return param;
211 }
212
Create()213 OH_AVMuxer* AVMuxerDemo::Create()
214 {
215 std::string outputFile(output_path_);
216 outputFd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
217 if (outputFd_ < 0) {
218 std::cout << "open file failed! outputFd_ is:" << outputFd_ << std::endl;
219 return nullptr;
220 }
221 return OH_AVMuxer_Create(outputFd_, output_format_);
222 }
223
Start()224 int32_t AVMuxerDemo::Start()
225 {
226 return OH_AVMuxer_Start(avmuxer_);
227 }
228
Stop()229 int32_t AVMuxerDemo::Stop()
230 {
231 return OH_AVMuxer_Stop(avmuxer_);
232 }
233
Destroy()234 int32_t AVMuxerDemo::Destroy()
235 {
236 if (avbuffer != nullptr) {
237 OH_AVBuffer_Destroy(avbuffer);
238 avbuffer = nullptr;
239 }
240 int32_t res = 0;
241 if (avmuxer_ != nullptr) {
242 res = OH_AVMuxer_Destroy(avmuxer_);
243 avmuxer_ = nullptr;
244 }
245 return res;
246 }
247
SetRotation(OH_AVMuxer * muxer,int32_t rotation)248 int32_t AVMuxerDemo::SetRotation(OH_AVMuxer* muxer, int32_t rotation)
249 {
250 return OH_AVMuxer_SetRotation(muxer, rotation);
251 }
252
AddTrack(OH_AVMuxer * muxer,int32_t & trackIndex,AudioTrackParam param)253 int32_t AVMuxerDemo::AddTrack(OH_AVMuxer* muxer, int32_t& trackIndex, AudioTrackParam param)
254 {
255 const int configBufferSize = 0x1FFF;
256 OH_AVFormat *trackFormat = OH_AVFormat_Create();
257 if (trackFormat == NULL) {
258 std::cout << "AddTrack: format failed!" << std::endl;
259 return AV_ERR_INVALID_VAL;
260 }
261 // set codec config
262 // 此处可以不设CONFIG
263 int extraSize = inputdatasize > configBufferSize ? configBufferSize : inputdatasize;
264 unsigned char buffer[configBufferSize] = {0};
265 errno_t res = 0;
266 res = strncpy_s(reinterpret_cast<char*>(buffer), configBufferSize, inputdata.c_str(), extraSize);
267 if (res != 0) {
268 return res;
269 }
270 OH_AVFormat_SetStringValue(trackFormat, OH_MD_KEY_CODEC_MIME, param.mimeType);
271 // audio
272 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, param.sampleRate);
273 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, param.channels);
274 OH_AVFormat_SetIntValue(trackFormat, "audio_samples_per_frame", param.frameSize);
275 //video
276 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_WIDTH, param.width);
277 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_HEIGHT, param.height);
278 OH_AVFormat_SetDoubleValue(trackFormat, OH_MD_KEY_FRAME_RATE, param.frameRate);
279 OH_AVFormat_SetIntValue(trackFormat, "video_delay", param.videoDelay);
280 // hdr vivid
281 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_COLOR_PRIMARIES, param.colorPrimaries);
282 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_TRANSFER_CHARACTERISTICS, param.colorTransfer);
283 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_MATRIX_COEFFICIENTS, param.colorMatrixCoeff);
284 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_RANGE_FLAG, param.colorRange);
285 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_VIDEO_IS_HDR_VIVID, param.isHdrVivid);
286 int32_t ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, trackFormat);
287 return ret;
288 }
289
290
AddCoverTrack(OH_AVMuxer * muxer,int32_t & trackId,AudioTrackParam param)291 int32_t AVMuxerDemo::AddCoverTrack(OH_AVMuxer* muxer, int32_t& trackId, AudioTrackParam param)
292 {
293 OH_AVFormat *trackFormat = OH_AVFormat_Create();
294 if (trackFormat == NULL) {
295 std::cout << "format failed!" << std::endl;
296 return AV_ERR_INVALID_VAL;
297 }
298 OH_AVFormat_SetStringValue(trackFormat, OH_MD_KEY_CODEC_MIME, param.mimeType);
299 // audio
300 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_AUD_SAMPLE_RATE, param.sampleRate);
301 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_AUD_CHANNEL_COUNT, param.channels);
302 OH_AVFormat_SetIntValue(trackFormat, "audio_samples_per_frame", param.frameSize);
303 //video
304 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_WIDTH, param.width);
305 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_HEIGHT, param.height);
306 OH_AVFormat_SetDoubleValue(trackFormat, OH_MD_KEY_FRAME_RATE, param.frameRate);
307 OH_AVFormat_SetIntValue(trackFormat, "video_delay", param.videoDelay);
308 // hdr vivid
309 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_COLOR_PRIMARIES, param.colorPrimaries);
310 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_TRANSFER_CHARACTERISTICS, param.colorTransfer);
311 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_MATRIX_COEFFICIENTS, param.colorMatrixCoeff);
312 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_RANGE_FLAG, param.colorRange);
313 OH_AVFormat_SetIntValue(trackFormat, OH_MD_KEY_VIDEO_IS_HDR_VIVID, param.isHdrVivid);
314 int32_t ret = OH_AVMuxer_AddTrack(muxer, &trackId, trackFormat);
315 return ret;
316 }
317
WriteTrackCover(OH_AVMuxer * muxer,int32_t trackIndex)318 void AVMuxerDemo::WriteTrackCover(OH_AVMuxer *muxer, int32_t trackIndex)
319 {
320 OH_AVCodecBufferAttr info;
321 memset_s(&info, sizeof(info), 0, sizeof(info));
322 info.size = inputdatasize;
323 OH_AVBuffer *av_buffer = OH_AVBuffer_Create(info.size);
324 if (av_buffer == NULL) {
325 std::cout << "WriteTrackCover: create OH_AVMemory error!" << std::endl;
326 return;
327 }
328 size_t frameBytes = 1024;
329 size_t cSize = inputdatasize < frameBytes ? inputdatasize : frameBytes;
330 errno_t res = 0;
331 res = strncpy_s(reinterpret_cast<char*>(OH_AVBuffer_GetAddr(av_buffer)), cSize, inputdata.c_str(), cSize);
332 if (res != 0) {
333 return;
334 }
335 if (OH_AVMuxer_WriteSampleBuffer(muxer, trackIndex, av_buffer) != AV_ERR_OK) {
336 OH_AVBuffer_Destroy(av_buffer);
337 av_buffer = nullptr;
338 std::cout << "OH_AVMuxer_WriteSample error!" << std::endl;
339 return;
340 }
341 if (av_buffer != nullptr) {
342 OH_AVBuffer_Destroy(av_buffer);
343 av_buffer = nullptr;
344 }
345 }
346
WriteSingleTrackSampleAVBuffer(OH_AVMuxer * muxer,int32_t trackIndex)347 void AVMuxerDemo::WriteSingleTrackSampleAVBuffer(OH_AVMuxer *muxer, int32_t trackIndex)
348 {
349 if (muxer == NULL || trackIndex < 0) {
350 std::cout << "WriteSingleTrackSample muxer is null " << trackIndex << std::endl;
351 return;
352 }
353 OH_AVCodecBufferAttr info;
354 OH_AVBuffer *buffer = NULL;
355 memset_s(&info, sizeof(info), 0, sizeof(info));
356 bool ret = UpdateWriteBufferInfoAVBuffer(&buffer, &info);
357 //此处只执行一次,正常要根据内容进行while循环将buffer所有数据写入,因为fuzz数据是假数据,故仅调用一次;
358 if (ret) {
359 OH_AVMuxer_WriteSampleBuffer(muxer, trackIndex, buffer);
360 }
361 if (buffer != NULL) {
362 OH_AVBuffer_Destroy(buffer);
363 buffer = nullptr;
364 }
365 }
366
UpdateWriteBufferInfoAVBuffer(OH_AVBuffer ** buffer,OH_AVCodecBufferAttr * info)367 bool AVMuxerDemo::UpdateWriteBufferInfoAVBuffer(OH_AVBuffer **buffer, OH_AVCodecBufferAttr *info)
368 {
369 //此处不区分音频类型,所有pts、size、flags均取一样的值
370 info->pts = INFO_PTS_100;
371 info->size = INFO_SIZE_1024;
372 info->flags = AVCODEC_BUFFER_FLAGS_NONE;
373 if (buffer == NULL || info == NULL) {
374 return false;
375 }
376 if (*buffer != NULL) {
377 std::cout << "UpdateWriteBufferInfoAVBuffer: buffer is NULL!" << std::endl;
378 OH_AVBuffer_Destroy(*buffer);
379 *buffer = NULL;
380 }
381 if (*buffer == NULL) {
382 *buffer = OH_AVBuffer_Create(info->size);
383 }
384 if (*buffer == NULL) {
385 std::cout << "UpdateWriteBufferInfoAVBuffer: error create OH_AVMemory! " << std::endl;
386 return false;
387 }
388 errno_t res = 0;
389 res = strncpy_s(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(*buffer)), info->size, inputdata.c_str(), info->size);
390 if (res != 0) {
391 return false;
392 }
393 OH_AVBuffer_SetBufferAttr(*buffer, info);
394 return true;
395 }