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