Skip to content

Skip packets the decoder rejects instead of ending the conversion - #337

Open
MAX-WiRED wants to merge 1 commit into
uvcat7:betafrom
MAX-WiRED:fix/decode-eof
Open

Skip packets the decoder rejects instead of ending the conversion#337
MAX-WiRED wants to merge 1 commit into
uvcat7:betafrom
MAX-WiRED:fix/decode-eof

Conversation

@MAX-WiRED

@MAX-WiRED MAX-WiRED commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Converting an mp3 fails. Audio → Convert simfile to ogg on a perfectly
ordinary mp3 reports

Conversion failed: Failed to decode a frame into the FIFO buffer.

and leaves a nearly complete file behind, which is why the failure is easy to
miss: the .ogg is there, it plays, and only the last fraction of a second is
gone.

What happens

Two things in decode_audio_frame, both at the end of the file.

The packet that was never read. At AVERROR_EOF the function sets
*finished and falls through to avcodec_send_packet with the packet
av_read_frame did not fill:

    if ((error = av_read_frame(input_format_context, input_packet)) < 0) {
        if (error == AVERROR_EOF)
            *finished = 1;
        else { ... goto cleanup; }
    }
    ...
    if ((error = avcodec_send_packet(input_codec_context, input_packet)) < 0) {

A null packet is what flushes a decoder; an empty one is just an empty one.

A packet the decoder rejects ends the conversion. An mp3 written with
padding after its last frame - which is common, and true of every file I
reproduced this on - ends on a packet that is not an mp3 frame. mp3float
answers AVERROR_INVALIDDATA and says Header missing, and one bad packet
takes the whole conversion down with it. Vorbis happens to tolerate the same
packet, which is why ogg input never showed the problem.

The change

At the end of the file the decoder is flushed with a null packet, and a packet
the decoder cannot make sense of is skipped rather than treated as fatal. That
is what ffmpeg's own examples do with AVERROR_INVALIDDATA, and it is what a
player does: one unreadable frame is not a reason to stop.

This also unblocks mp3 for #333, which runs the same conversion and hits the
same packet.

Testing

Built on Windows with clang-tidy and clang-format enforced, as the build does.

The mp3 that reported Conversion failed now reports

Conversion finished.
Changed music: 100sec_Kitchen_Battle.mp3 → 100sec_Kitchen_Battle.ogg

and the .ogg is 226 bytes longer than the one the failing run left behind - the
tail that used to be dropped. Converting an ogg, which worked before, still
works and is unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant