H264码合成TS专用API

来源:互联网 发布:nslookup查询域名 编辑:程序博客网 时间:2024/06/13 15:11

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具体内容

     

[cpp] view plain copy
  1. void taransTs(TNAL* pNal)  
  2. {  
  3.     NALU_t * nalu=NULL;  
  4.     Ts_Adaptation_field  ts_adaptation_field_Head;  
  5.     Ts_Adaptation_field  ts_adaptation_field_Tail;  
  6.     unsigned long  Timestamp_video = 0;    //一帧视频所用时间  
  7.     unsigned long  Timestamp_audio = 0;    //一帧音频所用时间   
  8.     unsigned int framerate = 60;  
  9.     unsigned int   videoframetype = 0;    //视频帧类型  
  10.      //赋值s  
  11.     //分配nal 资源  
  12.     nalu = AllocNALU(MAX_VIDEO_TAG_BUF_SIZE);  
  13.     nalu->len = pNal->size;       //设置包含nal 头的数据长度      
  14.     memcpy(nalu->buf, pNal->data, pNal->size);//拷贝一个nal 数据到数组中  
  15.     nalu->forbidden_bit = nalu->buf[4] & 0x80;                     //1 bit  设置nal 头  
  16.     nalu->nal_reference_idc = nalu->buf[4] & 0x60;                 // 2 bit  
  17.     nalu->nal_unit_type = (nalu->buf[4]) & 0x1f;                   // 5 bit  
  18.     //判断帧类型  
  19.     GetFrameType(nalu);   
  20.     FreeNALU(nalu);  
  21.   
  22.     //获得数据值  
  23.     Take_Out_Pes(&m_video_tspes, Timestamp_video, 0x00, &videoframetype, pNal->size, pNal->data);  
  24.     if (nalu->Frametype == FRAME_I || nalu->Frametype == FRAME_P || nalu->Frametype == FRAME_B)  
  25.     {  
  26.         //填写自适应段标志  
  27.         printf("3PES_VIDEO  :  SIZE = %d\n", m_video_tspes.Pes_Packet_Length_Beyond);  
  28.         WriteAdaptive_flags_Head(&ts_adaptation_field_Head, Timestamp_video); //填写自适应段标志帧头  
  29.         WriteAdaptive_flags_Tail(&ts_adaptation_field_Tail); //填写自适应段标志帧尾  
  30.         //计算一帧视频所用时间  
  31.         m_video_tspes.Pes_Packet_Length_Beyond = pNal->size;  
  32.         PES2TS(&m_video_tspes, TS_H264_PID, &ts_adaptation_field_Head, &ts_adaptation_field_Tail, Timestamp_video, Timestamp_audio);  
  33.         Timestamp_video += 1000 * 90 / framerate;   //90khz  
  34.     }  
  35.     else  
  36.     {  
  37.           
  38.         //填写自适应段标志  
  39.         printf("3+++PES_VIDEO  :  SIZE = %d\n", m_video_tspes.Pes_Packet_Length_Beyond);  
  40.         WriteAdaptive_flags_Tail(&ts_adaptation_field_Head); //填写自适应段标志  ,这里注意 其它帧类型不要算pcr 所以都用帧尾代替就行  
  41.         WriteAdaptive_flags_Tail(&ts_adaptation_field_Tail); //填写自适应段标志帧尾  
  42.         m_video_tspes.Pes_Packet_Length_Beyond = pNal->size;//lzy  
  43.         PES2TS(&m_video_tspes, TS_H264_PID, &ts_adaptation_field_Head, &ts_adaptation_field_Tail, Timestamp_video, Timestamp_audio);//具体内容见下  
  44.   
  45.     }  
  46.   
  47. }  
   2)输出参数TNAL结构体    

[cpp] view plain copy
  1. struct DLL_EXPORT TNAL  
  2. {  
  3.     int size;  //264码nalu长度  
  4.     unsigned char* data;  //内容  
  5.     TNAL(): size(0), data(NULL) {}  
  6. };  
3)合成所用的主角函数--PES2TS函数

