• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "demo_log.h"
24 #include "avcodec_common.h"
25 #include "avcodec_errors.h"
26 #include "native_avformat.h"
27 #include "native_avbuffer.h"
28 #include "ffmpeg_converter.h"
29 #include "media_description.h"
30 #include "avcodec_codec_name.h"
31 #include <fuzzer/FuzzedDataProvider.h>
32 
33 using namespace OHOS;
34 using namespace OHOS::MediaAVCodec;
35 using namespace OHOS::MediaAVCodec::AudioBufferDemo;
36 
37 constexpr int32_t WIDTH_720 = 720;
38 constexpr int32_t HEIGHT_480 = 480;
39 constexpr int32_t WIDTH_3840 = 3840;
40 constexpr int32_t HEIGHT_2160 = 2160;
41 constexpr int32_t COLOR_TRANSFER_2 = 2;
42 constexpr int32_t COLOR_TRANSFER_18 = 18;
43 constexpr int32_t FRAME_RATE_30 = 30;
44 constexpr int32_t FRAME_RATE_60 = 60;
45 constexpr int32_t FRAME_SIZE_1024 = 1024;
46 constexpr int32_t COLOR_PRIMARIES_2 = 2;
47 constexpr int32_t COLOR_PRIMARIES_9 = 9;
48 constexpr int32_t COLOR_MATRIXCIEFF_2 = 2;
49 constexpr int32_t COLOR_MATRIXCIEFF_9 = 9;
50 constexpr int32_t VIDEO_DELAY_2 = 2;
51 
52 constexpr int32_t CHANNELS_2 = 2;
53 
54 constexpr int32_t SAMPLE_RATE_8000 = 8000;
55 constexpr int32_t SAMPLE_RATE_16000 = 16000;
56 constexpr int32_t SAMPLE_RATE_44100 = 44100;
57 
58 constexpr const char* INPUT_AUDIO_FILE_PATH = "/data/test/media/aac_44100_2.bin";
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 (outputFd_ > -1) {
76         close(outputFd_);
77         outputFd_ = -1;
78     }
79     if (inputFd_ > -1) {
80         close(inputFd_);
81         inputFd_ = -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_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
94     } else if (inputFile.find("h265") != std::string::npos) {
95         audioType_ = AudioMuxerFormatType::TYPE_H265;
96         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
97     } else if (inputFile.find("mpeg4") != std::string::npos) {
98         audioType_ = AudioMuxerFormatType::TYPE_MPEG4;
99         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
100     } else if (inputFile.find("hdr") != std::string::npos) {
101         audioType_ = AudioMuxerFormatType::TYPE_HDR;
102         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
103     } else if (inputFile.find("jpg") != std::string::npos) {
104         audioType_ = AudioMuxerFormatType::TYPE_JPG;
105         output_path_ = M4A_OUTPUT_FILE_PATH;
106         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MPEG_4;
107     } else if (inputFile.find("amrwb") != std::string::npos) {
108         audioType_ = AudioMuxerFormatType::TYPE_AMRWB;
109         output_path_ = AMRWB_OUTPUT_FILE_PATH;
110         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_AMR;
111     } else if (inputFile.find("amrnb") != std::string::npos) {
112         audioType_ = AudioMuxerFormatType::TYPE_AMRNB;
113         output_path_ = AMRNB_OUTPUT_FILE_PATH;
114         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_AMR;
115     } else if (inputFile.find("mpeg3") != std::string::npos) {
116         audioType_ = AudioMuxerFormatType::TYPE_MPEG3;
117         output_path_ = MP3_OUTPUT_FILE_PATH;
118         output_format_ = OH_AVOutputFormat::AV_OUTPUT_FORMAT_MP3;
119     }
120     return true;
121 }
RunCase(const uint8_t * data,size_t size)122 bool AVMuxerDemo::RunCase(const uint8_t *data, size_t size)
123 {
124     std::string codecdata(reinterpret_cast<const char *>(data), size);
125     inputData_ = codecdata;
126     inputDataSize_ = size;
127     std::string outputFile(output_path_);
128     // 1.读取音频文件
129     inputFd_ = open(INPUT_AUDIO_FILE_PATH, O_RDONLY);
130     if (inputFd_ < 0) {
131         std::cout << "open file failed!!!" << std::endl;
132         return false;
133     }
134 	// 2.Create
135     avMuxer_ = Create();
136     DEMO_CHECK_AND_RETURN_RET_LOG(avMuxer_ != nullptr, false, "Fatal: Create fail");
137     DEMO_CHECK_AND_RETURN_RET_LOG(SetRotation(avMuxer_, 0) == AVCS_ERR_OK, false, "Fatal: SetRotation fail");
138     // 3.获取param
139     AudioTrackParam param = InitFormatParam(audioType_);
140     int32_t trackIndex = -1;
141     // 4.添加 UserMeta
142     int32_t retSet = SetFormat(data, size);
143     if (retSet == AV_ERR_OK) {
144         std::cout << "Add UserMeta Success!!!" << std::endl;
145     }
146     // 5.添加轨
147     int32_t res = 0;
148     res = AddTrack(avMuxer_, trackIndex, param);
149     DEMO_CHECK_AND_RETURN_RET_LOG(res == AVCS_ERR_OK, false, "Fatal: AddTrack fail");
150     // 6.Start
151     DEMO_CHECK_AND_RETURN_RET_LOG(Start() == AVCS_ERR_OK, false, "Fatal: Start fail");
152     // 7.写数据
153     WriteSingleTrackSampleAVBuffer(avMuxer_, trackIndex);
154     // 9.Stop
155     DEMO_CHECK_AND_RETURN_RET_LOG(Stop() == AVCS_ERR_OK, false, "Fatal: Stop fail");
156     // 9.Destroy
157     Destroy();
158     return true;
159 }
160 
InitFormatParam(AudioMuxerFormatType type)161 AudioTrackParam AVMuxerDemo::InitFormatParam(AudioMuxerFormatType type)
162 {
163     AudioTrackParam param;
164     param.sampleRate = SAMPLE_RATE_44100;
165     param.channels = CHANNELS_2;
166     param.frameSize = FRAME_SIZE_1024;
167     param.width = WIDTH_720;
168     param.height = HEIGHT_480;
169     param.isNeedCover = false;
170     param.frameRate = FRAME_RATE_60;
171     param.videoDelay = 0;
172     param.colorPrimaries = COLOR_PRIMARIES_2;
173     param.colorTransfer = COLOR_TRANSFER_2;
174     param.colorMatrixCoeff = COLOR_MATRIXCIEFF_2;
175     param.colorRange = 0;
176     param.isHdrVivid = 0;
177     param.isNeedVideo = false;
178     if (audioType_ == AudioMuxerFormatType::TYPE_AAC) {
179         param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AAC;
180     } else if (audioType_ == AudioMuxerFormatType::TYPE_H264) {
181         param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_AVC;
182     } else if (audioType_ == AudioMuxerFormatType::TYPE_H265) {
183         param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_HEVC;
184         param.videoDelay = VIDEO_DELAY_2;
185     } else if (audioType_ == AudioMuxerFormatType::TYPE_MPEG3 || audioType_ == AudioMuxerFormatType::TYPE_MPEG4) {
186         param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_MPEG;
187     } else if (audioType_ == AudioMuxerFormatType::TYPE_HDR) {
188         param.mimeType = OH_AVCODEC_MIMETYPE_VIDEO_HEVC;
189         param.width = WIDTH_3840;
190         param.height = HEIGHT_2160;
191         param.frameRate = FRAME_RATE_30;
192         param.colorPrimaries = COLOR_PRIMARIES_9;
193         param.colorTransfer = COLOR_TRANSFER_18;
194         param.colorMatrixCoeff = COLOR_MATRIXCIEFF_9;
195         param.isHdrVivid = 1;
196     } else if (audioType_ == AudioMuxerFormatType::TYPE_JPG) {
197         param.mimeType = OH_AVCODEC_MIMETYPE_IMAGE_JPG;
198         param.isNeedCover = true;
199     } else if (audioType_ == AudioMuxerFormatType::TYPE_AMRNB) {
200         param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AMR_NB;
201         param.sampleRate = SAMPLE_RATE_8000;
202         param.channels = 1;
203     } else if (audioType_ == AudioMuxerFormatType::TYPE_AMRWB) {
204         param.mimeType = OH_AVCODEC_MIMETYPE_AUDIO_AMR_WB;
205         param.sampleRate = SAMPLE_RATE_16000;
206         param.channels = 1;
207     }
208     return param;
209 }
210 
Create()211 OH_AVMuxer* AVMuxerDemo::Create()
212 {
213     std::string outputFile(output_path_);
214     outputFd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
215     if (outputFd_ < 0) {
216         std::cout << "open file failed! outputFd_ is:" << outputFd_ << std::endl;
217         return nullptr;
218     }
219     return OH_AVMuxer_Create(outputFd_, output_format_);
220 }
221 
Start()222 int32_t AVMuxerDemo::Start()
223 {
224     return OH_AVMuxer_Start(avMuxer_);
225 }
226 
Stop()227 int32_t AVMuxerDemo::Stop()
228 {
229     return OH_AVMuxer_Stop(avMuxer_);
230 }
231 
Destroy()232 int32_t AVMuxerDemo::Destroy()
233 {
234     if (trackFormat_ != nullptr) {
235         OH_AVFormat_Destroy(trackFormat_);
236         trackFormat_ = nullptr;
237     }
238     if (metaFormat_ != nullptr) {
239         OH_AVFormat_Destroy(metaFormat_);
240         metaFormat_ = nullptr;
241     }
242     return true;
243 }
244 
SetRotation(OH_AVMuxer * muxer,int32_t rotation)245 int32_t AVMuxerDemo::SetRotation(OH_AVMuxer* muxer, int32_t rotation)
246 {
247     return OH_AVMuxer_SetRotation(muxer, rotation);
248 }
249 
SetFormat(const uint8_t * data,size_t size)250 int32_t AVMuxerDemo::SetFormat(const uint8_t *data, size_t size)
251 {
252     // 只支持  1.(内置) OH_MD_KEY_CREATION_TIME
253     //         2.(自定义)string int float
254     FuzzedDataProvider fdp(data, size);
255 
256     metaFormat_ = OH_AVFormat_Create();
257 
258     std::string metaKeyPrefix("com.openharmony.");
259 
260     std::string fuzzKey1 = fdp.ConsumeRandomLengthString();
261     int fuzzValue1 = fdp.ConsumeIntegral<int>();
262     std::string fuzzKey2 = fdp.ConsumeRandomLengthString();
263     float fuzzValue2 = fdp.ConsumeFloatingPoint<float>();
264     std::string fuzzKey3 = fdp.ConsumeRandomLengthString();
265     std::string fuzzValue3 = fdp.ConsumeRandomLengthString();
266     std::string fuzzValue4 = fdp.ConsumeRandomLengthString();
267 
268     std::string metaKey1 = metaKeyPrefix + fuzzKey1;
269     std::string metaKey2 = metaKeyPrefix + fuzzKey2;
270     std::string metaKey3 = metaKeyPrefix + fuzzKey3;
271 
272     OH_AVFormat_SetIntValue(metaFormat_, metaKey1.c_str(), fuzzValue1);
273     OH_AVFormat_SetFloatValue(metaFormat_, metaKey2.c_str(), fuzzValue2);
274     OH_AVFormat_SetStringValue(metaFormat_, metaKey3.c_str(), fuzzValue3.c_str());
275     OH_AVFormat_SetStringValue(metaFormat_, OH_MD_KEY_CREATION_TIME, fuzzValue4.c_str());
276 
277     return OH_AVMuxer_SetFormat(avMuxer_, metaFormat_);
278 }
279 
AddTrack(OH_AVMuxer * muxer,int32_t & trackIndex,AudioTrackParam param)280 int32_t AVMuxerDemo::AddTrack(OH_AVMuxer* muxer, int32_t& trackIndex, AudioTrackParam param)
281 {
282     const int configBufferSize =  0x1FFF;
283     trackFormat_ = OH_AVFormat_Create();
284     if (trackFormat_ == nullptr) {
285         std::cout << "AddTrack: format failed!" << std::endl;
286         return AV_ERR_INVALID_VAL;
287     }
288     // set codec config
289     int extraSize = 0;
290     unsigned char buffer[configBufferSize] = {0};
291     read(inputFd_, reinterpret_cast<void *>(extraSize), sizeof(extraSize));
292     if (extraSize <= configBufferSize && extraSize > 0) {
293         read(inputFd_, buffer, extraSize);
294         OH_AVFormat_SetBuffer(trackFormat_, OH_MD_KEY_CODEC_CONFIG, buffer, extraSize);
295     }
296 
297     OH_AVFormat_SetStringValue(trackFormat_, OH_MD_KEY_CODEC_MIME, param.mimeType);
298     // audio
299     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_AUD_SAMPLE_RATE, param.sampleRate);
300     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_AUD_CHANNEL_COUNT, param.channels);
301     OH_AVFormat_SetIntValue(trackFormat_, "audio_samples_per_frame", param.frameSize);
302     //video
303     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_WIDTH, param.width);
304     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_HEIGHT, param.height);
305     OH_AVFormat_SetDoubleValue(trackFormat_, OH_MD_KEY_FRAME_RATE, param.frameRate);
306     OH_AVFormat_SetIntValue(trackFormat_, "video_delay", param.videoDelay);
307     // hdr vivid
308     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_COLOR_PRIMARIES, param.colorPrimaries);
309     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_TRANSFER_CHARACTERISTICS, param.colorTransfer);
310     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_MATRIX_COEFFICIENTS, param.colorMatrixCoeff);
311     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_RANGE_FLAG, param.colorRange);
312     OH_AVFormat_SetIntValue(trackFormat_, OH_MD_KEY_VIDEO_IS_HDR_VIVID, param.isHdrVivid);
313     int32_t ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, trackFormat_);
314     return ret;
315 }
316 
WriteSingleTrackSampleAVBuffer(OH_AVMuxer * muxer,int32_t trackIndex)317 void AVMuxerDemo::WriteSingleTrackSampleAVBuffer(OH_AVMuxer *muxer, int32_t trackIndex)
318 {
319     // 1.【安全检测】 Interface Protection(security check)
320     if (muxer == nullptr) {
321         std::cout << "WriteSingleTrackSampleAVBuffer: muxer is nullptr!!!" << std::endl;
322         return;
323     }
324     if (trackIndex < 0) {
325         std::cout << "WriteSingleTrackSampleAVBuffer: trackIndex error!!!" << std::endl;
326         return;
327     }
328     // 2.【创建info】 create info
329     OH_AVCodecBufferAttr info;
330     memset_s(&info, sizeof(info), 0, sizeof(info));
331 	// 3.【数据写入】 write data
332     OH_AVBuffer *buffer = nullptr;
333     bool ret = false;
334     do {
335         ret = UpdateWriteBufferInfoAVBuffer(&buffer, &info, trackIndex);
336     } while (ret);
337     // 4.【释放内存】 free buffer
338     if (buffer != nullptr) {
339         OH_AVBuffer_Destroy(buffer);
340         buffer = nullptr;
341     }
342 }
343 
UpdateWriteBufferInfoAVBuffer(OH_AVBuffer ** buffer,OH_AVCodecBufferAttr * info,int32_t trackIndex)344 bool AVMuxerDemo::UpdateWriteBufferInfoAVBuffer(OH_AVBuffer **buffer, OH_AVCodecBufferAttr *info, int32_t trackIndex)
345 {
346     // 1.【安全检测】Interface Protection(security check)
347     if (*buffer != nullptr) {
348         OH_AVBuffer_Destroy(*buffer);
349         *buffer = nullptr;
350     }
351     if (info == nullptr) {
352         std::cout << "UpdateWriteBufferInfoAVBuffer: info is nullptr!!! " << std::endl;
353         return false;
354     }
355     if (trackIndex < 0) {
356         std::cout << "UpdateWriteBufferInfoAVBuffer: trackIndex error!!!" << std::endl;
357         return false;
358     }
359     // 2.【获取info数据】get info msg
360     // info pts
361     int ret = read(inputFd_, (void*)&info->pts, sizeof(info->pts));
362     if (ret <= 0) {
363         return false;
364     }
365     // info flags
366     ret = read(inputFd_, (void*)&info->flags, sizeof(info->flags));
367     info->flags |= AVCODEC_BUFFER_FLAGS_CODEC_DATA;
368     info->flags |= AVCODEC_BUFFER_FLAGS_SYNC_FRAME;
369     if (ret <= 0) {
370         return false;
371     }
372     // info size
373     ret = read(inputFd_, (void*)&info->size, sizeof(info->size));
374     if (ret <= 0 || info->size < 0) {
375         return false;
376     }
377     // 3.【初始化buffer】initialization buffer
378     *buffer = OH_AVBuffer_Create(info->size);
379     if (*buffer == nullptr) {
380         std::cout << "UpdateWriteBufferInfoAVBuffer: buffer creation failed!!! " << std::endl;
381         return false;
382     }
383     ret = read(inputFd_, (void*)OH_AVBuffer_GetAddr(*buffer), info->size);
384     if (ret <= 0) {
385         std::cout << "UpdateWriteBufferInfoAVBuffer: buffer acquisition failed!!! " << std::endl;
386         return false;
387     }
388     // 4.【写入数据】write data
389     OH_AVErrCode res = OH_AVBuffer_SetBufferAttr(*buffer, info);
390     DEMO_CHECK_AND_RETURN_RET_LOG(res == AV_ERR_OK, false, "Fatal: OH_AVBuffer_SetBufferAttr fail!!!");
391     res = OH_AVMuxer_WriteSampleBuffer(avMuxer_, trackIndex, *buffer);
392     DEMO_CHECK_AND_RETURN_RET_LOG(res == AV_ERR_OK, false, "Fatal: OH_AVMuxer_WriteSampleBuffer fail!!!");
393     return true;
394 }