Opened 8 weeks ago

Closed 3 weeks ago

#8523 closed defect (fixed)

ffmpeg converts 30fps input to 29.97fps when converting to .mxf

Reported by: reakon Owned by:
Priority: normal Component: avformat
Version: git-master Keywords: mxf
Cc: adam.prajs@avid.com, cus Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:
I want to convert a 30fps file to .mxf format. The resulting file is 29.97fps. Hard-setting output to 30fps does not help.
How to reproduce:

C:\Users\aprajs\Downloads\ffmpeg-20200211-f15007a-win64-static\bin> .\ffmpeg -i 720p30.mov 720p30.mxf
ffmpeg version git-2020-02-11-f15007a Copyright (c) 2000-2020 the FFmpeg developers
  built with gcc 9.2.1 (GCC) 20200122
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --enable-amf
  libavutil      56. 39.100 / 56. 39.100
  libavcodec     58. 68.102 / 58. 68.102
  libavformat    58. 38.100 / 58. 38.100
  libavdevice    58.  9.103 / 58.  9.103
  libavfilter     7. 75.100 /  7. 75.100
  libswscale      5.  6.100 /  5.  6.100
  libswresample   3.  6.100 /  3.  6.100
  libpostproc    55.  6.100 / 55.  6.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '720p30.mov':
  Metadata:
    creation_time   : 2014-08-14T00:13:45.000000Z
  Duration: 00:01:00.03, start: 0.000000, bitrate: 106493 kb/s
    Stream #0:0(eng): Video: prores (HQ) (apch / 0x68637061), yuv422p10le(tv, bt709/unknown/unknown, progressive), 1280x720, 104954 kb/s, SAR 1:1 DAR 16:9, 30 fps, 30 tbr, 30 tbn, 30 tbc (default)
    Metadata:
      creation_time   : 2014-08-14T00:13:45.000000Z
      handler_name    : Apple Video Media Handler
      encoder         : Apple ProRes 422 HQ
      timecode        : 01:00:00:00
    Stream #0:1(eng): Audio: pcm_s16le (sowt / 0x74776F73), 48000 Hz, stereo, s16, 1536 kb/s (default)
    Metadata:
      creation_time   : 2014-08-14T00:13:45.000000Z
      handler_name    : Apple Sound Media Handler
    Stream #0:2(eng): Data: none (tmcd / 0x64636D74) (default)
    Metadata:
      creation_time   : 2014-08-14T00:14:03.000000Z
      handler_name    : Time Code Media Handler
      timecode        : 01:00:00:00
Stream mapping:
  Stream #0:0 -> #0:0 (prores (native) -> mpeg2video (native))
  Stream #0:1 -> #0:1 (pcm_s16le (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
[mxf @ 0000019024fad280] 1/30 input time base matched 1001/30000 container time base
Output #0, mxf, to '720p30.mxf':
  Metadata:
    encoder         : Lavf58.38.100
    Stream #0:0(eng): Video: mpeg2video (4:2:2), yuv422p, 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 30 fps, 29.97 tbn, 30 tbc (default)
    Metadata:
      creation_time   : 2014-08-14T00:13:45.000000Z
      handler_name    : Apple Video Media Handler
      timecode        : 01:00:00:00
      encoder         : Lavc58.68.102 mpeg2video
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: N/A
    Stream #0:1(eng): Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s (default)
    Metadata:
      creation_time   : 2014-08-14T00:13:45.000000Z
      handler_name    : Apple Sound Media Handler
      encoder         : Lavc58.68.102 pcm_s16le
[mxf @ 0000019024fad280] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 500 >= 500
[mxf @ 0000019024fad280] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 1500 >= 1500
frame= 1801 fps=300 q=24.8 Lsize=   29438kB time=00:01:00.00 bitrate=4019.2kbits/s speed=9.99x
video:16331kB audio:11250kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 6.732089%

Patches should be submitted to the ffmpeg-devel mailing list and not this bug tracker.

Attachments (2)

ffmpeg-20200214-094528.log (1.5 MB) - added by reakon 8 weeks ago.
report log
0001-libavformat-mxf-Add-support-for-30-48-1.001-48-100-1.patch (1.4 KB) - added by Tjoppen 6 weeks ago.

Download all attachments as: .zip

Change History (19)

Changed 8 weeks ago by reakon

report log

comment:1 Changed 8 weeks ago by reakon

  • Cc adam.prajs@avid.com added
  • Summary changed from ffmpeg converts 30fps intup to 29.97fps when converting to .mxf to ffmpeg converts 30fps input to 29.97fps when converting to .mxf

comment:2 Changed 8 weeks ago by cehoyos

  • Component changed from ffmpeg to avformat
  • Keywords fps convert removed

comment:3 follow-ups: Changed 7 weeks ago by Tjoppen

MXF is primarily aimed at broadcast where 30/1.001 fps reigns, so the MXF code in lavf is geared toward that. What are you doing where you need 30 fps?

comment:4 in reply to: ↑ 3 Changed 7 weeks ago by Balling

  • Status changed from new to open

Replying to Tjoppen:

MXF is primarily aimed at broadcast where 30/1.001 fps reigns, so the MXF code in lavf is geared toward that. What are you doing where you need 30 fps?

Well, are you aware The Witcher and The Irishman are using 24.000 fps, the same can be about 30 fps.

comment:5 Changed 7 weeks ago by Tjoppen

Film is 24 fps yes, which is why we have support for that in the muxer, and the NTSC variant 24/1.001 fps. There are a lot of metadata fields in MXF which are easy to get wrong, and I don't want us to output broken files.

I went over the specs and the MXF book, and predictably there are no recommendations for 30 fps.

