diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 3fc6dc195f..52ecd1d092 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);