mpeg.c 16.2 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1
/*
2
 * MPEG1/2 demuxer
3
 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard.
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
21

Fabrice Bellard's avatar
Fabrice Bellard committed
22
#include "avformat.h"
23
#include "mpeg.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
24

Fabrice Bellard's avatar
Fabrice Bellard committed
25
//#define DEBUG_SEEK
Fabrice Bellard's avatar
Fabrice Bellard committed
26

27 28 29
#undef NDEBUG
#include <assert.h>

Fabrice Bellard's avatar
Fabrice Bellard committed
30 31 32 33 34
/*********************************************/
/* demux code */

#define MAX_SYNC_SIZE 100000

35 36 37 38 39 40 41 42 43 44 45 46
static int cdxa_probe(AVProbeData *p)
{
    /* check file header */
    if (p->buf[0] == 'R' && p->buf[1] == 'I' &&
        p->buf[2] == 'F' && p->buf[3] == 'F' &&
        p->buf[8] == 'C' && p->buf[9] == 'D' &&
        p->buf[10] == 'X' && p->buf[11] == 'A')
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

47 48
static int mpegps_probe(AVProbeData *p)
{
49
    uint32_t code= -1;
50
    int sys=0, pspack=0, priv1=0, vid=0, audio=0;
51
    int i;
52
    int score=0;
53

54 55 56 57
    score = cdxa_probe(p);
    if (score > 0) return score;

    /* Search for MPEG stream */
58 59
    for(i=0; i<p->buf_size; i++){
        code = (code<<8) + p->buf[i];
60
        if ((code & 0xffffff00) == 0x100) {
61 62 63 64 65
            if(code == SYSTEM_HEADER_START_CODE) sys++;
            else if(code == PRIVATE_STREAM_1)    priv1++;
            else if(code == PACK_START_CODE)     pspack++;
            else if((code & 0xf0) == VIDEO_ID)   vid++;
            else if((code & 0xe0) == AUDIO_ID)   audio++;
66
        }
67
    }
68 69 70 71

    if(vid || audio)            /* invalid VDR files nd short PES streams */
        score= AVPROBE_SCORE_MAX/4;

Michael Niedermayer's avatar
Michael Niedermayer committed
72
//av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d len:%d\n", sys, priv1, pspack,vid, audio, p->buf_size);
73 74
    if(sys && sys*9 <= pspack*10)
        return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
75
    if((priv1 || vid || audio) && (priv1+vid+audio)*9 <= pspack*10)
76
        return AVPROBE_SCORE_MAX/2+2; // +1 for .mpg
77
    if((!!vid ^ !!audio) && (audio+vid > 1) && !sys && !pspack && p->buf_size>2048) /* PES stream */
78
        return AVPROBE_SCORE_MAX/2+2;
79 80 81

    //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
    return score;
82 83 84
}


Fabrice Bellard's avatar
Fabrice Bellard committed
85
typedef struct MpegDemuxContext {
86
    int32_t header_state;
87
    unsigned char psm_es_type[256];
Fabrice Bellard's avatar
Fabrice Bellard committed
88 89
} MpegDemuxContext;

Fabrice Bellard's avatar
Fabrice Bellard committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
static int mpegps_read_header(AVFormatContext *s,
                              AVFormatParameters *ap)
{
    MpegDemuxContext *m = s->priv_data;
    m->header_state = 0xff;
    s->ctx_flags |= AVFMTCTX_NOHEADER;

    /* no need to do more */
    return 0;
}

static int64_t get_pts(ByteIOContext *pb, int c)
{
    int64_t pts;
    int val;

    if (c < 0)
        c = get_byte(pb);
    pts = (int64_t)((c >> 1) & 0x07) << 30;
    val = get_be16(pb);
    pts |= (int64_t)(val >> 1) << 15;
    val = get_be16(pb);
    pts |= (int64_t)(val >> 1);
    return pts;
}

116
static int find_next_start_code(ByteIOContext *pb, int *size_ptr,
117
                                int32_t *header_state)
Fabrice Bellard's avatar
Fabrice Bellard committed
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
{
    unsigned int state, v;
    int val, n;

    state = *header_state;
    n = *size_ptr;
    while (n > 0) {
        if (url_feof(pb))
            break;
        v = get_byte(pb);
        n--;
        if (state == 0x000001) {
            state = ((state << 8) | v) & 0xffffff;
            val = state;
            goto found;
        }
        state = ((state << 8) | v) & 0xffffff;
    }
    val = -1;
 found:
    *header_state = state;
    *size_ptr = n;
    return val;
}

143
#if 0 /* unused, remove? */
Fabrice Bellard's avatar
Fabrice Bellard committed
144 145
/* XXX: optimize */
static int find_prev_start_code(ByteIOContext *pb, int *size_ptr)
Fabrice Bellard's avatar
Fabrice Bellard committed
146
{
Fabrice Bellard's avatar
Fabrice Bellard committed
147 148
    int64_t pos, pos_start;
    int max_size, start_code;
149

Fabrice Bellard's avatar
Fabrice Bellard committed
150 151
    max_size = *size_ptr;
    pos_start = url_ftell(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
152

Fabrice Bellard's avatar
Fabrice Bellard committed
153 154 155 156 157 158
    /* in order to go faster, we fill the buffer */
    pos = pos_start - 16386;
    if (pos < 0)
        pos = 0;
    url_fseek(pb, pos, SEEK_SET);
    get_byte(pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
159

Fabrice Bellard's avatar
Fabrice Bellard committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
    pos = pos_start;
    for(;;) {
        pos--;
        if (pos < 0 || (pos_start - pos) >= max_size) {
            start_code = -1;
            goto the_end;
        }
        url_fseek(pb, pos, SEEK_SET);
        start_code = get_be32(pb);
        if ((start_code & 0xffffff00) == 0x100)
            break;
    }
 the_end:
    *size_ptr = pos_start - pos;
    return start_code;
Fabrice Bellard's avatar
Fabrice Bellard committed
175
}
176
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
177

178 179 180
/**
 * Extracts stream types from a program stream map
 * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35
181
 *
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
 * @return number of bytes occupied by PSM in the bitstream
 */
static long mpegps_psm_parse(MpegDemuxContext *m, ByteIOContext *pb)
{
    int psm_length, ps_info_length, es_map_length;

    psm_length = get_be16(pb);
    get_byte(pb);
    get_byte(pb);
    ps_info_length = get_be16(pb);

    /* skip program_stream_info */
    url_fskip(pb, ps_info_length);
    es_map_length = get_be16(pb);

    /* at least one es available? */
    while (es_map_length >= 4){
        unsigned char type = get_byte(pb);
        unsigned char es_id = get_byte(pb);
        uint16_t es_info_length = get_be16(pb);
        /* remember mapping from stream id to stream type */
        m->psm_es_type[es_id] = type;
        /* skip program_stream_info */
        url_fskip(pb, es_info_length);
        es_map_length -= 4 + es_info_length;
    }
    get_be32(pb); /* crc32 */
    return 2 + psm_length;
}

212
/* read the next PES header. Return its position in ppos
Fabrice Bellard's avatar
Fabrice Bellard committed
213 214 215
   (if not NULL), and its start code, pts and dts.
 */
static int mpegps_read_pes_header(AVFormatContext *s,
216
                                  int64_t *ppos, int *pstart_code,
217
                                  int64_t *ppts, int64_t *pdts)
Fabrice Bellard's avatar
Fabrice Bellard committed
218 219
{
    MpegDemuxContext *m = s->priv_data;
Fabrice Bellard's avatar
Fabrice Bellard committed
220
    int len, size, startcode, c, flags, header_len;
221
    int pes_ext, ext2_len, id_ext, skip;
222 223
    int64_t pts, dts;
    int64_t last_sync= url_ftell(&s->pb);
Fabrice Bellard's avatar
Fabrice Bellard committed
224

225 226
 error_redo:
        url_fseek(&s->pb, last_sync, SEEK_SET);
Fabrice Bellard's avatar
Fabrice Bellard committed
227
 redo:
Fabrice Bellard's avatar
Fabrice Bellard committed
228 229 230 231
        /* next start code (should be immediately after) */
        m->header_state = 0xff;
        size = MAX_SYNC_SIZE;
        startcode = find_next_start_code(&s->pb, &size, &m->header_state);
232
        last_sync = url_ftell(&s->pb);
233
    //printf("startcode=%x pos=0x%"PRIx64"\n", startcode, url_ftell(&s->pb));
Fabrice Bellard's avatar
Fabrice Bellard committed
234
    if (startcode < 0)
235
        return AVERROR(EIO);
Fabrice Bellard's avatar
Fabrice Bellard committed
236 237 238 239 240 241 242 243 244 245 246
    if (startcode == PACK_START_CODE)
        goto redo;
    if (startcode == SYSTEM_HEADER_START_CODE)
        goto redo;
    if (startcode == PADDING_STREAM ||
        startcode == PRIVATE_STREAM_2) {
        /* skip them */
        len = get_be16(&s->pb);
        url_fskip(&s->pb, len);
        goto redo;
    }
247 248 249 250
    if (startcode == PROGRAM_STREAM_MAP) {
        mpegps_psm_parse(m, &s->pb);
        goto redo;
    }
251

Fabrice Bellard's avatar
Fabrice Bellard committed
252 253 254
    /* find matching stream */
    if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
          (startcode >= 0x1e0 && startcode <= 0x1ef) ||
255
          (startcode == 0x1bd) || (startcode == 0x1fd)))
Fabrice Bellard's avatar
Fabrice Bellard committed
256
        goto redo;
Fabrice Bellard's avatar
Fabrice Bellard committed
257 258 259
    if (ppos) {
        *ppos = url_ftell(&s->pb) - 4;
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
260
    len = get_be16(&s->pb);
Michael Niedermayer's avatar
Michael Niedermayer committed
261
    pts =
262
    dts = AV_NOPTS_VALUE;
Fabrice Bellard's avatar
Fabrice Bellard committed
263 264
    /* stuffing */
    for(;;) {
Fabrice Bellard's avatar
Fabrice Bellard committed
265
        if (len < 1)
266
            goto error_redo;
Fabrice Bellard's avatar
Fabrice Bellard committed
267 268 269
        c = get_byte(&s->pb);
        len--;
        /* XXX: for mpeg1, should test only bit 7 */
270
        if (c != 0xff)
Fabrice Bellard's avatar
Fabrice Bellard committed
271 272 273 274 275 276 277 278
            break;
    }
    if ((c & 0xc0) == 0x40) {
        /* buffer scale & size */
        get_byte(&s->pb);
        c = get_byte(&s->pb);
        len -= 2;
    }
279
    if ((c & 0xe0) == 0x20) {
Fabrice Bellard's avatar
Fabrice Bellard committed
280
        dts = pts = get_pts(&s->pb, c);
Fabrice Bellard's avatar
Fabrice Bellard committed
281
        len -= 4;
282 283 284 285
        if (c & 0x10){
            dts = get_pts(&s->pb, -1);
            len -= 5;
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
286 287
    } else if ((c & 0xc0) == 0x80) {
        /* mpeg 2 PES */
288
#if 0 /* some streams have this field set for no apparent reason */
Fabrice Bellard's avatar
Fabrice Bellard committed
289
        if ((c & 0x30) != 0) {
Fabrice Bellard's avatar
Fabrice Bellard committed
290 291
            /* Encrypted multiplex not handled */
            goto redo;
Fabrice Bellard's avatar
Fabrice Bellard committed
292
        }
293
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
294 295 296 297
        flags = get_byte(&s->pb);
        header_len = get_byte(&s->pb);
        len -= 2;
        if (header_len > len)
298
            goto error_redo;
Michael Niedermayer's avatar
Michael Niedermayer committed
299
        len -= header_len;
300
        if (flags & 0x80) {
Fabrice Bellard's avatar
Fabrice Bellard committed
301
            dts = pts = get_pts(&s->pb, -1);
Fabrice Bellard's avatar
Fabrice Bellard committed
302
            header_len -= 5;
303 304 305 306
            if (flags & 0x40) {
                dts = get_pts(&s->pb, -1);
                header_len -= 5;
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
307
        }
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        if (flags & 0x01) { /* PES extension */
            pes_ext = get_byte(&s->pb);
            header_len--;
            if (pes_ext & 0x40) { /* pack header - should be zero in PS */
                goto error_redo;
            }
            /* Skip PES private data, program packet sequence counter and P-STD buffer */
            skip = (pes_ext >> 4) & 0xb;
            skip += skip & 0x9;
            url_fskip(&s->pb, skip);
            header_len -= skip;

            if (pes_ext & 0x01) { /* PES extension 2 */
                ext2_len = get_byte(&s->pb);
                header_len--;
                if ((ext2_len & 0x7f) > 0) {
                    id_ext = get_byte(&s->pb);
                    if ((id_ext & 0x80) == 0)
                        startcode = ((startcode & 0xff) << 8) | id_ext;
                    header_len--;
                }
            }
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
331 332 333
        if(header_len < 0)
            goto error_redo;
        url_fskip(&s->pb, header_len);
Fabrice Bellard's avatar
Fabrice Bellard committed
334
    }
335 336 337
    else if( c!= 0xf )
        goto redo;

338
    if (startcode == PRIVATE_STREAM_1 && !m->psm_es_type[startcode & 0xff]) {
Fabrice Bellard's avatar
Fabrice Bellard committed
339 340
        startcode = get_byte(&s->pb);
        len--;
341
        if (startcode >= 0x80 && startcode <= 0xcf) {
Fabrice Bellard's avatar
Fabrice Bellard committed
342 343 344 345 346
            /* audio: skip header */
            get_byte(&s->pb);
            get_byte(&s->pb);
            get_byte(&s->pb);
            len -= 3;
347 348 349 350 351
            if (startcode >= 0xb0 && startcode <= 0xbf) {
                /* MLP/TrueHD audio has a 4-byte header */
                get_byte(&s->pb);
                len--;
            }
Fabrice Bellard's avatar
Fabrice Bellard committed
352 353
        }
    }
354 355
    if(len<0)
        goto error_redo;
356 357 358 359
    if(dts != AV_NOPTS_VALUE && ppos){
        int i;
        for(i=0; i<s->nb_streams; i++){
            if(startcode == s->streams[i]->id) {
360
                av_add_index_entry(s->streams[i], *ppos, dts, 0, 0, AVINDEX_KEYFRAME /* FIXME keyframe? */);
361 362 363
            }
        }
    }
364

Fabrice Bellard's avatar
Fabrice Bellard committed
365 366 367 368 369 370 371 372 373
    *pstart_code = startcode;
    *ppts = pts;
    *pdts = dts;
    return len;
}

static int mpegps_read_packet(AVFormatContext *s,
                              AVPacket *pkt)
{
374
    MpegDemuxContext *m = s->priv_data;
Fabrice Bellard's avatar
Fabrice Bellard committed
375
    AVStream *st;
376
    int len, startcode, i, type, codec_id = 0, es_type;
377
    int64_t pts, dts, dummy_pos; //dummy_pos is needed for the index building to work
Fabrice Bellard's avatar
Fabrice Bellard committed
378 379

 redo:
380
    len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts);
Fabrice Bellard's avatar
Fabrice Bellard committed
381 382
    if (len < 0)
        return len;
383

Fabrice Bellard's avatar
Fabrice Bellard committed
384 385 386 387 388 389
    /* now find stream */
    for(i=0;i<s->nb_streams;i++) {
        st = s->streams[i];
        if (st->id == startcode)
            goto found;
    }
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418

    es_type = m->psm_es_type[startcode & 0xff];
    if(es_type > 0){
        if(es_type == STREAM_TYPE_VIDEO_MPEG1){
            codec_id = CODEC_ID_MPEG2VIDEO;
            type = CODEC_TYPE_VIDEO;
        } else if(es_type == STREAM_TYPE_VIDEO_MPEG2){
            codec_id = CODEC_ID_MPEG2VIDEO;
            type = CODEC_TYPE_VIDEO;
        } else if(es_type == STREAM_TYPE_AUDIO_MPEG1 ||
                  es_type == STREAM_TYPE_AUDIO_MPEG2){
            codec_id = CODEC_ID_MP3;
            type = CODEC_TYPE_AUDIO;
        } else if(es_type == STREAM_TYPE_AUDIO_AAC){
            codec_id = CODEC_ID_AAC;
            type = CODEC_TYPE_AUDIO;
        } else if(es_type == STREAM_TYPE_VIDEO_MPEG4){
            codec_id = CODEC_ID_MPEG4;
            type = CODEC_TYPE_VIDEO;
        } else if(es_type == STREAM_TYPE_VIDEO_H264){
            codec_id = CODEC_ID_H264;
            type = CODEC_TYPE_VIDEO;
        } else if(es_type == STREAM_TYPE_AUDIO_AC3){
            codec_id = CODEC_ID_AC3;
            type = CODEC_TYPE_AUDIO;
        } else {
            goto skip;
        }
    } else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
419 420 421 422 423 424 425 426
        static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 };
        unsigned char buf[8];
        get_buffer(&s->pb, buf, 8);
        url_fseek(&s->pb, -8, SEEK_CUR);
        if(!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
            codec_id = CODEC_ID_CAVS;
        else
            codec_id = CODEC_ID_MPEG2VIDEO;
427 428 429 430
        type = CODEC_TYPE_VIDEO;
    } else if (startcode >= 0x1c0 && startcode <= 0x1df) {
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_MP2;
431
    } else if (startcode >= 0x80 && startcode <= 0x87) {
432 433
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_AC3;
434 435 436
    } else if ((startcode >= 0x88 && startcode <= 0x8f)
               ||( startcode >= 0x98 && startcode <= 0x9f)) {
        /* 0x90 - 0x97 is reserved for SDDS in DVD specs */
437 438
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_DTS;
439
    } else if (startcode >= 0xa0 && startcode <= 0xaf) {
440 441
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_PCM_S16BE;
442 443 444 445 446 447 448
    } else if (startcode >= 0xb0 && startcode <= 0xbf) {
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_MLP;
    } else if (startcode >= 0xc0 && startcode <= 0xcf) {
        /* Used for both AC-3 and E-AC-3 in EVOB files */
        type = CODEC_TYPE_AUDIO;
        codec_id = CODEC_ID_AC3;
449 450 451
    } else if (startcode >= 0x20 && startcode <= 0x3f) {
        type = CODEC_TYPE_SUBTITLE;
        codec_id = CODEC_ID_DVD_SUBTITLE;
452 453 454
    } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) {
        type = CODEC_TYPE_VIDEO;
        codec_id = CODEC_ID_VC1;
455 456 457 458 459 460
    } else {
    skip:
        /* skip packet */
        url_fskip(&s->pb, len);
        goto redo;
    }
461 462
    /* no stream found: add a new stream */
    st = av_new_stream(s, startcode);
463
    if (!st)
464
        goto skip;
465 466
    st->codec->codec_type = type;
    st->codec->codec_id = codec_id;
Fabrice Bellard's avatar
Fabrice Bellard committed
467
    if (codec_id != CODEC_ID_PCM_S16BE)
468
        st->need_parsing = AVSTREAM_PARSE_FULL;
Fabrice Bellard's avatar
Fabrice Bellard committed
469
 found:
470
    if(st->discard >= AVDISCARD_ALL)
471
        goto skip;
472
    if (startcode >= 0xa0 && startcode <= 0xaf) {
473 474 475 476 477 478 479 480 481 482 483
        int b1, freq;

        /* for LPCM, we just skip the header and consider it is raw
           audio data */
        if (len <= 3)
            goto skip;
        get_byte(&s->pb); /* emphasis (1), muse(1), reserved(1), frame number(5) */
        b1 = get_byte(&s->pb); /* quant (2), freq(2), reserved(1), channels(3) */
        get_byte(&s->pb); /* dynamic range control (0x80 = off) */
        len -= 3;
        freq = (b1 >> 4) & 3;
484 485 486
        st->codec->sample_rate = lpcm_freq_tab[freq];
        st->codec->channels = 1 + (b1 & 7);
        st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 2;
487
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
488 489 490
    av_new_packet(pkt, len);
    get_buffer(&s->pb, pkt->data, pkt->size);
    pkt->pts = pts;
Fabrice Bellard's avatar
Fabrice Bellard committed
491
    pkt->dts = dts;
492
    pkt->stream_index = st->index;
493
#if 0
494 495
    av_log(s, AV_LOG_DEBUG, "%d: pts=%0.3f dts=%0.3f size=%d\n",
           pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0, pkt->size);
496
#endif
497

Fabrice Bellard's avatar
Fabrice Bellard committed
498 499 500
    return 0;
}

501
static int mpegps_read_close(AVFormatContext *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
502 503 504 505
{
    return 0;
}

506
static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
507
                               int64_t *ppos, int64_t pos_limit)
Fabrice Bellard's avatar
Fabrice Bellard committed
508 509 510 511 512 513
{
    int len, startcode;
    int64_t pos, pts, dts;

    pos = *ppos;
#ifdef DEBUG_SEEK
514
    printf("read_dts: pos=0x%"PRIx64" next=%d -> ", pos, find_next);
Fabrice Bellard's avatar
Fabrice Bellard committed
515 516 517
#endif
    url_fseek(&s->pb, pos, SEEK_SET);
    for(;;) {
518
        len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts);
Fabrice Bellard's avatar
Fabrice Bellard committed
519 520 521 522 523 524
        if (len < 0) {
#ifdef DEBUG_SEEK
            printf("none (ret=%d)\n", len);
#endif
            return AV_NOPTS_VALUE;
        }
525
        if (startcode == s->streams[stream_index]->id &&
Fabrice Bellard's avatar
Fabrice Bellard committed
526 527 528
            dts != AV_NOPTS_VALUE) {
            break;
        }
529
        url_fskip(&s->pb, len);
Fabrice Bellard's avatar
Fabrice Bellard committed
530 531
    }
#ifdef DEBUG_SEEK
532
    printf("pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n", pos, dts, dts / 90000.0);
Fabrice Bellard's avatar
Fabrice Bellard committed
533 534
#endif
    *ppos = pos;
535
    return dts;
Fabrice Bellard's avatar
Fabrice Bellard committed
536 537
}

538
AVInputFormat mpegps_demuxer = {
539 540 541 542 543 544 545
    "mpeg",
    "MPEG PS format",
    sizeof(MpegDemuxContext),
    mpegps_probe,
    mpegps_read_header,
    mpegps_read_packet,
    mpegps_read_close,
546 547
    NULL, //mpegps_read_seek,
    mpegps_read_dts,
548
    .flags = AVFMT_SHOW_IDS,
Fabrice Bellard's avatar
Fabrice Bellard committed
549
};