[FFmpeg-devel] [PATCH] options to set stream id (custom TS pid)

Stefano Sabatini stefano.sabatini-lala
Sun Jun 13 23:52:11 CEST 2010


On date Sunday 2010-06-13 10:12:26 -0400, Mike Scheutzow encoded:
> Baptiste Coudurier wrote:
> >
> >>@@ -419,7 +424,28 @@
> >>              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 ) {
> >
> >Space around parentheses.
> Fixed in v5 patch.
> >
> >
> >Patch ok otherwise.
> >
> 
> Suggested commit description for ffmpeg_set_streamid_v3.patch:
> for ffmpeg.c, add command line option -streamid to set the value of
> AVStream.id for output streams.
> Patch by Mike Scheutzow mjs973 optonline net
> 
> Suggested commit description for mpegts_custom_pids_v5.patch:
> for mpegts muxer, allow libav application to assign a custom pid
> value to an output stream.
> Patch by Mike Scheutzow mjs973 optonline net
> 
> -- 
> Mike Scheutzow
> 
> 

> Index: ffmpeg.c
> ===================================================================
> --- ffmpeg.c	(revision 23373)
> +++ ffmpeg.c	(working copy)
> @@ -121,6 +121,9 @@
>  static AVMetaDataMap meta_data_maps[MAX_FILES];
>  static int nb_meta_data_maps;
>  
> +/* indexed by output file stream index */
> +static int streamid_map[MAX_STREAMS];
> +
>  static int frame_width  = 0;
>  static int frame_height = 0;
>  static float frame_aspect_ratio = 0;
> @@ -3326,7 +3329,7 @@
>      AVCodecContext *video_enc;
>      enum CodecID codec_id;
>  
> -    st = av_new_stream(oc, oc->nb_streams);
> +    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
>      if (!st) {
>          fprintf(stderr, "Could not alloc stream\n");
>          av_exit(1);
> @@ -3463,7 +3466,7 @@
>      AVCodecContext *audio_enc;
>      enum CodecID codec_id;
>  
> -    st = av_new_stream(oc, oc->nb_streams);
> +    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
>      if (!st) {
>          fprintf(stderr, "Could not alloc stream\n");
>          av_exit(1);
> @@ -3535,7 +3538,7 @@
>      AVStream *st;
>      AVCodecContext *subtitle_enc;
>  
> -    st = av_new_stream(oc, oc->nb_streams);
> +    st = av_new_stream(oc, streamid_map[oc->nb_streams]);
>      if (!st) {
>          fprintf(stderr, "Could not alloc stream\n");
>          av_exit(1);
> @@ -3603,6 +3606,27 @@
>      new_subtitle_stream(oc);
>  }
>  
> +/* arg format is "output-stream-index:streamid-value". */
> +static void opt_streamid(const char *arg)

void opt_streamid(const char *opt, const char *arg)

then you can use opt in the error messages, rather than hardcode them.

> +{
> +    int idx, value;
> +    char *p;
> +
> +    idx = strtol(arg, &p, 0);

parse_number_or_die()

> +    if (*p != ':' || idx < 0 || idx >= MAX_STREAMS) {
> +        fprintf(stderr, "Invalid -streamid: '%s'\n", arg);
> +        av_exit(1);
> +    }
> +
> +    p++;
> +    value = strtol(p, &p, 0);
> +    if (*p || value < 0) {
> +        fprintf(stderr, "Invalid -streamid: '%s'\n", arg);
> +        av_exit(1);
> +    }

ditto

> +    streamid_map[idx] = value;
> +}
> +
>  static void opt_output_file(const char *filename)
>  {
>      AVFormatContext *oc;
> @@ -3750,6 +3774,8 @@
>      oc->flags |= AVFMT_FLAG_NONBLOCK;
>  
>      set_context_opts(oc, avformat_opts, AV_OPT_FLAG_ENCODING_PARAM);
> +
> +    memset(streamid_map, 0, sizeof(streamid_map));
>  }
>  
>  /* same option as mencoder */
> @@ -4208,6 +4234,7 @@
>      { "vlang", HAS_ARG | OPT_STRING | OPT_VIDEO, {(void *)&video_language}, "set the ISO 639 language code (3 letters) of the current video stream" , "code" },
>      { "qphist", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, { (void *)&qp_hist }, "show QP histogram" },
>      { "force_fps", OPT_BOOL | OPT_EXPERT | OPT_VIDEO, {(void*)&force_fps}, "force the selected framerate, disable the best supported framerate selection" },
> +    { "streamid", HAS_ARG | OPT_EXPERT, {(void*)opt_streamid}, "set the value of an outfile streamid", "streamIndex:value" },
>  
>      /* audio options */
>      { "ab", OPT_FUNC2 | HAS_ARG | OPT_AUDIO, {(void*)opt_bitrate}, "set bitrate (in bits/s)", "bitrate" },
> Index: doc/ffmpeg-doc.texi
> ===================================================================
> --- doc/ffmpeg-doc.texi	(revision 23373)
> +++ doc/ffmpeg-doc.texi	(working copy)
> @@ -783,6 +783,13 @@
>  Set the maximum demux-decode delay.
>  @item -muxpreload @var{seconds}
>  Set the initial demux-decode delay.

> + at item -streamid @var{output-stream-index}:@var{new-value}
> +Assign a new value to a stream's stream-id field in the next output file. All stream-id fields are reset to default for each output file.
> +
> +For example, to set the stream 0 PID to 33 and the stream 1 PID to 36 for an output mpegts file:

Break long lines

> + at example
> +ffmpeg -i infile -streamid 0:33 -streamid 1:36 out.ts
> + at end example
>  @end table
>  
>  @section Preset files

> Index: libavformat/mpegtsenc.c
> ===================================================================
> --- libavformat/mpegtsenc.c	(revision 23373)
> +++ libavformat/mpegtsenc.c	(working copy)
> @@ -387,8 +387,9 @@
>      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 @@
>      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,28 @@
>              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, "error, stream id must be 16 to 8190\n");

"Invalid stream id %d, must be in the range..."

> +            goto fail;
> +        }
> +        if (ts_st->pid == service->pmt.pid) {
> +            av_log(s, AV_LOG_ERROR, "error, stream id conflicts with PMT (%d)\n",

"Stream id %d conflicts ..."

> +                   service->pmt.pid);
> +            goto fail;
> +        }
> +        for (j = 0; j < i; j++)
> +            if (pids[j] == ts_st->pid) {
> +                av_log(s, AV_LOG_ERROR, "error, stream %d id conflicts with "
> +                       "stream %d (%d)\n", i, j, st->id);

Confusing message.

All these "error, " are ugly, just remove them.

> +                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 +467,8 @@
>          }
>      }
>  
> +    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 +524,7 @@
>      return 0;
>  
>   fail:
> +    av_free(pids);
>      for(i = 0;i < s->nb_streams; i++) {
>          st = s->streams[i];
>          av_free(st->priv_data);

Regards.
-- 
FFmpeg = Fundamentalist and Faithful Mournful Pitiless Enigmatic Gargoyle



More information about the ffmpeg-devel mailing list