diff mbox

[FFmpeg-devel] doc/examples/remuxing: switch to codecpar

Message ID 20170328103219.6136-1-matthieu.bouron@gmail.com
State Accepted
Headers show

Commit Message

Matthieu Bouron March 28, 2017, 10:32 a.m. UTC
Also limits remuxing to audio, video and subtitle streams.
---
 doc/examples/remuxing.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 7 deletions(-)

Comments

wm4 March 28, 2017, 10:48 a.m. UTC | #1
On Tue, 28 Mar 2017 12:32:19 +0200
Matthieu Bouron <matthieu.bouron@gmail.com> wrote:

> Also limits remuxing to audio, video and subtitle streams.
> ---
>  doc/examples/remuxing.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 41 insertions(+), 7 deletions(-)
> 
> diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> index 65437d9abd..8615c73842 100644
> --- a/doc/examples/remuxing.c
> +++ b/doc/examples/remuxing.c
> @@ -50,6 +50,9 @@ int main(int argc, char **argv)
>      AVPacket pkt;
>      const char *in_filename, *out_filename;
>      int ret, i;
> +    int stream_index = 0;
> +    int *stream_mapping = NULL;
> +    int stream_mapping_size = 0;
>  
>      if (argc < 3) {
>          printf("usage: %s input output\n"
> @@ -83,25 +86,48 @@ int main(int argc, char **argv)
>          goto end;
>      }
>  
> +    stream_mapping_size = ifmt_ctx->nb_streams;
> +    stream_mapping = av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping));
> +    if (!stream_mapping) {
> +        ret = AVERROR(ENOMEM);
> +        goto end;
> +    }
> +
>      ofmt = ofmt_ctx->oformat;
>  
>      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> +        AVStream *out_stream;
>          AVStream *in_stream = ifmt_ctx->streams[i];
> -        AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
> +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> +
> +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> +            stream_mapping[i] = -1;
> +            continue;
> +        }
> +
> +        stream_mapping[i] = stream_index++;
> +
> +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
>          if (!out_stream) {
>              fprintf(stderr, "Failed allocating output stream\n");
>              ret = AVERROR_UNKNOWN;
>              goto end;
>          }
>  
> -        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
> +        ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
>          if (ret < 0) {
> -            fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
> +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> +            goto end;
> +        }
> +        out_stream->codecpar->codec_tag = 0;
> +
> +        ret = avformat_transfer_internal_stream_timing_info(ofmt, out_stream, in_stream, AVFMT_TBCF_AUTO);
> +        if (ret < 0) {
> +            fprintf(stderr, "Failed to copy stream timing info\n");

Remove this call. It was made for obscure corner cases like ffserver,
and one avi thing AFAIK?

>              goto end;
>          }
> -        out_stream->codec->codec_tag = 0;
> -        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> -            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
>      }
>      av_dump_format(ofmt_ctx, 0, out_filename, 1);
>  
> @@ -127,8 +153,14 @@ int main(int argc, char **argv)
>              break;
>  
>          in_stream  = ifmt_ctx->streams[pkt.stream_index];
> -        out_stream = ofmt_ctx->streams[pkt.stream_index];
> +        if (pkt.stream_index >= stream_mapping_size ||
> +            stream_mapping[pkt.stream_index] < 0) {
> +            av_packet_unref(&pkt);
> +            continue;
> +        }
>  
> +        pkt.stream_index = stream_mapping[pkt.stream_index];
> +        out_stream = ofmt_ctx->streams[pkt.stream_index];
>          log_packet(ifmt_ctx, &pkt, "in");
>  
>          /* copy packet */
> @@ -156,6 +188,8 @@ end:
>          avio_closep(&ofmt_ctx->pb);
>      avformat_free_context(ofmt_ctx);
>  
> +    av_freep(&stream_mapping);
> +
>      if (ret < 0 && ret != AVERROR_EOF) {
>          fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
>          return 1;
Matthieu Bouron March 28, 2017, 11:09 a.m. UTC | #2
On Tue, Mar 28, 2017 at 12:48 PM, wm4 <nfxjfg@googlemail.com> wrote:

> On Tue, 28 Mar 2017 12:32:19 +0200
> Matthieu Bouron <matthieu.bouron@gmail.com> wrote:
>
> > Also limits remuxing to audio, video and subtitle streams.
> > ---
> >  doc/examples/remuxing.c | 48 ++++++++++++++++++++++++++++++
> +++++++++++-------
> >  1 file changed, 41 insertions(+), 7 deletions(-)
> >
> > diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> > index 65437d9abd..8615c73842 100644
> > --- a/doc/examples/remuxing.c
> > +++ b/doc/examples/remuxing.c
> > @@ -50,6 +50,9 @@ int main(int argc, char **argv)
> >      AVPacket pkt;
> >      const char *in_filename, *out_filename;
> >      int ret, i;
> > +    int stream_index = 0;
> > +    int *stream_mapping = NULL;
> > +    int stream_mapping_size = 0;
> >
> >      if (argc < 3) {
> >          printf("usage: %s input output\n"
> > @@ -83,25 +86,48 @@ int main(int argc, char **argv)
> >          goto end;
> >      }
> >
> > +    stream_mapping_size = ifmt_ctx->nb_streams;
> > +    stream_mapping = av_mallocz_array(stream_mapping_size,
> sizeof(*stream_mapping));
> > +    if (!stream_mapping) {
> > +        ret = AVERROR(ENOMEM);
> > +        goto end;
> > +    }
> > +
> >      ofmt = ofmt_ctx->oformat;
> >
> >      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> > +        AVStream *out_stream;
> >          AVStream *in_stream = ifmt_ctx->streams[i];
> > -        AVStream *out_stream = avformat_new_stream(ofmt_ctx,
> in_stream->codec->codec);
> > +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> > +
> > +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> > +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> > +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> > +            stream_mapping[i] = -1;
> > +            continue;
> > +        }
> > +
> > +        stream_mapping[i] = stream_index++;
> > +
> > +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
> >          if (!out_stream) {
> >              fprintf(stderr, "Failed allocating output stream\n");
> >              ret = AVERROR_UNKNOWN;
> >              goto end;
> >          }
> >
> > -        ret = avcodec_copy_context(out_stream->codec,
> in_stream->codec);
> > +        ret = avcodec_parameters_copy(out_stream->codecpar,
> in_codecpar);
> >          if (ret < 0) {
> > -            fprintf(stderr, "Failed to copy context from input to
> output stream codec context\n");
> > +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> > +            goto end;
> > +        }
> > +        out_stream->codecpar->codec_tag = 0;
> > +
> > +        ret = avformat_transfer_internal_stream_timing_info(ofmt,
> out_stream, in_stream, AVFMT_TBCF_AUTO);
> > +        if (ret < 0) {
> > +            fprintf(stderr, "Failed to copy stream timing info\n");
>
> Remove this call. It was made for obscure corner cases like ffserver,
> and one avi thing AFAIK?
>
>

I just ran fate with ffmpeg.c compiled without the
avformat_transfer_internal_stream_timing_info call, and it broke in many
areas.

On the other hand, it only seems to transfer ist->time_base to
enc_ctx->time_base for the general case, which shouldn't be useful for
remuxing (i can be missing things though). I removed the call locally.

>              goto end;
> >          }
> > -        out_stream->codec->codec_tag = 0;
> > -        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> > -            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
> >      }
> >      av_dump_format(ofmt_ctx, 0, out_filename, 1);
> >
> > @@ -127,8 +153,14 @@ int main(int argc, char **argv)
> >              break;
> >
> >          in_stream  = ifmt_ctx->streams[pkt.stream_index];
> > -        out_stream = ofmt_ctx->streams[pkt.stream_index];
> > +        if (pkt.stream_index >= stream_mapping_size ||
> > +            stream_mapping[pkt.stream_index] < 0) {
> > +            av_packet_unref(&pkt);
> > +            continue;
> > +        }
> >
> > +        pkt.stream_index = stream_mapping[pkt.stream_index];
> > +        out_stream = ofmt_ctx->streams[pkt.stream_index];
> >          log_packet(ifmt_ctx, &pkt, "in");
> >
> >          /* copy packet */
> > @@ -156,6 +188,8 @@ end:
> >          avio_closep(&ofmt_ctx->pb);
> >      avformat_free_context(ofmt_ctx);
> >
> > +    av_freep(&stream_mapping);
> > +
> >      if (ret < 0 && ret != AVERROR_EOF) {
> >          fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
> >          return 1;
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
wm4 March 28, 2017, 11:31 a.m. UTC | #3
On Tue, 28 Mar 2017 13:09:54 +0200
Matthieu Bouron <matthieu.bouron@gmail.com> wrote:

> On Tue, Mar 28, 2017 at 12:48 PM, wm4 <nfxjfg@googlemail.com> wrote:
> 
> > On Tue, 28 Mar 2017 12:32:19 +0200
> > Matthieu Bouron <matthieu.bouron@gmail.com> wrote:
> >  
> > > Also limits remuxing to audio, video and subtitle streams.
> > > ---
> > >  doc/examples/remuxing.c | 48 ++++++++++++++++++++++++++++++  
> > +++++++++++-------  
> > >  1 file changed, 41 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> > > index 65437d9abd..8615c73842 100644
> > > --- a/doc/examples/remuxing.c
> > > +++ b/doc/examples/remuxing.c
> > > @@ -50,6 +50,9 @@ int main(int argc, char **argv)
> > >      AVPacket pkt;
> > >      const char *in_filename, *out_filename;
> > >      int ret, i;
> > > +    int stream_index = 0;
> > > +    int *stream_mapping = NULL;
> > > +    int stream_mapping_size = 0;
> > >
> > >      if (argc < 3) {
> > >          printf("usage: %s input output\n"
> > > @@ -83,25 +86,48 @@ int main(int argc, char **argv)
> > >          goto end;
> > >      }
> > >
> > > +    stream_mapping_size = ifmt_ctx->nb_streams;
> > > +    stream_mapping = av_mallocz_array(stream_mapping_size,  
> > sizeof(*stream_mapping));  
> > > +    if (!stream_mapping) {
> > > +        ret = AVERROR(ENOMEM);
> > > +        goto end;
> > > +    }
> > > +
> > >      ofmt = ofmt_ctx->oformat;
> > >
> > >      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> > > +        AVStream *out_stream;
> > >          AVStream *in_stream = ifmt_ctx->streams[i];
> > > -        AVStream *out_stream = avformat_new_stream(ofmt_ctx,  
> > in_stream->codec->codec);  
> > > +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> > > +
> > > +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> > > +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> > > +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> > > +            stream_mapping[i] = -1;
> > > +            continue;
> > > +        }
> > > +
> > > +        stream_mapping[i] = stream_index++;
> > > +
> > > +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
> > >          if (!out_stream) {
> > >              fprintf(stderr, "Failed allocating output stream\n");
> > >              ret = AVERROR_UNKNOWN;
> > >              goto end;
> > >          }
> > >
> > > -        ret = avcodec_copy_context(out_stream->codec,  
> > in_stream->codec);  
> > > +        ret = avcodec_parameters_copy(out_stream->codecpar,  
> > in_codecpar);  
> > >          if (ret < 0) {
> > > -            fprintf(stderr, "Failed to copy context from input to  
> > output stream codec context\n");  
> > > +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> > > +            goto end;
> > > +        }
> > > +        out_stream->codecpar->codec_tag = 0;
> > > +
> > > +        ret = avformat_transfer_internal_stream_timing_info(ofmt,  
> > out_stream, in_stream, AVFMT_TBCF_AUTO);  
> > > +        if (ret < 0) {
> > > +            fprintf(stderr, "Failed to copy stream timing info\n");  
> >
> > Remove this call. It was made for obscure corner cases like ffserver,
> > and one avi thing AFAIK?
> >
> >  
> 
> I just ran fate with ffmpeg.c compiled without the
> avformat_transfer_internal_stream_timing_info call, and it broke in many
> areas.

That doesn't mean anything.

> On the other hand, it only seems to transfer ist->time_base to
> enc_ctx->time_base for the general case, which shouldn't be useful for
> remuxing (i can be missing things though). I removed the call locally.

That should probably be done manually then.

The main purpose of avformat_transfer_internal_stream_timing_info is to
access obscure info that can be retrieved only by accessing the
libavformat internal AVCodecContext, and to make FATE pass.
Moritz Barsnick March 28, 2017, 2:21 p.m. UTC | #4
On Tue, Mar 28, 2017 at 12:32:19 +0200, Matthieu Bouron wrote:
> -            fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
> +            fprintf(stderr, "Failed to copy copy codec parameters\n");

"copy copy"?

Moritz
Matthieu Bouron March 28, 2017, 2:48 p.m. UTC | #5
On Tue, Mar 28, 2017 at 4:21 PM, Moritz Barsnick <barsnick@gmx.net> wrote:

> On Tue, Mar 28, 2017 at 12:32:19 +0200, Matthieu Bouron wrote:
> > -            fprintf(stderr, "Failed to copy context from input to
> output stream codec context\n");
> > +            fprintf(stderr, "Failed to copy copy codec parameters\n");
>
> "copy copy"?
>

Fixed locally. Thanks

[...]
Matthieu Bouron March 28, 2017, 2:54 p.m. UTC | #6
On Tue, Mar 28, 2017 at 12:32 PM, Matthieu Bouron <matthieu.bouron@gmail.com
> wrote:

> Also limits remuxing to audio, video and subtitle streams.
> ---
>  doc/examples/remuxing.c | 48 ++++++++++++++++++++++++++++++
> +++++++++++-------
>  1 file changed, 41 insertions(+), 7 deletions(-)
>
> diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> index 65437d9abd..8615c73842 100644
> --- a/doc/examples/remuxing.c
> +++ b/doc/examples/remuxing.c
> @@ -50,6 +50,9 @@ int main(int argc, char **argv)
>      AVPacket pkt;
>      const char *in_filename, *out_filename;
>      int ret, i;
> +    int stream_index = 0;
> +    int *stream_mapping = NULL;
> +    int stream_mapping_size = 0;
>
>      if (argc < 3) {
>          printf("usage: %s input output\n"
> @@ -83,25 +86,48 @@ int main(int argc, char **argv)
>          goto end;
>      }
>
> +    stream_mapping_size = ifmt_ctx->nb_streams;
> +    stream_mapping = av_mallocz_array(stream_mapping_size,
> sizeof(*stream_mapping));
> +    if (!stream_mapping) {
> +        ret = AVERROR(ENOMEM);
> +        goto end;
> +    }
> +
>      ofmt = ofmt_ctx->oformat;
>
>      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> +        AVStream *out_stream;
>          AVStream *in_stream = ifmt_ctx->streams[i];
> -        AVStream *out_stream = avformat_new_stream(ofmt_ctx,
> in_stream->codec->codec);
> +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> +
> +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> +            stream_mapping[i] = -1;
> +            continue;
> +        }
> +
> +        stream_mapping[i] = stream_index++;
> +
> +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
>          if (!out_stream) {
>              fprintf(stderr, "Failed allocating output stream\n");
>              ret = AVERROR_UNKNOWN;
>              goto end;
>          }
>
> -        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
> +        ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
>          if (ret < 0) {
> -            fprintf(stderr, "Failed to copy context from input to output
> stream codec context\n");
> +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> +            goto end;
> +        }
> +        out_stream->codecpar->codec_tag = 0;
> +
> +        ret = avformat_transfer_internal_stream_timing_info(ofmt,
> out_stream, in_stream, AVFMT_TBCF_AUTO);
> +        if (ret < 0) {
> +            fprintf(stderr, "Failed to copy stream timing info\n");
>              goto end;
>          }
> -        out_stream->codec->codec_tag = 0;
> -        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> -            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
>      }
>      av_dump_format(ofmt_ctx, 0, out_filename, 1);
>
> @@ -127,8 +153,14 @@ int main(int argc, char **argv)
>              break;
>
>          in_stream  = ifmt_ctx->streams[pkt.stream_index];
> -        out_stream = ofmt_ctx->streams[pkt.stream_index];
> +        if (pkt.stream_index >= stream_mapping_size ||
> +            stream_mapping[pkt.stream_index] < 0) {
> +            av_packet_unref(&pkt);
> +            continue;
> +        }
>
> +        pkt.stream_index = stream_mapping[pkt.stream_index];
> +        out_stream = ofmt_ctx->streams[pkt.stream_index];
>          log_packet(ifmt_ctx, &pkt, "in");
>
>          /* copy packet */
> @@ -156,6 +188,8 @@ end:
>          avio_closep(&ofmt_ctx->pb);
>      avformat_free_context(ofmt_ctx);
>
> +    av_freep(&stream_mapping);
> +
>      if (ret < 0 && ret != AVERROR_EOF) {
>          fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
>          return 1;
> --
> 2.12.0
>
>
Patch pushed (taking into account wm4 and Moritz reviews).
Michael Niedermayer March 28, 2017, 8:06 p.m. UTC | #7
On Tue, Mar 28, 2017 at 04:54:38PM +0200, Matthieu Bouron wrote:
> On Tue, Mar 28, 2017 at 12:32 PM, Matthieu Bouron <matthieu.bouron@gmail.com
> > wrote:
> 
> > Also limits remuxing to audio, video and subtitle streams.
> > ---
> >  doc/examples/remuxing.c | 48 ++++++++++++++++++++++++++++++
> > +++++++++++-------
> >  1 file changed, 41 insertions(+), 7 deletions(-)
> >
> > diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> > index 65437d9abd..8615c73842 100644
> > --- a/doc/examples/remuxing.c
> > +++ b/doc/examples/remuxing.c
> > @@ -50,6 +50,9 @@ int main(int argc, char **argv)
> >      AVPacket pkt;
> >      const char *in_filename, *out_filename;
> >      int ret, i;
> > +    int stream_index = 0;
> > +    int *stream_mapping = NULL;
> > +    int stream_mapping_size = 0;
> >
> >      if (argc < 3) {
> >          printf("usage: %s input output\n"
> > @@ -83,25 +86,48 @@ int main(int argc, char **argv)
> >          goto end;
> >      }
> >
> > +    stream_mapping_size = ifmt_ctx->nb_streams;
> > +    stream_mapping = av_mallocz_array(stream_mapping_size,
> > sizeof(*stream_mapping));
> > +    if (!stream_mapping) {
> > +        ret = AVERROR(ENOMEM);
> > +        goto end;
> > +    }
> > +
> >      ofmt = ofmt_ctx->oformat;
> >
> >      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> > +        AVStream *out_stream;
> >          AVStream *in_stream = ifmt_ctx->streams[i];
> > -        AVStream *out_stream = avformat_new_stream(ofmt_ctx,
> > in_stream->codec->codec);
> > +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> > +
> > +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> > +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> > +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> > +            stream_mapping[i] = -1;
> > +            continue;
> > +        }
> > +
> > +        stream_mapping[i] = stream_index++;
> > +
> > +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
> >          if (!out_stream) {
> >              fprintf(stderr, "Failed allocating output stream\n");
> >              ret = AVERROR_UNKNOWN;
> >              goto end;
> >          }
> >
> > -        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
> > +        ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
> >          if (ret < 0) {
> > -            fprintf(stderr, "Failed to copy context from input to output
> > stream codec context\n");
> > +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> > +            goto end;
> > +        }
> > +        out_stream->codecpar->codec_tag = 0;
> > +
> > +        ret = avformat_transfer_internal_stream_timing_info(ofmt,
> > out_stream, in_stream, AVFMT_TBCF_AUTO);
> > +        if (ret < 0) {
> > +            fprintf(stderr, "Failed to copy stream timing info\n");
> >              goto end;
> >          }
> > -        out_stream->codec->codec_tag = 0;
> > -        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> > -            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
> >      }
> >      av_dump_format(ofmt_ctx, 0, out_filename, 1);
> >
> > @@ -127,8 +153,14 @@ int main(int argc, char **argv)
> >              break;
> >
> >          in_stream  = ifmt_ctx->streams[pkt.stream_index];
> > -        out_stream = ofmt_ctx->streams[pkt.stream_index];
> > +        if (pkt.stream_index >= stream_mapping_size ||
> > +            stream_mapping[pkt.stream_index] < 0) {
> > +            av_packet_unref(&pkt);
> > +            continue;
> > +        }
> >
> > +        pkt.stream_index = stream_mapping[pkt.stream_index];
> > +        out_stream = ofmt_ctx->streams[pkt.stream_index];
> >          log_packet(ifmt_ctx, &pkt, "in");
> >
> >          /* copy packet */
> > @@ -156,6 +188,8 @@ end:
> >          avio_closep(&ofmt_ctx->pb);
> >      avformat_free_context(ofmt_ctx);
> >
> > +    av_freep(&stream_mapping);
> > +
> >      if (ret < 0 && ret != AVERROR_EOF) {
> >          fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
> >          return 1;
> > --
> > 2.12.0
> >
> >
> Patch pushed (taking into account wm4 and Moritz reviews).

This changes timestamps and durations
./ffmpeg -i matrixbench_mpeg2.mpg -t 10 -vcodec copy -acodec copy ref.mpg
doc/examples/remuxing ref.mpg old.mp4 >& OLD
...
doc/examples/remuxing ref.mpg new.mp4 >& NEW

...
 in: pts:48600 pts_time:0.54 dts:48600 dts_time:0.54 duration:2160 duration_time:0.024 stream_index:1
 out: pts:25920 pts_time:0.54 dts:25920 dts_time:0.54 duration:1152 duration_time:0.024 stream_index:1
 in: pts:48600 pts_time:0.54 dts:45000 dts_time:0.5 duration:3600 duration_time:0.04 stream_index:0
-out: pts:6912 pts_time:0.54 dts:6400 dts_time:0.5 duration:512 duration_time:0.04 stream_index:0
+out: pts:48600 pts_time:0.54 dts:45000 dts_time:0.5 duration:3600 duration_time:0.04 stream_index:0
 in: pts:NOPTS pts_time:NOPTS dts:48600 dts_time:0.54 duration:3600 duration_time:0.04 stream_index:0
-out: pts:NOPTS pts_time:NOPTS dts:6912 dts_time:0.54 duration:512 duration_time:0.04 stream_index:0
+out: pts:NOPTS pts_time:NOPTS dts:48600 dts_time:0.54 duration:3600 duration_time:0.04 stream_index:0
 in: pts:52200 pts_time:0.58 dts:52200 dts_time:0.58 duration:3600 duration_time:0.04 stream_index:0
-out: pts:7424 pts_time:0.58 dts:7424 dts_time:0.58 duration:512 duration_time:0.04 stream_index:0
+out: pts:52200 pts_time:0.58 dts:52200 dts_time:0.58 duration:3600 duration_time:0.04 stream_index:0
 in: pts:55800 pts_time:0.62 dts:55800 dts_time:0.62 duration:3600 duration_time:0.04 stream_index:0
-out: pts:7936 pts_time:0.62 dts:7936 dts_time:0.62 duration:512 duration_time:0.04 stream_index:0
+out: pts:55800 pts_time:0.62 dts:55800 dts_time:0.62 duration:3600 duration_time:0.04 stream_index:0
 in: pts:50760 pts_time:0.564 dts:50760 dts_time:0.564 duration:2160 duration_time:0.024 stream_index:1
 out: pts:27072 pts_time:0.564 dts:27072 dts_time:0.564 duration:1152 duration_time:0.024 stream_index:1

is this intended ?

 [...]
Matthieu Bouron March 29, 2017, 9:13 a.m. UTC | #8
On Tue, Mar 28, 2017 at 10:06:31PM +0200, Michael Niedermayer wrote:
> On Tue, Mar 28, 2017 at 04:54:38PM +0200, Matthieu Bouron wrote:
> > On Tue, Mar 28, 2017 at 12:32 PM, Matthieu Bouron <matthieu.bouron@gmail.com
> > > wrote:
> > 
> > > Also limits remuxing to audio, video and subtitle streams.
> > > ---
> > >  doc/examples/remuxing.c | 48 ++++++++++++++++++++++++++++++
> > > +++++++++++-------
> > >  1 file changed, 41 insertions(+), 7 deletions(-)
> > >
> > > diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
> > > index 65437d9abd..8615c73842 100644
> > > --- a/doc/examples/remuxing.c
> > > +++ b/doc/examples/remuxing.c
> > > @@ -50,6 +50,9 @@ int main(int argc, char **argv)
> > >      AVPacket pkt;
> > >      const char *in_filename, *out_filename;
> > >      int ret, i;
> > > +    int stream_index = 0;
> > > +    int *stream_mapping = NULL;
> > > +    int stream_mapping_size = 0;
> > >
> > >      if (argc < 3) {
> > >          printf("usage: %s input output\n"
> > > @@ -83,25 +86,48 @@ int main(int argc, char **argv)
> > >          goto end;
> > >      }
> > >
> > > +    stream_mapping_size = ifmt_ctx->nb_streams;
> > > +    stream_mapping = av_mallocz_array(stream_mapping_size,
> > > sizeof(*stream_mapping));
> > > +    if (!stream_mapping) {
> > > +        ret = AVERROR(ENOMEM);
> > > +        goto end;
> > > +    }
> > > +
> > >      ofmt = ofmt_ctx->oformat;
> > >
> > >      for (i = 0; i < ifmt_ctx->nb_streams; i++) {
> > > +        AVStream *out_stream;
> > >          AVStream *in_stream = ifmt_ctx->streams[i];
> > > -        AVStream *out_stream = avformat_new_stream(ofmt_ctx,
> > > in_stream->codec->codec);
> > > +        AVCodecParameters *in_codecpar = in_stream->codecpar;
> > > +
> > > +        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
> > > +            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
> > > +            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
> > > +            stream_mapping[i] = -1;
> > > +            continue;
> > > +        }
> > > +
> > > +        stream_mapping[i] = stream_index++;
> > > +
> > > +        out_stream = avformat_new_stream(ofmt_ctx, NULL);
> > >          if (!out_stream) {
> > >              fprintf(stderr, "Failed allocating output stream\n");
> > >              ret = AVERROR_UNKNOWN;
> > >              goto end;
> > >          }
> > >
> > > -        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
> > > +        ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
> > >          if (ret < 0) {
> > > -            fprintf(stderr, "Failed to copy context from input to output
> > > stream codec context\n");
> > > +            fprintf(stderr, "Failed to copy copy codec parameters\n");
> > > +            goto end;
> > > +        }
> > > +        out_stream->codecpar->codec_tag = 0;
> > > +
> > > +        ret = avformat_transfer_internal_stream_timing_info(ofmt,
> > > out_stream, in_stream, AVFMT_TBCF_AUTO);
> > > +        if (ret < 0) {
> > > +            fprintf(stderr, "Failed to copy stream timing info\n");
> > >              goto end;
> > >          }
> > > -        out_stream->codec->codec_tag = 0;
> > > -        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
> > > -            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
> > >      }
> > >      av_dump_format(ofmt_ctx, 0, out_filename, 1);
> > >
> > > @@ -127,8 +153,14 @@ int main(int argc, char **argv)
> > >              break;
> > >
> > >          in_stream  = ifmt_ctx->streams[pkt.stream_index];
> > > -        out_stream = ofmt_ctx->streams[pkt.stream_index];
> > > +        if (pkt.stream_index >= stream_mapping_size ||
> > > +            stream_mapping[pkt.stream_index] < 0) {
> > > +            av_packet_unref(&pkt);
> > > +            continue;
> > > +        }
> > >
> > > +        pkt.stream_index = stream_mapping[pkt.stream_index];
> > > +        out_stream = ofmt_ctx->streams[pkt.stream_index];
> > >          log_packet(ifmt_ctx, &pkt, "in");
> > >
> > >          /* copy packet */
> > > @@ -156,6 +188,8 @@ end:
> > >          avio_closep(&ofmt_ctx->pb);
> > >      avformat_free_context(ofmt_ctx);
> > >
> > > +    av_freep(&stream_mapping);
> > > +
> > >      if (ret < 0 && ret != AVERROR_EOF) {
> > >          fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
> > >          return 1;
> > > --
> > > 2.12.0
> > >
> > >
> > Patch pushed (taking into account wm4 and Moritz reviews).
> 
> This changes timestamps and durations
> ./ffmpeg -i matrixbench_mpeg2.mpg -t 10 -vcodec copy -acodec copy ref.mpg
> doc/examples/remuxing ref.mpg old.mp4 >& OLD
> ...
> doc/examples/remuxing ref.mpg new.mp4 >& NEW
> 
> ...
>  in: pts:48600 pts_time:0.54 dts:48600 dts_time:0.54 duration:2160 duration_time:0.024 stream_index:1
>  out: pts:25920 pts_time:0.54 dts:25920 dts_time:0.54 duration:1152 duration_time:0.024 stream_index:1
>  in: pts:48600 pts_time:0.54 dts:45000 dts_time:0.5 duration:3600 duration_time:0.04 stream_index:0
> -out: pts:6912 pts_time:0.54 dts:6400 dts_time:0.5 duration:512 duration_time:0.04 stream_index:0
> +out: pts:48600 pts_time:0.54 dts:45000 dts_time:0.5 duration:3600 duration_time:0.04 stream_index:0
>  in: pts:NOPTS pts_time:NOPTS dts:48600 dts_time:0.54 duration:3600 duration_time:0.04 stream_index:0
> -out: pts:NOPTS pts_time:NOPTS dts:6912 dts_time:0.54 duration:512 duration_time:0.04 stream_index:0
> +out: pts:NOPTS pts_time:NOPTS dts:48600 dts_time:0.54 duration:3600 duration_time:0.04 stream_index:0
>  in: pts:52200 pts_time:0.58 dts:52200 dts_time:0.58 duration:3600 duration_time:0.04 stream_index:0
> -out: pts:7424 pts_time:0.58 dts:7424 dts_time:0.58 duration:512 duration_time:0.04 stream_index:0
> +out: pts:52200 pts_time:0.58 dts:52200 dts_time:0.58 duration:3600 duration_time:0.04 stream_index:0
>  in: pts:55800 pts_time:0.62 dts:55800 dts_time:0.62 duration:3600 duration_time:0.04 stream_index:0
> -out: pts:7936 pts_time:0.62 dts:7936 dts_time:0.62 duration:512 duration_time:0.04 stream_index:0
> +out: pts:55800 pts_time:0.62 dts:55800 dts_time:0.62 duration:3600 duration_time:0.04 stream_index:0
>  in: pts:50760 pts_time:0.564 dts:50760 dts_time:0.564 duration:2160 duration_time:0.024 stream_index:1
>  out: pts:27072 pts_time:0.564 dts:27072 dts_time:0.564 duration:1152 duration_time:0.024 stream_index:1
> 
> is this intended ?

The new code makes the output stream time base matches the input stream
one.
In this case, it matches 1/90000, making the output pts/duration match
the input ones. The output dst_time/duration_time matches the input
ones and matches the values we got before the patch applied.

Unless I miss something here, the new values are correct.

Matthieu
diff mbox

Patch

diff --git a/doc/examples/remuxing.c b/doc/examples/remuxing.c
index 65437d9abd..8615c73842 100644
--- a/doc/examples/remuxing.c
+++ b/doc/examples/remuxing.c
@@ -50,6 +50,9 @@  int main(int argc, char **argv)
     AVPacket pkt;
     const char *in_filename, *out_filename;
     int ret, i;
+    int stream_index = 0;
+    int *stream_mapping = NULL;
+    int stream_mapping_size = 0;
 
     if (argc < 3) {
         printf("usage: %s input output\n"
@@ -83,25 +86,48 @@  int main(int argc, char **argv)
         goto end;
     }
 
+    stream_mapping_size = ifmt_ctx->nb_streams;
+    stream_mapping = av_mallocz_array(stream_mapping_size, sizeof(*stream_mapping));
+    if (!stream_mapping) {
+        ret = AVERROR(ENOMEM);
+        goto end;
+    }
+
     ofmt = ofmt_ctx->oformat;
 
     for (i = 0; i < ifmt_ctx->nb_streams; i++) {
+        AVStream *out_stream;
         AVStream *in_stream = ifmt_ctx->streams[i];
-        AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
+        AVCodecParameters *in_codecpar = in_stream->codecpar;
+
+        if (in_codecpar->codec_type != AVMEDIA_TYPE_AUDIO &&
+            in_codecpar->codec_type != AVMEDIA_TYPE_VIDEO &&
+            in_codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) {
+            stream_mapping[i] = -1;
+            continue;
+        }
+
+        stream_mapping[i] = stream_index++;
+
+        out_stream = avformat_new_stream(ofmt_ctx, NULL);
         if (!out_stream) {
             fprintf(stderr, "Failed allocating output stream\n");
             ret = AVERROR_UNKNOWN;
             goto end;
         }
 
-        ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
+        ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
         if (ret < 0) {
-            fprintf(stderr, "Failed to copy context from input to output stream codec context\n");
+            fprintf(stderr, "Failed to copy copy codec parameters\n");
+            goto end;
+        }
+        out_stream->codecpar->codec_tag = 0;
+
+        ret = avformat_transfer_internal_stream_timing_info(ofmt, out_stream, in_stream, AVFMT_TBCF_AUTO);
+        if (ret < 0) {
+            fprintf(stderr, "Failed to copy stream timing info\n");
             goto end;
         }
-        out_stream->codec->codec_tag = 0;
-        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
-            out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
     }
     av_dump_format(ofmt_ctx, 0, out_filename, 1);
 
@@ -127,8 +153,14 @@  int main(int argc, char **argv)
             break;
 
         in_stream  = ifmt_ctx->streams[pkt.stream_index];
-        out_stream = ofmt_ctx->streams[pkt.stream_index];
+        if (pkt.stream_index >= stream_mapping_size ||
+            stream_mapping[pkt.stream_index] < 0) {
+            av_packet_unref(&pkt);
+            continue;
+        }
 
+        pkt.stream_index = stream_mapping[pkt.stream_index];
+        out_stream = ofmt_ctx->streams[pkt.stream_index];
         log_packet(ifmt_ctx, &pkt, "in");
 
         /* copy packet */
@@ -156,6 +188,8 @@  end:
         avio_closep(&ofmt_ctx->pb);
     avformat_free_context(ofmt_ctx);
 
+    av_freep(&stream_mapping);
+
     if (ret < 0 && ret != AVERROR_EOF) {
         fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
         return 1;