ffmpeg解析TS流(转)

MPEG的系统层编码为不同的应用场景设计了两种格式: 
TS(Transport Stream) 和PS(Program Stream),
它们两者之间不具有层级关系,
在逻辑上,它们两者都是由PES(Packetized Elementary Stream)包组成的,
所以可以很方便地实现相互转换.
 
TS(Transport Stream): 
  是将具有一个或多个独立时间基的一个或多个节目(包括音频和视频)组成一个流,
  组成同一个节目的基本流(如一个视频流,多个音频流)的PES包有一个共用的时间基。
  TS的包长标准为188bytes.
 
从上面的定义可以分成三层来看TS/PS。
ES层   : 由单独的音频(如mp3),视频流(如h.264)组成基本的ES(Elementary Stream)。
PES层  : 将基本的ES按一定的规则(如H.264以AU)进行封装,并打上时间戳,组成PES。
TS/PS层: 将PES包进行切分后再封装成188bytes大小的TS包,
         同时还将一些节目信息也封装成TS包(称为section), 两者共同组成TS层。
 
从上面的总结,TS/PS总体上来说,是一种封装格式,用来承载数据。
所以FFmpeg
将TS/PS的解析文件定义在libavformat/mpegts.c文件中
将音频,视频的解码定义在libavcodec/mpeg12.c文件中
 
下面来看FFmpeg是如何进行TS的demuxer的。
1. MPEG2-TS的demuxer函数
  1. AVInputFormat ff_mpegts_demuxer = { 
  2.     "mpegts", 
  3.     NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"),
  4.     sizeof(MpegTSContext),
  5.     mpegts_probe,
  6.     mpegts_read_header,
  7.     mpegts_read_packet, 
  8.     mpegts_read_close, 
  9.     read_seek,
  10.     mpegts_get_pcr,
  11.     .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, 
  12. #ifdef USE_SYNCPOINT_SEARCH 
  13.     .read_seek2 = read_seek2, 
  14. #endif 
  15. };
 
2. 解析流中的TS格式

 

  1. /*
  2.  * 出现3种格式,主要原因是:
  3.  * TS标准是 188Bytes;
  4.  * 日本标准是192Bytes的DVH-S格式;
  5.  * 第三种的 204Bytes则是在188Bytes的基础上,加上16Bytes的FEC(前向纠错).
  6.  */
  7. #define TS_PACKET_SIZE 188
  8. #define TS_DVHS_PACKET_SIZE 192
  9. #define TS_FEC_PACKET_SIZE 204
  10. #define TS_MAX_PACKET_SIZE 204
  11. //< maximum score, half of that is used for file-extension-based detection
  12. #define AVPROBE_SCORE_MAX 100
 

  1. /*
  2.  * 函数功能:
  3.  * 分析流中是三种TS格式的哪一种
  4.  */
  5. static int mpegts_probe(AVProbeData *p)
  6. {
  7. #define CHECK_COUNT 10
  8.   const int size= p->buf_size;
  9.   int score, fec_score, dvhs_score;
  10.   int check_count= size / TS_FEC_PACKET_SIZE;
  11.   if (check_count < CHECK_COUNT)
  12.       return -1;
  13.   score     = analyze(p->buf, TS_PACKET_SIZE *check_count, TS_PACKET_SIZE , NULL) 
  14.               * CHECK_COUNT / check_count;
  15.   dvhs_score= analyze(p->buf, TS_DVHS_PACKET_SIZE*check_count, TS_DVHS_PACKET_SIZE, NULL)
  16.               * CHECK_COUNT / check_count;
  17.   fec_score = analyze(p->buf, TS_FEC_PACKET_SIZE *check_count, TS_FEC_PACKET_SIZE , NULL)
  18.               * CHECK_COUNT / check_count;
  19.   /* 
  20.    * we need a clear definition for the returned score ,
  21.    * otherwise things will become messy sooner or later
  22.    */
  23.   if (score > fec_score && score > dvhs_score && score > 6) 
  24.     return AVPROBE_SCORE_MAX + score - CHECK_COUNT;
  25.   else if(dvhs_score > score && dvhs_score > fec_score && dvhs_score > 6) 
  26.     return AVPROBE_SCORE_MAX + dvhs_score - CHECK_COUNT;
  27.   else if(fec_score > 6) 
  28.     return AVPROBE_SCORE_MAX + fec_score - CHECK_COUNT;
  29.   else 
  30.     return -1;
  31. }
 
  1. /*
  2.  * 函数功能:
  3.  * 在size大小的buf中,寻找满足特定格式,长度为packet_size的
  4.  * packet的个数;
  5.  * 显然,返回的值越大越可能是相应的格式(188/192/204)
  6.  */
  7. static int analyze(const uint8_t *buf, int size, int packet_size, int *index){
  8.   int stat[TS_MAX_PACKET_SI
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值