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