FFMS / ffms2

An FFmpeg based source library and Avisynth/VapourSynth plugin for easy frame accurate access
Other
574 stars 104 forks source link

Infinite Loop in GetAudio for certain files #423

Closed arch1t3cht closed 9 months ago

arch1t3cht commented 11 months ago

Hello - I was sent an audio file which makes FFMS2 lock up when reading the entire audio from start to finish.

Audio file

The file is here: https://www.dropbox.com/scl/fi/wljguppohkwgexiq50kqx/out.m4a?rlkey=lem4n70q5jqq5dgvkke9i8s79&dl=0 It seems like this file was produced by concatenating two audio files with ffmpeg, which definitely fits the analysis below.

Steps to reproduce

Open this audio file in FFMS2 and repeatedly call FFMS_GetAudio to read the audio from the beginning to the end. Eventually, FFMS2 will freeze. Specifically, this was reproduced in Aegisub, where opening that audio file (while having the Aegisub's Audio Cache Type set to either RAM or HDD) would work, but closing the file would make Aegisub freeze.

Analysis

Debugging shows that the GetAudio function enters an infinite loop,

https://github.com/FFMS/ffms2/blob/ef243ab40b8d4b6d18874c6cef0da1a2f55a6a45/src/core/audiosource.cpp#L381-L434

which is caused by the previous call to DecodeNextBlock getting AVERROR(EAGAIN) from avcodec_receive_frame.

https://github.com/FFMS/ffms2/blob/ef243ab40b8d4b6d18874c6cef0da1a2f55a6a45/src/core/audiosource.cpp#L306-L330

This happens somewhere in the middle of the audio file, likely at the point where the two files were concatenated. With this, CurrentFrame is already overwritten, but since avcodec_receive_frame didn't return data yet, no audio frame was added to the cache. Since the condition in line 427 assumes that there's a suitable audio frame in the cache, DecodeNextBlock isn't called any more and the function loops infinitely.

Fixes

A simple band-aid solution would be to check the return value of DecodeNextBlock in line 428 and throw an error if it's zero. Properly fixing this would mean sending more data to avcodec until avcodec_receive_frame works again, but I don't know enough about the code base and the packet counting involved to want to attempt that, if it's even possible.

Finally, a side note... it'd be really great to have a new release of ffms2 sometime soon. Linux distributions still have release 2.40, which still has the seeking regression in #394 , which causes seeking errors in lots of videos. New Aegisub users on Linux or Mac run into this a lot, for example.

myrsloik commented 9 months ago

Give the latest commit a try

arch1t3cht commented 9 months ago

Still happens, unfortunately, at the same timestamp as it did before the rewrite.

arch1t3cht commented 9 months ago

After a closer look, it doesn't happen on 16a06e71b67a0ba031742eda314a971ea524cca5 but was reintroduced by a6245947fe1d39fc0eadfafa5301598373d2235c .

myrsloik commented 9 months ago

Guess I'll simply revert the last commit then. Great success!