From 5fd4857354619bd8a7517fc5e675f5871ed48702 Mon Sep 17 00:00:00 2001
From: Mike Scheutzow <scheutzow@alcatel-lucent.com>
Date: Wed, 30 Jun 2010 22:39:13 +0000
Subject: [PATCH] Allow setting streamid when muxing mpegts.

Patch by Mike Scheutzow, scheutzow alcatel-lucent com

Originally committed as revision 23918 to svn://svn.ffmpeg.org/ffmpeg/trunk
---
 libavformat/mpegtsenc.c | 31 +++++++++++++++++++++++++++++--
 1 file changed, 29 insertions(+), 2 deletions(-)

diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index 3fc6dc195f0..52ecd1d092a 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -387,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;
@@ -411,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];
@@ -419,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;
@@ -441,6 +465,8 @@ static int mpegts_write_header(AVFormatContext *s)
         }
     }
 
+    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];
@@ -496,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);
-- 
GitLab