X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmpegts.c;h=ceec2a15c2b49e5966238292dce76445d43cfbae;hb=28f008a9d3a852d94b84b8409668eec1329d3e78;hp=0285fa0231625a7be9a8590a6b33601bff689cdc;hpb=f2c357d95d6dbc7db2eb37d0da2dd65ac2e24fee;p=ffmpeg diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 0285fa02316..ceec2a15c2b 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -21,6 +21,7 @@ //#define DEBUG //#define DEBUG_SEEK +//#define USE_SYNCPOINT_SEARCH #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" @@ -28,13 +29,14 @@ #include "avformat.h" #include "mpegts.h" #include "internal.h" +#include "seek.h" /* 1.0 second at 24Mbit/s */ #define MAX_SCAN_PACKETS 32000 /* maximum size in which we look for synchronisation if synchronisation is lost */ -#define MAX_RESYNC_SIZE 4096 +#define MAX_RESYNC_SIZE 65536 #define MAX_PES_PAYLOAD 200*1024 @@ -128,13 +130,15 @@ struct MpegTSContext { enum MpegTSState { MPEGTS_HEADER = 0, + MPEGTS_PESHEADER, MPEGTS_PESHEADER_FILL, MPEGTS_PAYLOAD, MPEGTS_SKIP, }; /* enough for PES header + length */ -#define PES_START_SIZE 9 +#define PES_START_SIZE 6 +#define PES_HEADER_SIZE 9 #define MAX_PES_HEADER_SIZE (9 + 255) struct PESContext { @@ -144,11 +148,13 @@ struct PESContext { MpegTSContext *ts; AVFormatContext *stream; AVStream *st; + AVStream *sub_st; /**< stream for the embedded AC3 stream in HDMV TrueHD */ enum MpegTSState state; /* used to get the format */ int data_index; int total_size; int pes_header_size; + int extended_stream_id; int64_t pts, dts; int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */ uint8_t header[MAX_PES_HEADER_SIZE]; @@ -353,7 +359,7 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter) } static int analyze(const uint8_t *buf, int size, int packet_size, int *index){ - int stat[packet_size]; + int stat[TS_MAX_PACKET_SIZE]; int i; int x=0; int best_score=0; @@ -495,6 +501,7 @@ static const StreamType ISO_types[] = { { 0x04, CODEC_TYPE_AUDIO, CODEC_ID_MP3 }, { 0x0f, CODEC_TYPE_AUDIO, CODEC_ID_AAC }, { 0x10, CODEC_TYPE_VIDEO, CODEC_ID_MPEG4 }, + { 0x11, CODEC_TYPE_AUDIO, CODEC_ID_AAC }, /* LATM syntax */ { 0x1b, CODEC_TYPE_VIDEO, CODEC_ID_H264 }, { 0xd1, CODEC_TYPE_VIDEO, CODEC_ID_DIRAC }, { 0xea, CODEC_TYPE_VIDEO, CODEC_ID_VC1 }, @@ -502,8 +509,12 @@ static const StreamType ISO_types[] = { }; static const StreamType HDMV_types[] = { + { 0x80, CODEC_TYPE_AUDIO, CODEC_ID_PCM_BLURAY }, { 0x81, CODEC_TYPE_AUDIO, CODEC_ID_AC3 }, { 0x82, CODEC_TYPE_AUDIO, CODEC_ID_DTS }, + { 0x83, CODEC_TYPE_AUDIO, CODEC_ID_TRUEHD }, + { 0x84, CODEC_TYPE_AUDIO, CODEC_ID_EAC3 }, + { 0x90, CODEC_TYPE_SUBTITLE, CODEC_ID_HDMV_PGS_SUBTITLE }, { 0 }, }; @@ -511,7 +522,6 @@ static const StreamType HDMV_types[] = { static const StreamType MISC_types[] = { { 0x81, CODEC_TYPE_AUDIO, CODEC_ID_AC3 }, { 0x8a, CODEC_TYPE_AUDIO, CODEC_ID_DTS }, - {0x100, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_SUBTITLE }, // demuxer internal { 0 }, }; @@ -524,9 +534,11 @@ static const StreamType REGD_types[] = { /* descriptor present */ static const StreamType DESC_types[] = { { 0x6a, CODEC_TYPE_AUDIO, CODEC_ID_AC3 }, /* AC-3 descriptor */ - { 0x7a, CODEC_TYPE_AUDIO, CODEC_ID_AC3 }, + { 0x7a, CODEC_TYPE_AUDIO, CODEC_ID_EAC3 }, /* E-AC-3 descriptor */ { 0x7b, CODEC_TYPE_AUDIO, CODEC_ID_DTS }, + { 0x56, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_TELETEXT }, { 0x59, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */ + { 0 }, }; static void mpegts_find_stream_type(AVStream *st, @@ -541,7 +553,7 @@ static void mpegts_find_stream_type(AVStream *st, } } -static AVStream *new_pes_av_stream(PESContext *pes, uint32_t prog_reg_desc) +static AVStream *new_pes_av_stream(PESContext *pes, uint32_t prog_reg_desc, uint32_t code) { AVStream *st = av_new_stream(pes->stream, pes->pid); @@ -551,20 +563,57 @@ static AVStream *new_pes_av_stream(PESContext *pes, uint32_t prog_reg_desc) av_set_pts_info(st, 33, 1, 90000); st->priv_data = pes; st->codec->codec_type = CODEC_TYPE_DATA; - st->codec->codec_id = CODEC_ID_PROBE; + st->codec->codec_id = CODEC_ID_NONE; st->need_parsing = AVSTREAM_PARSE_FULL; pes->st = st; dprintf(pes->stream, "stream_type=%x pid=%x prog_reg_desc=%.4s\n", pes->stream_type, pes->pid, (char*)&prog_reg_desc); + st->codec->codec_tag = pes->stream_type; + mpegts_find_stream_type(st, pes->stream_type, ISO_types); if (prog_reg_desc == AV_RL32("HDMV") && - st->codec->codec_id == CODEC_ID_PROBE) + st->codec->codec_id == CODEC_ID_NONE) { mpegts_find_stream_type(st, pes->stream_type, HDMV_types); - if (st->codec->codec_id == CODEC_ID_PROBE) + if (pes->stream_type == 0x83) { + // HDMV TrueHD streams also contain an AC3 coded version of the + // audio track - add a second stream for this + AVStream *sub_st; + // priv_data cannot be shared between streams + PESContext *sub_pes = av_malloc(sizeof(*sub_pes)); + if (!sub_pes) + return NULL; + memcpy(sub_pes, pes, sizeof(*sub_pes)); + + sub_st = av_new_stream(pes->stream, pes->pid); + if (!sub_st) { + av_free(sub_pes); + return NULL; + } + + av_set_pts_info(sub_st, 33, 1, 90000); + sub_st->priv_data = sub_pes; + sub_st->codec->codec_type = CODEC_TYPE_AUDIO; + sub_st->codec->codec_id = CODEC_ID_AC3; + sub_st->need_parsing = AVSTREAM_PARSE_FULL; + sub_pes->sub_st = pes->sub_st = sub_st; + } + } + if (st->codec->codec_id == CODEC_ID_NONE) mpegts_find_stream_type(st, pes->stream_type, MISC_types); + /* stream was not present in PMT, guess based on PES start code */ + if (st->codec->codec_id == CODEC_ID_NONE) { + if (code >= 0x1c0 && code <= 0x1df) { + st->codec->codec_type = CODEC_TYPE_AUDIO; + st->codec->codec_id = CODEC_ID_MP2; + } else if (code == 0x1bd) { + st->codec->codec_type = CODEC_TYPE_AUDIO; + st->codec->codec_id = CODEC_ID_AC3; + } + } + return st; } @@ -580,7 +629,6 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len int comp_page, anc_page; char language[4]; uint32_t prog_reg_desc = 0; /* registration descriptor */ - uint32_t reg_desc; /* registration descriptor */ #ifdef DEBUG dprintf(ts->stream, "PMT: len %i\n", section_len); @@ -626,6 +674,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len p += program_info_length; if (p >= p_end) return; + + // stop parsing after pmt, we found header + if (!ts->stream->nb_streams) + ts->stop_parse = 1; + for(;;) { st = 0; stream_type = get8(&p, p_end); @@ -643,7 +696,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (ts->pids[pid]) mpegts_close_filter(ts, ts->pids[pid]); //wrongly added sdt filter probably pes = add_pes_stream(ts, pid, pcr_pid, stream_type); if (pes) - st = new_pes_av_stream(pes, prog_reg_desc); + st = new_pes_av_stream(pes, prog_reg_desc, 0); } if (!st) @@ -673,11 +726,18 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len dprintf(ts->stream, "tag: 0x%02x len=%d\n", desc_tag, desc_len); - if (st->codec->codec_id == CODEC_ID_PROBE && + if (st->codec->codec_id == CODEC_ID_NONE && stream_type == STREAM_TYPE_PRIVATE_DATA) mpegts_find_stream_type(st, desc_tag, DESC_types); switch(desc_tag) { + case 0x56: /* DVB teletext descriptor */ + language[0] = get8(&p, desc_end); + language[1] = get8(&p, desc_end); + language[2] = get8(&p, desc_end); + language[3] = 0; + av_metadata_set(&st->metadata, "language", language); + break; case 0x59: /* subtitling descriptor */ language[0] = get8(&p, desc_end); language[1] = get8(&p, desc_end); @@ -697,20 +757,25 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len av_metadata_set(&st->metadata, "language", language); break; case 0x05: /* registration descriptor */ - reg_desc = bytestream_get_le32(&p); - if (st->codec->codec_id == CODEC_ID_PROBE && + st->codec->codec_tag = bytestream_get_le32(&p); + dprintf(ts->stream, "reg_desc=%.4s\n", (char*)&st->codec->codec_tag); + if (st->codec->codec_id == CODEC_ID_NONE && stream_type == STREAM_TYPE_PRIVATE_DATA) - mpegts_find_stream_type(st, reg_desc, REGD_types); + mpegts_find_stream_type(st, st->codec->codec_tag, REGD_types); break; default: break; } p = desc_end; + + if (prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) { + av_program_add_stream_index(ts->stream, h->id, pes->sub_st->index); + pes->sub_st->codec->codec_tag = st->codec->codec_tag; + } } p = desc_list_end; } /* all parameters are there */ - ts->stop_parse++; mpegts_close_filter(ts, filter); } @@ -747,17 +812,12 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len /* NIT info */ } else { av_new_program(ts->stream, sid); - ts->stop_parse--; mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); add_pat_entry(ts, sid); add_pid_to_pmt(ts, sid, 0); //add pat pid to program add_pid_to_pmt(ts, sid, pmt_pid); } } - /* not found */ - ts->stop_parse++; - - mpegts_close_filter(ts, filter); } static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len) @@ -855,7 +915,11 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) pkt->size = pes->data_index; memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); - pkt->stream_index = pes->st->index; + // Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID + if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76) + pkt->stream_index = pes->sub_st->index; + else + pkt->stream_index = pes->st->index; pkt->pts = pes->pts; pkt->dts = pes->dts; /* store position of first TS packet of this PES packet */ @@ -911,16 +975,44 @@ static int mpegts_push_data(MpegTSFilter *filter, pes->header[2] == 0x01) { /* it must be an mpeg2 PES stream */ code = pes->header[3] | 0x100; - if (!pes->st || pes->st->discard == AVDISCARD_ALL || - !((code >= 0x1c0 && code <= 0x1df) || - (code >= 0x1e0 && code <= 0x1ef) || - (code == 0x1bd) || (code == 0x1fd))) + dprintf(pes->stream, "pid=%x pes_code=%#x\n", pes->pid, code); + + if ((!pes->st && pes->stream->nb_streams == MAX_STREAMS) || + (pes->st && pes->st->discard == AVDISCARD_ALL) || + code == 0x1be) /* padding_stream */ goto skip; - pes->state = MPEGTS_PESHEADER_FILL; + + /* stream not present in PMT */ + if (!pes->st) + pes->st = new_pes_av_stream(pes, 0, code); + if (!pes->st) + return AVERROR(ENOMEM); + pes->total_size = AV_RB16(pes->header + 4); /* NOTE: a zero total size means the PES size is unbounded */ - pes->pes_header_size = pes->header[8] + 9; + if (!pes->total_size) + pes->total_size = MAX_PES_PAYLOAD; + + /* allocate pes buffer */ + pes->buffer = av_malloc(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 == CODEC_ID_NONE) { + dprintf(pes->stream, "pid=%x stream_type=%x probing\n", + pes->pid, pes->stream_type); + pes->st->codec->codec_id = CODEC_ID_PROBE; + } + } else { + pes->state = MPEGTS_PAYLOAD; + pes->data_index = 0; + } } else { /* otherwise, it should be a table */ /* skip packet */ @@ -932,6 +1024,21 @@ static int mpegts_push_data(MpegTSFilter *filter, break; /**********************************************/ /* PES packing parsing */ + case MPEGTS_PESHEADER: + len = PES_HEADER_SIZE - pes->data_index; + if (len < 0) + return -1; + 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_HEADER_SIZE) { + pes->pes_header_size = pes->header[8] + 9; + pes->state = MPEGTS_PESHEADER_FILL; + } + break; case MPEGTS_PESHEADER_FILL: len = pes->pes_header_size - pes->data_index; if (len < 0) @@ -944,7 +1051,7 @@ static int mpegts_push_data(MpegTSFilter *filter, buf_size -= len; if (pes->data_index == pes->pes_header_size) { const uint8_t *r; - unsigned int flags; + unsigned int flags, pes_ext, skip; flags = pes->header[7]; r = pes->header + 9; @@ -959,15 +1066,20 @@ static int mpegts_push_data(MpegTSFilter *filter, pes->dts = get_pts(r); r += 5; } - - if (pes->total_size > pes->data_index - 6) - pes->total_size -= pes->data_index - 6; - else - pes->total_size = MAX_PES_PAYLOAD; - /* allocate pes buffer */ - pes->buffer = av_malloc(pes->total_size+FF_INPUT_BUFFER_PADDING_SIZE); - if (!pes->buffer) - return AVERROR(ENOMEM); + pes->extended_stream_id = -1; + if (flags & 0x01) { /* PES extension */ + pes_ext = *r++; + /* Skip PES private data, program packet sequence counter and P-STD buffer */ + skip = (pes_ext >> 4) & 0xb; + skip += skip & 0x9; + r += skip; + if ((pes_ext & 0x41) == 0x01 && + (r + 2) <= (pes->header + pes->pes_header_size)) { + /* PES extension 2 */ + if ((r[0] & 0x7f) > 0 && (r[1] & 0x80) == 0) + pes->extended_stream_id = r[1]; + } + } /* we got the full header. We parse it and get the payload */ pes->state = MPEGTS_PAYLOAD; @@ -975,7 +1087,7 @@ static int mpegts_push_data(MpegTSFilter *filter, } break; case MPEGTS_PAYLOAD: - if (buf_size > 0) { + if (buf_size > 0 && pes->buffer) { if (pes->data_index+buf_size > pes->total_size) { new_pes_packet(pes, ts->pkt); pes->total_size = MAX_PES_PAYLOAD; @@ -1012,6 +1124,9 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid, int s pes->pid = pid; pes->pcr_pid = pcr_pid; pes->stream_type = stream_type; + pes->state = MPEGTS_SKIP; + pes->pts = AV_NOPTS_VALUE; + pes->dts = AV_NOPTS_VALUE; tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); if (!tss) { av_free(pes); @@ -1103,8 +1218,9 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) /* XXX: try to find a better synchro over several packets (use get_packet_size() ?) */ -static int mpegts_resync(ByteIOContext *pb) +static int mpegts_resync(AVFormatContext *s) { + ByteIOContext *pb = s->pb; int c, i; for(i = 0;i < MAX_RESYNC_SIZE; i++) { @@ -1116,13 +1232,15 @@ static int mpegts_resync(ByteIOContext *pb) return 0; } } + av_log(s, AV_LOG_ERROR, "max resync size reached, could not find sync byte\n"); /* no sync found */ return -1; } /* return -1 if error or EOF. Return 0 if OK. */ -static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size) +static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size) { + ByteIOContext *pb = s->pb; int skip, len; for(;;) { @@ -1133,8 +1251,8 @@ static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size) if (buf[0] != 0x47) { /* find a new packet start */ url_fseek(pb, -TS_PACKET_SIZE, SEEK_CUR); - if (mpegts_resync(pb) < 0) - return AVERROR_INVALIDDATA; + if (mpegts_resync(s) < 0) + return AVERROR(EAGAIN); else continue; } else { @@ -1150,7 +1268,6 @@ static int read_packet(ByteIOContext *pb, uint8_t *buf, int raw_packet_size) static int handle_packets(MpegTSContext *ts, int nb_packets) { AVFormatContext *s = ts->stream; - ByteIOContext *pb = s->pb; uint8_t packet[TS_PACKET_SIZE]; int packet_num, ret; @@ -1162,7 +1279,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) packet_num++; if (nb_packets != 0 && packet_num >= nb_packets) break; - ret = read_packet(pb, packet, ts->raw_packet_size); + ret = read_packet(s, packet, ts->raw_packet_size); if (ret != 0) return ret; ret = handle_packet(ts, packet); @@ -1269,7 +1386,7 @@ static int mpegts_read_header(AVFormatContext *s, mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1); - handle_packets(ts, s->probesize); + handle_packets(ts, s->probesize / ts->raw_packet_size); /* if could not find service, enable auto_guess */ ts->auto_guess = 1; @@ -1298,7 +1415,7 @@ static int mpegts_read_header(AVFormatContext *s, nb_pcrs = 0; nb_packets = 0; for(;;) { - ret = read_packet(s->pb, packet, ts->raw_packet_size); + ret = read_packet(s, packet, ts->raw_packet_size); if (ret < 0) return -1; pid = AV_RB16(packet + 1) & 0x1fff; @@ -1347,7 +1464,7 @@ static int mpegts_raw_read_packet(AVFormatContext *s, if (av_new_packet(pkt, TS_PACKET_SIZE) < 0) return AVERROR(ENOMEM); pkt->pos= url_ftell(s->pb); - ret = read_packet(s->pb, pkt->data, ts->raw_packet_size); + ret = read_packet(s, pkt->data, ts->raw_packet_size); if (ret < 0) { av_free_packet(pkt); return ret; @@ -1406,6 +1523,7 @@ static int mpegts_read_packet(AVFormatContext *s, PESContext *pes = ts->pids[i]->u.pes_filter.opaque; if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { new_pes_packet(pes, pkt); + pes->state = MPEGTS_SKIP; ret = 0; break; } @@ -1470,6 +1588,92 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index, return timestamp; } +#ifdef USE_SYNCPOINT_SEARCH + +static int read_seek2(AVFormatContext *s, + int stream_index, + int64_t min_ts, + int64_t target_ts, + int64_t max_ts, + int flags) +{ + int64_t pos; + + int64_t ts_ret, ts_adj; + int stream_index_gen_search; + AVStream *st; + AVParserState *backup; + + backup = ff_store_parser_state(s); + + // detect direction of seeking for search purposes + flags |= (target_ts - min_ts > (uint64_t)(max_ts - target_ts)) ? + AVSEEK_FLAG_BACKWARD : 0; + + if (flags & AVSEEK_FLAG_BYTE) { + // use position directly, we will search starting from it + pos = target_ts; + } else { + // search for some position with good timestamp match + if (stream_index < 0) { + stream_index_gen_search = av_find_default_stream_index(s); + if (stream_index_gen_search < 0) { + ff_restore_parser_state(s, backup); + return -1; + } + + st = s->streams[stream_index_gen_search]; + // timestamp for default must be expressed in AV_TIME_BASE units + ts_adj = av_rescale(target_ts, + st->time_base.den, + AV_TIME_BASE * (int64_t)st->time_base.num); + } else { + ts_adj = target_ts; + stream_index_gen_search = stream_index; + } + pos = av_gen_search(s, stream_index_gen_search, ts_adj, + 0, INT64_MAX, -1, + AV_NOPTS_VALUE, + AV_NOPTS_VALUE, + flags, &ts_ret, mpegts_get_pcr); + if (pos < 0) { + ff_restore_parser_state(s, backup); + return -1; + } + } + + // search for actual matching keyframe/starting position for all streams + if (ff_gen_syncpoint_search(s, stream_index, pos, + min_ts, target_ts, max_ts, + flags) < 0) { + ff_restore_parser_state(s, backup); + return -1; + } + + ff_free_parser_state(s, backup); + return 0; +} + +static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags) +{ + int ret; + if (flags & AVSEEK_FLAG_BACKWARD) { + flags &= ~AVSEEK_FLAG_BACKWARD; + ret = read_seek2(s, stream_index, INT64_MIN, target_ts, target_ts, flags); + if (ret < 0) + // for compatibility reasons, seek to the best-fitting timestamp + ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags); + } else { + ret = read_seek2(s, stream_index, target_ts, target_ts, INT64_MAX, flags); + if (ret < 0) + // for compatibility reasons, seek to the best-fitting timestamp + ret = read_seek2(s, stream_index, INT64_MIN, target_ts, INT64_MAX, flags); + } + return ret; +} + +#else + static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){ MpegTSContext *ts = s->priv_data; uint8_t buf[TS_PACKET_SIZE]; @@ -1493,6 +1697,8 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, in return 0; } +#endif + /**************************************************************/ /* parsing functions - called from other demuxers such as RTP */ @@ -1557,6 +1763,9 @@ AVInputFormat mpegts_demuxer = { read_seek, mpegts_get_pcr, .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, +#ifdef USE_SYNCPOINT_SEARCH + .read_seek2 = read_seek2, +#endif }; AVInputFormat mpegtsraw_demuxer = { @@ -1570,4 +1779,7 @@ AVInputFormat mpegtsraw_demuxer = { read_seek, mpegts_get_pcr, .flags = AVFMT_SHOW_IDS|AVFMT_TS_DISCONT, +#ifdef USE_SYNCPOINT_SEARCH + .read_seek2 = read_seek2, +#endif };