[Libav-user] Transcoding frame rate mismatch

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

[Libav-user] Transcoding frame rate mismatch

Vassilis
Hi all,

I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Best,
Vas

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Carl Eugen Hoyos-2
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Vassilis
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

James
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Vassilis
Well that did the trick! I can't thank you enough James and also second your comment that this should be updated in the transcoding.c example.
Is there anything we can do about this?

As for the GLOBAL_HEADER if I am not mistaken it is done indeed as you suggest, maybe this has been updated, here is the relevant code:

            if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
                enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
           
            /* Third parameter can be used to pass settings to encoder */
            ret = avcodec_open2(enc_ctx, encoder, NULL);

Thanks again!

On Tue, Nov 5, 2019 at 2:03 PM James Crisafulli <[hidden email]> wrote:
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

James
Glad it helped!
Ah yes, I just checked the git trunk examples and it is as you describe, so maybe it was changed at some point, and I was basing on an older version of transcoding.c.

- James

On Tue, 5 Nov 2019 at 12:36, Vassilis <[hidden email]> wrote:
Well that did the trick! I can't thank you enough James and also second your comment that this should be updated in the transcoding.c example.
Is there anything we can do about this?

As for the GLOBAL_HEADER if I am not mistaken it is done indeed as you suggest, maybe this has been updated, here is the relevant code:

            if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
                enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
           
            /* Third parameter can be used to pass settings to encoder */
            ret = avcodec_open2(enc_ctx, encoder, NULL);

Thanks again!

On Tue, Nov 5, 2019 at 2:03 PM James Crisafulli <[hidden email]> wrote:
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Gonzalo Garramuño
In reply to this post by Vassilis

I am glad someone finally answered this as I complained about this long time ago, with no answer.


El 05/11/19 a las 09:36, Vassilis escribió:
Well that did the trick! I can't thank you enough James and also second your comment that this should be updated in the transcoding.c example.
Is there anything we can do about this?

I still cannot get it to work.  I get a floating point exception with the division of this in my code:

stream->avg_frame_rate.num * stream->avg_frame_rate.den;

Where are you guys setting the avg_frame_rate?  The transcoding.c example never sets it.


On Tue, Nov 5, 2019 at 2:03 PM James Crisafulli <[hidden email]> wrote:
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Vassilis
This is not set indeed. Since there is no frame rate conversion I simply used the input stream (ifmt_ctx->streams[stream_index]->avg_frame_rate).

On Tue, Nov 5, 2019 at 3:25 PM Gonzalo Garramuño <[hidden email]> wrote:

I am glad someone finally answered this as I complained about this long time ago, with no answer.


El 05/11/19 a las 09:36, Vassilis escribió:
Well that did the trick! I can't thank you enough James and also second your comment that this should be updated in the transcoding.c example.
Is there anything we can do about this?

I still cannot get it to work.  I get a floating point exception with the division of this in my code:

stream->avg_frame_rate.num * stream->avg_frame_rate.den;

Where are you guys setting the avg_frame_rate?  The transcoding.c example never sets it.


On Tue, Nov 5, 2019 at 2:03 PM James Crisafulli <[hidden email]> wrote:
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Vassilis
I am pasting one of the administrators of the list in hopes that this may be fixed in the transcoding.c example; it is a rather significant error.

On Tue, Nov 5, 2019 at 3:28 PM Vassilis <[hidden email]> wrote:
This is not set indeed. Since there is no frame rate conversion I simply used the input stream (ifmt_ctx->streams[stream_index]->avg_frame_rate).

On Tue, Nov 5, 2019 at 3:25 PM Gonzalo Garramuño <[hidden email]> wrote:

I am glad someone finally answered this as I complained about this long time ago, with no answer.


El 05/11/19 a las 09:36, Vassilis escribió:
Well that did the trick! I can't thank you enough James and also second your comment that this should be updated in the transcoding.c example.
Is there anything we can do about this?

I still cannot get it to work.  I get a floating point exception with the division of this in my code:

stream->avg_frame_rate.num * stream->avg_frame_rate.den;

Where are you guys setting the avg_frame_rate?  The transcoding.c example never sets it.


On Tue, Nov 5, 2019 at 2:03 PM James Crisafulli <[hidden email]> wrote:
Hi,

I used to have the same issue with my application, which I based on transcoding.c (not transcoding but anyways, writing H264 to MP4 file).
You need to set the AVPacket duration field, for some reason it shows this issue if you let it automatically set it (set to -1).
I had to do this both using libx264 and mpeg4 encoders.

Example in my code from the muxing section:

av_packet_rescale_ts(&packet, codecCtx->time_base, stream->time_base);
packet.stream_index = 0;
// probably best to write this as av_rescale_* functions, but this is old code
// for example, if 25 FPS, and time_base is 12800, then packet.duration = 12800 / 25 = 512
packet.duration = stream->time_base.den / stream->time_base.num / stream->avg_frame_rate.num * stream->avg_frame_rate.den;
// now you can mux
ret = av_interleaved_write_frame(formatCtx, &packet);

I am not sure why this is needed, I found this in another codebase with a similar comment, and it fixed my issue.

