Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ao=null never receives EOF with ao-null-untimed #14427

Open
2 of 6 tasks
kasper93 opened this issue Jun 23, 2024 · 4 comments
Open
2 of 6 tasks

ao=null never receives EOF with ao-null-untimed #14427

kasper93 opened this issue Jun 23, 2024 · 4 comments
Labels

Comments

@kasper93
Copy link
Contributor

kasper93 commented Jun 23, 2024

mpv Information

mpv v0.38.0-590-gd36f72eb63-dirty Copyright © 2000-2024 mpv/MPlayer/mplayer2 projects
 built on Jun 23 2024 20:55:13
libplacebo version: v7.349.0 (v7.349.0-rc1-20-gea3d0673-dirty)
FFmpeg version: N-115634-g6a05128a13
FFmpeg library versions:
   libavcodec      61.7.100
   libavdevice     61.2.100
   libavfilter     10.2.102
   libavformat     61.3.104
   libavutil       59.21.100
   libswresample   5.2.100
   libswscale      8.2.100

Other Information

  • Linux version: Ubuntu 16.04
  • Kernel Version: 4.4
  • GPU Model: NVIDIA GeForce 256
  • Mesa/GPU Driver Version: 71.86.13
  • Window Manager and Version: NO
  • Source mpv: https://github.com/mpv-player/mpv
  • Introduced in version: I don't know

Reproduction Steps

  1. Extract provided sample file
  2. mpv --no-config --ao=null --untimed --ao-null-untimed ./clusterfuzz-testcase-minimized-fuzzer_loadfile-4665657266864128

Expected Behavior

mpv exits after playing the file

Actual Behavior

mpv hangs and never reports EOF

Log File

We get one frame of data, eat it, and than loop without any data.

[ao/null] starting AO
[ao/null] in=7168 space=8704(8704) pl=1, eof=0
[ao/null] in=0 space=8704(8704) pl=1, eof=0
[ao/null] in=0 space=8704(8704) pl=1, eof=0
[ao/null] in=0 space=8704(8704) pl=1, eof=0
[ao/null] in=0 space=8704(8704) pl=1, eof=0
<repeated inf times>

Sample Files

clusterfuzz-testcase-minimized-fuzzer_loadfile-4665657266864128.zip

I carefully read all instruction and confirm that I did the following:

  • I tested with the latest mpv version to validate that the issue is not already fixed.
  • I provided all required information including system and mpv version.
  • I produced the log file with the exact same set of files, parameters, and conditions used in "Reproduction Steps", with the addition of --log-file=output.txt.
  • I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
  • I attached the full, untruncated log file.
  • I attached the backtrace in the case of a crash.
@kasper93
Copy link
Contributor Author

@na-na-hi @ruihe774 Do you have ideas how we can fix untimed ao null? Last time @na-na-hi blamed our mkv demuxer, but it is not the case in this case.

Proposed change by @ruihe774 works, https://github.com/mpv-player/mpv/pull/14079/files#r1593338003 question is this is the best way to handle this.

Basically in non-untimed mode, when we happen to have 0 samples, we trigger audio underrun and this reinits things and trigger EOF. In untimed mode we skip reporting underruns, but then there is no code path to actually trigger EOF.

Help appreciated.

@na-na-hi
Copy link
Contributor

na-na-hi commented Jun 23, 2024

So what's happening here is that the demux layer is reporting EOF, but it doesn't reach to the end of audio filter chain for the first audio frame read (might be decoder's fault but not sure right now). Only after the ao is restarted (because of underrun which happens without --ao-null-untimed), the next audio frame filtered reports EOF.

For well-formed files and not invalid ones generated by fuzzers, this does not happen: even for a very short audio, the first audio frame already reports EOF.

I think the solution here is that for these malformed files, we have to make sure somehow that the first audio frame reports EOF in this case. If it's not possible, then we have to make ao read a few more frames to determine the EOF status.

@kasper93
Copy link
Contributor Author

kasper93 commented Jun 23, 2024

For well-formed files and not invalid ones generated by fuzzers, this does not happen: even for a very short audio, the first audio frame already reports EOF.

I think it can still happens, if the last frame fails to decode. Generally, we can have a valid file, corrupted at the and and similar can happen.

If we look at this

mpv/audio/decode/ad_lavc.c

Lines 194 to 201 in cd1b63f

static int receive_frame(struct mp_filter *da, struct mp_frame *out)
{
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
int ret = avcodec_receive_frame(avctx, priv->avframe);
if (ret == AVERROR_EOF) {

we can see that we expect AVERROR_EOF from the decoder, but we don't get it. If I call avcodec_receive_frame once more we get EOF. So this is what happens after ao reset. I'm not sure yet, why we don't try to read more data. We don't have EOF, but we stop reading, why? ao=null should eat every data and request more.

EDIT:

We get EOF from demuxer, so I think we should already report EOF, if we have no more data to decode. The stream is truncated, decoder doesn't detect EOF, but we never feed more data from demuxer, because there is none.

@na-na-hi
Copy link
Contributor

ffplay has the same issue. It doesn't exit when playing this file. Maybe this needs to be fixed in ffmpeg?

avcodec_receive_frame here also doesn't signal decoding error in this case.

If I call avcodec_receive_frame once more we get EOF.

Because we send the decoder a NULL packet, which is EOF propagated all the way from the stream layer. It seems that this EOF isn't propagated until we request the frame one more time, which isn't done because we're stuck on the last incomplete frame.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants