]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/mpegtsenc.c
Prevent infinite recursion of odml indexes.
[ffmpeg] / libavformat / mpegtsenc.c
index adb94af956dc069cb9441dd1d79e3ced6dace89a..52ecd1d092a68b6a99f53681205191da810f63c6 100644 (file)
@@ -23,6 +23,7 @@
 #include "libavutil/crc.h"
 #include "libavcodec/mpegvideo.h"
 #include "avformat.h"
+#include "internal.h"
 #include "mpegts.h"
 #include "adts.h"
 
@@ -386,8 +387,9 @@ static int mpegts_write_header(AVFormatContext *s)
     MpegTSService *service;
     AVStream *st, *pcr_st = NULL;
     AVMetadataTag *title;
-    int i;
+    int i, j;
     const char *service_name;
+    int *pids;
 
     ts->tsid = DEFAULT_TSID;
     ts->onid = DEFAULT_ONID;
@@ -410,6 +412,10 @@ static int mpegts_write_header(AVFormatContext *s)
     ts->sdt.write_packet = section_write_packet;
     ts->sdt.opaque = s;
 
+    pids = av_malloc(s->nb_streams);
+    if (!pids)
+        return AVERROR(ENOMEM);
+
     /* assign pids to each stream */
     for(i = 0;i < s->nb_streams; i++) {
         st = s->streams[i];
@@ -418,7 +424,26 @@ static int mpegts_write_header(AVFormatContext *s)
             goto fail;
         st->priv_data = ts_st;
         ts_st->service = service;
-        ts_st->pid = DEFAULT_START_PID + i;
+        /* MPEG pid values < 16 are reserved. Applications which set st->id in
+         * this range are assigned a calculated pid. */
+        if (st->id < 16) {
+            ts_st->pid = DEFAULT_START_PID + i;
+        } else if (st->id < 0x1FFF) {
+            ts_st->pid = st->id;
+        } else {
+            av_log(s, AV_LOG_ERROR, "Invalid stream id %d, must be less than 8191\n", st->id);
+            goto fail;
+        }
+        if (ts_st->pid == service->pmt.pid) {
+            av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid);
+            goto fail;
+        }
+        for (j = 0; j < i; j++)
+            if (pids[j] == ts_st->pid) {
+                av_log(s, AV_LOG_ERROR, "Duplicate stream id %d\n", ts_st->pid);
+                goto fail;
+            }
+        pids[i] = ts_st->pid;
         ts_st->payload_pts = AV_NOPTS_VALUE;
         ts_st->payload_dts = AV_NOPTS_VALUE;
         ts_st->first_pts_check = 1;
@@ -433,13 +458,15 @@ static int mpegts_write_header(AVFormatContext *s)
             st->codec->extradata_size > 0) {
             ts_st->adts = av_mallocz(sizeof(*ts_st->adts));
             if (!ts_st->adts)
-                return AVERROR_NOMEM;
+                return AVERROR(ENOMEM);
             if (ff_adts_decode_extradata(s, ts_st->adts, st->codec->extradata,
                                          st->codec->extradata_size) < 0)
                 return -1;
         }
     }
 
+    av_free(pids);
+
     /* if no video stream, use the first stream as PCR */
     if (service->pcr_pid == 0x1fff && s->nb_streams > 0) {
         pcr_st = s->streams[0];
@@ -495,6 +522,7 @@ static int mpegts_write_header(AVFormatContext *s)
     return 0;
 
  fail:
+    av_free(pids);
     for(i = 0;i < s->nb_streams; i++) {
         st = s->streams[i];
         av_free(st->priv_data);
@@ -836,7 +864,7 @@ static int mpegts_write_packet(AVFormatContext *s, AVPacket *pkt)
                 return -1;
             data = av_malloc(new_size);
             if (!data)
-                return AVERROR_NOMEM;
+                return AVERROR(ENOMEM);
             ff_adts_write_frame_header(adts, data, pkt->size, adts->pce_size);
             if (adts->pce_size) {
                 memcpy(data+ADTS_HEADER_SIZE, adts->pce_data, adts->pce_size);