1 /*
2 * Copyright (C) 2023 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 "native_avmuxer_demo.h"
17 #include <sys/types.h>
18 #include <fcntl.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <pthread.h>
22
23 #include "securec.h"
24 #include "native_avcodec_base.h"
25 #include "native_averrors.h"
26 #include "native_avformat.h"
27 #include "native_avmuxer.h"
28 #include "native_avmemory.h"
29 #include "native_avbuffer.h"
30 #include "avmuxer_demo_common.h"
31 #include "native_audio_channel_layout.h"
32
33
34 #define NORMAL 0
35 #define THREAD 1
36 #define MODE_ZERO 0
37 #define MODE_ONE 1
38 #define MODE_TWO 2
39 #define MODE_THREE 3
40 #define MODE_FOUR 4
41 #define MODE_FIVE 5
42 #define MODE_SIX 6
43 #define MODE_SEVEN 7
44 #define TYPE_BUFFER_SIZE 20
45 #define CONFIG_BUFFER_SIZE 0x1FFF
46
47 typedef struct AudioTrackParam AudioTrackParam;
48 typedef struct VideoTrackParam VideoTrackParam;
49 typedef struct FdListStr FdListStr;
50
51 struct WriteTrackSampleParam {
52 OH_AVMuxer *muxer;
53 int trackId;
54 int fd;
55 };
56
57 struct MuxerParam {
58 int outputFormat;
59 char outputFormatType[TYPE_BUFFER_SIZE];
60 int runMode;
61 char runModeType[TYPE_BUFFER_SIZE];
62 const AudioTrackParam *audioParams;
63 char audioType[TYPE_BUFFER_SIZE];
64 const VideoTrackParam *videoParams;
65 char videoType[TYPE_BUFFER_SIZE];
66 const VideoTrackParam *coverParams;
67 char coverType[TYPE_BUFFER_SIZE];
68 };
69
70 static struct MuxerParam g_muxerParam = {
71 .outputFormat = AV_OUTPUT_FORMAT_DEFAULT,
72 .outputFormatType = "",
73 .runMode = NORMAL,
74 .runModeType = "",
75 .audioParams = NULL,
76 .audioType = "",
77 .videoParams = NULL,
78 .videoType = "",
79 .coverParams = NULL,
80 .coverType = "",
81 };
82
SetFormat(OH_AVMuxer * muxer)83 void SetFormat(OH_AVMuxer *muxer)
84 {
85 OH_AVFormat *format = OH_AVFormat_Create();
86 if (format == NULL) {
87 printf("SetFormat failed!\n");
88 return;
89 }
90 OH_AVFormat_SetStringValue(format, OH_MD_KEY_CREATION_TIME, "2023-12-19T03:16:00.000000Z");
91 int ret = OH_AVMuxer_SetFormat(muxer, format);
92 OH_AVFormat_Destroy(format);
93 if (ret != AV_ERR_OK) {
94 printf("SetFormat failed!");
95 return;
96 }
97 printf("SetFormat success!");
98 }
99
AddTrackAudio(OH_AVMuxer * muxer,const AudioTrackParam * param,int fdInput)100 int AddTrackAudio(OH_AVMuxer *muxer, const AudioTrackParam *param, int fdInput)
101 {
102 if (fdInput < 0) {
103 printf("unselect audio, fd is %d\n", fdInput);
104 return -1;
105 }
106 OH_AVFormat *formatAudio = OH_AVFormat_CreateAudioFormat(param->mimeType,
107 param->sampleRate, param->channels);
108 if (formatAudio == NULL) {
109 printf("audio format failed!\n");
110 return AV_ERR_NO_MEMORY;
111 }
112 if (param->frameSize > 0) {
113 OH_AVFormat_SetIntValue(formatAudio, "audio_samples_per_frame", param->frameSize);
114 }
115 if (param == &g_audioAacPar) {
116 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_PROFILE, AAC_PROFILE_LC);
117 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AAC_IS_ADTS, 0);
118 } else if (param == &g_audioG711MUPar) {
119 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_U8);
120 OH_AVFormat_SetLongValue(formatAudio, OH_MD_KEY_BITRATE, 705600); // 705600 g711mu bit rate
121 } else if (param == &g_audioRawPar) {
122 OH_AVFormat_SetIntValue(formatAudio, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
123 OH_AVFormat_SetLongValue(formatAudio, OH_MD_KEY_CHANNEL_LAYOUT, CH_LAYOUT_STEREO);
124 }
125 int extraSize = 0;
126 unsigned char buffer[CONFIG_BUFFER_SIZE] = {0};
127 read(fdInput, (void*)&extraSize, sizeof(extraSize));
128 if (extraSize <= CONFIG_BUFFER_SIZE && extraSize > 0) {
129 read(fdInput, buffer, extraSize);
130 OH_AVFormat_SetBuffer(formatAudio, OH_MD_KEY_CODEC_CONFIG, buffer, extraSize);
131 }
132 printf("AddTrackAudio audio metadata size: %d\n", extraSize);
133 int trackIndex = -1;
134 int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatAudio);
135 OH_AVFormat_Destroy(formatAudio);
136 if (ret != AV_ERR_OK) {
137 printf("AddTrackAudio failed! mime: %s\n", param->mimeType);
138 return -1;
139 }
140 printf("AddTrackAudio success! trackIndex: %d\n", trackIndex);
141 return trackIndex;
142 }
143
AddTrackVideo(OH_AVMuxer * muxer,const VideoTrackParam * param,int fdInput)144 int AddTrackVideo(OH_AVMuxer *muxer, const VideoTrackParam *param, int fdInput)
145 {
146 if (fdInput < 0) {
147 printf("unselect video, fd is %d\n", fdInput);
148 return -1;
149 }
150 OH_AVFormat *formatVideo = OH_AVFormat_CreateVideoFormat(param->mimeType,
151 param->width, param->height);
152 if (formatVideo == NULL) {
153 printf("video format failed!\n");
154 return AV_ERR_NO_MEMORY;
155 }
156 OH_AVFormat_SetDoubleValue(formatVideo, OH_MD_KEY_FRAME_RATE, param->frameRate);
157 OH_AVFormat_SetIntValue(formatVideo, "video_delay", param->videoDelay); // 不对外key
158 if (param == &g_videoHdrPar) {
159 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_COLOR_PRIMARIES, param->colorPrimaries);
160 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_TRANSFER_CHARACTERISTICS, param->colorTransfer);
161 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_MATRIX_COEFFICIENTS, param->colorMatrixCoeff);
162 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_RANGE_FLAG, param->colorRange);
163 OH_AVFormat_SetIntValue(formatVideo, OH_MD_KEY_VIDEO_IS_HDR_VIVID, param->isHdrVivid);
164 }
165 int extraSize = 0;
166 unsigned char buffer[CONFIG_BUFFER_SIZE] = {0};
167 read(fdInput, (void*)&extraSize, sizeof(extraSize));
168 if (extraSize <= CONFIG_BUFFER_SIZE && extraSize > 0) {
169 read(fdInput, buffer, extraSize);
170 OH_AVFormat_SetBuffer(formatVideo, OH_MD_KEY_CODEC_CONFIG, buffer, extraSize);
171 }
172 printf("AddTrackVideo video metadata size: %d\n", extraSize);
173 int trackIndex = -1;
174 int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatVideo);
175 OH_AVFormat_Destroy(formatVideo);
176 if (ret != AV_ERR_OK) {
177 printf("AddTrackVideo failed! mime: %s\n", param->mimeType);
178 return -1;
179 }
180 printf("AddTrackVideo success! trackIndex: %d\n", trackIndex);
181 return trackIndex;
182 }
183
AddTrackCover(OH_AVMuxer * muxer,const VideoTrackParam * param,int fdInput)184 int AddTrackCover(OH_AVMuxer *muxer, const VideoTrackParam *param, int fdInput)
185 {
186 if (fdInput < 0) {
187 printf("unselect cover, fd is %d\n", fdInput);
188 return -1;
189 }
190
191 OH_AVFormat *formatCover = OH_AVFormat_Create();
192 if (formatCover == NULL) {
193 printf("cover format failed!\n");
194 return AV_ERR_NO_MEMORY;
195 }
196 OH_AVFormat_SetStringValue(formatCover, OH_MD_KEY_CODEC_MIME, param->mimeType);
197 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_WIDTH, param->width);
198 OH_AVFormat_SetIntValue(formatCover, OH_MD_KEY_HEIGHT, param->height);
199 int trackIndex = -1;
200 int ret = OH_AVMuxer_AddTrack(muxer, &trackIndex, formatCover);
201 OH_AVFormat_Destroy(formatCover);
202 if (ret != AV_ERR_OK) {
203 printf("AddTrackCover failed! mime: %s\n", param->mimeType);
204 return -1;
205 }
206 printf("AddTrackCover success! trackIndex: %d\n", trackIndex);
207 return trackIndex;
208 }
209
UpdateWriteBufferInfo(int fd,OH_AVMemory ** buffer,OH_AVCodecBufferAttr * info)210 static bool UpdateWriteBufferInfo(int fd, OH_AVMemory **buffer, OH_AVCodecBufferAttr *info)
211 {
212 if (fd < 0 || buffer == NULL || info == NULL) {
213 return false;
214 }
215
216 int ret = read(fd, (void*)&info->pts, sizeof(info->pts));
217 if (ret <= 0) {
218 return false;
219 }
220
221 ret = read(fd, (void*)&info->flags, sizeof(info->flags));
222 if (ret <= 0) {
223 return false;
224 }
225
226 ret = read(fd, (void*)&info->size, sizeof(info->size));
227 if (ret <= 0 || info->size < 0) {
228 return false;
229 }
230
231 if (*buffer != NULL && OH_AVMemory_GetSize(*buffer) < info->size) {
232 OH_AVMemory_Destroy(*buffer);
233 *buffer = NULL;
234 }
235 if (*buffer == NULL) {
236 *buffer = OH_AVMemory_Create(info->size);
237 }
238 if (*buffer == NULL) {
239 printf("error create OH_AVMemory! %d\n", info->size);
240 return false;
241 }
242 ret = read(fd, (void*)OH_AVMemory_GetAddr(*buffer), info->size);
243 if (ret <= 0) {
244 return false;
245 }
246 return true;
247 }
248
WriteSingleTrackSample(OH_AVMuxer * muxer,int trackId,int fd)249 void WriteSingleTrackSample(OH_AVMuxer *muxer, int trackId, int fd)
250 {
251 if (muxer == NULL || fd < 0 || trackId < 0) {
252 printf("WriteSingleTrackSample muxer is null or fd < 0, fd:%d\n", fd);
253 return;
254 }
255 OH_AVMemory *buffer = NULL;
256 OH_AVCodecBufferAttr info;
257 memset_s(&info, sizeof(info), 0, sizeof(info));
258 bool ret = UpdateWriteBufferInfo(fd, &buffer, &info);
259 while (ret) {
260 if (OH_AVMuxer_WriteSample(muxer, trackId, buffer, info) != AV_ERR_OK) {
261 printf("OH_AVMuxer_WriteSample error!\n");
262 break;
263 }
264 ret = UpdateWriteBufferInfo(fd, &buffer, &info);
265 }
266
267 if (buffer != NULL) {
268 OH_AVMemory_Destroy(buffer);
269 }
270 }
271
ThreadWriteTrackSample(void * param)272 void *ThreadWriteTrackSample(void *param)
273 {
274 struct WriteTrackSampleParam *wrTrackParam = (struct WriteTrackSampleParam *)param;
275 WriteSingleTrackSample(wrTrackParam->muxer, wrTrackParam->trackId, wrTrackParam->fd);
276 return NULL;
277 }
278
WriteTrackSample(OH_AVMuxer * muxer,int audioTrackIndex,int videoTrackIndex,FdListStr * fdStr)279 void WriteTrackSample(OH_AVMuxer *muxer, int audioTrackIndex, int videoTrackIndex, FdListStr *fdStr)
280 {
281 if (fdStr == NULL || fdStr->inAudioFd < 0 || fdStr->inVideoFd < 0) {
282 printf("WriteTrackSample start failed!\n");
283 return;
284 }
285 printf("WriteTrackSample\n");
286 OH_AVMemory *audioBuffer = NULL;
287 OH_AVMemory *videoBuffer = NULL;
288 OH_AVCodecBufferAttr audioInfo;
289 OH_AVCodecBufferAttr videoInfo;
290 memset_s(&audioInfo, sizeof(audioInfo), 0, sizeof(audioInfo));
291 memset_s(&videoInfo, sizeof(videoInfo), 0, sizeof(videoInfo));
292 bool audioRet = UpdateWriteBufferInfo(fdStr->inAudioFd, &audioBuffer, &audioInfo);
293 bool videoRet = UpdateWriteBufferInfo(fdStr->inVideoFd, &videoBuffer, &videoInfo);
294 bool isOver = false;
295
296 while ((audioRet || videoRet) && !isOver) {
297 int ret = AV_ERR_OK;
298 if (audioRet && videoRet && audioInfo.pts <= videoInfo.pts) {
299 ret = OH_AVMuxer_WriteSample(muxer, audioTrackIndex, audioBuffer, audioInfo);
300 audioRet = UpdateWriteBufferInfo(fdStr->inAudioFd, &audioBuffer, &audioInfo);
301 } else if (audioRet && videoRet) {
302 ret = OH_AVMuxer_WriteSample(muxer, videoTrackIndex, videoBuffer, videoInfo);
303 videoRet = UpdateWriteBufferInfo(fdStr->inVideoFd, &videoBuffer, &videoInfo);
304 } else if (audioRet) {
305 ret = OH_AVMuxer_WriteSample(muxer, audioTrackIndex, audioBuffer, audioInfo);
306 isOver = true;
307 } else {
308 ret = OH_AVMuxer_WriteSample(muxer, videoTrackIndex, videoBuffer, videoInfo);
309 isOver = true;
310 }
311 if (ret != AV_ERR_OK) {
312 printf("OH_AVMuxer_WriteSample error!\n");
313 break;
314 }
315 }
316 if (audioBuffer != NULL) {
317 OH_AVMemory_Destroy(audioBuffer);
318 }
319 if (videoBuffer != NULL) {
320 OH_AVMemory_Destroy(videoBuffer);
321 }
322 }
323
WriteTrackCover(OH_AVMuxer * muxer,int coverTrackIndex,int fdInput)324 void WriteTrackCover(OH_AVMuxer *muxer, int coverTrackIndex, int fdInput)
325 {
326 printf("WriteTrackCover\n");
327 OH_AVCodecBufferAttr info;
328 memset_s(&info, sizeof(info), 0, sizeof(info));
329 struct stat fileStat;
330 fstat(fdInput, &fileStat);
331 info.size = fileStat.st_size;
332 OH_AVBuffer *avMemBuffer = OH_AVBuffer_Create(info.size);
333 if (avMemBuffer == NULL) {
334 printf("OH_AVBuffer create error! size: %d \n", info.size);
335 return;
336 }
337 if (OH_AVBuffer_SetBufferAttr(avMemBuffer, &info) != AV_ERR_OK) {
338 printf("OH_AVBuffer_SetBufferAttr error!\n");
339 return;
340 }
341 if (read(fdInput, (void*)OH_AVBuffer_GetAddr(avMemBuffer), info.size) <= 0) {
342 printf("OH_AVBuffer_GetAddr error!\n");
343 OH_AVBuffer_Destroy(avMemBuffer);
344 return;
345 }
346 if (OH_AVMuxer_WriteSampleBuffer(muxer, coverTrackIndex, avMemBuffer) != AV_ERR_OK) {
347 printf("OH_AVMuxer_WriteSampleBuffer error!\n");
348 OH_AVBuffer_Destroy(avMemBuffer);
349 return;
350 }
351 OH_AVBuffer_Destroy(avMemBuffer);
352 }
353
GetInputNum(int defaultNum)354 int GetInputNum(int defaultNum)
355 {
356 int num = getchar();
357 if (num == '\n') { // default
358 return defaultNum;
359 }
360 if (ungetc(num, stdin) == EOF) {
361 printf("GetInputNum ungetc failed!");
362 }
363 if (scanf_s("%d", &num) <= 0) {
364 num = defaultNum;
365 }
366 while ((getchar()) != '\n') {}
367 return num;
368 }
369
NativeSelectMuxerType(void)370 void NativeSelectMuxerType(void)
371 {
372 printf("\nplese select muxer type : 0.mp4 1.m4a 2.amr 3.mp3 4.wav 5.aac\n");
373 int num = GetInputNum(0);
374 switch (num) {
375 case MODE_ZERO:
376 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_MPEG_4;
377 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "mp4");
378 break;
379 case MODE_ONE:
380 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_M4A;
381 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "m4a");
382 break;
383 case MODE_TWO:
384 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_AMR;
385 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "amr");
386 break;
387 case MODE_THREE:
388 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_MP3;
389 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "mp3");
390 break;
391 case MODE_FOUR:
392 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_WAV;
393 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "wav");
394 break;
395 case MODE_FIVE:
396 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_AAC;
397 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "aac");
398 break;
399 default:
400 g_muxerParam.outputFormat = AV_OUTPUT_FORMAT_MPEG_4;
401 (void)snprintf_s(g_muxerParam.outputFormatType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "mp4");
402 break;
403 }
404 printf("select mode:%d\n", num);
405 }
406
NativeSelectRunMode(void)407 void NativeSelectRunMode(void)
408 {
409 printf("\nplese select audio vide wrtie mode:\n");
410 printf("0. audio video write in sample thread\n");
411 printf("1. audio video write in different thread\n");
412 int num = GetInputNum(0);
413 switch (num) {
414 case MODE_ZERO:
415 g_muxerParam.runMode = NORMAL;
416 (void)snprintf_s(g_muxerParam.runModeType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", RUN_NORMAL);
417 break;
418 case MODE_ONE:
419 g_muxerParam.runMode = THREAD;
420 (void)snprintf_s(g_muxerParam.runModeType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", RUN_MUL_THREAD);
421 break;
422 default:
423 g_muxerParam.runMode = NORMAL;
424 (void)snprintf_s(g_muxerParam.runModeType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", RUN_NORMAL);
425 break;
426 }
427 printf("select mode:%d\n", num);
428 }
429
NativeSelectAudio(void)430 void NativeSelectAudio(void)
431 {
432 printf("\nplese select audio mode: 0.noAudio 1.aac 2.mpeg 3.amr-nb 4.amr-wb 5.g711mu 6.raw 7.flac\n");
433 int num = GetInputNum(1);
434 switch (num) {
435 case MODE_ONE:
436 g_muxerParam.audioParams = &g_audioAacPar;
437 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "aac");
438 break;
439 case MODE_TWO:
440 g_muxerParam.audioParams = &g_audioMpegPar;
441 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "mpeg");
442 break;
443 case MODE_THREE:
444 g_muxerParam.audioParams = &g_audioAmrNbPar;
445 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "amr");
446 break;
447 case MODE_FOUR:
448 g_muxerParam.audioParams = &g_audioAmrWbPar;
449 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "amr");
450 break;
451 case MODE_FIVE:
452 g_muxerParam.audioParams = &g_audioG711MUPar;
453 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "g711mu");
454 break;
455 case MODE_SIX:
456 g_muxerParam.audioParams = &g_audioRawPar;
457 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "raw");
458 break;
459 case MODE_SEVEN:
460 g_muxerParam.audioParams = &g_audioFlacPar;
461 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "flac");
462 break;
463 default:
464 g_muxerParam.audioParams = NULL;
465 (void)snprintf_s(g_muxerParam.audioType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "noAudio");
466 break;
467 }
468 printf("select mode:%d\n", num);
469 }
470
NativeSelectVideo(void)471 void NativeSelectVideo(void)
472 {
473 printf("\nplese select video mode: 0.noVideo 1.h264 2.mpeg4 3.h265 4.hdr vivid\n");
474 int num = GetInputNum(1);
475 switch (num) {
476 case MODE_ONE:
477 g_muxerParam.videoParams = &g_videoH264Par;
478 (void)snprintf_s(g_muxerParam.videoType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "h264");
479 break;
480 case MODE_TWO:
481 g_muxerParam.videoParams = &g_videoMpeg4Par;
482 (void)snprintf_s(g_muxerParam.videoType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "mpeg4");
483 break;
484 case MODE_THREE:
485 g_muxerParam.videoParams = &g_videoH265Par;
486 (void)snprintf_s(g_muxerParam.videoType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "h265");
487 break;
488 case MODE_FOUR:
489 g_muxerParam.videoParams = &g_videoHdrPar;
490 (void)snprintf_s(g_muxerParam.videoType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "hdr-vivid");
491 break;
492 default:
493 g_muxerParam.videoParams = NULL;
494 (void)snprintf_s(g_muxerParam.videoType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "noVideo");
495 break;
496 }
497 printf("select mode:%d\n", num);
498 }
499
NativeSelectCover(void)500 void NativeSelectCover(void)
501 {
502 printf("\nplese select cover mode: 0.noCover 1.jpg 2.png 3.bmp\n");
503 int num = GetInputNum(1);
504 switch (num) {
505 case MODE_ONE:
506 g_muxerParam.coverParams = &g_jpegCoverPar;
507 (void)snprintf_s(g_muxerParam.coverType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "jpg");
508 break;
509 case MODE_TWO:
510 g_muxerParam.coverParams = &g_pngCoverPar;
511 (void)snprintf_s(g_muxerParam.coverType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "png");
512 break;
513 case MODE_THREE:
514 g_muxerParam.coverParams = &g_bmpCoverPar;
515 (void)snprintf_s(g_muxerParam.coverType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "bmp");
516 break;
517 default:
518 g_muxerParam.coverParams = NULL;
519 (void)snprintf_s(g_muxerParam.coverType, TYPE_BUFFER_SIZE, TYPE_BUFFER_SIZE - 1, "%s", "noCover");
520 break;
521 }
522 printf("select mode:%d\n", num);
523 }
524
NativeSelectMode(void)525 void NativeSelectMode(void)
526 {
527 if (g_muxerParam.outputFormat != AV_OUTPUT_FORMAT_DEFAULT) {
528 return;
529 }
530
531 NativeSelectMuxerType();
532 NativeSelectRunMode();
533 NativeSelectAudio();
534 NativeSelectVideo();
535 NativeSelectCover();
536 }
537
OpenAllInputFile(FdListStr * fdStr)538 int OpenAllInputFile(FdListStr *fdStr)
539 {
540 if (!fdStr) {
541 printf("fdStr is null!\n");
542 return -1;
543 }
544
545 if (g_muxerParam.audioParams) {
546 fdStr->inAudioFd = open(g_muxerParam.audioParams->fileName, O_RDONLY);
547 if (fdStr->inAudioFd < 0) {
548 printf("open %s failed!!\n", g_muxerParam.audioParams->fileName);
549 } else {
550 printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.audioParams->fileName,
551 fdStr->inAudioFd, fcntl(fdStr->inAudioFd, F_GETFL, 0));
552 }
553 }
554
555 if (g_muxerParam.videoParams) {
556 fdStr->inVideoFd = open(g_muxerParam.videoParams->fileName, O_RDONLY);
557 if (fdStr->inVideoFd < 0) {
558 printf("open %s failed!!\n", g_muxerParam.videoParams->fileName);
559 } else {
560 printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.videoParams->fileName,
561 fdStr->inVideoFd, fcntl(fdStr->inVideoFd, F_GETFL, 0));
562 }
563 }
564
565 if (g_muxerParam.coverParams) {
566 fdStr->inCoverFd = open(g_muxerParam.coverParams->fileName, O_RDONLY);
567 if (fdStr->inCoverFd < 0) {
568 printf("open %s failed!!\n", g_muxerParam.coverParams->fileName);
569 } else {
570 printf("open file %s success, -fd:%d, -flags %x\n", g_muxerParam.coverParams->fileName,
571 fdStr->inCoverFd, fcntl(fdStr->inCoverFd, F_GETFL, 0));
572 }
573 }
574 return 0;
575 }
576
DoRunMuxer(FdListStr * fdStr,OH_AVMuxer * muxer)577 int DoRunMuxer(FdListStr *fdStr, OH_AVMuxer *muxer)
578 {
579 if (fdStr == NULL || muxer == NULL) {
580 printf("fdStr or muxer is null!\n");
581 return -1;
582 }
583
584 if (OH_AVMuxer_SetRotation(muxer, 0) != AV_ERR_OK) {
585 printf("set failed!\n");
586 return -1;
587 }
588 SetFormat(muxer);
589 int audioTrackIndex = AddTrackAudio(muxer, g_muxerParam.audioParams, fdStr->inAudioFd);
590 int videoTrackIndex = AddTrackVideo(muxer, g_muxerParam.videoParams, fdStr->inVideoFd);
591 int coverTrackIndex = AddTrackCover(muxer, g_muxerParam.coverParams, fdStr->inCoverFd);
592
593 if (OH_AVMuxer_Start(muxer) != AV_ERR_OK) {
594 printf("start muxer failed!\n");
595 return -1;
596 }
597
598 if (coverTrackIndex >= 0) {
599 WriteTrackCover(muxer, coverTrackIndex, fdStr->inCoverFd);
600 }
601
602 if (g_muxerParam.runMode == NORMAL) {
603 printf("== write audio video sample in same thread\n");
604 if (audioTrackIndex >= 0 && videoTrackIndex >= 0) {
605 WriteTrackSample(muxer, audioTrackIndex, videoTrackIndex, fdStr);
606 } else if (audioTrackIndex >= 0) {
607 WriteSingleTrackSample(muxer, audioTrackIndex, fdStr->inAudioFd);
608 } else if (videoTrackIndex >= 0) {
609 WriteSingleTrackSample(muxer, videoTrackIndex, fdStr->inVideoFd);
610 }
611 } else if (g_muxerParam.runMode == THREAD) {
612 printf("== write audio video sample in different thread\n");
613 pthread_t auThread;
614 pthread_t viThread;
615
616 struct WriteTrackSampleParam audioThParam = {muxer, audioTrackIndex, fdStr->inAudioFd};
617 struct WriteTrackSampleParam videoThparam = {muxer, videoTrackIndex, fdStr->inVideoFd};
618 pthread_create(&auThread, NULL, ThreadWriteTrackSample, &audioThParam);
619 pthread_create(&viThread, NULL, ThreadWriteTrackSample, &videoThparam);
620
621 pthread_join(viThread, NULL);
622 pthread_join(auThread, NULL);
623 }
624
625 if (OH_AVMuxer_Stop(muxer) != AV_ERR_OK) {
626 printf("stop muxer failed!\n");
627 return -1;
628 }
629 printf("native avmuxer finish! fd:out:%d, audio:%d, video:%d, cover:%d\n",
630 fdStr->outputFd, fdStr->inAudioFd, fdStr->inVideoFd, fdStr->inCoverFd);
631 return 0;
632 }
633
CloseAllFd(FdListStr * fdStr)634 void CloseAllFd(FdListStr *fdStr)
635 {
636 printf("close fd : [");
637 int fdTotalCount = sizeof(*fdStr) / sizeof(fdStr->start[0]);
638 for (int i = 0; i < fdTotalCount; i++) {
639 printf("%d, ", fdStr->start[i]);
640 if (fdStr->start[i] > 0) {
641 close(fdStr->start[i]);
642 fdStr->start[i] = -1;
643 }
644 }
645 printf("\b\b]\n");
646 }
647
RunNativeMuxer(const char * out)648 int RunNativeMuxer(const char *out)
649 {
650 FdListStr fdStr;
651 int fdTotalCount = sizeof(fdStr) / sizeof(fdStr.start[0]);
652 printf("fd list total size is %d\n", fdTotalCount);
653 for (int i = 0; i < fdTotalCount; i++) {
654 fdStr.start[i] = -1;
655 }
656
657 if (OpenAllInputFile(&fdStr) < 0) {
658 CloseAllFd(&fdStr);
659 return -1;
660 }
661
662 char outFileName[CONFIG_BUFFER_SIZE] = {0};
663 int err = snprintf_s(outFileName, sizeof(outFileName), sizeof(outFileName) - 1, "%s_%s_%s_%s_%s.%s",
664 out, g_muxerParam.runModeType, g_muxerParam.audioType, g_muxerParam.videoType,
665 g_muxerParam.coverType, g_muxerParam.outputFormatType);
666 if (err <= 0) {
667 CloseAllFd(&fdStr);
668 return -1;
669 }
670
671 fdStr.outputFd = open(outFileName, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
672 if (fdStr.outputFd < 0) {
673 printf("open file failed! filePath is: %s %d\n", outFileName, fdStr.outputFd);
674 CloseAllFd(&fdStr);
675 return -1;
676 }
677 printf("open file %s success, -fd:%d, -flags %x\n", outFileName, fdStr.outputFd, fcntl(fdStr.outputFd, F_GETFL, 0));
678 long long testTimeStart = GetTimestamp();
679 OH_AVMuxer *muxer = OH_AVMuxer_Create(fdStr.outputFd, g_muxerParam.outputFormat);
680 DoRunMuxer(&fdStr, muxer);
681
682 if (muxer != NULL) {
683 OH_AVMuxer_Destroy(muxer);
684 muxer = NULL;
685 }
686
687 CloseAllFd(&fdStr);
688 long long testTimeEnd = GetTimestamp();
689 printf("muxer used time: %lld us\n", testTimeEnd - testTimeStart);
690
691 return 0;
692 }
693