mpv-player / mpv

🎥 Command line video player
https://mpv.io
Other
28.37k stars 2.91k forks source link

gdigrab captures a single frame, then closes #7493

Open csolisr opened 4 years ago

csolisr commented 4 years ago

I'm currently attempting to capture desktop footage in order to post-process it with mpv via vapoursynth and display it back to the screen. In order to do so, I'm using gdigrab (via ffmpeg) to capture a specific window. However, whenever I attempt it, the window shows a single frame of footage, then closes shortly after.

Important Information

Provide following Information:

Reproduction steps

Run mpv av://gdigrab:title="Title of the window" or mpv av://gdigrab:desktop.

Expected behavior

mpv is expected to capture the footage from the selected application, then display it back and apply the Vapoursynth filter if applicable.

Actual behavior

mpv captures a single frame, displays it for under a second, then exits.

Log file

mpv_error_2.log.txt

Some particular lines that were of my interest:

[vd] Codec list:
[vd]     bmp - BMP (Windows and OS/2 bitmap)
[vd] Opening decoder bmp
[vd] No hardware decoding requested.
[vd] Using software decoding.
[vd] Detected 4 logical cores.
[vd] Requesting 5 threads for decoding.
[vd] Selected codec: bmp (BMP (Windows and OS/2 bitmap))
[vf] User filter list:
[vf]   (empty)
[cplayer] Starting playback...
[vd] DR failed - disabling.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[lavf] EOF reached.
[vd] Decoder format: 1920x1080 [0:1] bgra auto/auto/auto/auto/auto CL=unknown
[vf] [in] 1920x1080 bgra rgb/bt.709/srgb/full/display SP=1.000000 CL=mpeg1/jpeg
[vf] [userdeint] 1920x1080 bgra rgb/bt.709/srgb/full/display SP=1.000000 CL=mpeg1/jpeg
[vf] [userdeint] (disabled)
[vf] [autorotate] 1920x1080 bgra rgb/bt.709/srgb/full/display SP=1.000000 CL=mpeg1/jpeg
[vf] [autorotate] (disabled)
[vf] [convert] 1920x1080 bgra rgb/bt.709/srgb/full/display SP=1.000000 CL=mpeg1/jpeg
[vf] [convert] (disabled)
[vf] [out] 1920x1080 bgra rgb/bt.709/srgb/full/display SP=1.000000 CL=mpeg1/jpeg
[vf] filter input EOF
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[vf] filter output EOF
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Capturing whole desktop as 1920x1080x32 at (0,0)
[lavf] Could not set AVOption user_agent='libmpv'
[lavf] Could not set AVOption tls_verify='0'
[lavf] Could not set AVOption icy='1'
[lavf] Could not set AVOption timeout='60000000'
[cplayer] Set property: shared-script-properties -> 1
[ffmpeg/demuxer] gdigrab: Stream #0: not enough frames to estimate rate; consider increasing probesize
[lavf] avformat_find_stream_info() finished after 0 bytes.

