]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mpegts.c
Print meaningful error messages when url_fopen fails.
[ffmpeg] / libavformat / mpegts.c
index 5d2567109ab7f58dcc61b073c2885b345d5476f8..921ddd5e39b3aa30a3dc426d2ff6d70653ed5215 100644 (file)
@@ -128,13 +128,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 {
@@ -511,7 +513,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 +525,10 @@ 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 },
     { 0x59, CODEC_TYPE_SUBTITLE, CODEC_ID_DVB_SUBTITLE }, /* subtitling descriptor */
+    { 0 },
 };
 
 static void mpegts_find_stream_type(AVStream *st,
@@ -541,7 +543,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);
 
@@ -558,12 +560,25 @@ static AVStream *new_pes_av_stream(PESContext *pes, uint32_t prog_reg_desc)
     dprintf(pes->stream, "stream_type=%x pid=%x prog_reg_desc=%.4s\n",
             pes->stream_type, pes->pid, (char*)&prog_reg_desc);
 
-        mpegts_find_stream_type(st, pes->stream_type, ISO_types);
-        if (prog_reg_desc == AV_RL32("HDMV") &&
-            st->codec->codec_id == CODEC_ID_PROBE)
-            mpegts_find_stream_type(st, pes->stream_type, HDMV_types);
-        if (st->codec->codec_id == CODEC_ID_PROBE)
-            mpegts_find_stream_type(st, pes->stream_type, MISC_types);
+    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)
+        mpegts_find_stream_type(st, pes->stream_type, HDMV_types);
+    if (st->codec->codec_id == CODEC_ID_PROBE)
+        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_PROBE) {
+        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;
 }
@@ -577,10 +592,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
     const uint8_t *p, *p_end, *desc_list_end, *desc_end;
     int program_info_length, pcr_pid, pid, stream_type;
     int desc_list_len, desc_len, desc_tag;
-    int comp_page = 0, anc_page = 0; /* initialize to kill warnings */
-    char language[4] = {0}; /* initialize to kill warnings */
+    int comp_page, anc_page;
+    char language[4];
     uint32_t prog_reg_desc = 0; /* registration descriptor */
-    uint32_t reg_desc = 0; /* registration descriptor */
 
 #ifdef DEBUG
     dprintf(ts->stream, "PMT: len %i\n", section_len);
@@ -643,7 +657,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)
@@ -697,10 +711,11 @@ 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);
+                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_PROBE &&
                     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;
@@ -911,16 +926,39 @@ 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;
+                    } else {
+                        pes->state = MPEGTS_PAYLOAD;
+                        pes->data_index = 0;
+                    }
                 } else {
                     /* otherwise, it should be a table */
                     /* skip packet */
@@ -932,6 +970,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)
@@ -960,15 +1013,6 @@ static int mpegts_push_data(MpegTSFilter *filter,
                     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);
-
                 /* we got the full header. We parse it and get the payload */
                 pes->state = MPEGTS_PAYLOAD;
                 pes->data_index = 0;
@@ -1012,6 +1056,7 @@ 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;
     tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes);
     if (!tss) {
         av_free(pes);