X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpegts.c;h=2238bdc04fa048057aa70bb623ca2e7ff7b84d96;hb=db5effe1a4209e8ace97857e5de0d66a73fe7477;hp=9bb206ecd6aa43692f76cb97181491f24b901c95;hpb=80e4fe4063001d0cf468d5f4c7c02ba5b04484b7;p=ffmpeg diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 9bb206ecd6a..2238bdc04fa 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -164,6 +164,7 @@ typedef struct PESContext { enum MpegTSState state; /* used to get the format */ int data_index; + int flags; /**< copied to the AVPacket flags */ int total_size; int pes_header_size; int extended_stream_id; @@ -636,6 +637,12 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->destruct = av_destruct_packet; pkt->data = pes->buffer; pkt->size = pes->data_index; + + if(pes->total_size != MAX_PES_PAYLOAD && + pes->pes_header_size + pes->data_index != pes->total_size + 6) { + av_log(pes->stream, AV_LOG_WARNING, "PES packet size mismatch\n"); + pes->flags |= AV_PKT_FLAG_CORRUPT; + } memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); // Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID @@ -647,12 +654,14 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->dts = pes->dts; /* store position of first TS packet of this PES packet */ pkt->pos = pes->ts_packet_pos; + pkt->flags = pes->flags; /* reset pts values */ pes->pts = AV_NOPTS_VALUE; pes->dts = AV_NOPTS_VALUE; pes->buffer = NULL; pes->data_index = 0; + pes->flags = 0; } /* return non zero if a packet could be constructed */ @@ -889,9 +898,8 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size, avio_r8(&pb); len = ff_mp4_read_descr(s, &pb, &tag); if (tag == MP4ESDescrTag) { - *es_id = avio_rb16(&pb); /* ES_ID */ + ff_mp4_parse_es_descr(&pb, es_id); av_dlog(s, "ES_ID %#x\n", *es_id); - avio_r8(&pb); /* priority */ len = ff_mp4_read_descr(s, &pb, &tag); if (tag == MP4DecConfigDescrTag) { *dec_config_descr = av_malloc(len); @@ -1269,7 +1277,8 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) { AVFormatContext *s = ts->stream; MpegTSFilter *tss; - int len, pid, cc, expected_cc, cc_ok, afc, is_start; + 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; @@ -1285,20 +1294,36 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) if (!tss) return 0; + 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 = (packet[3] & 0x10) ? (tss->last_cc + 1) & 0x0f : tss->last_cc; - cc_ok = (tss->last_cc < 0) || (expected_cc == cc); + 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_WARNING, "Continuity Check Failed\n"); + if(tss->type == MPEGTS_PES) { + PESContext *pc = tss->u.pes_filter.opaque; + pc->flags |= AV_PKT_FLAG_CORRUPT; + } + } - /* skip adaptation field */ - afc = (packet[3] >> 4) & 3; - p = packet + 4; - if (afc == 0) /* reserved value */ - return 0; - if (afc == 2) /* adaptation field only */ + if (!has_payload) return 0; - if (afc == 3) { + p = packet + 4; + if (has_adaptation) { /* skip adapation field */ p += p[0] + 1; } @@ -1399,7 +1424,22 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) { AVFormatContext *s = ts->stream; uint8_t packet[TS_PACKET_SIZE]; - int packet_num, ret; + int packet_num, ret = 0; + + if (avio_tell(s->pb) != ts->last_pos) { + int i; +// av_dlog("Skipping after seek\n"); + /* seek detected, flush pes buffer */ + for (i = 0; i < NB_PID_MAX; i++) { + if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) { + PESContext *pes = ts->pids[i]->u.pes_filter.opaque; + av_freep(&pes->buffer); + ts->pids[i]->last_cc = -1; + pes->data_index = 0; + pes->state = MPEGTS_SKIP; /* skip until pes header */ + } + } + } ts->stop_parse = 0; packet_num = 0; @@ -1411,12 +1451,13 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) break; ret = read_packet(s, packet, ts->raw_packet_size); if (ret != 0) - return ret; + break; ret = handle_packet(ts, packet); if (ret != 0) - return ret; + break; } - return 0; + ts->last_pos = avio_tell(s->pb); + return ret; } static int mpegts_probe(AVProbeData *p) @@ -1487,17 +1528,6 @@ static int mpegts_read_header(AVFormatContext *s, int len; int64_t pos; -#if FF_API_FORMAT_PARAMETERS - if (ap) { - if (ap->mpeg2ts_compute_pcr) - ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr; - if(ap->mpeg2ts_raw){ - av_log(s, AV_LOG_ERROR, "use mpegtsraw_demuxer!\n"); - return -1; - } - } -#endif - /* read the first 1024 bytes to get packet size */ pos = avio_tell(pb); len = avio_read(pb, buf, sizeof(buf)); @@ -1515,7 +1545,7 @@ static int mpegts_read_header(AVFormatContext *s, /* normal demux */ /* first do a scaning to get all the services */ - if (avio_seek(pb, pos, SEEK_SET) < 0) + if (pb->seekable && avio_seek(pb, pos, SEEK_SET) < 0) av_log(s, AV_LOG_ERROR, "Unable to seek back to the start\n"); mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); @@ -1636,18 +1666,6 @@ static int mpegts_read_packet(AVFormatContext *s, MpegTSContext *ts = s->priv_data; int ret, i; - if (avio_tell(s->pb) != ts->last_pos) { - /* seek detected, flush pes buffer */ - for (i = 0; i < NB_PID_MAX; i++) { - if (ts->pids[i] && ts->pids[i]->type == MPEGTS_PES) { - PESContext *pes = ts->pids[i]->u.pes_filter.opaque; - av_freep(&pes->buffer); - pes->data_index = 0; - pes->state = MPEGTS_SKIP; /* skip until pes header */ - } - } - } - ts->pkt = pkt; ret = handle_packets(ts, 0); if (ret < 0) { @@ -1665,8 +1683,6 @@ static int mpegts_read_packet(AVFormatContext *s, } } - ts->last_pos = avio_tell(s->pb); - return ret; } @@ -1887,15 +1903,15 @@ void ff_mpegts_parse_close(MpegTSContext *ts) } AVInputFormat ff_mpegts_demuxer = { - "mpegts", - NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"), - sizeof(MpegTSContext), - mpegts_probe, - mpegts_read_header, - mpegts_read_packet, - mpegts_read_close, - read_seek, - mpegts_get_pcr, + .name = "mpegts", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 transport stream format"), + .priv_data_size = sizeof(MpegTSContext), + .read_probe = mpegts_probe, + .read_header = mpegts_read_header, + .read_packet = mpegts_read_packet, + .read_close = mpegts_read_close, + .read_seek = read_seek, + .read_timestamp = mpegts_get_pcr, .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, #ifdef USE_SYNCPOINT_SEARCH .read_seek2 = read_seek2, @@ -1903,15 +1919,14 @@ AVInputFormat ff_mpegts_demuxer = { }; AVInputFormat ff_mpegtsraw_demuxer = { - "mpegtsraw", - NULL_IF_CONFIG_SMALL("MPEG-2 raw transport stream format"), - sizeof(MpegTSContext), - NULL, - mpegts_read_header, - mpegts_raw_read_packet, - mpegts_read_close, - read_seek, - mpegts_get_pcr, + .name = "mpegtsraw", + .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 raw transport stream format"), + .priv_data_size = sizeof(MpegTSContext), + .read_header = mpegts_read_header, + .read_packet = mpegts_raw_read_packet, + .read_close = mpegts_read_close, + .read_seek = read_seek, + .read_timestamp = mpegts_get_pcr, .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, #ifdef USE_SYNCPOINT_SEARCH .read_seek2 = read_seek2,