I have already tried using a large value --demuxer-lavf-probesize (in order to increase the amount of bytes probed (around 1920x1080x32x2 = 132710400 to be absolutely safe), as it might be sampling a single frame and declaring it a standalone bitmap file, but the change didn't seem to fix the issue.

Sample files

N/A

ghost commented 4 years ago

[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6) I think the ffmpeg code simply fails. Does it work with ffmpeg CLI?

csolisr commented 4 years ago

Just checked with the command ffmpeg -f gdigrab -i desktop output.mkv, the record does capture continuously, while ffplay -f gdigrab -i desktop displays the desktop correctly (although with some looping feedback, of course). The problem seems to be the way mpv detects the ffmpeg stream, taking it incorrectly as a BMP frame.

ghost commented 4 years ago

Do you have a log with ffmpeg?

csolisr commented 4 years ago

Sorry for the delay, here's a debug file of my testing: ffmpeg-debug.txt

ghost commented 4 years ago

Hm, I can't tell why it works with ffmpeg CLI, but not in mpv. They use different ffmpeg versions, though. There's a slight (but probably unlikely) chance that there was a bug that was fixed in the later ffmpeg version.

The problem seems to be the way mpv detects the ffmpeg stream, taking it incorrectly as a BMP frame.

No, that's because it seems to successfully read at most one frame, but then ffmpeg reports I/O errors. With both ffmpeg CLI and mpv, the stream is a series of bmp frames, maybe that's the way gdigrab works.

You could try --demuxer-lavf-hacks=no, in case mpv tries to adjust the frame rate.

csolisr commented 4 years ago

An upgrade later, and using the trick you proposed, I still can't capture more than a frame:

`"C:\Program Files\mpv\mpv.com" av://gdigrab:desktop --demuxer-lavf-hacks=no --no-config
[ffmpeg/demuxer] gdigrab: Custom AVIOContext makes no sense and will be ignored with AVFMT_NOFILE format.
[ffmpeg/demuxer] gdigrab: Stream #0: not enough frames to estimate rate; consider increasing probesize
 (+) Video --vid=1 (bmp 1920x1080 29.970fps)
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[ffmpeg/demuxer] gdigrab: Failed to capture image (error 6)
[lavf] error reading packet: I/O error.
[lavf] ...treating it as fatal error.
VO: [gpu] 1920x1080 bgra
V: 00:00:00 / 00:00:00

Exiting... (End of file)
csolisr commented 4 years ago

A more verbose output: mpv-no-config.txt

SuRGeoNix commented 1 year ago

I came across this issue and fixed it by calling the avformat_open_input from a UI thread for all formats that have to do with devices. Just test mpv and still has this issue with mpv "av://gdigrab:desktop" command. Hope that helps and possible find a better solution. Draft notes from https://github.com/SuRGeoNix/Flyleaf/blob/e03e217bb89cc95842f2068cb5cb818d43322f30/FlyleafLib/MediaFramework/MediaDemuxer/Demuxer.cs#L400:-

// Some devices required to be opened from a UI thread | after 20-40 sec. of demuxing -> [gdigrab @ 0000019affe3f2c0] Failed to capture image (error 6) or (error 8)
bool isDevice = inFmt != null && inFmt->priv_class != null && (
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT) ||
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT) ||
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_INPUT) ||
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_OUTPUT) ||
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT) ||
    inFmt->priv_class->category.HasFlag(AVClassCategory.AV_CLASS_CATEGORY_DEVICE_VIDEO_OUTPUT)
    );
...
if (isDevice)
    Utils.UIInvoke(() => OpenFormat(url, inFmt, fmtOptExtra, out ret));
else
    OpenFormat(url, inFmt, fmtOptExtra, out ret);
csolisr commented 1 year ago

Just to confirm: does the fix require patching the source code, or is there a workaround I can use in the command line launch parameters?

SuRGeoNix commented 1 year ago

@csolisr My comment was referring to a different repository which also uses FFmpeg as media framework. It was just a note for mpv's developers to try and possible fix the issue. Might FFmpeg/FFplay works because they possible run avformat_open_input from the main(UI) thread anyways (didn't check). It is also possible that my issue was different (possible .NET issue) from mpv's. If it is the same issue then probably it happens for other devices (eg. decklink) and not just gdigrab.

DenisIvanovIvanov commented 5 months ago

@csolisr @SuRGeoNix I had the same issue and just to confirm that if I open the device from different thread than the UI one, then the error code appears. Using .NET and Ffmpeg.AutoGen.

I came across here for workarounds, because we also have option for RTSP, which depending on the stream, can block the UI for quite long and its frustrating. Guess we will keep it like that for now.

SuRGeoNix commented 5 months ago

@DenisIvanovIvanov There is another workaround for the UI delay issue. Some formats (eg. decklink) don't require UI just STA (it has something to do with COM objects) so you could just try to run it on STA instead of UI thread.