Might as well mention that in transcoding.c, it also doesn't set the GLOBAL_HEADER flag at the right time, and as such you get a malformed file if writing MP4 format. I noticed it wouldn't open in Adobe Premiere, and Windows 10 Films & TV player, and ffprobe had warnings about it as well but did manage to read it.

// TOO LATE! has to be done before avcodec open!! In transcoding.c, it does this after the call and as such the flags are ignored.
if (formatCtx->oformat->flags & AVFMT_GLOBALHEADER)
{
codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}

To fix that, I have hard coded the flag early when I know I am writing MP4, before avcodec_open():

codecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
AVDictionary *encoderOpts = nullptr;
ret = avcodec_open2(codecCtx, codecCtx->codec, &encoderOpts);

And now everything works well for me. Hopefully it fixed the issues for you as well.
Would be nice to see transcoding.c updated to fix these small issues as it is used as a base by so many people looking into libav* development.

- James 

On Tue, 5 Nov 2019 at 11:07, Vassilis <[hidden email]> wrote:
This can not be reproduced with the ffmpeg cli, conversion works fine there.
However it can be reproduced with transcoding.c for all input files.
Additionally to what I mentioned, 29.96 fps test files result in 29.98 and 30 to 30.11.
Another 24 fps file resulted in 24.03. The changes seem to be related with 
the duration of the file: the longer the file the shorter the marginal fps difference. 
The output frame rate can be determined with both fffmpeg -i as well as with
QuickTime 7 and VLC. Like I mentioned, I have spent some time with investigating this
and it looks like an issue with the correct conversion of the last frame; I was able
to get different framerate values when tampering with the pts of the last frame
but this looked like a nasty hack that I shouldn't be doing, plus it fails
again when re-encoding the file.  Here is the info from an input/output test file
that has the frame rate changed from 24 fps to 24.03:

 Duration: 00:00:36.08, start: 0.000000, bitrate: 178309 kb/s
    Stream #0:0(eng): Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p10le(tv, bt709/unknown/unknown), 1920x1080, 176160 kb/s, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 23976 tbn, 23976 tbc (default)

  Duration: 00:00:36.10, start: 0.000000, bitrate: 116072 kb/s
    Stream #0:0: Video: dnxhd (DNXHD) (AVdn / 0x6E645641), yuv422p(tv, bt709/unknown/unknown), 1920x1080, 116526 kb/s, SAR 1:1 DAR 16:9, 24.03 fps, 24 tbr, 12288 tbn, 12288 tbc (default)

You'll notice that there is a slight change in the duration as well, but this happens with the ffmpeg conversion with the cli as well.

Let me know if you need more information and thanks for the help!


On Tue, Nov 5, 2019 at 3:42 AM Carl Eugen Hoyos <[hidden email]> wrote:
Am Di., 5. Nov. 2019 um 00:16 Uhr schrieb Vassilis <[hidden email]>:
> I am trying simply to perform a transcoding process using the transcoding.c example from doc/examples. However I am seeing a very strange result (even when the example is not modified at all, ie not even changing codecs); the transcoded file has a marginally different frame rate than the original file. For example for a frame rate of 24 fps I get 24.14 fps. I also implemented this with the newer av_send/receive packet/frame functions to no avail. I would be most grateful for any insights, I've spent quite some time trying to troubleshoot this.

Can you reproduce the issue with the ffmpeg cli or only with transcoding.c?

Why do you think that the output frame rate is 24.14? What does ffmpeg
-i show for your input file?

Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".


_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Carl Eugen Hoyos-2
In reply to this post by Vassilis
Am Di., 5. Nov. 2019 um 13:36 Uhr schrieb Vassilis <[hidden email]>:
>
> Well that did the trick! I can't thank you enough James and also second your
> comment that this should be updated in the transcoding.c example.
> Is there anything we can do about this?

Send a patch made with "git format-patch" to the FFmpeg development
mailing list.

Please find out what top-posting means and avoid it on all FFmpeg
mailing lists, Carl Eugen
_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".
Reply | Threaded
Open this post in threaded view
|

Re: Transcoding frame rate mismatch

Vassilis
Send a patch made with "git format-patch" to the FFmpeg development
mailing list.

Please find out what top-posting means and avoid it on all FFmpeg
mailing lists, Carl Eugen

I don't have any repos set up for ffmpeg maybe you or someone else who does
could do this very quickly? I wouldn't want to waste anyone's time with bad patches.
The code, as it fits in the transcoding example is this:

    av_packet_rescale_ts(&enc_pkt,
                         stream_ctx[stream_index].enc_ctx->time_base,
                         ofmt_ctx->streams[stream_index]->time_base);
   
    // Calculate packet duration, using input frame rate as there is no frame rate conversion
    if (ifmt_ctx->streams[stream_index]->codecpar->codec_type ==
        AVMEDIA_TYPE_VIDEO){
       
        enc_pkt.duration = ofmt_ctx->streams[stream_index]->time_base.den / ofmt_ctx->streams[stream_index]->time_base.num / ifmt_ctx->streams[stream_index]->avg_frame_rate.num * ifmt_ctx->streams[stream_index]->avg_frame_rate.den;
    }

Thanks for your help!
 

_______________________________________________
Libav-user mailing list
[hidden email]
https://ffmpeg.org/mailman/listinfo/libav-user

To unsubscribe, visit link above, or email
[hidden email] with subject "unsubscribe".