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