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
46typedef struct AudioTrackParam AudioTrackParam;
47typedef struct VideoTrackParam VideoTrackParam;
48typedef struct FdListStr FdListStr;
49
50struct WriteTrackSampleParam {
51    OH_AVMuxer *muxer;
52    int trackId;
53    int fd;
54};
55
56struct 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
69static 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
82int 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
123int 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
163int 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
189static 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
228void 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
251void *ThreadWriteTrackSample(void *param)
252{
253    struct WriteTrackSampleParam *wrTrackParam = (struct WriteTrackSampleParam *)param;
254    WriteSingleTrackSample(wrTrackParam->muxer, wrTrackParam->trackId, wrTrackParam->fd);
255    return NULL;
256}
257
258void 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
303void 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
333int 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
349void 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
382void 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
405void 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
442void 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
471void 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
496void 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
509int 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
548int 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
604void 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
618int 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