ffmpeg for MPEG2 TS

如果RTSP传输的是RTP/MPEG2 TS数据,那么ffmpeg的数据流过程如下:

rtsp_read_packet----->rtp_parse_packet--->rtp_valid_packet_in_sequence-------------------------------------------->

-------------------------------->如果是MPEG2 TS------>mpegts_parse_packet

--------------------------------->else s->parse_packet

---------------------------------->else  copy buf to packet and return;

static void handle_packet(MpegTSContext *ts, const uint8_t *packet)

该函数解析MPEG2 TS PACKET

 

view plain copy to clipboard print ?
  1. /* handle one TS packet */  
  2. static void handle_packet(MpegTSContext *ts, const uint8_t *packet)  
  3. {  
  4.     AVFormatContext *s = ts->stream;  
  5.     MpegTSFilter *tss;  
  6.     int len, pid, cc, cc_ok, afc, is_start;  
  7.     const uint8_t *p, *p_end;  
  8.   
  9. //根据iso13818-1种ts packet的格式描述,可以从ts packet中获取PID  
  10.     pid = AV_RB16(packet + 1) & 0x1fff;  
  11.     if(pid && discard_pid(ts, pid))  
  12.         return;  
  13. //如果start_indicator为1表示该ts packet中是PES packet的起始数据  
  14.     is_start = packet[1] & 0x40;  
  15.   
  16.     tss = ts->pids[pid];  
  17. //tss为null,表示pid对应的program的filter还没有创建,所以创建一个pes stream以及pes filter  
  18. //一般会创建两种ts filer:PES filter,用来过滤一个节目  
  19. //--------------------:section filer,用来过滤PSI信息  
  20.     if (ts->auto_guess && tss == NULL && is_start) {  
  21.         //参考add_pes_stream, add_pes_stream函数返回的PESContext变量没有在这里保存起来,但是在add_pes_stream函数中将其作为PESFilter的opaque变量传给了PESFilter,而PESFilter又可以通过ts->pids[pid]得到  
  22.         add_pes_stream(ts, pid, -1, 0);  
  23.         tss = ts->pids[pid];  
  24.     }  
  25.     if (!tss)  
  26.         return;  
  27.   
  28.     /* continuity check (currently not used) */  
  29.     cc = (packet[3] & 0xf);  
  30. //在add_pes_stream中将tss的last_cc设为-1  
  31.     cc_ok = (tss->last_cc < 0) || ((((tss->last_cc + 1) & 0x0f) == cc));  
  32.     tss->last_cc = cc;  
  33.   
  34.     /* skip adaptation field */  
  35.     afc = (packet[3] >> 4) & 3;  
  36.     p = packet + 4;  
  37.     if (afc == 0) /* reserved value */  
  38.         return;  
  39.     if (afc == 2) /* adaptation field only */  
  40.         return;  
  41.     if (afc == 3) {  
  42.         /* skip adapation field */  
  43.         p += p[0] + 1;---------------〉获取TS PACKET中的data byte  
  44.     }  
  45.   /* if past the end of packet, ignore */  
  46.     p_end = packet + TS_PACKET_SIZE;  
  47.     if (p >= p_end)  
  48.         return;  
  49.   
  50.     ts->pos47= url_ftell(ts->stream->pb) % ts->raw_packet_size;  
  51.   
  52.   
  53.     //SECTION FILTER  
  54.     if (tss->type == MPEGTS_SECTION) {  
  55.         if (is_start) {  
  56.             /* pointer field present */  
  57.             len = *p++;  
  58.             if (p + len > p_end)  
  59.                 return;  
  60.             if (len && cc_ok) {  
  61.                 /* write remaining section bytes */  
  62.                 write_section_data(s, tss,  
  63.                                    p, len, 0);  
  64.                 /* check whether filter has been closed */  
  65.                 if (!ts->pids[pid])  
  66.                     return;  
  67.             }  
  68.             p += len;  
  69.             if (p < p_end) {  
  70.                 write_section_data(s, tss,  
  71.                                    p, p_end - p, 1);  
  72.             }  
  73.         } else {  
  74.             if (cc_ok) {  
  75.                 write_section_data(s, tss,  
  76.                                    p, p_end - p, 0);  
  77.             }  
  78.         }  
  79.     } else {  
  80.        //PES filter, pes_cb为mpegts_push_data  
  81.         tss->u.pes_filter.pes_cb(tss,  
  82.                                  p, p_end - p, is_start);  
  83.     }  
  84. }  
  85.               

 

mpegts_push_data在构造一个PES packet:

 

