随笔-118  评论-133  文章-4  trackbacks-0
static int mpegts_read_packet(AVFormatContext *s, AVPacket *pkt)
{
xxxx
    ret 
= handle_packets(ts, 0);
xxxx     
}

static int handle_packets(MpegTSContext *ts, int nb_packets)
{
xxxx
    ts
->stop_parse = 0;
    packet_num 
= 0;
    memset(packet 
+ TS_PACKET_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
    
for (;;) {
        packet_num
++;
        
if (nb_packets != 0 && packet_num >= nb_packets ||
            ts
->stop_parse > 1) {
            ret 
= AVERROR(EAGAIN);
            
break;
        }
        
if (ts->stop_parse > 0)  //收到完整的pes包,stop_parse会置为'1'
            break;

        ret 
= read_packet(s, packet, ts->raw_packet_size, &data);   //读取一个TS包(TS_PACKET_SIZE)
        if (ret != 0)
            
break;
        ret 
= handle_packet(ts, data);  //处理读取的TS包(状态机)
        finished_reading_packet(s, ts->raw_packet_size);
        
if (ret != 0)
            
break;
    }
    ts
->last_pos = avio_tell(s->pb);
    
return ret;
}

/* handle one TS packet */
static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
{
    MpegTSFilter 
*tss;
    
int len, pid, cc, expected_cc, cc_ok, afc, is_start, is_discontinuity,
        has_adaptation, has_payload;
    
const uint8_t *p, *p_end;
    int64_t pos;

    pid 
= AV_RB16(packet + 1& 0x1fff;
    
if (pid && discard_pid(ts, pid))
        
return 0;
    is_start 
= packet[1& 0x40;
    tss 
= ts->pids[pid];
    
if (ts->auto_guess && tss == NULL && is_start) {
        add_pes_stream(ts, pid, 
-1);
        tss 
= ts->pids[pid];
    }
    
if (!tss)
        
return 0;
    ts
->current_pid = pid;

    afc 
= (packet[3>> 4& 3;
    
if (afc == 0/* reserved value */
        
return 0;
    has_adaptation   
= afc & 2;
    has_payload      
= afc & 1;
    is_discontinuity 
= has_adaptation &&
                       packet[
4!= 0 && /* with length > 0 */
                       (packet[
5& 0x80); /* and discontinuity indicated */

    
/* continuity check (currently not used) */
    cc 
= (packet[3& 0xf);
    expected_cc 
= has_payload ? (tss->last_cc + 1& 0x0f : tss->last_cc;
    cc_ok 
= pid == 0x1FFF || // null packet PID
            is_discontinuity ||
            tss
->last_cc < 0 ||
            expected_cc 
== cc;

    tss
->last_cc = cc;
    
if (!cc_ok) {
        av_log(ts
->stream, AV_LOG_DEBUG,
               
"Continuity check failed for pid %d expected %d got %d\n",
               pid, expected_cc, cc);
        
if (tss->type == MPEGTS_PES) {
            PESContext 
*pc = tss->u.pes_filter.opaque;
            pc
->flags |= AV_PKT_FLAG_CORRUPT;   //PES包损坏
        }
    }

    
if (!has_payload && tss->type != MPEGTS_PCR)
        
return 0;
    p 
= packet + 4;
    
if (has_adaptation) {
        
/* skip adaptation field */
        p 
+= p[0+ 1;
    }
    
/* if past the end of packet, ignore */
    p_end 
= packet + TS_PACKET_SIZE;
    
if (p > p_end || (p == p_end && tss->type != MPEGTS_PCR))
        
return 0;

    pos 
= avio_tell(ts->stream->pb);
    
if (pos >= 0) {
        av_assert0(pos 
>= TS_PACKET_SIZE);
        ts
->pos47_full = pos - TS_PACKET_SIZE;
    }

    
if (tss->type == MPEGTS_SECTION) {  //PSI包处理
xxxx
    }
else {
        
int ret;
        int64_t pcr_h;
        
int pcr_l;
        
if (parse_pcr(&pcr_h, &pcr_l, packet) == 0)
            tss
->last_pcr = pcr_h * 300 + pcr_l;
        
// Note: The position here points actually behind the current packet.
        if (tss->type == MPEGTS_PES) {  //PES包处理
            if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start,
                                                pos 
- ts->raw_packet_size)) < 0)    //mpegts_push_data
                return ret;
        }
    }

    
return 0;
}

static int mpegts_push_data(MpegTSFilter *filter,
                            
const uint8_t *buf, int buf_size, int is_start,
                            int64_t pos)
{
    PESContext 
*pes   = filter->u.pes_filter.opaque;
    MpegTSContext 
*ts = pes->ts;
    
const uint8_t *p;
    
int len, code;

    
if (!ts->pkt)
        
return 0;

    
if (is_start) {
        
if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) {  //当前包还没处理完,新的包到来。
            new_pes_packet(pes, ts->pkt);   //把pes的数据传给pkt(提交给上层)
            ts->stop_parse = 1//当前包结束解析
        } else {
            reset_pes_packet_state(pes);    
//新的开始
        }
        pes
->state         = MPEGTS_HEADER;
        pes
->ts_packet_pos = pos;
    }
    p 
= buf;
    
while (buf_size > 0) {
        
switch (pes->state) {
        
case MPEGTS_HEADER: //解析pes包头部
            len = PES_START_SIZE - pes->data_index;
            
if (len > buf_size)
                len 
= buf_size;
            memcpy(pes
->header + pes->data_index, p, len);
            pes
->data_index += len;
            p 
+= len;
            buf_size 
-= len;
            
if (pes->data_index == PES_START_SIZE) {
                
/* we got all the PES or section header. We can now
                 * decide 
*/
                
if (pes->header[0== 0x00 && pes->header[1== 0x00 &&
                    pes
->header[2== 0x01) {
                    
/* it must be an mpeg2 PES stream */
                    code 
= pes->header[3| 0x100;
                    av_dlog(pes
->stream, "pid=%x pes_code=%#x\n", pes->pid,
                            code);

                    
if ((pes->st && pes->st->discard == AVDISCARD_ALL &&
                         (
!pes->sub_st ||
                          pes
->sub_st->discard == AVDISCARD_ALL)) ||
                        code 
== 0x1be/* padding_stream */
                        
goto skip;

                    
/* stream not present in PMT */
                    
if (!pes->st) {
                        
if (ts->skip_changes)
                            
goto skip;

                        pes
->st = avformat_new_stream(ts->stream, NULL);
                        
if (!pes->st)
                            
return AVERROR(ENOMEM);
                        pes
->st->id = pes->pid;
                        mpegts_set_stream_info(pes
->st, pes, 00);
                    }

                    pes
->total_size = AV_RB16(pes->header + 4);
                    
/* NOTE: a zero total size means the PES size is
                     * unbounded 
*/
                    
if (!pes->total_size)
                        pes
->total_size = MAX_PES_PAYLOAD;

                    
/* allocate pes buffer */
                    pes
->buffer = av_buffer_alloc(pes->total_size +
                                                  FF_INPUT_BUFFER_PADDING_SIZE);
                    
if (!pes->buffer)
                        
return AVERROR(ENOMEM);

                    
if (code != 0x1bc && code != 0x1bf && /* program_stream_map, private_stream_2 */
                        code 
!= 0x1f0 && code != 0x1f1 && /* ECM, EMM */
                        code 
!= 0x1ff && code != 0x1f2 && /* program_stream_directory, DSMCC_stream */
                        code 
!= 0x1f8) {                  /* ITU-T Rec. H.222.1 type E stream */
                        pes
->state = MPEGTS_PESHEADER;
                        
if (pes->st->codec->codec_id == AV_CODEC_ID_NONE && !pes->st->request_probe) {
                            av_dlog(pes
->stream,
                                    
"pid=%x stream_type=%x probing\n",
                                    pes
->pid,
                                    pes
->stream_type);
                            av_log(pes
->stream, AV_LOG_WARNING, "----request_probe\n");
                            pes
->st->request_probe = 1;
                        }
                    } 
else {
                        pes
->state      = MPEGTS_PAYLOAD;
                        pes
->data_index = 0;
                    }
                } 
else {
                    
/* otherwise, it should be a table */
                    
/* skip packet */
skip:
                    pes
->state = MPEGTS_SKIP;
                    
continue;
                }
            }
            
break;
xxxx
        
case MPEGTS_PAYLOAD:
            
if (pes->buffer) {
                
if (pes->data_index > 0 &&
                    pes
->data_index + buf_size > pes->total_size) { //加上新的数据超出一个pes包的长度(当前包结束)   ???
                    new_pes_packet(pes, ts->pkt);   //把pes的数据传给pkt(提交给上层)
                    pes->total_size = MAX_PES_PAYLOAD;
                    pes
->buffer = av_buffer_alloc(pes->total_size +
                                                  FF_INPUT_BUFFER_PADDING_SIZE);
                    
if (!pes->buffer)
                        
return AVERROR(ENOMEM);
                    ts
->stop_parse = 1//当前包结束解析
                } else if (pes->data_index == 0 &&
                           buf_size 
> pes->total_size) {
                    
// pes packet size is < ts size packet and pes data is padded with 0xff
                    
// not sure if this is legal in ts but see issue #2392
                    buf_size = pes->total_size;
                }
                memcpy(pes
->buffer->data + pes->data_index, p, buf_size);   //拷贝数据到pes->buffer(可能还没拷完整个pes packet的数据)
                pes->data_index += buf_size;
                
/* emit complete packets with known packet size
                 * decreases demuxer delay for infrequent packets like subtitles from
                 * a couple of seconds to milliseconds for properly muxed files.
                 * total_size is the number of bytes following pes_packet_length
                 * in the pes header, i.e. not counting the first PES_START_SIZE bytes 
*/
                
if (!ts->stop_parse && pes->total_size < MAX_PES_PAYLOAD &&
                    pes
->pes_header_size + pes->data_index == pes->total_size + PES_START_SIZE) {
                    ts
->stop_parse = 1//数据已经拷贝完,停止解析。
                    new_pes_packet(pes, ts->pkt);   //把pes的数据传给pkt(提交给上层)
                }
            }
            buf_size 
= 0;
            
break;
        
case MPEGTS_SKIP:
            buf_size 
= 0;
            
break;
        }
    }

    
return 0;
}


posted on 2016-05-18 11:30 lfc 阅读(665) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。