[cpp] view plain copy
  1. int PES2TS(TsPes * ts_pes, unsigned int Video_Audio_PID, Ts_Adaptation_field * ts_adaptation_field_Head, Ts_Adaptation_field * ts_adaptation_field_Tail,  
  2.     unsigned long  Videopts, unsigned long Adudiopts)  
  3. {  
  4.     TsPacketHeader ts_header;  
  5.     unsigned int ts_pos = 0;  
  6.     unsigned int FirstPacketLoadLength = 0;                                   //分片包的第一个包的负载长度  
  7.     unsigned int NeafPacketCount = 0;                                          //分片包的个数  
  8.     unsigned int AdaptiveLength = 0;                                           //要填写0XFF的长度  
  9.     unsigned char * NeafBuf = NULL;                                            //分片包 总负载的指针  
  10.     unsigned char TSbuf[TS_PACKET_SIZE];  
  11.   
  12.     memset(TSbuf, 0, TS_PACKET_SIZE);  
  13.     FirstPacketLoadLength = 188 - 4 - 1 - ts_adaptation_field_Head->adaptation_field_length - 14; //计算分片包的第一个包的负载长度  
  14.     NeafPacketCount += 1;                                                                   //第一个分片包    
  15.   
  16.     //一个包的情况  
  17.     //  printf("Pes_Packet_Length_Beyond=%d,FirstPacketLoadLength=%d\n", ts_pes->Pes_Packet_Length_Beyond, FirstPacketLoadLength);  
  18.   
  19.     if (ts_pes->Pes_Packet_Length_Beyond < FirstPacketLoadLength)                           //这里是 sps ,pps ,sei等  
  20.         // if (lens < FirstPacketLoadLength)                           //这里是 sps ,pps ,sei等 lzy  
  21.     {  
  22.         memset(TSbuf, 0xFF, TS_PACKET_SIZE);  
  23.         WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x01, 0x03);                          //PID = TS_H264_PID,有效荷载单元起始指示符_play_init = 0x01, ada_field_C,0x03,含有调整字段和有效负载 ;  
  24.         ts_pos += 4;  
  25.         TSbuf[ts_pos + 0] = 184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 1;  
  26.         TSbuf[ts_pos + 1] = 0x00;  
  27.         ts_pos += 2;  
  28.         memset(TSbuf + ts_pos, 0xFF, (184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 2));  
  29.         ts_pos += (184 - ts_pes->Pes_Packet_Length_Beyond - 9 - 5 - 2);  
  30.   
  31.         TSbuf[ts_pos + 0] = (ts_pes->packet_start_code_prefix >> 16) & 0xFF;  
  32.         TSbuf[ts_pos + 1] = (ts_pes->packet_start_code_prefix >> 8) & 0xFF;  
  33.         TSbuf[ts_pos + 2] = ts_pes->packet_start_code_prefix & 0xFF;  
  34.         TSbuf[ts_pos + 3] = ts_pes->stream_id;  
  35.         TSbuf[ts_pos + 4] = ((ts_pes->PES_packet_length) >> 8) & 0xFF;  
  36.         TSbuf[ts_pos + 5] = (ts_pes->PES_packet_length) & 0xFF;  
  37.         TSbuf[ts_pos + 6] = ts_pes->marker_bit << 6 | ts_pes->PES_scrambling_control << 4 | ts_pes->PES_priority << 3 |  
  38.             ts_pes->data_alignment_indicator << 2 | ts_pes->copyright << 1 | ts_pes->original_or_copy;  
  39.         TSbuf[ts_pos + 7] = ts_pes->PTS_DTS_flags << 6 | ts_pes->ESCR_flag << 5 | ts_pes->ES_rate_flag << 4 |  
  40.             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;  
  41.         TSbuf[ts_pos + 8] = ts_pes->PES_header_data_length;  
  42.         ts_pos += 9;  
  43.   
  44.         if (ts_pes->stream_id == TS_H264_STREAM_ID)  
  45.         {  
  46.             TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Videopts >> 29) & 0x0E) | 0x01) & 0xff);  
  47.             TSbuf[ts_pos + 1] = (((((Videopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);  
  48.             TSbuf[ts_pos + 2] = ((((Videopts >> 14) & 0xfffe) | 0x01) & 0xff);  
  49.             TSbuf[ts_pos + 3] = (((((Videopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);  
  50.             TSbuf[ts_pos + 4] = ((((Videopts << 1) & 0xfffe) | 0x01) & 0xff);  
  51.             ts_pos += 5;  
  52.   
  53.         }  
  54.         else if (ts_pes->stream_id == TS_AAC_STREAM_ID)  
  55.         {  
  56.             TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Adudiopts >> 29) & 0x0E) | 0x01) & 0xff);  
  57.             TSbuf[ts_pos + 1] = (((((Adudiopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);  
  58.             TSbuf[ts_pos + 2] = ((((Adudiopts >> 14) & 0xfffe) | 0x01) & 0xff);  
  59.             TSbuf[ts_pos + 3] = (((((Adudiopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);  
  60.             TSbuf[ts_pos + 4] = ((((Adudiopts << 1) & 0xfffe) | 0x01) & 0xff);  
  61.             ts_pos += 5;  
  62.         }  
  63.         else  
  64.         {  
  65.             printf("ts_pes->stream_id  error 0x%x \n", ts_pes->stream_id);  
  66.             return getchar();  
  67.         }  
  68.         memcpy(TSbuf + ts_pos, ts_pes->Es, ts_pes->Pes_Packet_Length_Beyond);  
  69.   
  70.         //将包写入文件  
  71.         fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);                               //将一包数据写入文件  
  72.         memcpy(fTo, TSbuf, 188);  
  73.   
  74.   
  75.         WritePacketNum++;                                                      //已经写入文件的包个数++  
  76.         return WritePacketNum;  
  77.     }  
  78.   
  79.     NeafPacketCount += (ts_pes->Pes_Packet_Length_Beyond - FirstPacketLoadLength) / 184;  
  80.     NeafPacketCount += 1;                                                                   //最后一个分片包  
  81.     AdaptiveLength = 188 - 4 - 1 - ((ts_pes->Pes_Packet_Length_Beyond - FirstPacketLoadLength) % 184);  //要填写0XFF的长度  
  82.     if ((WritePacketNum % 40) == 0)                                                         //每40个包打一个 pat,一个pmt  
  83.     {  
  84.         Write_Pat(m_One_Frame_Buf);                                                         //创建PAT,具体内容见下  
  85.         Write_Pmt(m_One_Frame_Buf);                                                         //创建PMT,具体内容见下  
  86.     }  
  87.     //开始处理第一个包,分片包的个数最少也会是两个   
  88.     WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x01, 0x03);                              //PID = TS_H264_PID,有效荷载单元起始指示符_play_init = 0x01, ada_field_C,0x03,含有调整字段和有效负载 ;  
  89.     ts_pos += 4;  
  90.     TSbuf[ts_pos] = ts_adaptation_field_Head->adaptation_field_length;                      //自适应字段的长度,自己填写的  
  91.     ts_pos += 1;  
  92.   
  93.     CreateAdaptive_Ts(ts_adaptation_field_Head, TSbuf + ts_pos, (188 - 4 - 1 - 14));          //填写自适应字段  
  94.     ts_pos += ts_adaptation_field_Head->adaptation_field_length;                            //填写自适应段所需要的长度  
  95.   
  96.     TSbuf[ts_pos + 0] = (ts_pes->packet_start_code_prefix >> 16) & 0xFF;  
  97.     TSbuf[ts_pos + 1] = (ts_pes->packet_start_code_prefix >> 8) & 0xFF;  
  98.     TSbuf[ts_pos + 2] = ts_pes->packet_start_code_prefix & 0xFF;  
  99.     TSbuf[ts_pos + 3] = ts_pes->stream_id;  
  100.     TSbuf[ts_pos + 4] = ((ts_pes->PES_packet_length) >> 8) & 0xFF;  
  101.     TSbuf[ts_pos + 5] = (ts_pes->PES_packet_length) & 0xFF;  
  102.     TSbuf[ts_pos + 6] = ts_pes->marker_bit << 6 | ts_pes->PES_scrambling_control << 4 | ts_pes->PES_priority << 3 |  
  103.         ts_pes->data_alignment_indicator << 2 | ts_pes->copyright << 1 | ts_pes->original_or_copy;  
  104.     TSbuf[ts_pos + 7] = ts_pes->PTS_DTS_flags << 6 | ts_pes->ESCR_flag << 5 | ts_pes->ES_rate_flag << 4 |  
  105.         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;  
  106.     TSbuf[ts_pos + 8] = ts_pes->PES_header_data_length;  
  107.     ts_pos += 9;  
  108.   
  109.     if (ts_pes->stream_id == TS_H264_STREAM_ID)  
  110.     {  
  111.         TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Videopts >> 29) & 0x0E) | 0x01) & 0xff);  
  112.         TSbuf[ts_pos + 1] = (((((Videopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);  
  113.         TSbuf[ts_pos + 2] = ((((Videopts >> 14) & 0xfffe) | 0x01) & 0xff);  
  114.         TSbuf[ts_pos + 3] = (((((Videopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);  
  115.         TSbuf[ts_pos + 4] = ((((Videopts << 1) & 0xfffe) | 0x01) & 0xff);  
  116.         ts_pos += 5;  
  117.   
  118.     }  
  119.     else if (ts_pes->stream_id == TS_AAC_STREAM_ID)  
  120.     {  
  121.         TSbuf[ts_pos + 0] = (((0x3 << 4) | ((Adudiopts >> 29) & 0x0E) | 0x01) & 0xff);  
  122.         TSbuf[ts_pos + 1] = (((((Adudiopts >> 14) & 0xfffe) | 0x01) >> 8) & 0xff);  
  123.         TSbuf[ts_pos + 2] = ((((Adudiopts >> 14) & 0xfffe) | 0x01) & 0xff);  
  124.         TSbuf[ts_pos + 3] = (((((Adudiopts << 1) & 0xfffe) | 0x01) >> 8) & 0xff);  
  125.         TSbuf[ts_pos + 4] = ((((Adudiopts << 1) & 0xfffe) | 0x01) & 0xff);  
  126.         ts_pos += 5;  
  127.     }  
  128.     else  
  129.     {  
  130.         printf("ts_pes->stream_id  error 0x%x \n", ts_pes->stream_id);  
  131.         return getchar();  
  132.     }  
  133.   
  134.     NeafBuf = ts_pes->Es;  
  135.   
  136.   
  137.   
  138.     memcpy(TSbuf + ts_pos, NeafBuf, FirstPacketLoadLength);  
  139.   
  140.     NeafBuf += FirstPacketLoadLength;  
  141.     ts_pes->Pes_Packet_Length_Beyond -= FirstPacketLoadLength;  
  142.     //将包写入文件  
  143.     fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);                               //将一包数据写入文件  lzy  
  144.     memcpy(fTo,TSbuf,188);  
  145.   
  146.   
  147.     WritePacketNum++;                                                      //已经写入文件的包个数++  
  148.   
  149.     while (ts_pes->Pes_Packet_Length_Beyond)  
  150.     {  
  151.         ts_pos = 0;  
  152.         memset(TSbuf, 0, TS_PACKET_SIZE);  
  153.   
  154.         if ((WritePacketNum % 40) == 0)                                                         //每40个包打一个 pat,一个pmt  
  155.         {  
  156.             Write_Pat(m_One_Frame_Buf);                                                         //创建PAT  
  157.             Write_Pmt(m_One_Frame_Buf);                                                         //创建PMT  
  158.         }  
  159.         if (ts_pes->Pes_Packet_Length_Beyond >= 184)  
  160.         {  
  161.             //处理中间包     
  162.             WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x01);     //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x01,仅有有效负载;      
  163.             ts_pos += 4;  
  164.             memcpy(TSbuf + ts_pos, NeafBuf, 184);  
  165.             NeafBuf += 184;  
  166.             ts_pes->Pes_Packet_Length_Beyond -= 184;  
  167.             fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);  
  168.             memcpy(fTo, TSbuf, 188);  
  169.         }  
  170.         else  
  171.         {  
  172.             if (ts_pes->Pes_Packet_Length_Beyond == 183 || ts_pes->Pes_Packet_Length_Beyond == 182)  
  173.             {  
  174.                 if ((WritePacketNum % 40) == 0)                                                         //每40个包打一个 pat,一个pmt  
  175.                 {  
  176.                     Write_Pat(m_One_Frame_Buf);                                                         //创建PAT  
  177.                     Write_Pmt(m_One_Frame_Buf);                                                         //创建PMT  
  178.                 }  
  179.   
  180.                 WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x03);   //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x03,含有调整字段和有效负载;  
  181.                 ts_pos += 4;  
  182.                 TSbuf[ts_pos + 0] = 0x01;  
  183.                 TSbuf[ts_pos + 1] = 0x00;  
  184.                 ts_pos += 2;  
  185.                 memcpy(TSbuf + ts_pos, NeafBuf, 182);  
  186.   
  187.                 NeafBuf += 182;  
  188.                 ts_pes->Pes_Packet_Length_Beyond -= 182;  
  189.                 fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);  
  190.                 memcpy(fTo, TSbuf, 188);  
  191.               
  192.             }  
  193.             else  
  194.             {  
  195.                 if ((WritePacketNum % 40) == 0)                                                         //每40个包打一个 pat,一个pmt  
  196.                 {  
  197.                     Write_Pat(m_One_Frame_Buf);                                                         //创建PAT  
  198.                     Write_Pmt(m_One_Frame_Buf);                                                         //创建PMT  
  199.                 }  
  200.   
  201.                 WriteStruct_Packetheader(TSbuf, Video_Audio_PID, 0x00, 0x03);  //PID = TS_H264_PID,不是有效荷载单元起始指示符_play_init = 0x00, ada_field_C,0x03,含有调整字段和有效负载;  
  202.                 ts_pos += 4;  
  203.                 TSbuf[ts_pos + 0] = 184 - ts_pes->Pes_Packet_Length_Beyond - 1;  
  204.                 TSbuf[ts_pos + 1] = 0x00;  
  205.                 ts_pos += 2;  
  206.                 memset(TSbuf + ts_pos, 0xFF, (184 - ts_pes->Pes_Packet_Length_Beyond - 2));  
  207.                 ts_pos += (184 - ts_pes->Pes_Packet_Length_Beyond - 2);  
  208.                 memcpy(TSbuf + ts_pos, NeafBuf, ts_pes->Pes_Packet_Length_Beyond);  
  209.                 ts_pes->Pes_Packet_Length_Beyond = 0;  
  210.                 fwrite(TSbuf, 188, 1, pVideo_Audio_Ts_File);   //将一包数据写入文件  
  211.                 memcpy(fTo, TSbuf, 188);  
  212.   
  213.                 WritePacketNum++;  
  214.             }  
  215.         }  
  216.         WritePacketNum++;  
  217.     }  
  218.     printf("\nWritePacketNum=%d\n", WritePacketNum);  
  219.     return WritePacketNum;  
  220. }  
注:该函数中,合成的TS流都放置在TSbuf中。


4)写PAT函数---Write_Pat、Write_Pmt函数

[cpp] view plain copy
  1. int Write_Pat(unsigned char * buf)  
  2. {  
  3.     WriteStruct_Pat(buf);  
  4.     memcpy(fTo, (char *)buf,188);  
  5.     printf("pmt++++");  
  6.     return WriteFile(pVideo_Audio_Ts_File, (char *)buf, TS_PACKET_SIZE);  
  7.       
  8. }  
[cpp] view plain copy
  1. <pre name="code" class="cpp">int Write_Pmt(unsigned char * buf)  
  2. {  
  3.     WriteStruct_Pmt(buf);  
  4.     memcpy(fTo, (char *)buf, 188);  
  5.     return WriteFile(pVideo_Audio_Ts_File, (char *)buf, TS_PACKET_SIZE);  
  6.   
  7. }  


以上为该API中重要函数,但是由于该API在tstool基础上改编而来,自然少不了要加上TSTOOL库文件。

库文件我已经打包,下载地址为:http://download.csdn.NET/detail/xiahua882/9636902。

最后,上一张我在VS2013工程中引用图





 

0
 
0




原创粉丝点击