view plain copy to clipboard print ?
  1. /* return non zero if a packet could be constructed */  
  2. static void mpegts_push_data(MpegTSFilter *filter,  
  3.                              const uint8_t *buf, int buf_size, int is_start)  
  4. {  
  5.     PESContext *pes = filter->u.pes_filter.opaque;  
  6.     MpegTSContext *ts = pes->ts;  
  7.     const uint8_t *p;  
  8.     int len, code;  
  9.   
  10.     if(!ts->pkt)  
  11.         return;  
  12.   
  13.    //开始一个PES packet  
  14.     if (is_start) {  
  15.       //pes->data_index表示pes packet的数据的位置  
  16.         pes->state = MPEGTS_HEADER;  
  17.         pes->data_index = 0;  
  18.     }  
  19.     p = buf;  
  20.     while (buf_size > 0) {  
  21.         switch(pes->state) {  
  22.         case MPEGTS_HEADER:  
  23.         //PES_START_SIZE=9,表示PES PACKET HEADER的长度,参考iso13818-1  
  24.             len = PES_START_SIZE - pes->data_index;  
  25.             if (len > buf_size)  
  26.                 len = buf_size;  
  27.           //将PES packet header部分复制到pes->header中,pes->header根据不同的pes类型,或有不同的结构  
  28.             memcpy(pes->header + pes->data_index, p, len);  
  29.             pes->data_index += len;  
  30.             p += len;  
  31.             buf_size -= len;  
  32.             if (pes->data_index == PES_START_SIZE) {  
  33.                 //获取到PES PACKET的长度  
  34.                 /* we got all the PES or section header. We can now 
  35.                    decide */  
  36. #if 0  
  37.                 av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);  
  38. #endif  
  39.   
  40.         //packet_start_code_prefix为0x000001  
  41.                 if (pes->header[0] == 0x00 && pes->header[1] == 0x00 &&  
  42.                     pes->header[2] == 0x01) {  
  43.                     /* it must be an mpeg2 PES stream */  
  44.                    //pes->header[3]为stream id  
  45.                     code = pes->header[3] | 0x100;  
  46.                  //0xc0---0xdf-------->audio stream  
  47.                  //0xe0---0xef-------->video stream  
  48.                  //0xbd----->private stream1  
  49.                  //0xfd----->???  
  50.                     if (!((code >= 0x1c0 && code <= 0x1df) ||  
  51.                           (code >= 0x1e0 && code <= 0x1ef) ||  
  52.                           (code == 0x1bd) || (code == 0x1fd)))  
  53.                     goto skip;  
  54.                     if (!pes->st) {  
  55.                         /* allocate stream */  
  56.                         //为该PES分配AVStream  
  57.                         new_pes_av_stream(pes, code);  
  58.                     }  
  59.   
  60.                    //下面进行pes packet分析  
  61.                     pes->state = MPEGTS_PESHEADER_FILL;  
  62.                    //对于video/audio stream等,  
  63.                      //total_size指的是下面的packet length  
  64.                     pes->total_size = AV_RB16(pes->header + 4);  
  65.                     /* NOTE: a zero total size means the PES size is 
  66.                        unbounded */  
  67.                     if (pes->total_size)  
  68.                         pes->total_size += 6;  
  69.                    //pes_header_size   
  70.                    pes->pes_header_size = pes->header[8] + 9;  
  71.                 } else {  
  72.                     /* otherwise, it should be a table */  
  73.                     /* skip packet */  
  74.                 skip:  
  75.                     pes->state = MPEGTS_SKIP;  
  76.                     continue;  
  77.                 }  
  78.             }  
  79.             break;  
  80.      /**********************************************/  
  81.             /* PES packing parsing */  
  82.         case MPEGTS_PESHEADER_FILL:  
  83.               //pes_header_size指的是pes packet header中optional fields的长度, optional fields由header_length前面的一个byte指定  
  84.             len = pes->pes_header_size - pes->data_index;  
  85.             if (len > buf_size)  
  86.                 len = buf_size;  
  87.             memcpy(pes->header + pes->data_index, p, len);  
  88.             pes->data_index += len;  
  89.             p += len;  
  90.             buf_size -= len;  
  91.             if (pes->data_index == pes->pes_header_size) {  
  92.                 const uint8_t *r;  
  93.                 unsigned int flags;  
  94.   
  95.                 flags = pes->header[7];  
  96.                 r = pes->header + 9;  
  97.                 pes->pts = AV_NOPTS_VALUE;  
  98.                 pes->dts = AV_NOPTS_VALUE;  
  99.                 //PTS_DTS_FLAG=10, ONLY PTS  
  100.                 if ((flags & 0xc0) == 0x80) {  
  101.                     pes->pts = get_pts(r);  
  102.                     r += 5;  
  103.                  //PTS_DTS_FLAG=11, PTS & DTS  
  104.                 } else if ((flags & 0xc0) == 0xc0) {  
  105.                     pes->pts = get_pts(r);  
  106.                     r += 5;  
  107.                     pes->dts = get_pts(r);  
  108.                     r += 5;  
  109.                 }  
  110.                 /* we got the full header. We parse it and get the payload */  
  111.                 pes->state = MPEGTS_PAYLOAD;  
  112.             }  
  113.             break;  
  114.       case MPEGTS_PAYLOAD:  
  115.          //将PES packet的data 部分copy到 AVPacket中  
  116.             if (pes->total_size) {  
  117.                 len = pes->total_size - pes->data_index;  
  118.                 if (len > buf_size)  
  119.                     len = buf_size;  
  120.             } else {  
  121.                 len = buf_size;  
  122.             }  
  123.             if (len > 0) {  
  124.                 AVPacket *pkt = ts->pkt;  
  125.                 if (pes->st && av_new_packet(pkt, len) == 0) {  
  126.                     memcpy(pkt->data, p, len);  
  127.                     pkt->stream_index = pes->st->index;  
  128.                     pkt->pts = pes->pts;  
  129.                     pkt->dts = pes->dts;  
  130.                     /* reset pts values */  
  131.                     pes->pts = AV_NOPTS_VALUE;  
  132.                     pes->dts = AV_NOPTS_VALUE;  
  133.                     //stop_parse指示mpegts_parse_packet可以停止parse packet  
  134.                     ts->stop_parse = 1;  
  135.                     return;  
  136.                 }  
  137.             }  
  138.             buf_size = 0;  
  139.             break;  
  140.         case MPEGTS_SKIP:  
  141.             buf_size = 0;  
  142.             break;  
  143.         }  
  144.     }  
  145. }  

 

由于mpeg2ts里面指定了stream id来去分video/audio/psi,对于video/audio的具体的格式还要进一步的分析。

你可能感兴趣的:(Stream,header,filter,null,byte,hex)