LCOV - code coverage report
Current view: top level - libavformat - mpeg.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 435 608 71.5 %
Date: 2017-12-17 23:02:56 Functions: 14 15 93.3 %

          Line data    Source code
       1             : /*
       2             :  * MPEG-1/2 demuxer
       3             :  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      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
      20             :  */
      21             : 
      22             : #include "avformat.h"
      23             : #include "internal.h"
      24             : #include "mpeg.h"
      25             : 
      26             : #if CONFIG_VOBSUB_DEMUXER
      27             : # include "subtitles.h"
      28             : # include "libavutil/bprint.h"
      29             : # include "libavutil/opt.h"
      30             : #endif
      31             : 
      32             : #include "libavutil/avassert.h"
      33             : 
      34             : /*********************************************/
      35             : /* demux code */
      36             : 
      37             : #define MAX_SYNC_SIZE 100000
      38             : 
      39       43974 : static int check_pes(const uint8_t *p, const uint8_t *end)
      40             : {
      41             :     int pes1;
      42       91103 :     int pes2 = (p[3] & 0xC0) == 0x80 &&
      43       47859 :                (p[4] & 0xC0) != 0x40 &&
      44        3731 :                ((p[4] & 0xC0) == 0x00 ||
      45        1226 :                 (p[4] & 0xC0) >> 2 == (p[6] & 0xF0));
      46             : 
      47       43974 :     for (p += 3; p < end && *p == 0xFF; p++) ;
      48       43974 :     if ((*p & 0xC0) == 0x40)
      49        5242 :         p += 2;
      50             : 
      51       43974 :     if ((*p & 0xF0) == 0x20)
      52        1350 :         pes1 = p[0] & p[2] & p[4] & 1;
      53       42624 :     else if ((*p & 0xF0) == 0x30)
      54        1184 :         pes1 = p[0] & p[2] & p[4] & p[5] & p[7] & p[9] & 1;
      55             :     else
      56       41440 :         pes1 = *p == 0x0F;
      57             : 
      58       43974 :     return pes1 || pes2;
      59             : }
      60             : 
      61       44290 : static int check_pack_header(const uint8_t *buf)
      62             : {
      63       44290 :     return (buf[1] & 0xC0) == 0x40 || (buf[1] & 0xF0) == 0x20;
      64             : }
      65             : 
      66        6130 : static int mpegps_probe(AVProbeData *p)
      67             : {
      68        6130 :     uint32_t code = -1;
      69             :     int i;
      70        6130 :     int sys = 0, pspack = 0, priv1 = 0, vid = 0;
      71        6130 :     int audio = 0, invalid = 0, score = 0;
      72        6130 :     int endpes = 0;
      73             : 
      74   128249707 :     for (i = 0; i < p->buf_size; i++) {
      75   128243577 :         code = (code << 8) + p->buf[i];
      76   128243577 :         if ((code & 0xffffff00) == 0x100) {
      77       44290 :             int len  = p->buf[i + 1] << 8 | p->buf[i + 2];
      78       44290 :             int pes  = endpes <= i && check_pes(p->buf + i, p->buf + p->buf_size);
      79       44290 :             int pack = check_pack_header(p->buf + i);
      80             : 
      81       44290 :             if (code == SYSTEM_HEADER_START_CODE)
      82          14 :                 sys++;
      83       44276 :             else if (code == PACK_START_CODE && pack)
      84          34 :                 pspack++;
      85       44242 :             else if ((code & 0xf0) == VIDEO_ID && pes) {
      86          72 :                 endpes = i + len;
      87          72 :                 vid++;
      88             :             }
      89             :             // skip pes payload to avoid start code emulation for private
      90             :             // and audio streams
      91       44170 :             else if ((code & 0xe0) == AUDIO_ID &&  pes) {audio++; i+=len;}
      92       44160 :             else if (code == PRIVATE_STREAM_1  &&  pes) {priv1++; i+=len;}
      93       44148 :             else if (code == 0x1fd             &&  pes) vid++; //VC1
      94             : 
      95       44148 :             else if ((code & 0xf0) == VIDEO_ID && !pes) invalid++;
      96       43669 :             else if ((code & 0xe0) == AUDIO_ID && !pes) invalid++;
      97       43153 :             else if (code == PRIVATE_STREAM_1  && !pes) invalid++;
      98             :         }
      99             :     }
     100             : 
     101        6130 :     if (vid + audio > invalid + 1) /* invalid VDR files nd short PES streams */
     102          15 :         score = AVPROBE_SCORE_EXTENSION / 2;
     103             : 
     104             : //     av_log(NULL, AV_LOG_ERROR, "vid:%d aud:%d sys:%d pspack:%d invalid:%d size:%d \n",
     105             : //            vid, audio, sys, pspack, invalid, p->buf_size);
     106             : 
     107        6130 :     if (sys > invalid && sys * 9 <= pspack * 10)
     108           9 :         return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2
     109           9 :                                                      : AVPROBE_SCORE_EXTENSION / 2 + 1; // 1 more than mp3
     110        6121 :     if (pspack > invalid && (priv1 + vid + audio) * 10 >= pspack * 9)
     111             :         return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2
     112          10 :                           : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg
     113        6111 :     if ((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys &&
     114           9 :         !pspack && p->buf_size > 2048 && vid + audio > invalid) /* PES stream */
     115           0 :         return (audio > 12 || vid > 6 + 2 * invalid) ? AVPROBE_SCORE_EXTENSION + 2
     116           0 :                                                      : AVPROBE_SCORE_EXTENSION / 2;
     117             : 
     118             :     // 02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1
     119             :     // mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6
     120             :     // Have\ Yourself\ a\ Merry\ Little\ Christmas.mp3 0 0 0 5 0 1 len:21618
     121        6111 :     return score;
     122             : }
     123             : 
     124             : typedef struct MpegDemuxContext {
     125             :     AVClass *class;
     126             :     int32_t header_state;
     127             :     unsigned char psm_es_type[256];
     128             :     int sofdec;
     129             :     int dvd;
     130             :     int imkh_cctv;
     131             : #if CONFIG_VOBSUB_DEMUXER
     132             :     AVFormatContext *sub_ctx;
     133             :     FFDemuxSubtitlesQueue q[32];
     134             :     char *sub_name;
     135             : #endif
     136             : } MpegDemuxContext;
     137             : 
     138          15 : static int mpegps_read_header(AVFormatContext *s)
     139             : {
     140          15 :     MpegDemuxContext *m = s->priv_data;
     141          15 :     char buffer[7] = { 0 };
     142          15 :     int64_t last_pos = avio_tell(s->pb);
     143             : 
     144          15 :     m->header_state = 0xff;
     145          15 :     s->ctx_flags   |= AVFMTCTX_NOHEADER;
     146             : 
     147          15 :     avio_get_str(s->pb, 6, buffer, sizeof(buffer));
     148          15 :     if (!memcmp("IMKH", buffer, 4)) {
     149           0 :         m->imkh_cctv = 1;
     150          15 :     } else if (!memcmp("Sofdec", buffer, 6)) {
     151           0 :         m->sofdec = 1;
     152             :     } else
     153          15 :        avio_seek(s->pb, last_pos, SEEK_SET);
     154             : 
     155             :     /* no need to do more */
     156          15 :     return 0;
     157             : }
     158             : 
     159        1865 : static int64_t get_pts(AVIOContext *pb, int c)
     160             : {
     161             :     uint8_t buf[5];
     162             : 
     163        1865 :     buf[0] = c < 0 ? avio_r8(pb) : c;
     164        1865 :     avio_read(pb, buf + 1, 4);
     165             : 
     166        1865 :     return ff_parse_pes_pts(buf);
     167             : }
     168             : 
     169       13967 : static int find_next_start_code(AVIOContext *pb, int *size_ptr,
     170             :                                 int32_t *header_state)
     171             : {
     172             :     unsigned int state, v;
     173             :     int val, n;
     174             : 
     175       13967 :     state = *header_state;
     176       13967 :     n     = *size_ptr;
     177      230703 :     while (n > 0) {
     178      216736 :         if (avio_feof(pb))
     179         110 :             break;
     180      216626 :         v = avio_r8(pb);
     181      216626 :         n--;
     182      216626 :         if (state == 0x000001) {
     183       13857 :             state = ((state << 8) | v) & 0xffffff;
     184       13857 :             val   = state;
     185       13857 :             goto found;
     186             :         }
     187      202769 :         state = ((state << 8) | v) & 0xffffff;
     188             :     }
     189         110 :     val = -1;
     190             : 
     191       13967 : found:
     192       13967 :     *header_state = state;
     193       13967 :     *size_ptr     = n;
     194       13967 :     return val;
     195             : }
     196             : 
     197             : /**
     198             :  * Extract stream types from a program stream map
     199             :  * According to ISO/IEC 13818-1 ('MPEG-2 Systems') table 2-35
     200             :  *
     201             :  * @return number of bytes occupied by PSM in the bitstream
     202             :  */
     203           0 : static long mpegps_psm_parse(MpegDemuxContext *m, AVIOContext *pb)
     204             : {
     205             :     int psm_length, ps_info_length, es_map_length;
     206             : 
     207           0 :     psm_length = avio_rb16(pb);
     208           0 :     avio_r8(pb);
     209           0 :     avio_r8(pb);
     210           0 :     ps_info_length = avio_rb16(pb);
     211             : 
     212             :     /* skip program_stream_info */
     213           0 :     avio_skip(pb, ps_info_length);
     214           0 :     /*es_map_length = */avio_rb16(pb);
     215             :     /* Ignore es_map_length, trust psm_length */
     216           0 :     es_map_length = psm_length - ps_info_length - 10;
     217             : 
     218             :     /* at least one es available? */
     219           0 :     while (es_map_length >= 4) {
     220           0 :         unsigned char type      = avio_r8(pb);
     221           0 :         unsigned char es_id     = avio_r8(pb);
     222           0 :         uint16_t es_info_length = avio_rb16(pb);
     223             : 
     224             :         /* remember mapping from stream id to stream type */
     225           0 :         m->psm_es_type[es_id] = type;
     226             :         /* skip program_stream_info */
     227           0 :         avio_skip(pb, es_info_length);
     228           0 :         es_map_length -= 4 + es_info_length;
     229             :     }
     230           0 :     avio_rb32(pb); /* crc32 */
     231           0 :     return 2 + psm_length;
     232             : }
     233             : 
     234             : /* read the next PES header. Return its position in ppos
     235             :  * (if not NULL), and its start code, pts and dts.
     236             :  */
     237        8385 : static int mpegps_read_pes_header(AVFormatContext *s,
     238             :                                   int64_t *ppos, int *pstart_code,
     239             :                                   int64_t *ppts, int64_t *pdts)
     240             : {
     241        8385 :     MpegDemuxContext *m = s->priv_data;
     242             :     int len, size, startcode, c, flags, header_len;
     243             :     int pes_ext, ext2_len, id_ext, skip;
     244             :     int64_t pts, dts;
     245        8385 :     int64_t last_sync = avio_tell(s->pb);
     246             : 
     247        8385 : error_redo:
     248        8385 :     avio_seek(s->pb, last_sync, SEEK_SET);
     249       13967 : redo:
     250             :     /* next start code (should be immediately after) */
     251       13967 :     m->header_state = 0xff;
     252       13967 :     size      = MAX_SYNC_SIZE;
     253       13967 :     startcode = find_next_start_code(s->pb, &size, &m->header_state);
     254       13967 :     last_sync = avio_tell(s->pb);
     255       13967 :     if (startcode < 0) {
     256         110 :         if (avio_feof(s->pb))
     257         110 :             return AVERROR_EOF;
     258             :         // FIXME we should remember header_state
     259           0 :         return FFERROR_REDO;
     260             :     }
     261             : 
     262       13857 :     if (startcode == PACK_START_CODE)
     263        5000 :         goto redo;
     264        8857 :     if (startcode == SYSTEM_HEADER_START_CODE)
     265          55 :         goto redo;
     266        8802 :     if (startcode == PADDING_STREAM) {
     267         473 :         avio_skip(s->pb, avio_rb16(s->pb));
     268         473 :         goto redo;
     269             :     }
     270        8329 :     if (startcode == PRIVATE_STREAM_2) {
     271          44 :         if (!m->sofdec) {
     272             :             /* Need to detect whether this from a DVD or a 'Sofdec' stream */
     273           3 :             int len = avio_rb16(s->pb);
     274           3 :             int bytesread = 0;
     275           3 :             uint8_t *ps2buf = av_malloc(len);
     276             : 
     277           3 :             if (ps2buf) {
     278           3 :                 bytesread = avio_read(s->pb, ps2buf, len);
     279             : 
     280           3 :                 if (bytesread != len) {
     281           0 :                     avio_skip(s->pb, len - bytesread);
     282             :                 } else {
     283           3 :                     uint8_t *p = 0;
     284           3 :                     if (len >= 6)
     285           3 :                         p = memchr(ps2buf, 'S', len - 5);
     286             : 
     287           3 :                     if (p)
     288           0 :                         m->sofdec = !memcmp(p+1, "ofdec", 5);
     289             : 
     290           3 :                     m->sofdec -= !m->sofdec;
     291             : 
     292           3 :                     if (m->sofdec < 0) {
     293           6 :                         if (len == 980  && ps2buf[0] == 0) {
     294             :                             /* PCI structure? */
     295           3 :                             uint32_t startpts = AV_RB32(ps2buf + 0x0d);
     296           3 :                             uint32_t endpts = AV_RB32(ps2buf + 0x11);
     297           3 :                             uint8_t hours = ((ps2buf[0x19] >> 4) * 10) + (ps2buf[0x19] & 0x0f);
     298           3 :                             uint8_t mins  = ((ps2buf[0x1a] >> 4) * 10) + (ps2buf[0x1a] & 0x0f);
     299           3 :                             uint8_t secs  = ((ps2buf[0x1b] >> 4) * 10) + (ps2buf[0x1b] & 0x0f);
     300             : 
     301           6 :                             m->dvd = (hours <= 23 &&
     302           3 :                                       mins  <= 59 &&
     303           3 :                                       secs  <= 59 &&
     304           6 :                                       (ps2buf[0x19] & 0x0f) < 10 &&
     305           6 :                                       (ps2buf[0x1a] & 0x0f) < 10 &&
     306           9 :                                       (ps2buf[0x1b] & 0x0f) < 10 &&
     307             :                                       endpts >= startpts);
     308           0 :                         } else if (len == 1018 && ps2buf[0] == 1) {
     309             :                             /* DSI structure? */
     310           0 :                             uint8_t hours = ((ps2buf[0x1d] >> 4) * 10) + (ps2buf[0x1d] & 0x0f);
     311           0 :                             uint8_t mins  = ((ps2buf[0x1e] >> 4) * 10) + (ps2buf[0x1e] & 0x0f);
     312           0 :                             uint8_t secs  = ((ps2buf[0x1f] >> 4) * 10) + (ps2buf[0x1f] & 0x0f);
     313             : 
     314           0 :                             m->dvd = (hours <= 23 &&
     315           0 :                                       mins  <= 59 &&
     316           0 :                                       secs  <= 59 &&
     317           0 :                                       (ps2buf[0x1d] & 0x0f) < 10 &&
     318           0 :                                       (ps2buf[0x1e] & 0x0f) < 10 &&
     319           0 :                                       (ps2buf[0x1f] & 0x0f) < 10);
     320             :                         }
     321             :                     }
     322             :                 }
     323             : 
     324           3 :                 av_free(ps2buf);
     325             : 
     326             :                 /* If this isn't a DVD packet or no memory
     327             :                  * could be allocated, just ignore it.
     328             :                  * If we did, move back to the start of the
     329             :                  * packet (plus 'length' field) */
     330           6 :                 if (!m->dvd || avio_skip(s->pb, -(len + 2)) < 0) {
     331             :                     /* Skip back failed.
     332             :                      * This packet will be lost but that can't be helped
     333             :                      * if we can't skip back
     334             :                      */
     335             :                     goto redo;
     336             :                 }
     337             :             } else {
     338             :                 /* No memory */
     339           0 :                 avio_skip(s->pb, len);
     340           0 :                 goto redo;
     341             :             }
     342          41 :         } else if (!m->dvd) {
     343           0 :             int len = avio_rb16(s->pb);
     344           0 :             avio_skip(s->pb, len);
     345           0 :             goto redo;
     346             :         }
     347             :     }
     348        8329 :     if (startcode == PROGRAM_STREAM_MAP) {
     349           0 :         mpegps_psm_parse(m, s->pb);
     350           0 :         goto redo;
     351             :     }
     352             : 
     353             :     /* find matching stream */
     354        8383 :     if (!((startcode >= 0x1c0 && startcode <= 0x1df) ||
     355        7409 :           (startcode >= 0x1e0 && startcode <= 0x1ef) ||
     356          98 :           (startcode == 0x1bd) ||
     357             :           (startcode == PRIVATE_STREAM_2) ||
     358             :           (startcode == 0x1fd)))
     359          54 :         goto redo;
     360        8275 :     if (ppos) {
     361        8146 :         *ppos = avio_tell(s->pb) - 4;
     362             :     }
     363        8275 :     len = avio_rb16(s->pb);
     364        8275 :     pts =
     365        8275 :     dts = AV_NOPTS_VALUE;
     366        8275 :     if (startcode != PRIVATE_STREAM_2)
     367             :     {
     368             :     /* stuffing */
     369             :     for (;;) {
     370        8231 :         if (len < 1)
     371           0 :             goto error_redo;
     372        8231 :         c = avio_r8(s->pb);
     373        8231 :         len--;
     374             :         /* XXX: for MPEG-1, should test only bit 7 */
     375        8231 :         if (c != 0xff)
     376        8231 :             break;
     377             :     }
     378        8231 :     if ((c & 0xc0) == 0x40) {
     379             :         /* buffer scale & size */
     380           0 :         avio_r8(s->pb);
     381           0 :         c    = avio_r8(s->pb);
     382           0 :         len -= 2;
     383             :     }
     384        8231 :     if ((c & 0xe0) == 0x20) {
     385         727 :         dts  =
     386         727 :         pts  = get_pts(s->pb, c);
     387         727 :         len -= 4;
     388         727 :         if (c & 0x10) {
     389         471 :             dts  = get_pts(s->pb, -1);
     390         471 :             len -= 5;
     391             :         }
     392        7504 :     } else if ((c & 0xc0) == 0x80) {
     393             :         /* mpeg 2 PES */
     394        4716 :         flags      = avio_r8(s->pb);
     395        4716 :         header_len = avio_r8(s->pb);
     396        4716 :         len       -= 2;
     397        4716 :         if (header_len > len)
     398           0 :             goto error_redo;
     399        4716 :         len -= header_len;
     400        4716 :         if (flags & 0x80) {
     401         636 :             dts         = pts = get_pts(s->pb, -1);
     402         636 :             header_len -= 5;
     403         636 :             if (flags & 0x40) {
     404          31 :                 dts         = get_pts(s->pb, -1);
     405          31 :                 header_len -= 5;
     406             :             }
     407             :         }
     408        4716 :         if (flags & 0x3f && header_len == 0) {
     409           0 :             flags &= 0xC0;
     410           0 :             av_log(s, AV_LOG_WARNING, "Further flags set but no bytes left\n");
     411             :         }
     412        4716 :         if (flags & 0x01) { /* PES extension */
     413          17 :             pes_ext = avio_r8(s->pb);
     414          17 :             header_len--;
     415             :             /* Skip PES private data, program packet sequence counter
     416             :              * and P-STD buffer */
     417          17 :             skip  = (pes_ext >> 4) & 0xb;
     418          17 :             skip += skip & 0x9;
     419          17 :             if (pes_ext & 0x40 || skip > header_len) {
     420           0 :                 av_log(s, AV_LOG_WARNING, "pes_ext %X is invalid\n", pes_ext);
     421           0 :                 pes_ext = skip = 0;
     422             :             }
     423          17 :             avio_skip(s->pb, skip);
     424          17 :             header_len -= skip;
     425             : 
     426          17 :             if (pes_ext & 0x01) { /* PES extension 2 */
     427           0 :                 ext2_len = avio_r8(s->pb);
     428           0 :                 header_len--;
     429           0 :                 if ((ext2_len & 0x7f) > 0) {
     430           0 :                     id_ext = avio_r8(s->pb);
     431           0 :                     if ((id_ext & 0x80) == 0)
     432           0 :                         startcode = ((startcode & 0xff) << 8) | id_ext;
     433           0 :                     header_len--;
     434             :                 }
     435             :             }
     436             :         }
     437        4716 :         if (header_len < 0)
     438           0 :             goto error_redo;
     439        4716 :         avio_skip(s->pb, header_len);
     440        2788 :     } else if (c != 0xf)
     441           0 :         goto redo;
     442             :     }
     443             : 
     444        8275 :     if (startcode == PRIVATE_STREAM_1) {
     445         470 :         startcode = avio_r8(s->pb);
     446         470 :         len--;
     447             :     }
     448        8275 :     if (len < 0)
     449           0 :         goto error_redo;
     450        8275 :     if (dts != AV_NOPTS_VALUE && ppos) {
     451             :         int i;
     452        3936 :         for (i = 0; i < s->nb_streams; i++) {
     453        3913 :             if (startcode == s->streams[i]->id &&
     454        1252 :                 (s->pb->seekable & AVIO_SEEKABLE_NORMAL) /* index useless on streams anyway */) {
     455        1252 :                 ff_reduce_index(s, i);
     456        1252 :                 av_add_index_entry(s->streams[i], *ppos, dts, 0, 0,
     457             :                                    AVINDEX_KEYFRAME /* FIXME keyframe? */);
     458             :             }
     459             :         }
     460             :     }
     461             : 
     462        8275 :     *pstart_code = startcode;
     463        8275 :     *ppts        = pts;
     464        8275 :     *pdts        = dts;
     465        8275 :     return len;
     466             : }
     467             : 
     468        7323 : static int mpegps_read_packet(AVFormatContext *s,
     469             :                               AVPacket *pkt)
     470             : {
     471        7323 :     MpegDemuxContext *m = s->priv_data;
     472             :     AVStream *st;
     473             :     int len, startcode, i, es_type, ret;
     474        7323 :     int lpcm_header_len = -1; //Init to suppress warning
     475        7323 :     int request_probe= 0;
     476        7323 :     enum AVCodecID codec_id = AV_CODEC_ID_NONE;
     477             :     enum AVMediaType type;
     478             :     int64_t pts, dts, dummy_pos; // dummy_pos is needed for the index building to work
     479             : 
     480        7803 : redo:
     481        7803 :     len = mpegps_read_pes_header(s, &dummy_pos, &startcode, &pts, &dts);
     482        7803 :     if (len < 0)
     483          63 :         return len;
     484             : 
     485        7740 :     if (startcode >= 0x80 && startcode <= 0xcf) {
     486         311 :         if (len < 4)
     487           0 :             goto skip;
     488             : 
     489             :         /* audio: skip header */
     490         311 :         avio_r8(s->pb);
     491         311 :         lpcm_header_len = avio_rb16(s->pb);
     492         311 :         len -= 3;
     493         311 :         if (startcode >= 0xb0 && startcode <= 0xbf) {
     494             :             /* MLP/TrueHD audio has a 4-byte header */
     495           0 :             avio_r8(s->pb);
     496           0 :             len--;
     497             :         }
     498             :     }
     499             : 
     500             :     /* now find stream */
     501       11336 :     for (i = 0; i < s->nb_streams; i++) {
     502       11308 :         st = s->streams[i];
     503       11308 :         if (st->id == startcode)
     504        7712 :             goto found;
     505             :     }
     506             : 
     507          28 :     es_type = m->psm_es_type[startcode & 0xff];
     508          28 :         if (es_type == STREAM_TYPE_VIDEO_MPEG1) {
     509           0 :             codec_id = AV_CODEC_ID_MPEG2VIDEO;
     510           0 :             type     = AVMEDIA_TYPE_VIDEO;
     511          28 :         } else if (es_type == STREAM_TYPE_VIDEO_MPEG2) {
     512           0 :             codec_id = AV_CODEC_ID_MPEG2VIDEO;
     513           0 :             type     = AVMEDIA_TYPE_VIDEO;
     514          28 :         } else if (es_type == STREAM_TYPE_AUDIO_MPEG1 ||
     515             :                    es_type == STREAM_TYPE_AUDIO_MPEG2) {
     516           0 :             codec_id = AV_CODEC_ID_MP3;
     517           0 :             type     = AVMEDIA_TYPE_AUDIO;
     518          28 :         } else if (es_type == STREAM_TYPE_AUDIO_AAC) {
     519           0 :             codec_id = AV_CODEC_ID_AAC;
     520           0 :             type     = AVMEDIA_TYPE_AUDIO;
     521          28 :         } else if (es_type == STREAM_TYPE_VIDEO_MPEG4) {
     522           0 :             codec_id = AV_CODEC_ID_MPEG4;
     523           0 :             type     = AVMEDIA_TYPE_VIDEO;
     524          28 :         } else if (es_type == STREAM_TYPE_VIDEO_H264) {
     525           0 :             codec_id = AV_CODEC_ID_H264;
     526           0 :             type     = AVMEDIA_TYPE_VIDEO;
     527          28 :         } else if (es_type == STREAM_TYPE_AUDIO_AC3) {
     528           0 :             codec_id = AV_CODEC_ID_AC3;
     529           0 :             type     = AVMEDIA_TYPE_AUDIO;
     530          28 :         } else if (m->imkh_cctv && es_type == 0x91) {
     531           0 :             codec_id = AV_CODEC_ID_PCM_MULAW;
     532           0 :             type     = AVMEDIA_TYPE_AUDIO;
     533          42 :     } else if (startcode >= 0x1e0 && startcode <= 0x1ef) {
     534             :         static const unsigned char avs_seqh[4] = { 0, 0, 1, 0xb0 };
     535             :         unsigned char buf[8];
     536             : 
     537          14 :         avio_read(s->pb, buf, 8);
     538          14 :         avio_seek(s->pb, -8, SEEK_CUR);
     539          14 :         if (!memcmp(buf, avs_seqh, 4) && (buf[6] != 0 || buf[7] != 1))
     540           2 :             codec_id = AV_CODEC_ID_CAVS;
     541             :         else
     542          12 :             request_probe= 1;
     543          14 :         type = AVMEDIA_TYPE_VIDEO;
     544          14 :     } else if (startcode == PRIVATE_STREAM_2) {
     545           3 :         type = AVMEDIA_TYPE_DATA;
     546           3 :         codec_id = AV_CODEC_ID_DVD_NAV;
     547          11 :     } else if (startcode >= 0x1c0 && startcode <= 0x1df) {
     548           7 :         type     = AVMEDIA_TYPE_AUDIO;
     549          14 :         if (m->sofdec > 0) {
     550           0 :             codec_id = AV_CODEC_ID_ADPCM_ADX;
     551             :             // Auto-detect AC-3
     552           0 :             request_probe = 50;
     553           7 :         } else if (m->imkh_cctv && startcode == 0x1c0 && len > 80) {
     554           0 :             codec_id = AV_CODEC_ID_PCM_ALAW;
     555           0 :             request_probe = 50;
     556             :         } else {
     557           7 :             codec_id = AV_CODEC_ID_MP2;
     558           7 :             if (m->imkh_cctv)
     559           0 :                 request_probe = 25;
     560             :         }
     561           4 :     } else if (startcode >= 0x80 && startcode <= 0x87) {
     562           1 :         type     = AVMEDIA_TYPE_AUDIO;
     563           1 :         codec_id = AV_CODEC_ID_AC3;
     564           6 :     } else if ((startcode >= 0x88 && startcode <= 0x8f) ||
     565           4 :                (startcode >= 0x98 && startcode <= 0x9f)) {
     566             :         /* 0x90 - 0x97 is reserved for SDDS in DVD specs */
     567           0 :         type     = AVMEDIA_TYPE_AUDIO;
     568           0 :         codec_id = AV_CODEC_ID_DTS;
     569           3 :     } else if (startcode >= 0xa0 && startcode <= 0xaf) {
     570           1 :         type     = AVMEDIA_TYPE_AUDIO;
     571           2 :         if (lpcm_header_len == 6 || startcode == 0xa1) {
     572           0 :             codec_id = AV_CODEC_ID_MLP;
     573             :         } else {
     574           1 :             codec_id = AV_CODEC_ID_PCM_DVD;
     575             :         }
     576           2 :     } else if (startcode >= 0xb0 && startcode <= 0xbf) {
     577           0 :         type     = AVMEDIA_TYPE_AUDIO;
     578           0 :         codec_id = AV_CODEC_ID_TRUEHD;
     579           2 :     } else if (startcode >= 0xc0 && startcode <= 0xcf) {
     580             :         /* Used for both AC-3 and E-AC-3 in EVOB files */
     581           0 :         type     = AVMEDIA_TYPE_AUDIO;
     582           0 :         codec_id = AV_CODEC_ID_AC3;
     583           2 :     } else if (startcode >= 0x20 && startcode <= 0x3f) {
     584           2 :         type     = AVMEDIA_TYPE_SUBTITLE;
     585           2 :         codec_id = AV_CODEC_ID_DVD_SUBTITLE;
     586           0 :     } else if (startcode >= 0xfd55 && startcode <= 0xfd5f) {
     587           0 :         type     = AVMEDIA_TYPE_VIDEO;
     588           0 :         codec_id = AV_CODEC_ID_VC1;
     589             :     } else {
     590           0 : skip:
     591             :         /* skip packet */
     592         480 :         avio_skip(s->pb, len);
     593         480 :         goto redo;
     594             :     }
     595             :     /* no stream found: add a new stream */
     596          28 :     st = avformat_new_stream(s, NULL);
     597          28 :     if (!st)
     598           0 :         goto skip;
     599          28 :     st->id                = startcode;
     600          28 :     st->codecpar->codec_type = type;
     601          28 :     st->codecpar->codec_id   = codec_id;
     602          28 :     if (   st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW
     603          28 :         || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) {
     604           0 :         st->codecpar->channels = 1;
     605           0 :         st->codecpar->channel_layout = AV_CH_LAYOUT_MONO;
     606           0 :         st->codecpar->sample_rate = 8000;
     607             :     }
     608          28 :     st->request_probe     = request_probe;
     609          28 :     st->need_parsing      = AVSTREAM_PARSE_FULL;
     610             : 
     611        7740 : found:
     612        7740 :     if (st->discard >= AVDISCARD_ALL)
     613         480 :         goto skip;
     614        7260 :     if (startcode >= 0xa0 && startcode <= 0xaf) {
     615         305 :       if (st->codecpar->codec_id == AV_CODEC_ID_MLP) {
     616           0 :             if (len < 6)
     617           0 :                 goto skip;
     618           0 :             avio_skip(s->pb, 6);
     619           0 :             len -=6;
     620             :       }
     621             :     }
     622        7260 :     ret = av_get_packet(s->pb, pkt, len);
     623             : 
     624        7260 :     pkt->pts          = pts;
     625        7260 :     pkt->dts          = dts;
     626        7260 :     pkt->pos          = dummy_pos;
     627        7260 :     pkt->stream_index = st->index;
     628             : 
     629        7260 :     if (s->debug & FF_FDEBUG_TS)
     630           0 :         av_log(s, AV_LOG_TRACE, "%d: pts=%0.3f dts=%0.3f size=%d\n",
     631           0 :             pkt->stream_index, pkt->pts / 90000.0, pkt->dts / 90000.0,
     632             :             pkt->size);
     633             : 
     634        7260 :     return (ret < 0) ? ret : 0;
     635             : }
     636             : 
     637          91 : static int64_t mpegps_read_dts(AVFormatContext *s, int stream_index,
     638             :                                int64_t *ppos, int64_t pos_limit)
     639             : {
     640             :     int len, startcode;
     641             :     int64_t pos, pts, dts;
     642             : 
     643          91 :     pos = *ppos;
     644          91 :     if (avio_seek(s->pb, pos, SEEK_SET) < 0)
     645           0 :         return AV_NOPTS_VALUE;
     646             : 
     647             :     for (;;) {
     648         360 :         len = mpegps_read_pes_header(s, &pos, &startcode, &pts, &dts);
     649         451 :         if (len < 0) {
     650          45 :             if (s->debug & FF_FDEBUG_TS)
     651           0 :                 av_log(s, AV_LOG_TRACE, "none (ret=%d)\n", len);
     652          45 :             return AV_NOPTS_VALUE;
     653             :         }
     654         729 :         if (startcode == s->streams[stream_index]->id &&
     655         323 :             dts != AV_NOPTS_VALUE) {
     656          46 :             break;
     657             :         }
     658         360 :         avio_skip(s->pb, len);
     659             :     }
     660          46 :     if (s->debug & FF_FDEBUG_TS)
     661           0 :         av_log(s, AV_LOG_TRACE, "pos=0x%"PRIx64" dts=0x%"PRIx64" %0.3f\n",
     662             :             pos, dts, dts / 90000.0);
     663          46 :     *ppos = pos;
     664          46 :     return dts;
     665             : }
     666             : 
     667             : AVInputFormat ff_mpegps_demuxer = {
     668             :     .name           = "mpeg",
     669             :     .long_name      = NULL_IF_CONFIG_SMALL("MPEG-PS (MPEG-2 Program Stream)"),
     670             :     .priv_data_size = sizeof(MpegDemuxContext),
     671             :     .read_probe     = mpegps_probe,
     672             :     .read_header    = mpegps_read_header,
     673             :     .read_packet    = mpegps_read_packet,
     674             :     .read_timestamp = mpegps_read_dts,
     675             :     .flags          = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT,
     676             : };
     677             : 
     678             : #if CONFIG_VOBSUB_DEMUXER
     679             : 
     680             : #define REF_STRING "# VobSub index file,"
     681             : #define MAX_LINE_SIZE 2048
     682             : 
     683        6130 : static int vobsub_probe(AVProbeData *p)
     684             : {
     685        6130 :     if (!strncmp(p->buf, REF_STRING, sizeof(REF_STRING) - 1))
     686           1 :         return AVPROBE_SCORE_MAX;
     687        6129 :     return 0;
     688             : }
     689             : 
     690           1 : static int vobsub_read_header(AVFormatContext *s)
     691             : {
     692           1 :     int i, ret = 0, header_parsed = 0, langidx = 0;
     693           1 :     MpegDemuxContext *vobsub = s->priv_data;
     694             :     size_t fname_len;
     695             :     char *header_str;
     696             :     AVBPrint header;
     697           1 :     int64_t delay = 0;
     698           1 :     AVStream *st = NULL;
     699           1 :     int stream_id = -1;
     700           1 :     char id[64] = {0};
     701           1 :     char alt[MAX_LINE_SIZE] = {0};
     702             :     AVInputFormat *iformat;
     703             : 
     704           1 :     if (!vobsub->sub_name) {
     705             :         char *ext;
     706           1 :         vobsub->sub_name = av_strdup(s->filename);
     707           1 :         if (!vobsub->sub_name) {
     708           0 :             ret = AVERROR(ENOMEM);
     709           0 :             goto end;
     710             :         }
     711             : 
     712           1 :         fname_len = strlen(vobsub->sub_name);
     713           1 :         ext = vobsub->sub_name - 3 + fname_len;
     714           1 :         if (fname_len < 4 || *(ext - 1) != '.') {
     715           0 :             av_log(s, AV_LOG_ERROR, "The input index filename is too short "
     716             :                    "to guess the associated .SUB file\n");
     717           0 :             ret = AVERROR_INVALIDDATA;
     718           0 :             goto end;
     719             :         }
     720           1 :         memcpy(ext, !strncmp(ext, "IDX", 3) ? "SUB" : "sub", 3);
     721           1 :         av_log(s, AV_LOG_VERBOSE, "IDX/SUB: %s -> %s\n", s->filename, vobsub->sub_name);
     722             :     }
     723             : 
     724           1 :     if (!(iformat = av_find_input_format("mpeg"))) {
     725           0 :         ret = AVERROR_DEMUXER_NOT_FOUND;
     726           0 :         goto end;
     727             :     }
     728             : 
     729           1 :     vobsub->sub_ctx = avformat_alloc_context();
     730           1 :     if (!vobsub->sub_ctx) {
     731           0 :         ret = AVERROR(ENOMEM);
     732           0 :         goto end;
     733             :     }
     734             : 
     735           1 :     if ((ret = ff_copy_whiteblacklists(vobsub->sub_ctx, s)) < 0)
     736           0 :         goto end;
     737             : 
     738           1 :     ret = avformat_open_input(&vobsub->sub_ctx, vobsub->sub_name, iformat, NULL);
     739           1 :     if (ret < 0) {
     740           0 :         av_log(s, AV_LOG_ERROR, "Unable to open %s as MPEG subtitles\n", vobsub->sub_name);
     741           0 :         goto end;
     742             :     }
     743             : 
     744           1 :     av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED);
     745           1 :     while (!avio_feof(s->pb)) {
     746             :         char line[MAX_LINE_SIZE];
     747          63 :         int len = ff_get_line(s->pb, line, sizeof(line));
     748             : 
     749          63 :         if (!len)
     750           1 :             break;
     751             : 
     752          62 :         line[strcspn(line, "\r\n")] = 0;
     753             : 
     754          62 :         if (!strncmp(line, "id:", 3)) {
     755           1 :             if (sscanf(line, "id: %63[^,], index: %u", id, &stream_id) != 2) {
     756           0 :                 av_log(s, AV_LOG_WARNING, "Unable to parse index line '%s', "
     757             :                        "assuming 'id: und, index: 0'\n", line);
     758           0 :                 strcpy(id, "und");
     759           0 :                 stream_id = 0;
     760             :             }
     761             : 
     762           1 :             if (stream_id >= FF_ARRAY_ELEMS(vobsub->q)) {
     763           0 :                 av_log(s, AV_LOG_ERROR, "Maximum number of subtitles streams reached\n");
     764           0 :                 ret = AVERROR(EINVAL);
     765           0 :                 goto end;
     766             :             }
     767             : 
     768           1 :             header_parsed = 1;
     769           1 :             alt[0] = '\0';
     770             :             /* We do not create the stream immediately to avoid adding empty
     771             :              * streams. See the following timestamp entry. */
     772             : 
     773           1 :             av_log(s, AV_LOG_DEBUG, "IDX stream[%d] id=%s\n", stream_id, id);
     774             : 
     775          61 :         } else if (!strncmp(line, "timestamp:", 10)) {
     776             :             AVPacket *sub;
     777             :             int hh, mm, ss, ms;
     778             :             int64_t pos, timestamp;
     779          47 :             const char *p = line + 10;
     780             : 
     781          47 :             if (stream_id == -1) {
     782           0 :                 av_log(s, AV_LOG_ERROR, "Timestamp declared before any stream\n");
     783           0 :                 ret = AVERROR_INVALIDDATA;
     784           0 :                 goto end;
     785             :             }
     786             : 
     787          47 :             if (!st || st->id != stream_id) {
     788           1 :                 st = avformat_new_stream(s, NULL);
     789           1 :                 if (!st) {
     790           0 :                     ret = AVERROR(ENOMEM);
     791           0 :                     goto end;
     792             :                 }
     793           1 :                 st->id = stream_id;
     794           1 :                 st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
     795           1 :                 st->codecpar->codec_id   = AV_CODEC_ID_DVD_SUBTITLE;
     796           1 :                 avpriv_set_pts_info(st, 64, 1, 1000);
     797           1 :                 av_dict_set(&st->metadata, "language", id, 0);
     798           1 :                 if (alt[0])
     799           0 :                     av_dict_set(&st->metadata, "title", alt, 0);
     800             :             }
     801             : 
     802          47 :             if (sscanf(p, "%02d:%02d:%02d:%03d, filepos: %"SCNx64,
     803             :                        &hh, &mm, &ss, &ms, &pos) != 5) {
     804           0 :                 av_log(s, AV_LOG_ERROR, "Unable to parse timestamp line '%s', "
     805             :                        "abort parsing\n", line);
     806           0 :                 ret = AVERROR_INVALIDDATA;
     807           0 :                 goto end;
     808             :             }
     809          47 :             timestamp = (hh*3600LL + mm*60LL + ss) * 1000LL + ms + delay;
     810          47 :             timestamp = av_rescale_q(timestamp, av_make_q(1, 1000), st->time_base);
     811             : 
     812          47 :             sub = ff_subtitles_queue_insert(&vobsub->q[s->nb_streams - 1], "", 0, 0);
     813          47 :             if (!sub) {
     814           0 :                 ret = AVERROR(ENOMEM);
     815           0 :                 goto end;
     816             :             }
     817          47 :             sub->pos = pos;
     818          47 :             sub->pts = timestamp;
     819          47 :             sub->stream_index = s->nb_streams - 1;
     820             : 
     821          14 :         } else if (!strncmp(line, "alt:", 4)) {
     822           0 :             const char *p = line + 4;
     823             : 
     824           0 :             while (*p == ' ')
     825           0 :                 p++;
     826           0 :             av_log(s, AV_LOG_DEBUG, "IDX stream[%d] name=%s\n", stream_id, p);
     827           0 :             av_strlcpy(alt, p, sizeof(alt));
     828           0 :             header_parsed = 1;
     829             : 
     830          14 :         } else if (!strncmp(line, "delay:", 6)) {
     831           0 :             int sign = 1, hh = 0, mm = 0, ss = 0, ms = 0;
     832           0 :             const char *p = line + 6;
     833             : 
     834           0 :             while (*p == ' ')
     835           0 :                 p++;
     836           0 :             if (*p == '-' || *p == '+') {
     837           0 :                 sign = *p == '-' ? -1 : 1;
     838           0 :                 p++;
     839             :             }
     840           0 :             sscanf(p, "%d:%d:%d:%d", &hh, &mm, &ss, &ms);
     841           0 :             delay = ((hh*3600LL + mm*60LL + ss) * 1000LL + ms) * sign;
     842             : 
     843          14 :         } else if (!strncmp(line, "langidx:", 8)) {
     844           1 :             const char *p = line + 8;
     845             : 
     846           1 :             if (sscanf(p, "%d", &langidx) != 1)
     847           0 :                 av_log(s, AV_LOG_ERROR, "Invalid langidx specified\n");
     848             : 
     849          13 :         } else if (!header_parsed) {
     850          13 :             if (line[0] && line[0] != '#')
     851           3 :                 av_bprintf(&header, "%s\n", line);
     852             :         }
     853             :     }
     854             : 
     855           1 :     if (langidx < s->nb_streams)
     856           1 :         s->streams[langidx]->disposition |= AV_DISPOSITION_DEFAULT;
     857             : 
     858           2 :     for (i = 0; i < s->nb_streams; i++) {
     859           1 :         vobsub->q[i].sort = SUB_SORT_POS_TS;
     860           1 :         vobsub->q[i].keep_duplicates = 1;
     861           1 :         ff_subtitles_queue_finalize(s, &vobsub->q[i]);
     862             :     }
     863             : 
     864           1 :     if (!av_bprint_is_complete(&header)) {
     865           0 :         av_bprint_finalize(&header, NULL);
     866           0 :         ret = AVERROR(ENOMEM);
     867           0 :         goto end;
     868             :     }
     869           1 :     av_bprint_finalize(&header, &header_str);
     870           2 :     for (i = 0; i < s->nb_streams; i++) {
     871           1 :         AVStream *sub_st = s->streams[i];
     872           1 :         sub_st->codecpar->extradata      = av_strdup(header_str);
     873           1 :         sub_st->codecpar->extradata_size = header.len;
     874             :     }
     875           1 :     av_free(header_str);
     876             : 
     877           1 : end:
     878           1 :     return ret;
     879             : }
     880             : 
     881          47 : static int vobsub_read_packet(AVFormatContext *s, AVPacket *pkt)
     882             : {
     883          47 :     MpegDemuxContext *vobsub = s->priv_data;
     884             :     FFDemuxSubtitlesQueue *q;
     885          47 :     AVIOContext *pb = vobsub->sub_ctx->pb;
     886          47 :     int ret, psize, total_read = 0, i;
     887          47 :     AVPacket idx_pkt = { 0 };
     888             : 
     889          47 :     int64_t min_ts = INT64_MAX;
     890          47 :     int sid = 0;
     891          94 :     for (i = 0; i < s->nb_streams; i++) {
     892          47 :         FFDemuxSubtitlesQueue *tmpq = &vobsub->q[i];
     893             :         int64_t ts;
     894          47 :         av_assert0(tmpq->nb_subs);
     895          47 :         ts = tmpq->subs[tmpq->current_sub_idx].pts;
     896          47 :         if (ts < min_ts) {
     897          47 :             min_ts = ts;
     898          47 :             sid = i;
     899             :         }
     900             :     }
     901          47 :     q = &vobsub->q[sid];
     902          47 :     ret = ff_subtitles_queue_read_packet(q, &idx_pkt);
     903          47 :     if (ret < 0)
     904           0 :         return ret;
     905             : 
     906             :     /* compute maximum packet size using the next packet position. This is
     907             :      * useful when the len in the header is non-sense */
     908          47 :     if (q->current_sub_idx < q->nb_subs) {
     909          46 :         psize = q->subs[q->current_sub_idx].pos - idx_pkt.pos;
     910             :     } else {
     911           1 :         int64_t fsize = avio_size(pb);
     912           1 :         psize = fsize < 0 ? 0xffff : fsize - idx_pkt.pos;
     913             :     }
     914             : 
     915          47 :     avio_seek(pb, idx_pkt.pos, SEEK_SET);
     916             : 
     917          47 :     av_init_packet(pkt);
     918          47 :     pkt->size = 0;
     919          47 :     pkt->data = NULL;
     920             : 
     921             :     do {
     922             :         int n, to_read, startcode;
     923             :         int64_t pts, dts;
     924         131 :         int64_t old_pos = avio_tell(pb), new_pos;
     925             :         int pkt_size;
     926             : 
     927         131 :         ret = mpegps_read_pes_header(vobsub->sub_ctx, NULL, &startcode, &pts, &dts);
     928         131 :         if (ret < 0) {
     929           2 :             if (pkt->size) // raise packet even if incomplete
     930          44 :                 break;
     931           2 :             goto fail;
     932             :         }
     933         129 :         to_read = ret & 0xffff;
     934         129 :         new_pos = avio_tell(pb);
     935         129 :         pkt_size = ret + (new_pos - old_pos);
     936             : 
     937             :         /* this prevents reads above the current packet */
     938         129 :         if (total_read + pkt_size > psize)
     939          42 :             break;
     940          87 :         total_read += pkt_size;
     941             : 
     942             :         /* the current chunk doesn't match the stream index (unlikely) */
     943          87 :         if ((startcode & 0x1f) != s->streams[idx_pkt.stream_index]->id)
     944           0 :             break;
     945             : 
     946          87 :         ret = av_grow_packet(pkt, to_read);
     947          87 :         if (ret < 0)
     948           0 :             goto fail;
     949             : 
     950          87 :         n = avio_read(pb, pkt->data + (pkt->size - to_read), to_read);
     951          87 :         if (n < to_read)
     952           0 :             pkt->size -= to_read - n;
     953          87 :     } while (total_read < psize);
     954             : 
     955          46 :     pkt->pts = pkt->dts = idx_pkt.pts;
     956          46 :     pkt->pos = idx_pkt.pos;
     957          46 :     pkt->stream_index = idx_pkt.stream_index;
     958             : 
     959          46 :     av_packet_unref(&idx_pkt);
     960          46 :     return 0;
     961             : 
     962           1 : fail:
     963           1 :     av_packet_unref(pkt);
     964           1 :     av_packet_unref(&idx_pkt);
     965           1 :     return ret;
     966             : }
     967             : 
     968           1 : static int vobsub_read_seek(AVFormatContext *s, int stream_index,
     969             :                             int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
     970             : {
     971           1 :     MpegDemuxContext *vobsub = s->priv_data;
     972             : 
     973             :     /* Rescale requested timestamps based on the first stream (timebase is the
     974             :      * same for all subtitles stream within a .idx/.sub). Rescaling is done just
     975             :      * like in avformat_seek_file(). */
     976           1 :     if (stream_index == -1 && s->nb_streams != 1) {
     977           0 :         int i, ret = 0;
     978           0 :         AVRational time_base = s->streams[0]->time_base;
     979           0 :         ts = av_rescale_q(ts, AV_TIME_BASE_Q, time_base);
     980           0 :         min_ts = av_rescale_rnd(min_ts, time_base.den,
     981           0 :                                 time_base.num * (int64_t)AV_TIME_BASE,
     982             :                                 AV_ROUND_UP   | AV_ROUND_PASS_MINMAX);
     983           0 :         max_ts = av_rescale_rnd(max_ts, time_base.den,
     984           0 :                                 time_base.num * (int64_t)AV_TIME_BASE,
     985             :                                 AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX);
     986           0 :         for (i = 0; i < s->nb_streams; i++) {
     987           0 :             int r = ff_subtitles_queue_seek(&vobsub->q[i], s, stream_index,
     988             :                                             min_ts, ts, max_ts, flags);
     989           0 :             if (r < 0)
     990           0 :                 ret = r;
     991             :         }
     992           0 :         return ret;
     993             :     }
     994             : 
     995           1 :     if (stream_index == -1) // only 1 stream
     996           0 :         stream_index = 0;
     997           1 :     return ff_subtitles_queue_seek(&vobsub->q[stream_index], s, stream_index,
     998             :                                    min_ts, ts, max_ts, flags);
     999             : }
    1000             : 
    1001           1 : static int vobsub_read_close(AVFormatContext *s)
    1002             : {
    1003             :     int i;
    1004           1 :     MpegDemuxContext *vobsub = s->priv_data;
    1005             : 
    1006           2 :     for (i = 0; i < s->nb_streams; i++)
    1007           1 :         ff_subtitles_queue_clean(&vobsub->q[i]);
    1008           1 :     if (vobsub->sub_ctx)
    1009           1 :         avformat_close_input(&vobsub->sub_ctx);
    1010           1 :     return 0;
    1011             : }
    1012             : 
    1013             : static const AVOption options[] = {
    1014             :     { "sub_name", "URI for .sub file", offsetof(MpegDemuxContext, sub_name), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM },
    1015             :     { NULL }
    1016             : };
    1017             : 
    1018             : static const AVClass vobsub_demuxer_class = {
    1019             :     .class_name = "vobsub",
    1020             :     .item_name  = av_default_item_name,
    1021             :     .option     = options,
    1022             :     .version    = LIBAVUTIL_VERSION_INT,
    1023             : };
    1024             : 
    1025             : AVInputFormat ff_vobsub_demuxer = {
    1026             :     .name           = "vobsub",
    1027             :     .long_name      = NULL_IF_CONFIG_SMALL("VobSub subtitle format"),
    1028             :     .priv_data_size = sizeof(MpegDemuxContext),
    1029             :     .read_probe     = vobsub_probe,
    1030             :     .read_header    = vobsub_read_header,
    1031             :     .read_packet    = vobsub_read_packet,
    1032             :     .read_seek2     = vobsub_read_seek,
    1033             :     .read_close     = vobsub_read_close,
    1034             :     .flags          = AVFMT_SHOW_IDS,
    1035             :     .extensions     = "idx",
    1036             :     .priv_class     = &vobsub_demuxer_class,
    1037             : };
    1038             : #endif

Generated by: LCOV version 1.13