音视频封装demo:将h264数据和aac数据封装(mux)成TS文件(纯手工,不依赖第三方开源库)

2024-07-13 1498阅读

1、README

a. demo使用
$ make clean && make DEBUG=1
$
$ ./ts_mux_h264_aac
Usage:
   ./ts_mux_h264_aac avfile/test1_856x480_24fps.h264 24 avfile/test1_44100_stereo.aac out1.ts
   ./ts_mux_h264_aac avfile/test2_720x480_30fps.h264 60 avfile/test2_48000_stereo.aac out2.ts
   ./ts_mux_h264_aac avfile/test3_1280x720_20fps.h264 20 avfile/test1_44100_stereo.aac out3.ts

(注:目前合成的out1.ts在使用potPlayer播放时进度条有点问题,待修复。)

音视频封装demo:将h264数据和aac数据封装(mux)成TS文件(纯手工,不依赖第三方开源库)
(图片来源网络,侵删)

目前合成视频的现象:

(out2.ts含有除SPS、PPS、IDR、PSLICE以外的其他NALU,所以主要看out1.ts和out3.ts)

  • out1.ts:
    • 电影和电视、ACG播放器
      • 播放不流畅(含有B帧,而程序只填pts没填dts导致,对比out3.ts可知,无关紧要);
      • 正常播放进度条时长正常(29s),拖动后有声音但画面卡住一会才动、音视频同步;
      • VLC
        • 播放不流畅(含有B帧,而程序只填pts没填dts导致,对比out3.ts可知,无关紧要);
        • 正常播放进度条时长正常(29s),拖动后有声音但画面会灰屏有画面在动过一会才恢复、音视频同步;
        • potplayer
          • 播放流畅;
          • 正常播放时进度条时长不正常(21s),拖动画面不会卡住、但音视频有时不同步;
          • out3.ts
            • 电影和电视、ACG播放器
              • 播放流畅;
              • 正常播放进度条时长正常(30s),拖动后有声音但画面卡住一会才动、音视频“同步”;
              • VLC
                • 播放流畅;
                • 正常播放进度条时长正常(30s),拖动后有声音但画面会灰屏有画面在动过一会才恢复、音视频“同步”;
                • potplayer
                  • 播放流畅;
                  • 正常播放时进度条时长不正常(8s),拖动画面和声音都会卡住一会才动;
                    b. 参考文章
                    • 【科普】TS文件格式:什么是TS?如何打开和转换它?_都叫兽软件

                    • TS封装格式 - CrazyDiode - 博客园(推荐!!看这篇基本就够了!!!其余文章作为参考即可。)

                    • TS文件格式_LaugustusJ的博客-CSDN博客_ts文件(没仔细看)

                    • TS 文件格式解析_影音视频技术-CSDN博客_ts格式解析(没仔细看)

                    • 测试验证:h264实时流封装ts文件存储,完整实现 - jamin-snails的个人空间 - OSCHINA - 中文开源技术交流社区(没仔细看)

                      工具下载:

                      • SpecialFTS.exe(demo中的tools/SpecialFTS_1.1.7z)【源码下载地址】

                        参考源码:

                        • https://download.csdn.net/download/zhuweigangzwg/5605869?spm=1003.2166.3001.6637.7(推荐!!)
                        • https://github.com/Jsnails/MUX_TS(根据前者进行改动的,可以不用看)
                          c. demo目录架构
                          $ tree
                          .
                          ├── aac_adts.c
                          ├── aac_adts.h
                          ├── avfile
                          │   ├── out1.ts
                          │   ├── out2.ts
                          │   ├── out3.ts
                          │   ├── test1_44100_stereo.aac
                          │   ├── test1_856x480_24fps.h264
                          │   ├── test2_48000_stereo.aac
                          │   ├── test2_720x480_30fps.h264
                          │   └── test3_1280x720_20fps.h264
                          ├── crcLib.c
                          ├── crcLib.h
                          ├── docs
                          │   ├── TS封装格式 - CrazyDiode - 博客园.mhtml
                          │   ├── TS文件格式_LaugustusJ的博客-CSDN博客_ts文件.mhtml
                          │   ├── TS 文件格式解析_影音视频技术-CSDN博客_ts格式解析.mhtml
                          │   ├── 测试验证:h264实时流封装ts文件存储,完整实现 - jamin-snails的个人空间 - OSCHINA - 中文开源技术交流社区.mhtml
                          │   └── 【科普】TS文件格式:什么是TS?如何打开和转换它?_都叫兽软件.mhtml
                          ├── h264_nalu.c
                          ├── h264_nalu.h
                          ├── main.c
                          ├── Makefile
                          ├── README.md
                          ├── reference_src
                          │   ├── H264_AAC_TS_MUX.tar.bz2
                          │   └── MUX_TS-master.zip
                          ├── tools
                          │   └── SpecialFTS_1.1.7z
                          ├── ts.c
                          └── ts.h
                          

                          2、主要代码片段

                          ts.h
                          #ifndef __TS_H__
                          #define __TS_H__
                          #include 
                          #include 
                          #include 
                          #include 
                          //#define ENABLE_DEBUG
                          #ifdef ENABLE_DEBUG
                          	#define DEBUG(fmt, args...)     printf(fmt, ##args)
                          #else
                          	#define DEBUG(fmt, args...)
                          #endif
                          #define TS_HEADER_SYNC_BYTE 	0x47
                          #define TS_PACKET_HEADER_SIZE 	4
                          #define TS_PACKET_SIZE 			188
                          /* PID: 13 bit */
                          #define TS_PID_PAT 				0x0000 	/* fixed */
                          #define TS_PID_PMT 				0x0FFF 	/* custom */
                          #define TS_PID_H264 			0x0007 	/* custom */
                          #define TS_PID_AAC 				0x0008 	/* custom */
                          #define TS_STREAM_ID_VIDEO 		0xE0 	/* always */
                          #define TS_STREAM_ID_AUDIO 		0xC0 	/* always */
                          #define PMT_STREAM_TYPE_H264 	0x1B 	/* fixed */
                          #define PMT_STREAM_TYPE_AAC 	0x0F 	/* fixed */
                          #define PMT_STREAM_TYPE_MP3 	0x03 	/* fixed */
                          /* ts layer header element member.
                           * [Note: It is not stored as defined type size!!!]
                           */
                          typedef struct tsHeader
                          {
                          	uint8_t  sync_byte;                    // 8b, must be 0x47
                          	uint8_t  transport_error_indicator;    // 1b, transport error flag, always '0'. '1': after the adapt field of the ts head is a useless byte, this byte is in the adaptive area length.
                          	uint8_t  payload_unit_start_indicator; // 1b, the load unit starts the identifier, and a complete packet begins with a tag of '1'.
                          	uint8_t  transport_priority;           // 1b, always '0'.
                          	uint16_t pid;                          // 13b, packet id.
                          	uint8_t  transport_scrambling_control; // 2b, always '00'. transfer disturbance control.
                          	uint8_t  adaptation_field_control;     // 2b, whether has adaption field. '00': reserved, '01': playload, '10': adaption_field, '11': playload+adaption_field.
                          	uint8_t  continuity_counter;           // 4b, increasing counter, 0~f, the starting value is not necessarily 0, but it must be continuous.
                          }T_TsHeader, *PT_TsHeader;
                          /* adaptationField element member.
                           * [Note: It is not stored as defined type size!!!]
                           */
                          typedef struct adaptationField
                          {
                          	uint8_t adaptation_field_length;              // 1B
                          	uint8_t discontinuty_indicator;               // 1b, the continuous state of the current transfer.
                          	uint8_t random_access_indicator;              // 1b, the next pes group with the same pid should contain the PTS fields and a raw flow access point.
                          	uint8_t elementary_stream_priority_indicator; // 1b, priority
                          	/* 5 flags for optional fields */
                          	uint8_t pcr_flag;                             // 1b
                          	uint8_t opcr_flag;                            // 1b
                          	uint8_t splicing_point_flag;                  // 1b
                          	uint8_t transport_private_data_flag;          // 1b
                          	uint8_t adaptation_field_extension_flag;      // 1b
                          	/* optional fields */
                          	uint64_t pcr;                         // 42b, Program Clock Reference
                          	uint64_t opcr;                        // 42b
                          	uint8_t splice_countdown;             // 1B
                          	uint8_t transport_private_data_len;   // 1B
                          	uint8_t transport_private_data[256];
                          }T_AdaptationField, *PT_AdaptationField;
                          /* pts and dts element member.
                           * [Note: It is not stored as defined type size!!!]
                           */
                          typedef struct tsPtsDts
                          {
                          	uint8_t  reserved_1;  // 4b
                          	uint8_t  pts_32_30;   // 3b
                          	uint8_t  marker_bit1; // 1b
                          	uint32_t pts_29_15;   // 15b
                          	uint8_t  marker_bit2; // 1b
                          	uint32_t pts_14_0;    // 15b
                          	uint8_t  marker_bit3; // 1b
                          	uint8_t  reserved_2;  // 4b
                          	uint8_t  dts_32_30;   // 3b
                          	uint8_t  marker_bit4; // 1b
                          	uint32_t dts_29_15;   // 15b
                          	uint8_t  marker_bit5; // 1b
                          	uint32_t dts_14_0;    // 15b
                          	uint8_t  marker_bit6; // 3b
                          }TsPtsDts;
                          /* PAT element member.
                           * [Note: It is not stored as defined type size!!!]
                           */
                          typedef struct pat
                          {
                          	uint8_t table_id;                 // 8b, PAT is fixed 0x00.
                          	uint8_t section_syntax_indicator; // 1b, fixed '1'.
                          	uint8_t zero;                     // 1b, fixed '0'.
                          	uint8_t reserved_1;               // 2b, fixed '11'.
                          	uint16_t section_length;          // 12b, length of data behind, comtain "crc32 code".
                          	uint16_t transport_stream_id;     // 16b, fixed 0x0001.
                          	uint8_t reserved_2;               // 2b, fixed '11'.
                          	uint8_t version_number;           // 5b, fixed '00000'.
                          	uint8_t current_next_indicator;   // 1b, fixed '1', the "pat" is available, '0' is wait for next "pat".
                          	uint8_t section_number;           // 8b, fixed 0x00.
                          	uint8_t last_section_number;      // 8b, fixed 0x00.
                          	/* loop start */
                          	uint32_t program_number;          // 16b, 0x0000: NIT, 0x0001: PMT.
                          	uint8_t reserved_3;               // 3b, fixed '111'.
                          	uint32_t pid;                     // 13b, program_number pid
                          	/* loop end */
                          	uint32_t crc_32;                  // 32b, the crc32 check code for the previous data
                          }T_Pat, *PT_Pat;
                          /* PMT element member.
                           * [Note: It is not stored as defined type size!!!]
                           */
                          typedef struct pmt
                          {
                          	uint8_t  table_id;                 // 8b, PMT is fixed 0x02.
                          	uint8_t  section_syntax_indicator; // 1b, fixed '1'.
                          	uint8_t  zero;                     // 1b, fixed '0'.
                          	uint8_t  reserved_1;               // 2b, fixed '11'.
                          	uint32_t section_length;           // 12b, length of data behind, comtain "crc32 code".
                          	uint32_t program_number;           // 16b, pid of applicable program.
                          	uint8_t  reserved_2;               // 2b, fixed '11'.
                          	uint8_t  version_number;           // 5b, fixed '00000', if pat variable will be '00001'.
                          	uint8_t  current_next_indicator;   // 1b, fixed '1'.
                          	uint8_t  section_number;           // 8b, fixed 0x00.
                          	uint8_t  last_section_number;      // 8b, fixed 0x00.
                          	uint8_t  reserved_3;               // 3b, fixed '111'.
                          	uint32_t pcr_pid;                  // 13b, The pcr is grouped by the ts, which is designated as the video pid.
                          	uint8_t  reserved_4;               // 4b, fixed '1111'.
                          	uint32_t program_info_length;      // 12b, program describes, 0x000 for no.
                          	/* loop start */
                          	/* program 1 */
                          	uint8_t  stream_type_video;        // 8b, stream type. 0x1b: h264  0x0f: aac  0x03: mp3
                          	uint8_t  reserved_5_video;         // 3b, fixed '111'
                          	uint32_t elementary_pid_video;     // 13b, pid of "stream type"
                          	uint8_t  reserved_6_video;         // 4b, fixed '1111'
                          	uint32_t es_info_length_video;     // 12b, program describes, 0x000 for no.
                          	/* program 2 */
                          	uint8_t  stream_type_audio;
                          	uint8_t  reserved_5_audio;
                          	uint32_t elementary_pid_audio;
                          	uint8_t  reserved_6_audio;
                          	uint32_t es_info_length_audio;
                          	/* loop end */
                          	uint32_t crc_32;                   // 32b, the crc32 check code for the previous data
                          }T_Pmt, *PT_Pmt;
                          
                          /* custom "PES" structure, it includes "pes header" and "es data".
                           * so the member's size is different in ts file.
                           */
                          typedef struct
                          {
                          	/* "pes header"(not contain pts/dts) : 9 Bytes */
                          	uint32_t packet_start_code_prefix;  // 3B, start code, must be 0x000001.
                          	uint8_t  stream_id;                 // 1B, audio(0xc0~0xdf), always 0xc0; video(0xe0~0xef), always 0xe0.
                          	uint32_t pes_packet_length;         // 2B, the length of the data behind, 0 indicates unlimited length.
                          										// 1B: always 0x80 in this Byte.
                          	uint8_t  marker_bit;                //   2b, must be '10'.
                          	uint8_t  pes_scrambling_control;    //   2b, pes packet scrambling control.
                          	uint8_t  pes_priority;              //   1b, pes packet priority.
                          	uint8_t  data_alignment_indicator;  //   1b, '1': the follows video or audio syncword is shown in the back of the pes package.
                          	uint8_t  copyright;                 //   1b, copyright protection.
                          	uint8_t  original_or_copy;          //   1b, playload source.
                          										// 1B: 0x80: only pts; 0xc0: pts+dts
                          	uint8_t  pts_dts_flags;             //   2b, '10': PTS; '11': PTS+DTS, '00': none, '01': reserved.
                          	uint8_t  escr_flag;                 //   1b, '1': escr_base+escr_expand; '0': none.
                          	uint8_t  es_rate_flag;              //   1b, es rate.
                          	uint8_t  dsm_trick_mode_flag;       //   1b, whether the 8 bitt connection field exists.
                          	uint8_t  additional_copy_info_flag; //   1b, additional copy information.
                          	uint8_t  pes_crc_flag;              //   1b, whether there is a call.
                          	uint8_t  pes_extension_flag;        //   1b, extension.
                          	uint8_t  pes_data_length;           // 1B, 5 or 10, the length of the data(pts, dts) behind.
                          	TsPtsDts ts_pts_dts;                // pts+dts structure.
                          	/* "es data": 1024*1024+4 Bytes max */
                          	//uint8_t  av_data[MAX_ONE_FRAME_SIZE]; // one frame audio or video data.
                          	uint8_t* av_data; 					// one frame audio or video data.
                          	uint8_t* av_data_cur_ptr; 			// position for current "av_data"
                          	uint32_t av_data_len;				// length of data.
                          }T_PesEsStruct, *PT_PesEsStruct;
                          
                          /************************************************************************
                           * function describe: Mux h264 and aac to TS file.
                           * params:
                           *   [h264FileName]: h264 file.(in)
                           *   [vFps]: video fps.(in)
                           *   [aacFileName]: aac file file.(in)
                           *   [tsFileName]: ts file.(in)
                           * return: 0-success  other-error
                           ************************************************************************/
                          int ts_mux_h264_aac(char *h264FileName, uint32_t vFps, char *aacFileName, char *tsFileName);
                          #endif
                          
                          ts.c
                          #include "h264_nalu.h"
                          #include "aac_adts.h"
                          #include "ts.h"
                          #include "crcLib.h"
                          static uint32_t endian_convert(uint32_t val)
                          {
                          	return (((val >>  0)  & 0xff) >  8)  & 0xff) > 16) & 0xff) > 24) & 0xff) 
                          	if(!ptAdaptationField)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	ptAdaptationField-adaptation_field_length = 7; /* pcr_flag = 1: has pcr */
                          	ptAdaptationField->discontinuty_indicator = 0;
                          	ptAdaptationField->random_access_indicator = 0; /* is keyflame? always 0, you can set it such "iskeyflame?1:0" */
                          	ptAdaptationField->elementary_stream_priority_indicator = 0;
                          	/* 5 flags for optional fields */
                          	ptAdaptationField->pcr_flag = 1;
                          	ptAdaptationField->opcr_flag = 0;
                          	ptAdaptationField->splicing_point_flag = 0;
                          	ptAdaptationField->transport_private_data_flag = 0;
                          	ptAdaptationField->adaptation_field_extension_flag = 0;
                          	ptAdaptationField->pcr  = pts * 300;
                          	ptAdaptationField->opcr = 0;
                          	ptAdaptationField->splice_countdown = 0;
                          	ptAdaptationField->transport_private_data_len = 0;
                          	return 0;
                          }
                          static int fixCommonAdaptionFieldStruct(T_AdaptationField *ptAdaptationField)
                          {
                          	if(!ptAdaptationField)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	ptAdaptationField->adaptation_field_length = 1; /* 5 flags = 0 */
                          	ptAdaptationField->discontinuty_indicator = 0;
                          	ptAdaptationField->random_access_indicator = 0; /* is keyflame? always 0, you can set it such "iskeyflame?1:0" */
                          	ptAdaptationField->elementary_stream_priority_indicator = 0;
                          	/* 5 flags for optional fields */
                          	ptAdaptationField->pcr_flag = 0;
                          	ptAdaptationField->opcr_flag = 0;
                          	ptAdaptationField->splicing_point_flag = 0;
                          	ptAdaptationField->transport_private_data_flag = 0;
                          	ptAdaptationField->adaptation_field_extension_flag = 0;
                          	ptAdaptationField->pcr  = 0;
                          	ptAdaptationField->opcr = 0;
                          	ptAdaptationField->splice_countdown = 0;
                          	ptAdaptationField->transport_private_data_len = 0;
                          	return 0;
                          }
                          static int fixAdtsFrameToPesStruct(uint8_t *adtsData, uint32_t adtsDataLen, uint64_t pts, T_PesEsStruct *ptAdtsPesStu)
                          {
                          	if(!ptAdtsPesStu || !adtsData || !adtsDataLen)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* pes header */
                          	ptAdtsPesStu->packet_start_code_prefix = 0x000001;
                          	ptAdtsPesStu->stream_id = TS_STREAM_ID_AUDIO;
                          	ptAdtsPesStu->pes_packet_length = 0;
                          	ptAdtsPesStu->marker_bit = 0b10;
                          	ptAdtsPesStu->pes_scrambling_control = 0b00;
                          	ptAdtsPesStu->pes_priority = 0b0;
                          	ptAdtsPesStu->data_alignment_indicator = 0b0;
                          	ptAdtsPesStu->copyright = 0b0;
                          	ptAdtsPesStu->original_or_copy = 0b0;
                          	ptAdtsPesStu->pts_dts_flags = 0b10;  // '10': audio(aac) only PTS
                          	ptAdtsPesStu->escr_flag = 0b0;
                          	ptAdtsPesStu->es_rate_flag = 0b0;
                          	ptAdtsPesStu->dsm_trick_mode_flag = 0b0;
                          	ptAdtsPesStu->additional_copy_info_flag = 0b0;
                          	ptAdtsPesStu->pes_crc_flag = 0b0;
                          	ptAdtsPesStu->pes_extension_flag = 0b0;
                          	ptAdtsPesStu->pes_data_length = 5;   // pts_dts_flags = '10': audio(aac) only PTS
                          	ptAdtsPesStu->ts_pts_dts.reserved_1 = 0b1111;
                          	if(pts > 0x7FFFFFFF)
                          	{
                          		ptAdtsPesStu->ts_pts_dts.pts_32_30 = (pts >> 30) & 0x07;
                          		ptAdtsPesStu->ts_pts_dts.marker_bit1 = 0b1;
                          	}
                          	else
                          	{
                          		ptAdtsPesStu->ts_pts_dts.pts_32_30  = 0;
                          		ptAdtsPesStu->ts_pts_dts.marker_bit1 = 0b0;
                          	}
                          	if(pts > 0x7FFF)
                          	{
                          		ptAdtsPesStu->ts_pts_dts.pts_29_15 = (pts >> 15) & 0x007FFF;
                          		ptAdtsPesStu->ts_pts_dts.marker_bit2 = 0b1;
                          	}
                          	else
                          	{
                          		ptAdtsPesStu->ts_pts_dts.pts_29_15 = 0;
                          		ptAdtsPesStu->ts_pts_dts.marker_bit2 = 0b0;
                          	}
                          	ptAdtsPesStu->ts_pts_dts.pts_14_0 = pts & 0x007FFF;
                          	ptAdtsPesStu->ts_pts_dts.marker_bit3 = 0b1;
                          	/* es data */
                          	ptAdtsPesStu->av_data = adtsData;
                          	ptAdtsPesStu->av_data_len = adtsDataLen;
                          	return 0;
                          }
                          int fixH264FrameToPesStruct(uint8_t *h264Data, uint32_t h264DataLen, uint64_t pts, T_PesEsStruct* ptH264PesStu)
                          {
                          	if(!ptH264PesStu || !h264Data || !h264DataLen)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* pes header */
                          	ptH264PesStu->packet_start_code_prefix = 0x000001;
                          	ptH264PesStu->stream_id = TS_STREAM_ID_VIDEO;
                          	ptH264PesStu->pes_packet_length = 0;
                          	ptH264PesStu->marker_bit = 0b10;
                          	ptH264PesStu->pes_scrambling_control = 0b00;
                          	ptH264PesStu->pes_priority = 0b0;
                          	ptH264PesStu->data_alignment_indicator = 0b0;
                          	ptH264PesStu->copyright = 0b0;
                          	ptH264PesStu->original_or_copy = 0b0;
                          	ptH264PesStu->pts_dts_flags = 0b10;   // '10':  only PTS
                          	ptH264PesStu->escr_flag = 0b0;
                          	ptH264PesStu->es_rate_flag = 0b0;
                          	ptH264PesStu->dsm_trick_mode_flag = 0b0;
                          	ptH264PesStu->additional_copy_info_flag = 0b0;
                          	ptH264PesStu->pes_crc_flag = 0b0;
                          	ptH264PesStu->pes_extension_flag = 0b0;
                          	ptH264PesStu->pes_data_length = 5;   // pts_dts_flags = '10'
                          	ptH264PesStu->ts_pts_dts.reserved_1 = 0x03;
                          	if(pts > 0x7FFFFFFF)
                          	{
                          		ptH264PesStu->ts_pts_dts.pts_32_30 = (pts >> 30) & 0x07;
                          		ptH264PesStu->ts_pts_dts.marker_bit1 = 0b1;
                          	}
                          	else
                          	{
                          		ptH264PesStu->ts_pts_dts.pts_32_30  = 0;
                          		ptH264PesStu->ts_pts_dts.marker_bit1 = 0b0;
                          	}
                          	if(pts > 0x7FFF)
                          	{
                          		ptH264PesStu->ts_pts_dts.pts_29_15 = (pts >> 15) & 0x007FFF ;
                          		ptH264PesStu->ts_pts_dts.marker_bit2 = 0b1;
                          	}
                          	else
                          	{
                          		ptH264PesStu->ts_pts_dts.pts_29_15 = 0;
                          		ptH264PesStu->ts_pts_dts.marker_bit2 = 0b0;
                          	}
                          	ptH264PesStu->ts_pts_dts.pts_14_0 = pts & 0x007FFF;
                          	ptH264PesStu->ts_pts_dts.marker_bit3 = 0b1;
                          	/* es data */
                          	ptH264PesStu->av_data = h264Data;
                          	ptH264PesStu->av_data_len = h264DataLen;
                          	return 0;
                          }
                          static int fixFirstPacketAdaptionField(T_AdaptationField *adaptationField, uint8_t adaptFieldLen, uint8_t *adaptBuf)
                          {
                          	uint8_t adaptiveFlags = 0x00;
                          	uint8_t adaptivePos = 1; // offset
                          	if(!adaptationField || !adaptBuf)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	if(adaptationField->discontinuty_indicator)
                          	{
                          		adaptiveFlags |= 0x80;
                          	}
                          	if(adaptationField->random_access_indicator)
                          	{
                          		adaptiveFlags |= 0x40;
                          	}
                          	if(adaptationField->elementary_stream_priority_indicator)
                          	{
                          		adaptiveFlags |= 0x20;
                          	}
                          	if(adaptationField->pcr_flag)
                          	{
                          		adaptiveFlags |= 0x10;
                          		uint64_t pcr_base = adaptationField->pcr / 300;
                          		uint64_t pcr_ext = adaptationField->pcr % 300;
                          		adaptBuf[adaptivePos + 0] = (pcr_base >> 25) & 0xff;
                          		adaptBuf[adaptivePos + 1] = (pcr_base >> 17) & 0xff;
                          		adaptBuf[adaptivePos + 2] = (pcr_base >> 9) & 0xff;
                          		adaptBuf[adaptivePos + 3] = (pcr_base >> 1) & 0xff;
                          		adaptBuf[adaptivePos + 4] = pcr_base > 8 | 0x7e;
                          		adaptBuf[adaptivePos + 5] = (pcr_ext) & 0xff;
                          		adaptivePos += 6;
                          	}
                          	if(adaptationField->opcr_flag)
                          	{
                          		adaptiveFlags |= 0x08;
                          		uint64_t opcr_base = adaptationField->opcr / 300;
                          		uint64_t opcr_ext = adaptationField->opcr % 300;
                          		adaptBuf[adaptivePos + 0] = (opcr_base >> 25) & 0xff;
                          		adaptBuf[adaptivePos + 1] = (opcr_base >> 17) & 0xff;
                          		adaptBuf[adaptivePos + 2] = (opcr_base >> 9) & 0xff;
                          		adaptBuf[adaptivePos + 3] = (opcr_base >> 1) & 0xff;
                          		adaptBuf[adaptivePos + 4] = ((opcr_base > 8) & 0x01);
                          		adaptBuf[adaptivePos + 5] = (opcr_ext) & 0xff;
                          		adaptivePos += 6;
                          	}
                          	if(adaptationField->splicing_point_flag)
                          	{
                          		adaptiveFlags |= 0x04;
                          		adaptBuf[adaptivePos] = adaptationField->splice_countdown;
                          		adaptivePos += 1;
                          	}
                          	if(adaptationField->transport_private_data_flag)
                          	{
                          		adaptiveFlags |= 0x02;
                          		if(adaptationField->transport_private_data_len + 1 > adaptFieldLen - adaptivePos)
                          			return -2;
                          		else
                          		{
                          			adaptBuf[adaptivePos] = adaptationField->transport_private_data_len;
                          			memcpy(&adaptBuf[adaptivePos + 1], adaptationField->transport_private_data, adaptBuf[adaptivePos]);
                          			adaptivePos += (1 + adaptBuf[adaptivePos]);
                          		}
                          	}
                          	if(adaptationField->adaptation_field_extension_flag)
                          	{
                          		adaptiveFlags |= 0x01;
                          		adaptBuf[adaptivePos] = 1;
                          		adaptBuf[adaptivePos + 1] = 0;
                          	}
                          	adaptBuf[0] = adaptiveFlags;
                          	return 0;
                          }
                          static int generateTsHeaderData(uint16_t pid, uint8_t payloadStartInd, uint8_t adaptFieldControl, uint8_t *outTsHeaderData)
                          {
                          	T_TsHeader tsHeader = {0};
                          	static uint8_t continuity_counter_pat = 0; /* 0~f */
                          	static uint8_t continuity_counter_pmt = 0; /* 0~f */
                          	static uint8_t continuity_counter_audio = 0; /* 0~f */
                          	static uint8_t continuity_counter_video = 0; /* 0~f */
                          	if(!outTsHeaderData)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* fix */
                          	tsHeader.sync_byte = TS_HEADER_SYNC_BYTE;
                          	tsHeader.transport_error_indicator = 0;
                          	tsHeader.payload_unit_start_indicator = payloadStartInd;
                          	tsHeader.transport_priority = 0;
                          	tsHeader.pid = pid;
                          	tsHeader.transport_scrambling_control = 0;
                          	tsHeader.adaptation_field_control = adaptFieldControl;
                          	switch(pid)
                          	{
                          		case TS_PID_PAT:  tsHeader.continuity_counter = continuity_counter_pat++ % 0x10;   break;
                          		case TS_PID_PMT:  tsHeader.continuity_counter = continuity_counter_pmt++ % 0x10;   break;
                          		case TS_PID_AAC:  tsHeader.continuity_counter = continuity_counter_audio++ % 0x10; break;
                          		case TS_PID_H264: tsHeader.continuity_counter = continuity_counter_video++ % 0x10; break;
                          		default: return -2;
                          	}
                          	/* save */
                          	outTsHeaderData[0] = tsHeader.sync_byte;
                          	outTsHeaderData[1] = tsHeader.transport_error_indicator 
                          	T_Pat pat = {};
                          	uint8_t tsBuf[TS_PACKET_SIZE] = {0};
                          	uint32_t crc_32 = 0xFFFFFFFF;
                          	if(!fpTsFile)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* 1. fix params */
                          	pat.table_id = 0x00;
                          	pat.section_syntax_indicator = 0b1;
                          	pat.zero = 0b0;
                          	pat.reserved_1 = 0b11;
                          	pat.section_length = 13; 			// 16 Bytes(pat total size) - 3 Bytes(sizeof table_id~section_length)
                          	pat.transport_stream_id = 0x0001;
                          	pat.reserved_2 = 0b11;
                          	pat.version_number = 0b00000;
                          	pat.current_next_indicator = 0b1; 	// available
                          	pat.section_number = 0x00;
                          	pat.last_section_number = 0x00;
                          	pat.program_number = 0x0001; 		// PMT
                          	pat.reserved_3 = 0b111;
                          	pat.pid = TS_PID_PMT; 				// program_number: 0x0001 - pmt's pid
                          	//pat.crc_32 = crc_32; 				// we'll calculate when write to buf.
                          	/* 2. fix ts data */
                          	/* 2.1 fix ts data: ts header */
                          	generateTsHeaderData(TS_PID_PAT, 0b1, 0b01, tsBuf); // 0b1: start, 0b01: playload.
                          	/* 2.2 fix ts data: adaptation field length */
                          	tsBuf[4] = 0; /* no adaption field */
                          	/* 2.3 fix ts data: pat data */
                          	tsBuf[5] = pat.table_id;
                          	tsBuf[6] = pat.section_syntax_indicator  8) & 0x0F);
                          	tsBuf[16]= pat.pid & 0x00FF;
                          	crc_32 = endian_convert(crc32_mpeg_2(&tsBuf[5], 16 - 5 + 1));
                          	memcpy(&tsBuf[17], (unsigned char *)&crc_32, 4);
                          	/* 2.4 fix ts data: clear with "0xff" */
                          	memset(&tsBuf[21], 0xff, TS_PACKET_SIZE - 21);
                          	/* 3. write to file */
                          	fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          	return 0;
                          }
                          static int packPmt2TsAndWriteToFile(FILE *fpTsFile)
                          {
                          	T_Pmt pmt;
                          	uint8_t tsBuf[TS_PACKET_SIZE] = {0};
                          	uint32_t crc_32 = 0xFFFFFFFF;
                          	if(!fpTsFile)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* 1. fix params */
                          	pmt.table_id = 0x02;
                          	pmt.section_syntax_indicator = 0b1;
                          	pmt.zero = 0b0;
                          	pmt.reserved_1 = 0b11;
                          	pmt.section_length = 23; 			// 16 + 5 + 5 - 3
                          	pmt.program_number = 1; 			// only one program
                          	pmt.reserved_2 = 0b11;
                          	pmt.version_number = 0b0000;
                          	pmt.current_next_indicator = 0b1; 	// available
                          	pmt.section_number = 0x00;
                          	pmt.last_section_number = 0x00;
                          	pmt.reserved_3 = 0b111;
                          	pmt.pcr_pid = TS_PID_H264;
                          	pmt.reserved_4 = 0b1111;
                          	pmt.program_info_length = 0x000;
                          	pmt.stream_type_video = PMT_STREAM_TYPE_H264; 	// video type
                          	pmt.reserved_5_video = 0b111;
                          	pmt.elementary_pid_video = TS_PID_H264; 		// video pid
                          	pmt.reserved_6_video= 0b1111;
                          	pmt.es_info_length_video = 0x000;
                          	pmt.stream_type_audio = PMT_STREAM_TYPE_AAC; 	// audio type
                          	pmt.reserved_5_audio = 0b111;
                          	pmt.elementary_pid_audio = TS_PID_AAC; 			// audio pid
                          	pmt.reserved_6_audio = 0b1111;
                          	pmt.es_info_length_audio = 0x000;
                          	//pmt.crc_32 = crc_32; 							// we'll calculate when write to buf.
                          	/* 2. fix ts data */
                          	/* 2.1 fix ts data: ts header */
                          	generateTsHeaderData(TS_PID_PMT, 0b1, 0b01, tsBuf); // 0b1: start, 0b01: playload.
                          	/* 2.2 fix ts data: adaptation field length */
                          	tsBuf[4] = 0; /* no adaption field */
                          	/* 2.3 fix ts data: pmt data */
                          	tsBuf[5] = pmt.table_id;
                          	tsBuf[6] = pmt.section_syntax_indicator > 8;
                          	tsBuf[9] = pmt.program_number & 0x00FF;
                          	tsBuf[10] = pmt.reserved_2  8) & 0x0F);
                          	tsBuf[16]= pmt.program_info_length & 0xFF;
                          	tsBuf[17]= pmt.stream_type_video;
                          	tsBuf[18]= pmt.reserved_5_video > 8 ) & 0x1F);
                          	tsBuf[19]= pmt.elementary_pid_video & 0x00FF;
                          	tsBuf[20]= pmt.reserved_6_video> 8) & 0x0F);
                          	tsBuf[21]= pmt.es_info_length_video & 0x0FF;
                          	tsBuf[22]= pmt.stream_type_audio;
                          	tsBuf[23]= pmt.reserved_5_audio> 8 ) & 0x1F);
                          	tsBuf[24]= pmt.elementary_pid_audio & 0x00FF;
                          	tsBuf[25]= pmt.reserved_6_audio > 8) & 0x0F);
                          	tsBuf[26]= pmt.es_info_length_audio & 0x0FF;
                          	crc_32 = endian_convert(crc32_mpeg_2(&tsBuf[5], 26 - 5 + 1));
                          	memcpy(&tsBuf[27], (unsigned char  *)&crc_32, 4);
                          	/* 2.4 fix ts data: clear with "0xff" */
                          	memset(&tsBuf[31], 0xff, TS_PACKET_SIZE - 31);
                          	/* 3. write to file */
                          	fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          	return 0;
                          }
                          static int packPes2TsAndWriteToFile(T_PesEsStruct* ptPesStu,
                          											uint16_t pid,
                          											T_AdaptationField *adaptionField,
                          											uint64_t pts,
                          											FILE *fpTsFile)
                          {
                          	uint8_t tsBuf[TS_PACKET_SIZE] = {0};
                          	uint8_t tsBufPos = 0;
                          	uint8_t stuffingLen = 0;
                          	uint32_t firstPacketLoadLen = 0;
                          	if (!ptPesStu || !adaptionField || !fpTsFile)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* calcurate the first packet playload length */
                          	firstPacketLoadLen = TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE
                          						- adaptionField->adaptation_field_length
                          						- 1  /* sizeof adaptation_field_length */
                          						- 9  /* pes header(not contain pts/dts) */
                          						- 5; /* pts */
                          	if(ptPesStu->av_data_len av_data_len
                          						 - 1  /* sizeof adaptation_field_length */
                          						 - 9  /* pes header(not contain pts/dts) */
                          						 - 5; /* pts */
                          		/* 2.2 adaptation field: discontinuty_indicator ~ adaptation_field_extension_flag. (0x00: no optional fields) */
                          		tsBuf[tsBufPos + 1] = 0x00;
                          		tsBufPos += 2;
                          		/* 2.3 adaptation field: stuffing bytes */
                          		stuffingLen = TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE
                          						  - ptPesStu->av_data_len
                          						  - 2  /* adaptation_field_length ~ adaptation_field_extension_flag */
                          						  - 9  /* pes header(not contain pts/dts) */
                          						  - 5; /* pts */
                          		memset(tsBuf + tsBufPos, 0xff, stuffingLen);
                          		tsBufPos += stuffingLen;
                          		/* 3. payload */
                          		/* 3.1 payload: pes header. (not contain pts/dts) */
                          		tsBuf[tsBufPos + 0] = (ptPesStu->packet_start_code_prefix >> 16) & 0xff;
                          		tsBuf[tsBufPos + 1] = (ptPesStu->packet_start_code_prefix >> 8) & 0xff;
                          		tsBuf[tsBufPos + 2] = ptPesStu->packet_start_code_prefix & 0xff;
                          		tsBuf[tsBufPos + 3] = ptPesStu->stream_id;
                          		tsBuf[tsBufPos + 4] = (ptPesStu->pes_packet_length >> 8) & 0xff;
                          		tsBuf[tsBufPos + 5] = ptPesStu->pes_packet_length & 0xff;
                          		tsBuf[tsBufPos + 6] = ptPesStu->marker_bit pes_scrambling_control pes_priority data_alignment_indicator copyright original_or_copy;
                          		tsBuf[tsBufPos + 7] = ptPesStu->pts_dts_flags escr_flag es_rate_flag dsm_trick_mode_flag additional_copy_info_flag pes_crc_flag pes_extension_flag;
                          		tsBuf[tsBufPos + 8] = ptPesStu->pes_data_length;
                          		tsBufPos += 9;
                          		/* 3.2 payload: pts */
                          		tsBuf[tsBufPos + 0] = (((0x3 > 29) & 0x0E) | 0x01) & 0xff);
                          		tsBuf[tsBufPos + 1] = (((((pts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
                          		tsBuf[tsBufPos + 2] = ((((pts >> 14) & 0xfffe) | 0x01) & 0xff);
                          		tsBuf[tsBufPos + 3] = (((((pts > 8) & 0xff);
                          		tsBuf[tsBufPos + 4] = ((((pts av_data, ptPesStu->av_data_len);
                          		/* 4. write to file */
                          		fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          		return 0;
                          	}
                          	else
                          	{
                          		/* 1. ts header */
                          		generateTsHeaderData(pid, 0b1, 0b11, tsBuf); // 0b1: start, 0b11: adaption_field + playload.
                          		tsBufPos += TS_PACKET_HEADER_SIZE;
                          		/* 2. adaptation field */
                          		/* 2.1 adaptation field: adaptation field length */
                          		tsBuf[tsBufPos] = adaptionField->adaptation_field_length;
                          		tsBufPos += 1;
                          		/* 2.2 adaptation field: discontinuty_indicator ~ adaptation_field_extension_flag.
                          		 *     whether the pcr_flag is equal to 1 in this demo,
                          		 *     and "adaptionField->adaptation_field_length = 1 or 7"
                          		 */
                          		fixFirstPacketAdaptionField(adaptionField,
                          								    (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 1 - 9 - 5),
                          									&tsBuf[tsBufPos]);
                          		tsBufPos += adaptionField->adaptation_field_length;
                          		/* 3. payload*/
                          		/* 3.1 payload: pes header. (not contain pts/dts) */
                          		tsBuf[tsBufPos + 0] = (ptPesStu->packet_start_code_prefix >> 16) & 0xFF;
                          		tsBuf[tsBufPos + 1] = (ptPesStu->packet_start_code_prefix >> 8) & 0xFF;
                          		tsBuf[tsBufPos + 2] = ptPesStu->packet_start_code_prefix & 0xFF;
                          		tsBuf[tsBufPos + 3] = ptPesStu->stream_id;
                          		tsBuf[tsBufPos + 4] = ((ptPesStu->pes_packet_length) >> 8) & 0xFF;
                          		tsBuf[tsBufPos + 5] = (ptPesStu->pes_packet_length) & 0xFF;
                          		tsBuf[tsBufPos + 6] = ptPesStu->marker_bit pes_scrambling_control pes_priority data_alignment_indicator copyright original_or_copy;
                          		tsBuf[tsBufPos + 7] = ptPesStu->pts_dts_flags escr_flag es_rate_flag dsm_trick_mode_flag additional_copy_info_flag pes_crc_flag pes_extension_flag;
                          		tsBuf[tsBufPos + 8] = ptPesStu->pes_data_length;
                          		tsBufPos += 9;
                          		/* 3.2 payload: pts */
                          		tsBuf[tsBufPos + 0] = (((0x3 > 29) & 0x0E) | 0x01) & 0xff);
                          		tsBuf[tsBufPos + 1] = (((((pts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
                          		tsBuf[tsBufPos + 2] = ((((pts >> 14) & 0xfffe) | 0x01) & 0xff);
                          		tsBuf[tsBufPos + 3] = (((((pts > 8) & 0xff);
                          		tsBuf[tsBufPos + 4] = ((((pts av_data_cur_ptr = ptPesStu->av_data;
                          		memcpy(tsBuf + tsBufPos, ptPesStu->av_data_cur_ptr, firstPacketLoadLen);
                          		/* 4. write to file */
                          		fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          		/* >> change the pointer to pack remain es(Elementary Stream) data! av_data_cur_ptr += firstPacketLoadLen;
                          		ptPesStu->av_data_len     -= firstPacketLoadLen;
                          		/* >> pack remain es(Elementary Stream) data! av_data_len)
                          		{
                          			tsBufPos = 0;
                          			memset(tsBuf, 0, TS_PACKET_SIZE);
                          			if(ptPesStu->av_data_len >= (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE)) /* 184 */
                          			{
                          				generateTsHeaderData(pid, 0b0, 0b01, tsBuf); // 0b0: It isn't the start, 0b01: only playload.
                          				tsBufPos += TS_PACKET_HEADER_SIZE;
                          				memcpy(tsBuf + tsBufPos, ptPesStu->av_data_cur_ptr, (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE));
                          				fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          				/* >> change the pointer to pack remain es(Elementary Stream) data! av_data_cur_ptr += (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE);
                          				ptPesStu->av_data_len     -= (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE);
                          			}
                          			else if(ptPesStu->av_data_len == (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 1) ||\
                          					ptPesStu->av_data_len == (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 2)) /* 183 or 182 */
                          			{
                          				generateTsHeaderData(pid, 0b0, 0b11, tsBuf); // 0b0: It isn't the start, 0b11: adaption_field + playload.
                          				tsBufPos += TS_PACKET_HEADER_SIZE;
                          				tsBuf[tsBufPos + 0] = 0x01;
                          				tsBuf[tsBufPos + 1] = 0x00;
                          				tsBufPos += 2;
                          				memcpy(&tsBuf[tsBufPos], ptPesStu->av_data_cur_ptr, (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 2));
                          				fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          				/* >> change the pointer to pack remain es(Elementary Stream) data! av_data_cur_ptr += (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 2);
                          				ptPesStu->av_data_len     -= (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - 2);
                          			}
                          			else
                          			{
                          				generateTsHeaderData(pid, 0b0, 0b11, tsBuf); // 0b0: It isn't the start, 0b11: adaption_field + playload.
                          				tsBufPos += TS_PACKET_HEADER_SIZE;
                          				tsBuf[tsBufPos + 0] = TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - ptPesStu->av_data_len - 1;
                          				tsBuf[tsBufPos + 1] = 0x00;
                          				tsBufPos += 2;
                          				memset(&tsBuf[tsBufPos], 0xff, (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - ptPesStu->av_data_len - 2));
                          				tsBufPos += (TS_PACKET_SIZE - TS_PACKET_HEADER_SIZE - ptPesStu->av_data_len - 2);
                          				memcpy(&tsBuf[tsBufPos], ptPesStu->av_data_cur_ptr, ptPesStu->av_data_len);
                          				fwrite(tsBuf, 1, TS_PACKET_SIZE, fpTsFile);
                          				/* >>  es(Elementary Stream) data empty! av_data_len = 0;
                          			}
                          		}
                          	}
                          	return 0;
                          }
                          
                          int ts_mux_h264_aac(char *h264FileName, uint32_t vFps, char *aacFileName, char *tsFileName)
                          {
                          	int ret = -1;
                          	uint64_t timeStamp_us_a = 0;
                          	uint64_t timeStamp_us_v = 0;
                          	uint32_t videoFps = vFps;
                          	uint32_t audioSampleRate = -1;
                          	FILE *fpH264 = NULL;
                          	FILE *fpAAC  = NULL;
                          	FILE *fpTs  = NULL;
                          	uint8_t *h264Buf = NULL;
                          	uint8_t *aacBuf = NULL;
                          	T_AdtsHeader adtsHeader = {};
                          	T_NaluInfo naluInfo = {};
                          	T_PesEsStruct pesStu = {};
                          	T_AdaptationField adaptationField = {};
                          	if (!h264FileName || !videoFps || !aacFileName || !tsFileName)
                          	{
                          		printf("[%s:%d] Params invalid!\n", __FUNCTION__, __LINE__);
                          		return -1;
                          	}
                          	/* open file */
                          	fpH264 = fopen(h264FileName, "rb");
                          	if (!fpH264)
                          	{
                          		DEBUG("[%s:%d] open %s error!\n", __FUNCTION__, __LINE__, h264FileName);
                          		return -2;
                          	}
                          	fpAAC  = fopen(aacFileName,  "rb");
                          	if (!fpAAC)
                          	{
                          		DEBUG("[%s:%d] open %s error!\n", __FUNCTION__, __LINE__, aacFileName);
                          		return -3;
                          	}
                          	fpTs  = fopen(tsFileName,  "wb");
                          	if (!fpTs)
                          	{
                          		DEBUG("[%s:%d] open %s error!\n", __FUNCTION__, __LINE__, tsFileName);
                          		return -4;
                          	}
                          	/* alloc tmp memory */
                          	h264Buf = (uint8_t *)malloc(MAX_NALU_SIZE);
                          	if (!h264Buf)
                          	{
                          		DEBUG("[%s:%d] malloc error!\n", __FUNCTION__, __LINE__);
                          		return -5;
                          	}
                          	aacBuf = (uint8_t *)malloc(MAX_ADTS_SIZE);
                          	if (!aacBuf)
                          	{
                          		DEBUG("[%s:%d] malloc error!\n", __FUNCTION__, __LINE__);
                          		return -6;
                          	}
                          	/* parse AAC-ADTS */
                          	ret = getAdtsFrame(fpAAC, aacBuf, &adtsHeader);
                          	if(!ret)
                          	{
                          		fseek(fpAAC, 0, SEEK_SET); // reset
                          		switch(adtsHeader.sampling_freq_index)
                          		{
                          			case SFI_96000: audioSampleRate = 96000; break;
                          			case SFI_88200: audioSampleRate = 88200; break;
                          			case SFI_64000: audioSampleRate = 64000; break;
                          			case SFI_48000: audioSampleRate = 48000; break;
                          			case SFI_44100: audioSampleRate = 44100; break;
                          			case SFI_32000: audioSampleRate = 32000; break;
                          			case SFI_24000: audioSampleRate = 24000; break;
                          			case SFI_22050: audioSampleRate = 22050; break;
                          			case SFI_16000: audioSampleRate = 16000; break;
                          			case SFI_12000: audioSampleRate = 12000; break;
                          			case SFI_11025: audioSampleRate = 11025; break;
                          			case SFI_8000:  audioSampleRate =  8000; break;
                          			case SFI_7350:  audioSampleRate =  7350; break;
                          			default:        audioSampleRate =     0; break;
                          		}
                          		DEBUG("AAC Info:\n"
                          			  "\t id: %d\n"
                          			  "\t profile: %d\n"
                          			  "\t freq index: %d\n"
                          			  "\t sample rate: %d)\n"
                          			  "\t channels: %d\n",
                          			  adtsHeader.id, adtsHeader.profile,
                          			  adtsHeader.sampling_freq_index, audioSampleRate,
                          			  adtsHeader.channel_configuration);
                          	}
                          	#if 1 /* The PAT and PMT can show anywhere. */
                          	ret = packPat2TsAndWriteToFile(fpTs);
                          	if(ret  timeStamp_us_v)
                          		{
                          			ret = getOneH264Nalu(fpH264, h264Buf, &naluInfo);
                          			if (ret  
                          
                          main.c
                          #include 
                          #include "ts.h"
                          int main(int argc, char *argv[])
                          {
                          	if(argc == 1)
                          	{
                          		printf("Usage: \n"
                          			   "   %s avfile/test1_856x480_24fps.h264 24 avfile/test1_44100_stereo.aac out1.ts\n"
                          			   "   %s avfile/test2_720x480_30fps.h264 60 avfile/test2_48000_stereo.aac out2.ts\n"
                          			   "   %s avfile/test3_1280x720_20fps.h264 20 avfile/test1_44100_stereo.aac out3.ts\n",
                          			   argv[0], argv[0], argv[0]);
                          		return -1;
                          	}
                          	if(0 == ts_mux_h264_aac(argv[1], atoi(argv[2]), argv[3], argv[4]))
                          		printf("\033[32mMux ts file success!\033[0m \n");
                          	else
                          		printf("\033[31mMux ts file failed!\033[0m \n");
                          	return 0;
                          }
                          

                          3、demo下载地址(任选一个)

                          • https://download.csdn.net/download/weixin_44498318/89526734
                          • https://gitee.com/linriming/av_ts_mux_with_h264_aac.git
                          • https://github.com/linriming20/av_ts_mux_with_h264_aac.git
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]