http://blog.csdn.net/xiahua882/article/details/52622402
版权声明:本文为博主原创文章,未经博主允许不得转载。
为方便264码转换为TS码,针对TSTOOL源码进行分析修改,做成函数接口,供方便调用。目前该接口在VS2013工程环境已经测试通过,不废话,直接上货。
1.函数API------- void taransTs(TNAL* pNal)
输入参数:TNAL* pNal----264码流帧nalu;TNAL结构见下
返回: 无
注:生成的ts码流数据在该函数中,用户可根据自己需要决定是否修改
2.相关函数结构
1)API函数taransTs具体内容
- void taransTs(TNAL* pNal)
- {
- NALU_t * nalu=NULL;
- Ts_Adaptation_field ts_adaptation_field_Head;
- Ts_Adaptation_field ts_adaptation_field_Tail;
- unsigned long Timestamp_video = 0; //一帧视频所用时间
- unsigned long Timestamp_audio = 0; //一帧音频所用时间
- unsigned int framerate = 60;
- unsigned int videoframetype = 0; //视频帧类型
- //赋值s
- //分配nal 资源
- nalu = AllocNALU(MAX_VIDEO_TAG_BUF_SIZE);
- nalu->len = pNal->size; //设置包含nal 头的数据长度
- memcpy(nalu->buf, pNal->data, pNal->size);//拷贝一个nal 数据到数组中
- nalu->forbidden_bit = nalu->buf[4] & 0x80; //1 bit 设置nal 头
- nalu->nal_reference_idc = nalu->buf[4] & 0x60; // 2 bit
- nalu->nal_unit_type = (nalu->buf[4]) & 0x1f; // 5 bit
- //判断帧类型
- GetFrameType(nalu);
- FreeNALU(nalu);
- //获得数据值
- Take_Out_Pes(&m_video_tspes, Timestamp_video, 0x00, &videoframetype, pNal->size, pNal->data);
- if (nalu->Frametype == FRAME_I || nalu->Frametype == FRAME_P || nalu->Frametype == FRAME_B)
- {
- //填写自适应段标志
- printf("3PES_VIDEO : SIZE = %d\n", m_video_tspes.Pes_Packet_Length_Beyond);
- WriteAdaptive_flags_Head(&ts_adaptation_field_Head, Timestamp_video); //填写自适应段标志帧头
- WriteAdaptive_flags_Tail(&ts_adaptation_field_Tail); //填写自适应段标志帧尾
- //计算一帧视频所用时间
- m_video_tspes.Pes_Packet_Length_Beyond = pNal->size;
- PES2TS(&m_video_tspes, TS_H264_PID, &ts_adaptation_field_Head, &ts_adaptation_field_Tail, Timestamp_video, Timestamp_audio);
- Timestamp_video += 1000 * 90 / framerate; //90khz
- }
- else
- {
- //填写自适应段标志
- printf("3+++PES_VIDEO : SIZE = %d\n", m_video_tspes.Pes_Packet_Length_Beyond);
- WriteAdaptive_flags_Tail(&ts_adaptation_field_Head); //填写自适应段标志 ,这里注意 其它帧类型不要算pcr 所以都用帧尾代替就行
- WriteAdaptive_flags_Tail(&ts_adaptation_field_Tail); //填写自适应段标志帧尾
- m_video_tspes.Pes_Packet_Length_Beyond = pNal->size;//lzy
- PES2TS(&m_video_tspes, TS_H264_PID, &ts_adaptation_field_Head, &ts_adaptation_field_Tail, Timestamp_video, Timestamp_audio);//具体内容见下
- }
- }
- struct DLL_EXPORT TNAL
- {
- int size; //264码nalu长度
- unsigned char* data; //内容
- TNAL(): size(0), data(NULL) {}
- };
- int PES2TS(TsPes * ts_pes, unsigned int Video_Audio_PID, Ts_Adaptation_field * ts_adaptation_field_Head, Ts_Adaptation_field * ts_adaptation_field_Tail,
- unsigned long Videopts, unsigned long Adudiopts)
- {
- TsPacketHeader ts_header;
- unsigned int ts_pos = 0;
- unsigned int FirstPacketLoadLength = 0; //分片包的第一个包的负载长度
- unsigned int NeafPacketCount = 0; //分片包的个数
- unsigned int AdaptiveLength = 0; //要填写0XFF的长度
- unsigned char * NeafBuf = NULL; //分片包 总负载的指针
- unsigned char TSbuf[TS_PACKET_SIZE];
- memset(TSbuf, 0, TS_PACKET_SIZE);
- FirstPacketLoadLength = 188 - 4 - 1 - ts_adaptation_field_Head->adaptation_field_length - 14; //计算分片包的第一个包的负载长度
- NeafPacketCount += 1; //第一个分片包
- //一个包的情况
- // printf("Pes_Packet_Length_Beyond=%d,FirstPacketLoadLength=%d\n", ts_pes->Pes_Packet_Length_Beyond, FirstPacketLoadLength);
- if (ts_pes->Pes_Packet_Length_Beyond < FirstPacketLoadLength) //这里是 sps ,pps ,sei等
- // if (lens < FirstPacketLoadLength) //这里是 sps ,pps ,sei等 lzy
- {
- memset(TSbuf, 0xFF, TS_PACKET_SIZE);
- WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x01, 0x03); //PID = TS_H264_PID,有效荷载单元起始指示符_play_init = 0x01, ada_field_C,0x03,含有调整字段和有效负载 ;
- ts_pos += 4;
- TSbuf[ts_pos + 0] = 184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 1;
- TSbuf[ts_pos + 1] = 0x00;
- ts_pos += 2;
- memset(TSbuf + ts_pos, 0xFF, (184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 2));
- ts_pos += (184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 2);
- TSbuf[ts_pos + 0] = (ts_pes->packet_start_code_prefix >> 16) & 0xFF;
- TSbuf[ts_pos + 1] = (ts_pes->packet_start_code_prefix >> 8) & 0xFF;
- TSbuf[ts_pos + 2] = ts_pes->packet_start_code_prefix & 0xFF;
- TSbuf[ts_pos + 3] = ts_pes->stream_id;
- TSbuf[ts_pos + 4] = ((ts_pes->PES_packet_length) >> 8) & 0xFF;
- TSbuf[ts_pos + 5] = (ts_pes->PES_packet_length) & 0xFF;
- TSbuf[ts_pos + 6] = ts_pes->marker_bit << 6 | ts_pes->PES_scrambling_control << 4 | ts_pes->PES_priority << 3 |
- ts_pes->data_alignment_indicator << 2 | ts_pes->copyright << 1 | ts_pes->original_or_copy;
- TSbuf[ts_pos + 7] = ts_pes->PTS_DTS_flags << 6 | ts_pes->ESCR_flag << 5 | ts_pes->ES_rate_flag << 4 |
- ts_pes->DSM_trick_mode_flag << 3 | ts_pes->additional_copy_info_flag << 2 | ts_pes->PES_CRC_flag << 1 | ts_pes->PES_extension_flag;
- TSbuf[ts_pos + 8] = ts_pes->PES_header_data_length;
- ts_pos += 9;
- if (ts_pes->stream_id == TS_H264_STREAM_ID)
- {
- TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Videopts >> 29) & 0x0E) | 0x01) & 0xff);
- TSbuf[ts_pos + 1] = (((((Videopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 2] = ((((Videopts >> 14) & 0xfffe) | 0x01) & 0xff);
- TSbuf[ts_pos + 3] = (((((Videopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 4] = ((((Videopts << 1) & 0xfffe) | 0x01) & 0xff);
- ts_pos += 5;
- }
- else if (ts_pes->stream_id == TS_AAC_STREAM_ID)
- {
- TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Adudiopts >> 29) & 0x0E) | 0x01) & 0xff);
- TSbuf[ts_pos + 1] = (((((Adudiopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 2] = ((((Adudiopts >> 14) & 0xfffe) | 0x01) & 0xff);
- TSbuf[ts_pos + 3] = (((((Adudiopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 4] = ((((Adudiopts << 1) & 0xfffe) | 0x01) & 0xff);
- ts_pos += 5;
- }
- else
- {
- printf("ts_pes->stream_id error 0x%x \n", ts_pes->stream_id);
- return getchar();
- }
- memcpy(TSbuf + ts_pos, ts_pes->Es, ts_pes->Pes_Packet_Length_Beyond);
- //将包写入文件
- fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File); //将一包数据写入文件
- memcpy(fTo, TSbuf, 188);
- WritePacketNum++; //已经写入文件的包个数++
- return WritePacketNum;
- }
- NeafPacketCount += (ts_pes->Pes_Packet_Length_Beyond - FirstPacketLoadLength) / 184;
- NeafPacketCount += 1; //最后一个分片包
- AdaptiveLength = 188 - 4 - 1 - ((ts_pes->Pes_Packet_Length_Beyond - FirstPacketLoadLength) % 184); //要填写0XFF的长度
- if ((WritePacketNum % 40) == 0) //每40个包打一个 pat,一个pmt
- {
- Write_Pat(m_One_Frame_Buf); //创建PAT,具体内容见下
- Write_Pmt(m_One_Frame_Buf); //创建PMT,具体内容见下
- }
- //开始处理第一个包,分片包的个数最少也会是两个
- WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x01, 0x03); //PID = TS_H264_PID,有效荷载单元起始指示符_play_init = 0x01, ada_field_C,0x03,含有调整字段和有效负载 ;
- ts_pos += 4;
- TSbuf[ts_pos] = ts_adaptation_field_Head->adaptation_field_length; //自适应字段的长度,自己填写的
- ts_pos += 1;
- CreateAdaptive_Ts(ts_adaptation_field_Head, TSbuf + ts_pos, (188 - 4 - 1 - 14)); //填写自适应字段
- ts_pos += ts_adaptation_field_Head->adaptation_field_length; //填写自适应段所需要的长度
- TSbuf[ts_pos + 0] = (ts_pes->packet_start_code_prefix >> 16) & 0xFF;
- TSbuf[ts_pos + 1] = (ts_pes->packet_start_code_prefix >> 8) & 0xFF;
- TSbuf[ts_pos + 2] = ts_pes->packet_start_code_prefix & 0xFF;
- TSbuf[ts_pos + 3] = ts_pes->stream_id;
- TSbuf[ts_pos + 4] = ((ts_pes->PES_packet_length) >> 8) & 0xFF;
- TSbuf[ts_pos + 5] = (ts_pes->PES_packet_length) & 0xFF;
- TSbuf[ts_pos + 6] = ts_pes->marker_bit << 6 | ts_pes->PES_scrambling_control << 4 | ts_pes->PES_priority << 3 |
- ts_pes->data_alignment_indicator << 2 | ts_pes->copyright << 1 | ts_pes->original_or_copy;
- TSbuf[ts_pos + 7] = ts_pes->PTS_DTS_flags << 6 | ts_pes->ESCR_flag << 5 | ts_pes->ES_rate_flag << 4 |
- ts_pes->DSM_trick_mode_flag << 3 | ts_pes->additional_copy_info_flag << 2 | ts_pes->PES_CRC_flag << 1 | ts_pes->PES_extension_flag;
- TSbuf[ts_pos + 8] = ts_pes->PES_header_data_length;
- ts_pos += 9;
- if (ts_pes->stream_id == TS_H264_STREAM_ID)
- {
- TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Videopts >> 29) & 0x0E) | 0x01) & 0xff);
- TSbuf[ts_pos + 1] = (((((Videopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 2] = ((((Videopts >> 14) & 0xfffe) | 0x01) & 0xff);
- TSbuf[ts_pos + 3] = (((((Videopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 4] = ((((Videopts << 1) & 0xfffe) | 0x01) & 0xff);
- ts_pos += 5;
- }
- else if (ts_pes->stream_id == TS_AAC_STREAM_ID)
- {
- TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Adudiopts >> 29) & 0x0E) | 0x01) & 0xff);
- TSbuf[ts_pos + 1] = (((((Adudiopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 2] = ((((Adudiopts >> 14) & 0xfffe) | 0x01) & 0xff);
- TSbuf[ts_pos + 3] = (((((Adudiopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);
- TSbuf[ts_pos + 4] = ((((Adudiopts << 1) & 0xfffe) | 0x01) & 0xff);
- ts_pos += 5;
- }
- else
- {
- printf("ts_pes->stream_id error 0x%x \n", ts_pes->stream_id);
- return getchar();
- }
- NeafBuf = ts_pes->Es;
- memcpy(TSbuf + ts_pos, NeafBuf, FirstPacketLoadLength);
- NeafBuf += FirstPacketLoadLength;
- ts_pes->Pes_Packet_Length_Beyond -= FirstPacketLoadLength;
- //将包写入文件
- fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File); //将一包数据写入文件 lzy
- memcpy(fTo,TSbuf,188);
- WritePacketNum++; //已经写入文件的包个数++
- while (ts_pes->Pes_Packet_Length_Beyond)
- {
- ts_pos = 0;
- memset(TSbuf, 0, TS_PACKET_SIZE);
- if ((WritePacketNum % 40) == 0) //每40个包打一个 pat,一个pmt
- {
- Write_Pat(m_One_Frame_Buf); //创建PAT
- Write_Pmt(m_One_Frame_Buf); //创建PMT
- }
- if (ts_pes->Pes_Packet_Length_Beyond >= 184)
- {
- //处理中间包
- WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x01); //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x01,仅有有效负载;
- ts_pos += 4;
- memcpy(TSbuf + ts_pos, NeafBuf, 184);
- NeafBuf += 184;
- ts_pes->Pes_Packet_Length_Beyond -= 184;
- fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);
- memcpy(fTo, TSbuf, 188);
- }
- else
- {
- if (ts_pes->Pes_Packet_Length_Beyond == 183 || ts_pes->Pes_Packet_Length_Beyond == 182)
- {
- if ((WritePacketNum % 40) == 0) //每40个包打一个 pat,一个pmt
- {
- Write_Pat(m_One_Frame_Buf); //创建PAT
- Write_Pmt(m_One_Frame_Buf); //创建PMT
- }
- WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x03); //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x03,含有调整字段和有效负载;
- ts_pos += 4;
- TSbuf[ts_pos + 0] = 0x01;
- TSbuf[ts_pos + 1] = 0x00;
- ts_pos += 2;
- memcpy(TSbuf + ts_pos, NeafBuf, 182);
- NeafBuf += 182;
- ts_pes->Pes_Packet_Length_Beyond -= 182;
- fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);
- memcpy(fTo, TSbuf, 188);
- }
- else
- {
- if ((WritePacketNum % 40) == 0) //每40个包打一个 pat,一个pmt
- {
- Write_Pat(m_One_Frame_Buf); //创建PAT
- Write_Pmt(m_One_Frame_Buf); //创建PMT
- }
- WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x03); //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x03,含有调整字段和有效负载;
- ts_pos += 4;
- TSbuf[ts_pos + 0] = 184 - ts_pes->Pes_Packet_Length_Beyond - 1;
- TSbuf[ts_pos + 1] = 0x00;
- ts_pos += 2;
- memset(TSbuf + ts_pos, 0xFF, (184 - ts_pes->Pes_Packet_Length_Beyond - 2));
- ts_pos += (184 - ts_pes->Pes_Packet_Length_Beyond - 2);
- memcpy(TSbuf + ts_pos, NeafBuf, ts_pes->Pes_Packet_Length_Beyond);
- ts_pes->Pes_Packet_Length_Beyond = 0;
- fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File); //将一包数据写入文件
- memcpy(fTo, TSbuf, 188);
- WritePacketNum++;
- }
- }
- WritePacketNum++;
- }
- printf("\nWritePacketNum=%d\n", WritePacketNum);
- return WritePacketNum;
- }
4)写PAT函数---Write_Pat、Write_Pmt函数
- int Write_Pat(unsigned char * buf)
- {
- WriteStruct_Pat(buf);
- memcpy(fTo, (char *)buf,188);
- printf("pmt++++");
- return WriteFile(pVideo_Audio_Ts_File, (char *)buf, TS_PACKET_SIZE);
- }
- <pre name="code" class="cpp">int Write_Pmt(unsigned char * buf)
- {
- WriteStruct_Pmt(buf);
- memcpy(fTo, (char *)buf, 188);
- return WriteFile(pVideo_Audio_Ts_File, (char *)buf, TS_PACKET_SIZE);
- }
以上为该API中重要函数,但是由于该API在tstool基础上改编而来,自然少不了要加上TSTOOL库文件。
库文件我已经打包,下载地址为:http://download.csdn.NET/detail/xiahua882/9636902。
最后,上一张我在VS2013工程中引用图
-
顶
- 0
-
踩
- 0