comment:6 in reply to: ↑ 3 Changed 7 weeks ago by reakon

Replying to Tjoppen:

MXF is primarily aimed at broadcast where 30/1.001 fps reigns, so the MXF code in lavf is geared toward that. What are you doing where you need 30 fps?

MacOS Catalina ships without QuickTime? Player 7, which we (Pro Tools) used to open .mov files. While we are working on picking up the slack with an internal solution, some clients are using ffmpeg-based converters to convert their unsupported .mov files to supported .mxf format, and they are reporting this issue. I also see 47fps and 48fps files are converted to 50 fps.
Aside from that, I'd generally expect output framerate to match input's, unless specified otherwise. Since, as you said, MXF is aimed at broadcast, I think conversion to it should trust the user to know what output he/she wants, instead of shoehorning input into assumed "proper" output.

comment:7 Changed 7 weeks ago by Tjoppen

The problem is that we can't define mxf_spf for every conceivable framerate. At the moment it is defined thus:

static const MXFSamplesPerFrame mxf_spf[] = {
    { { 1001, 24000 }, { 2002, 0,    0,    0,    0,    0 } }, // FILM 23.976
    { { 1, 24},        { 2000, 0,    0,    0,    0,    0 } }, // FILM 24
    { { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97
    { { 1, 30 },       { 1600, 0,    0,    0,    0,    0 } }, // 30
    { { 1001, 60000 }, { 801,  801,  800,  801,  801,  0 } }, // NTSC 59.94
    { { 1, 25 },       { 1920, 0,    0,    0,    0,    0 } }, // PAL 25
    { { 1, 50 },       { 960,  0,    0,    0,    0,    0 } }, // PAL 50
    { { 1, 60 },       { 800,  0,    0,    0,    0,    0 } },
};

mxf_content_package_rates relates to this as well:

static const int mxf_content_package_rates[] = {
    3, 2, 7, 13, 4, 10, 12,
};

The muxer even warns about the inexact match:

[mxf @ 00000187ba421d80] 1/30 input time base matched 1001/30000 container time base

IMO the muxer should outright refuse if the user isn't specifying *exacly* the right time base, to avoid outputting things that will lose sync. With MXF being picky is a necessity.

It might be possible to add support for specific rates without too much engineering effort, but a general solution that also respects mxf_spf would be trickier. Of course, audio-only MXF or .wav could be a solution for Pro Tools

comment:8 Changed 7 weeks ago by reakon

Actually, video-only MXF would be of more help, as MXF is used in Pro Tools mostly for video post-production.
Framerates supported by Pro Tools and Media Composer are: 24/1.001, 24, 25, 30/1.001, 30, 48/1.001, 48, 50, 60/1.001, 60, 100, 120/1.001 and 120. That covers most of rates used by video industry, and we don't really deal with arbitrary non-standard rates. Therefore I don't expect any further tinkering to be necessary anytime soon.

comment:9 Changed 7 weeks ago by Tjoppen

That sounds like a reasonable list. However, is there a spec for what to put in mxf_spf for the rates in that list that don't cleanly divide 48 kHz?

comment:10 follow-up: Changed 7 weeks ago by reakon

The closest to a spec I can find is a mention about IEC61937-14:2017 standard in kexoplayer's source code covering similar functionality. Though, since rates for 30/1.001 an 60/1.001 are already defined, we can calculate average rate for remaining 120/1.001 as such:

samplerate/framerate = samples/frames = 48000/(120/1.001) = 4004/10 = 400.4

Spreading it to 5 frames would give 2x 401 sample frames and 3x 400 frames. I'm not sure if these should be put in a specific sequence tho.

comment:11 Changed 7 weeks ago by cus

  • Cc cus added

As far as I remember simple rounding rules gets you the sequences above, so maybe we should just use that instead of hard-coded tables.

comment:12 in reply to: ↑ 10 ; follow-up: Changed 6 weeks ago by Tjoppen

Replying to reakon:

The closest to a spec I can find is a mention about IEC61937-14:2017 standard in kexoplayer's source code covering similar functionality. Though, since rates for 30/1.001 an 60/1.001 are already defined, we can calculate average rate for remaining 120/1.001 as such:

samplerate/framerate = samples/frames = 48000/(120/1.001) = 4004/10 = 400.4

Spreading it to 5 frames would give 2x 401 sample frames and 3x 400 frames. I'm not sure if these should be put in a specific sequence tho.

Alternating them similar to what is done now is probably OK, even if I would like to see a spec. Please give the attached patch a go. I don't have any suitable material for it, but it passes FATE at least.

comment:13 in reply to: ↑ 12 ; follow-up: Changed 6 weeks ago by cehoyos

Replying to Tjoppen:

Please give the attached patch a go.

Is there really no way to calculate the numbers?

comment:14 Changed 6 weeks ago by cus

Probably there is, but maybe we would lose some future flexibility. Also it is easier to fix existing code than to rework it, so I'd like to see this merged if noone is working on a table-less approach.

comment:15 in reply to: ↑ 13 Changed 6 weeks ago by Tjoppen

Replying to cehoyos:

Replying to Tjoppen:

Please give the attached patch a go.

Is there really no way to calculate the numbers?

I calculated them using galculator if that's what you're asking. If you're asking how we could have it handle arbitrary framerates then I don't think you know how picky MXF decoders tend to be.

comment:16 Changed 6 weeks ago by cus

Okay, I had a bit of time to try and get rid of the sample tables, patches are on ffmpeg-devel:

http://mplayerhq.hu/pipermail/ffmpeg-devel/2020-February/257751.html

comment:17 Changed 3 weeks ago by cus

  • Resolution set to fixed
  • Status changed from open to closed
Note: See TracTickets for help on using tickets.