Opened 3 years ago

Closed 2 years ago

#9621 closed defect (fixed)

flac parser sync heuristics issue

Reported by: Mattias Wadman Owned by:
Priority: important Component: avcodec
Version: git-master Keywords: flac regression
Cc: Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no

Description

Summary of the bug:

Here is a flac file that decodes fine with the flac referenced decoder but fails with CRC error with ffmpeg. Unfortunately i can't share the whole original file but i've managed to cut out the first 27 frames and manually corrected CRCs and MD5 checksums and it fails in the same way.

How to reproduce:

$ flac -t flac_validate_bug.flac

flac 1.3.3
Copyright (C) 2000-2009  Josh Coalson, 2011-2016  Xiph.Org Foundation
flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are
welcome to redistribute it under certain conditions.  Type `flac' for details.

flac_validate_bug.flac: ok

ffmpeg master 2020-01-31:

$ ./ffmpeg -v trace -i flac_validate_bug.flac -f null -
ffmpeg version N-105439-g1530b3f566 Copyright (c) 2000-2022 the FFmpeg developers
  built with Apple clang version 13.0.0 (clang-1300.0.29.30)
  configuration:
  libavutil      57. 19.100 / 57. 19.100
  libavcodec     59. 20.100 / 59. 20.100
  libavformat    59. 17.101 / 59. 17.101
  libavdevice    59.  5.100 / 59.  5.100
  libavfilter     8. 26.101 /  8. 26.101
  libswscale      6.  5.100 /  6.  5.100
  libswresample   4.  4.100 /  4.  4.100
Splitting the commandline.
Reading option '-v' ... matched as option 'v' (set logging level) with argument 'trace'.
Reading option '-i' ... matched as input url with argument 'flac_validate_bug.flac'.
Reading option '-f' ... matched as option 'f' (force format) with argument 'null'.
Reading option '-' ... matched as output url.
Finished splitting the commandline.
Parsing a group of options: global .
Applying option v (set logging level) with argument trace.
Successfully parsed a group of options.
Parsing a group of options: input url flac_validate_bug.flac.
Successfully parsed a group of options.
Opening an input file: flac_validate_bug.flac.
[NULL @ 0x7feb7b804080] Opening 'flac_validate_bug.flac' for reading
[file @ 0x7feb7b804880] Setting default whitelist 'file,crypto,data'
Probing flac score:100 size:2048
[flac @ 0x7feb7b804080] Format flac probed with size=2048 and score=100
[flac @ 0x7feb7b804080] Before avformat_find_stream_info() pos: 8238 bytes read:20879 seeks:0 nb_streams:1
[flac @ 0x7feb7b804080] All info found
[flac @ 0x7feb7b804080] stream 0: start_time: 0 duration: 2.60063
[flac @ 0x7feb7b804080] format: start_time: 0 duration: 2.60064 (estimate from stream) bitrate=64 kb/s
[flac @ 0x7feb7b804080] After avformat_find_stream_info() pos: 10286 bytes read:20879 seeks:0 frames:1
Input #0, flac, from 'flac_validate_bug.flac':
  Duration: 00:00:02.60, start: 0.000000, bitrate: 64 kb/s
  Stream #0:0, 1, 1/44100: Audio: flac, 44100 Hz, stereo, s16
Successfully opened the file.
Parsing a group of options: output url -.
Applying option f (force format) with argument null.
Successfully parsed a group of options.
Opening an output file: -.
Successfully opened the file.
detected 4 logical cores
Stream mapping:
  Stream #0:0 -> #0:0 (flac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
cur_dts is invalid st:0 (0) [init:0 i_done:0 finish:0] (this is harmless if it occurs once at the start per stream)
    Last message repeated 4 times
[graph_0_in_0_0 @ 0x7feb7b905b40] Setting 'time_base' to value '1/44100'
[graph_0_in_0_0 @ 0x7feb7b905b40] Setting 'sample_rate' to value '44100'
[graph_0_in_0_0 @ 0x7feb7b905b40] Setting 'sample_fmt' to value 's16'
[graph_0_in_0_0 @ 0x7feb7b905b40] Setting 'channel_layout' to value '0x3'
[graph_0_in_0_0 @ 0x7feb7b905b40] tb:1/44100 samplefmt:s16 samplerate:44100 chlayout:0x3
[format_out_0_0 @ 0x7feb7b9060c0] Setting 'sample_fmts' to value 's16'
[AVFilterGraph @ 0x7feb7bb09f00] query_formats: 4 queried, 9 merged, 0 already done, 0 delayed
Output #0, null, to 'pipe:':
  Metadata:
    encoder         : Lavf59.17.101
  Stream #0:0, 0, 1/44100: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
    Metadata:
      encoder         : Lavc59.20.100 pcm_s16le
[NULL @ 0x7feb7b9051c0] sample/frame number mismatch in adjacent frames
[NULL @ 0x7feb7b9051c0] crc check failed from offset 0 (frame 27) to 2027 (frame 27)
[flac @ 0x7feb7bb07bc0] illegal residual coding method 2
[flac @ 0x7feb7bb07bc0] decode_frame() failed
[flac @ 0x7feb7bb07300] invalid residual
[flac @ 0x7feb7bb07300] decode_frame() failed
Error while decoding stream #0:0: Invalid data found when processing input
    Last message repeated 1 times
[null @ 0x7feb7bb04540] Application provided invalid, non monotonically increasing dts to muxer in stream 0: 102400 >= 32256
[out_0_0 @ 0x7feb7b905f00] EOF on sink link out_0_0:default.
No more output streams to write to, finishing.
size=N/A time=00:00:02.41 bitrate=N/A speed=1.31e+03x
video:0kB audio:432kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Input file #0 (flac_validate_bug.flac):
  Input stream #0:0 (audio): 29 packets read (12641 bytes); 27 frames decoded (110592 samples);
  Total: 29 packets (12641 bytes) demuxed
Output file #0 (pipe:):
  Output stream #0:0 (audio): 27 frames encoded (110592 samples); 27 packets muxed (442368 bytes);
  Total: 27 packets (442368 bytes) muxed
27 frames successfully decoded, 2 decoding errors
[AVIOContext @ 0x7feb7b804a00] Statistics: 20879 bytes read, 0 seeks

I think the issue is that the flac parser falsely finds a frame header inside the samples data of frame 26. If i use fq (disclaimer im the author of the tool) i can see that inside frame 26 at byte 2603 there is a bunch of bytes that very much looks like a flac header and seems to fool all current validation code checks in frame_header_is_valid/ff_flac_decode_frame_header and also even happens to have end of header bits indicating it is frame number 27.

Here i run fq to show the header of frame 26 and also show the header when decoding byte 2603 and forward of frame 266 as a flac frame. I also see that "illegal residual coding method 2" seems to match.

$ fq -o line_bytes=10 '.frames[26] | ., (tobytesrange[2603:] | flac_frame) | (.header | d), .subframes[1].residual_coding_method' flac_validate_bug.flac
      │00 01 02 03 04 05 06 07 08 09│0123456789│.frames[26].header{}:
0x2b52│            ff f8            │    ..    │  sync: 0b11111111111110 (valid)
0x2b52│               f8            │     .    │  reserved0: 0 (valid)
0x2b52│               f8            │     .    │  blocking_strategy: "fixed" (0)
0x2b52│                  c9         │      .   │  block_size: 4096 (0b1100)
0x2b52│                  c9         │      .   │  sample_rate: 44100 (0b1001)
0x2b52│                     18      │       .  │  channel_assignment: 2 (1) (lr)
0x2b52│                     18      │       .  │  sample_size: 16 (0b100)
0x2b52│                     18      │       .  │  reserved1: 0 (valid)
      │                             │          │  end_of_header{}:
0x2b52│                        1a   │        . │    frame_number: 26
0x2b52│                           84│         .│  crc: 0x84 (valid)
      │00 01 02 03 04 05 06 07 08 09│0123456789│
0x3476│   86                        │ .        │.frames[26].subframes[1].residual_coding_method: 4 (0) (rice)
      │00 01 02 03 04 05 06 07 08 09│0123456789│.header{}:
0x357a│                     ff f8   │       .. │  sync: 0b11111111111110 (valid)
0x357a│                        f8   │        . │  reserved0: 0 (valid)
0x357a│                        f8   │        . │  blocking_strategy: "fixed" (0)
0x357a│                           39│         9│  block_size: 1152 (0b11)
0x357a│                           39│         9│  sample_rate: 44100 (0b1001)
0x3584│88                           │.         │  channel_assignment: 2 (8) (left/side stereo)
      │                             │          │  side_channel_index: 1
0x3584│88                           │.         │  sample_size: 16 (0b100)
0x3584│88                           │.         │  reserved1: 0 (valid)
      │                             │          │  end_of_header{}:
0x3584│   1b                        │ .        │    frame_number: 27
0x3584│      0e                     │  .       │  crc: 0xe (valid)
      │00 01 02 03 04 05 06 07 08 09│0123456789│
0x3944│      b1 2e                  │  ..      │.subframes[1].residual_coding_method: 2

I reported and fixed a similar issue some month ago https://trac.ffmpeg.org/ticket/9185 but this time I haven't yet been able to figure what more heuristic that could be added.

An alternative to ever increasing number of heuristics might be to optionally allow the flac parser and flac decoder to use AV_CODEC_CAP_SUBFRAMES somehow? I've done some failed attempt at bypassing the flac parser and let the decoder read frame by frame.

Attachments (1)

flac_validate_bug.flac (20.4 KB ) - added by Mattias Wadman 3 years ago.

Download all attachments as: .zip

Change History (6)

by Mattias Wadman, 3 years ago

Attachment: flac_validate_bug.flac added

comment:1 by Balling, 3 years ago

The file has CRC16 mismatch. It is thus invalid the issue can be closed (at least that is how I read https://github.com/xiph/flac/issues/276#issuecomment-1028093654). I think we are not going to validate crc16 by default, just like we do not verify md5 of flac. Full stop, it is too slow and unless it somehow helps with ER (not really the case with flac, even over network), who cares. We have same bugs in wv, in mp4, in mkv, in ts, in Dolby vision RPU, etc, etc, etc. ER may be needed for phone VoLTE codecs, like EVS and some other that are actually implemented in ffmpeg.

Last edited 3 years ago by Balling (previous) (diff)

comment:2 by Carl Eugen Hoyos, 2 years ago

Keywords: regression added
Reproduced by developer: set
Status: newopen

comment:3 by Carl Eugen Hoyos, 2 years ago

Priority: normalimportant

comment:5 by Elon Musk, 2 years ago

Resolution: fixed
Status: openclosed
Note: See TracTickets for help on using tickets.