Message ID | 20170328103219.6136-1-matthieu.bouron@gmail.com |
---|---|
State | Accepted |
Headers | show |
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;
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 >
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.
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
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 [...]
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).
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 ? [...]
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 --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;