Opened 8 months ago
Closed 7 months ago
#10540 closed defect (needs_more_info)
Some Meridian Lossless Packing encoded files have excess samples
Reported by: | MGislv | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avcodec |
Version: | Keywords: | mlp | |
Cc: | MGislv | Blocked By: | |
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
While the actual audio content is lossless, excess samples get added at the end, causing the decoded file to have a different checksum.
How to reproduce:
I'm using the stable 6.0 version from Arch Linux. The sample file is 44KHz/16bit, same happens with 48KHz/24bit.
Attachments:
7s-sinetone-sample.wav --> sample.wav
7s-sinetone-sample.mlp --> sample.mlp
Decoded-7s-sinetone-sample.wav --> D_sample.wav
Convert sample file to mlp and decode it
ffmpeg started on 2023-08-28 at 14:16:57 Report written to "ffmpeg-20230828-141657.log" Log level: 99 Command line: ffmpeg -v 9 -loglevel 99 -report -i sample.wav -strict -2 sample.mlp ffmpeg version n6.0 Copyright (c) 2000-2023 the FFmpeg developers built with gcc 13.1.1 (GCC) 20230429 configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enab libavutil 58. 2.100 / 58. 2.100 libavcodec 60. 3.100 / 60. 3.100 libavformat 60. 3.100 / 60. 3.100 libavdevice 60. 1.100 / 60. 1.100 libavfilter 9. 3.100 / 9. 3.100 libswscale 7. 1.100 / 7. 1.100 libswresample 4. 10.100 / 4. 10.100 libpostproc 57. 1.100 / 57. 1.100 Splitting the commandline. Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'. Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'. Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'. Reading option '-i' ... matched as input url with argument 'sample.wav'. Reading option '-strict' ...Routing option strict to both codec and muxer layer matched as AVOption 'strict' with argument '-2'. Reading option 'sample.mlp' ... matched as output url. Finished splitting the commandline. Parsing a group of options: global . Applying option v (set logging level) with argument 9. Applying option loglevel (set logging level) with argument 99. Applying option report (generate a report) with argument 1. Successfully parsed a group of options. Parsing a group of options: input url sample.wav. Successfully parsed a group of options. Opening an input file: sample.wav. [NULL @ 0x560fae271740] Opening 'sample.wav' for reading [file @ 0x560fae271d80] Setting default whitelist 'file,crypto,data' Probing wav score:99 size:2048 [wav @ 0x560fae271740] Format wav probed with size=2048 and score=99 [wav @ 0x560fae271740] Before avformat_find_stream_info() pos: 44 bytes read:65580 seeks:1 nb_streams:1 [wav @ 0x560fae271740] probing stream 0 pp:32 Probing adp score:25 size:4096 [wav @ 0x560fae271740] Probe with size=4096, packets=2469 detected adp with score=25 [wav @ 0x560fae271740] probing stream 0 pp:31 Probing adp score:25 size:8192 [wav @ 0x560fae271740] Probe with size=8192, packets=2470 detected adp with score=25 [wav @ 0x560fae271740] probing stream 0 pp:30 [wav @ 0x560fae271740] probing stream 0 pp:29 Probing adp score:25 size:16384 [wav @ 0x560fae271740] Probe with size=16384, packets=2472 detected adp with score=25 [wav @ 0x560fae271740] probing stream 0 pp:28 [wav @ 0x560fae271740] probing stream 0 pp:27 [wav @ 0x560fae271740] probing stream 0 pp:26 [wav @ 0x560fae271740] probing stream 0 pp:25 Probing adp score:25 size:32768 [wav @ 0x560fae271740] Probe with size=32768, packets=2476 detected adp with score=25 [wav @ 0x560fae271740] probing stream 0 pp:24 [wav @ 0x560fae271740] probing stream 0 pp:23 [wav @ 0x560fae271740] probing stream 0 pp:22 [wav @ 0x560fae271740] probing stream 0 pp:21 [wav @ 0x560fae271740] probing stream 0 pp:20 [wav @ 0x560fae271740] probing stream 0 pp:19 [wav @ 0x560fae271740] probing stream 0 pp:18 [wav @ 0x560fae271740] probing stream 0 pp:17 Probing adp score:25 size:65536 [wav @ 0x560fae271740] Probe with size=65536, packets=2484 detected adp with score=25 [wav @ 0x560fae271740] probing stream 0 pp:16 [wav @ 0x560fae271740] probing stream 0 pp:15 [wav @ 0x560fae271740] probing stream 0 pp:14 [wav @ 0x560fae271740] probing stream 0 pp:13 [wav @ 0x560fae271740] probing stream 0 pp:12 [wav @ 0x560fae271740] probing stream 0 pp:11 [wav @ 0x560fae271740] probing stream 0 pp:10 [wav @ 0x560fae271740] probing stream 0 pp:9 [wav @ 0x560fae271740] probing stream 0 pp:8 [wav @ 0x560fae271740] probing stream 0 pp:7 [wav @ 0x560fae271740] probing stream 0 pp:6 [wav @ 0x560fae271740] probing stream 0 pp:5 [wav @ 0x560fae271740] probing stream 0 pp:4 [wav @ 0x560fae271740] probing stream 0 pp:3 [wav @ 0x560fae271740] probing stream 0 pp:2 [wav @ 0x560fae271740] probing stream 0 pp:1 Probing adp score:25 size:131072 [wav @ 0x560fae271740] Probe with size=131072, packets=2500 detected adp with score=25 [wav @ 0x560fae271740] probed stream 0 [wav @ 0x560fae271740] parser not found for codec pcm_s16le, packets or times may be invalid. [wav @ 0x560fae271740] All info found [wav @ 0x560fae271740] stream 0: start_time: NOPTS duration: 7 [wav @ 0x560fae271740] format: start_time: NOPTS duration: 7 (estimate from stream) bitrate=1411 kb/s [wav @ 0x560fae271740] After avformat_find_stream_info() pos: 204844 bytes read:294956 seeks:1 frames:50 Guessed Channel Layout for Input Stream #0.0 : stereo Input #0, wav, from 'sample.wav': Duration: 00:00:07.00, bitrate: 1411 kb/s Stream #0:0, 50, 1/44100: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 2 channels, s16, 1411 kb/s Successfully opened the file. Parsing a group of options: output url sample.mlp. Successfully parsed a group of options. Opening an output file: sample.mlp. [file @ 0x560fae2c9100] Setting default whitelist 'file,crypto,data' Successfully opened the file. Stream mapping: Stream #0:0 -> #0:0 (pcm_s16le (native) -> mlp (native)) Press [q] to stop, [?] for help [aost#0:0/mlp @ 0x560fae2b4380] cur_dts is invalid [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream) detected 12 logical cores [graph_0_in_0_0 @ 0x560fae2cd500] Setting 'time_base' to value '1/44100' [graph_0_in_0_0 @ 0x560fae2cd500] Setting 'sample_rate' to value '44100' [graph_0_in_0_0 @ 0x560fae2cd500] Setting 'sample_fmt' to value 's16' [graph_0_in_0_0 @ 0x560fae2cd500] Setting 'channel_layout' to value 'stereo' [graph_0_in_0_0 @ 0x560fae2cd500] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:stereo [format_out_0_0 @ 0x560fae2cdb40] Setting 'sample_fmts' to value 's16|s32' [format_out_0_0 @ 0x560fae2cdb40] Setting 'sample_rates' to value '44100|48000|88200|96000|176400|192000' [format_out_0_0 @ 0x560fae2cdb40] Setting 'channel_layouts' to value 'mono|stereo|3.0(back)|quad|2.1|3.0|4.0|5.0|3.1|4.1|5.1' [AVFilterGraph @ 0x560fae2cb240] query_formats: 4 queried, 9 merged, 0 already done, 0 delayed Output #0, mlp, to 'sample.mlp': Metadata: encoder : Lavf60.3.100 Stream #0:0, 0, 1/44100: Audio: mlp, 44100 Hz, stereo, s16, 128 kb/s Metadata: encoder : Lavc60.3.100 mlp size= 0kB time=00:00:00.00 bitrate= 0.0kbits/s speed=N/A EOF in input file 0 Terminating demuxer thread 0 [out_0_0 @ 0x560fae2cd9c0] EOF on sink link out_0_0:default. No more output streams to write to, finishing. [out#0/mlp @ 0x560fae2ada80] All streams finished [out#0/mlp @ 0x560fae2ada80] Terminating muxer thread [AVIOContext @ 0x560fae2c9240] Statistics: 400660 bytes written, 0 seeks, 2 writeouts size= 391kB time=00:00:06.99 bitrate= 457.9kbits/s speed= 279x video:0kB audio:391kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000% Input file #0 (sample.wav): Input stream #0:0 (audio): 302 packets read (1234800 bytes); 302 frames decoded (308700 samples); Total: 302 packets (1234800 bytes) demuxed Output file #0 (sample.mlp): Output stream #0:0 (audio): 7718 frames encoded (308700 samples); 7718 packets muxed (400660 bytes); Total: 7718 packets (400660 bytes) muxed 302 frames successfully decoded, 0 decoding errors [AVIOContext @ 0x560fae279ec0] Statistics: 1300380 bytes read, 1 seeks
Decode:
ffmpeg started on 2023-08-28 at 14:20:55 Report written to "ffmpeg-20230828-142055.log" Log level: 99 Command line: ffmpeg -v 9 -loglevel 99 -report -i sample.mlp -strict -2 D_sample.wav ffmpeg version n6.0 Copyright (c) 2000-2023 the FFmpeg developers built with gcc 13.1.1 (GCC) 20230429 configuration: --prefix=/usr --disable-debug --disable-static --disable-stripping --enable-amf --enable-avisynth --enable-cuda-llvm --enable-lto --enable-fontconfig --enable-gmp --enable-gnutls --enable-gpl --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libdav1d --enable-libdrm --enable-libfreetype --enable-libfribidi --enable-libgsm --enable-libiec61883 --enable-libjack --enable-libjxl --enable-libmfx --enable-libmodplug --enable-libmp3lame --enable-libopencore_amrnb --enable-libopencore_amrwb --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librav1e --enable-librsvg --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libsvtav1 --enable-libtheora --enable-libv4l2 --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxcb --enable-libxml2 --enable-libxvid --enable-libzimg --enable-nvdec --enable-nvenc --enable-opencl --enab libavutil 58. 2.100 / 58. 2.100 libavcodec 60. 3.100 / 60. 3.100 libavformat 60. 3.100 / 60. 3.100 libavdevice 60. 1.100 / 60. 1.100 libavfilter 9. 3.100 / 9. 3.100 libswscale 7. 1.100 / 7. 1.100 libswresample 4. 10.100 / 4. 10.100 libpostproc 57. 1.100 / 57. 1.100 Splitting the commandline. Reading option '-v' ... matched as option 'v' (set logging level) with argument '9'. Reading option '-loglevel' ... matched as option 'loglevel' (set logging level) with argument '99'. Reading option '-report' ... matched as option 'report' (generate a report) with argument '1'. Reading option '-i' ... matched as input url with argument 'sample.mlp'. Reading option '-strict' ...Routing option strict to both codec and muxer layer matched as AVOption 'strict' with argument '-2'. Reading option 'D_sample.wav' ... matched as output url. Finished splitting the commandline. Parsing a group of options: global . Applying option v (set logging level) with argument 9. Applying option loglevel (set logging level) with argument 99. Applying option report (generate a report) with argument 1. Successfully parsed a group of options. Parsing a group of options: input url sample.mlp. Successfully parsed a group of options. Opening an input file: sample.mlp. [NULL @ 0x55f16ee49740] Opening 'sample.mlp' for reading [file @ 0x55f16ee49d80] Setting default whitelist 'file,crypto,data' Probing mlp score:100 size:65536 [mlp @ 0x55f16ee49740] Format mlp probed with size=65536 and score=100 [mlp @ 0x55f16ee49740] Before avformat_find_stream_info() pos: 0 bytes read:65536 seeks:0 nb_streams:1 [mlp @ 0x55f16ee49740] All info found [mlp @ 0x55f16ee49740] stream 0: start_time: 0 duration: NOPTS [mlp @ 0x55f16ee49740] format: start_time: 0 duration: NOPTS (estimate from bit rate) bitrate=0 kb/s [mlp @ 0x55f16ee49740] After avformat_find_stream_info() pos: 1024 bytes read:65536 seeks:0 frames:1 Input #0, mlp, from 'sample.mlp': Duration: N/A, start: 0.000000, bitrate: N/A Stream #0:0, 1, 1/44100: Audio: mlp, 44100 Hz, stereo, s16 Successfully opened the file. Parsing a group of options: output url D_sample.wav. Successfully parsed a group of options. Opening an output file: D_sample.wav. [file @ 0x55f16ee62ec0] Setting default whitelist 'file,crypto,data' Successfully opened the file. Stream mapping: Stream #0:0 -> #0:0 (mlp (native) -> pcm_s16le (native)) Press [q] to stop, [?] for help [aost#0:0/pcm_s16le @ 0x55f16ee62680] cur_dts is invalid [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream) detected 12 logical cores [graph_0_in_0_0 @ 0x55f16ee66080] Setting 'time_base' to value '1/44100' [graph_0_in_0_0 @ 0x55f16ee66080] Setting 'sample_rate' to value '44100' [graph_0_in_0_0 @ 0x55f16ee66080] Setting 'sample_fmt' to value 's16' [graph_0_in_0_0 @ 0x55f16ee66080] Setting 'channel_layout' to value 'stereo' [graph_0_in_0_0 @ 0x55f16ee66080] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:stereo [format_out_0_0 @ 0x55f16ee66780] Setting 'sample_fmts' to value 's16' [AVFilterGraph @ 0x55f16ee63dc0] query_formats: 4 queried, 9 merged, 0 already done, 0 delayed Output #0, wav, to 'D_sample.wav': Metadata: ISFT : Lavf60.3.100 Stream #0:0, 0, 1/44100: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, stereo, s16, 1411 kb/s Metadata: encoder : Lavc60.3.100 pcm_s16le size= 0kB time=00:00:00.00 bitrate=N/A speed=N/A EOF in input file 0 Terminating demuxer thread 0 [out_0_0 @ 0x55f16ee665c0] EOF on sink link out_0_0:default. No more output streams to write to, finishing. [out#0/wav @ 0x55f16ee51cc0] All streams finished [out#0/wav @ 0x55f16ee51cc0] Terminating muxer thread [AVIOContext @ 0x55f16ee63000] Statistics: 1234966 bytes written, 4 seeks, 7 writeouts size= 1206kB time=00:00:06.99 bitrate=1411.5kbits/s speed= 179x video:0kB audio:1206kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.006316% Input file #0 (sample.mlp): Input stream #0:0 (audio): 7718 packets read (400660 bytes); 7718 frames decoded (308720 samples); Total: 7718 packets (400660 bytes) demuxed Output file #0 (D_sample.wav): Output stream #0:0 (audio): 7718 frames encoded (308720 samples); 7718 packets muxed (1234880 bytes); Total: 7718 packets (1234880 bytes) muxed 7718 frames successfully decoded, 0 decoding errors [AVIOContext @ 0x55f16ee51ec0] Statistics: 400660 bytes read, 0 seeks
I then converted them to flac to compare the MD5 signature (there's probably an easier way but whatever). The checksum should be different as the decoded file differs by having 20 more samples at the end. The rest of the file seems unaffected.
Attachments (5)
Change History (21)
by , 8 months ago
Attachment: | 7s-sinetone-sample.wav added |
---|
by , 8 months ago
Attachment: | 7s-sinetone-sample.mlp added |
---|
by , 8 months ago
Attachment: | Decoded-7s-sinetone-sample.wav added |
---|
comment:2 by , 8 months ago
Same happens with STEREO TrueHD files, see: https://forum.doom9.org/showpost.php?p=1975891&postcount=246
Plex decoder and ffmpeg decoder agree (besides some zeroes in the end).
It looks like shorten_by is a little wrong in our encoder? See 9f420163c6207b9c54badd30056974a6b3450bfd
It is true: Decoded-7s-sinetone-sample.wav has 308720 samples per channel and original has 308700 samples per each of 2 channels.
Please note that our mlp encoder was VERY broken in the past. It produced .mlp files that were after decode NOT LONGER by 20 samples but shorter (308080 per channel in this case, so 620 samples gone). And back then it was just that some FRAMES in actual mlp bitsream were absent.
comment:3 by , 8 months ago
This gets correctly decoded
Yes. This is decoded the same even by Plex Transcoder.exe
comment:4 by , 8 months ago
Status: | new → open |
---|
Looking into Beyond Compare there is quite a big difference in the very end of the files between thd and mlp files encoded from 7s-sinetone-sample.wav but there is almost no difference between THD and MLP encoded from 10s-sine.wav. That is the bug I imagine and yes THD file decoded by PLEX encoded by ffmpeg from 7s-sinetone-sample.wav is very different in the end.
It looks like MLP and THD encoders are almost the same with some flags differences only. Very strange.
comment:5 by , 8 months ago
From what I gather THD is just an extension of MLP, in the sense that they use similar compression schemes with the only difference being the supported channel configurations. There must be a lot of code shared between the two in ffmpeg.
If that's the case the file size should be close too.
comment:6 by , 8 months ago
MLP/THD encoder is marked experimental for the reason.
There is no point to report bugs about experimental code.
Much better way of contributing is providing actual patches.
comment:7 by , 8 months ago
MLP/THD encoder is marked experimental for a reason.
It is mostly lossless with our own decoder. But not with official Plex EAE.exe, that uses Dolby SDK or with LG C9 OLED TV HW decoder. See my bug: #9958
There is no point to report bugs about experimental code.
Do you have any idea how to make FFmpeg's TrueHD encoder on par with Dolby Media Encoder and ESPECIALLY with old lossless Dolby Encoder? Because as of now the compression produces too big thd files.
Much better way of contributing is providing actual patches.
To Dolby too? Because Dolby Media encoder is not lossless.
comment:8 by , 8 months ago
Well, the reason is obvious. 44.1 kHz sampling rate has 1 102.500 FPS (40 SPF, samples per frame). And indeed: 308720 is perfectly divided by 40, while 308700 is not. This is where shorten_by should be applied and it should remove those 20 samples. As for 10s-sine.wav it has 441000 samples. That is also perfect divide. Same for sample from #4786.
How to prove if it is encoder at fault? Simple. Just reencode the 7s-sinetone-sample.mlp again to mlp. It should write a different file, because shorten_by is now different. BUT it is not different. That proves encoder is at fault.
The patch is to add ctx->avctx->codec_id == AV_CODEC_ID_MLP here in https://github.com/FFmpeg/FFmpeg/blob/a94a6617a3e9924e093ae9be54bc639fba6a4cde/libavcodec/mlpenc.c#L1085
so it looks like
if (ctx->avctx->codec_id == AV_CODEC_ID_TRUEHD || ctx->avctx->codec_id == AV_CODEC_ID_MLP ) {
comment:9 by , 8 months ago
Nowhere in MLP specification it specifies it supports shorten by.
Do you have actual MLP encodes that are not encoded by FFmpeg and last frame samples are not padded with silence?
comment:10 by , 8 months ago
Well, lets find out. Give me mlp with shorten_by and I will decode it with Plex decoder. THD with shorten_by created by ffmpeg is decoded corrupt ANYWAY. So unless there is a bug in Plex decoder...
comment:11 by , 8 months ago
Here is how THD encoded with ffmpeg from 7s-sinetone-sample.wav is decoded with Plex. Very different. It has 308680 samples! SO THAT means IT does apply shorten_by but instead of decoding the last frame (together 308720 samples, 7718 frames) and removing 20 samples (308700 now, as original is) it decodes -1 frame and STILL removes 20 samples. WHAT is also interesting is that this -1 frame is still corrupted, it is x2 less in aplitude. Dolby reference player command agrees with both. So that means what??? https://0x0.st/HpMD.wav
comment:12 by , 8 months ago
FFmpeg encoded output is useless to me, better compare with reference MLP encoder if you ever manage to get last frame in smaller number of samples.
comment:13 by , 8 months ago
Why do you think MLP is different from THD's shorten_by?? Also, maybe it was signalled by MPEG-TS on dvd. I do have one DVD-A like that. Dunno how to check.
So no idea whether you did an off-by-one mistake in shorten_by? Because reference decoders think you need to shorten the previous frame. Maybe you need to encode one extra frame and shorten_by signals that you need to remove this frame and then shorten the previous.
In other words I think that the frame in which shorten_by is situated needs to be discarded.
What was the sample you used to verify shorten_by??
comment:14 by , 8 months ago
Plex does not have MLP encoder nor decoder IIRC, they just repack it or something IIRC.
There is real reference MLP encoder if you can access it, it would show it.
comment:15 by , 8 months ago
nor decoder IIRC,
Yes, there is a decoder of MLP. There is no encoder of MLP.
"C:\Program Files\Plex\Plex Media Server\Plex Transcoder.exe" -decoders
A..... eac3_mf EAC3 via MediaFoundation (codec eac3) A..... eac3_eae EAE EAC3 (codec eac3) AF...D flac FLAC (Free Lossless Audio Codec) A..... mlp_eae EAE MLP (codec mlp) A....D opus Opus A....D pcm_alaw PCM A-law / G.711 A-law A....D pcm_f32be PCM 32-bit floating point big-endian A....D pcm_f32le PCM 32-bit floating point little-endian A....D pcm_f64be PCM 64-bit floating point big-endian A....D pcm_f64le PCM 64-bit floating point little-endian A....D pcm_lxf PCM signed 20-bit little-endian planar
comment:16 by , 7 months ago
Resolution: | → needs_more_info |
---|---|
Status: | open → closed |
Nothing can be done to resolve this, please provide original .mlp (not .thd) file that is not multiple of 20 samples when decoded by reference decoder.
Do not use FFmpeg mlp decoder to decode or for comparison as that one will also pad to multiple number or 20 (of whatever it is) samples.
What mailing list should I email for the attachments? I used streams.videolan.org/upload/ to upload three files:
7s-sinetone-sample.wav --> sample.wav
7s-sinetone-sample.mlp --> sample.mlp
Decoded-7s-sinetone-sample.wav --> D_sample.wav
Edit: figured out I could use the trac inteface