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

Automatically retry with a lower definition on MediaCodec error #2947

Merged
merged 11 commits into from
Jan 21, 2022

Conversation

rom1v
Copy link
Collaborator

@rom1v rom1v commented Jan 15, 2022

Some devices are not able to encode at the device screen definition.

Instead of just failing, automatically try with a lower definition (fallback) on any MediaCodec error.

This is a recurrent issue for new users. The solution is explained in the FAQ (and sometimes in the error message, depending on the error), but it will help a lot if scrcpy automatically retries with different "max size" values.

An option --no-downsize-on-error is also added to disable this behavior.

Here are binaries (replace in your v1.21 release):

  • scrcpy.exe sha256:bdf50503f7f0f2771758abd877344e10a7cd37d3b3539bef2d80c7323807a41e
  • scrcpy-server sha256:c2edcdb775776d5bca93fe04ca37159c7dc2cd36a6b7619e583c702e75eaa855
v2 (obsolete)
  • scrcpy.exe sha256:9f43f1ef5452b0a826cce78740fd2b93582b36accd5b9295796322c1ee02c5f8
  • scrcpy-server sha256:86d9c13a88f9523150017c50061bf04b5ad234808139df31b337c2701e6b3791
v1 (obsolete)
  • scrcpy.exe sha256:d5043a52eb572b445ffc4410d8327bb363258d0303dd645bc56423805296694d
  • scrcpy-server sha256:86d9c13a88f9523150017c50061bf04b5ad234808139df31b337c2701e6b3791

I don't have any device which actually fails, so tests and feedback are welcome.

@rom1v
Copy link
Collaborator Author

rom1v commented Jan 16, 2022

There is a problem with the initial size: if the device downsize the video stream before the first frame, the window initial size will also be scaled down. I will work on it.

@rom1v
Copy link
Collaborator Author

rom1v commented Jan 16, 2022

There is a problem with the initial size

I fixed it and updated the binaries in the thread.

Please test :)

@rom1v rom1v force-pushed the downsize_on_error branch from 3a0a68f to 8af00e8 Compare January 17, 2022 19:23
@rom1v
Copy link
Collaborator Author

rom1v commented Jan 17, 2022

I updated to downsize on error only before the first frame.

The purpose of automatic downscaling on error is to make mirroring work by just starting scrcpy without an explicit -m value, even if the encoder could not encode at the screen definition. If it fails later, just fail, resizing at any time might be unexpected, so disable it.

@rom1v rom1v changed the title Automatically try with a lower defintiion on MediaCodec error Automatically try with a lower definition on MediaCodec error Jan 18, 2022
@rom1v rom1v mentioned this pull request Jan 18, 2022
@Valkhes
Copy link

Valkhes commented Jan 20, 2022

Hi rom1v,

Following this commit, I wonder if it will helps on my phone. I have a Pixel 2 XL, and trying to use an encoder that is listed which is the "OMX.google.h264.encoder" encoder.

When trying to launch scrcpy and get the frames, I'm having this error :

java.lang.IllegalArgumentException
at android.media.MediaCodec.native_configure(Native Method)
at android.media.MediaCodec.configure(MediaCodec.java:2127)
at android.media.MediaCodec.configure(MediaCodec.java:2043)
at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:233)
at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:86)
at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:65)
at com.genymobile.scrcpy.Server.scrcpy(Server.java:93)
at com.genymobile.scrcpy.Server.main(Server.java:309)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399)

Looking at some issues and the FAQ, it looks a lot like this problem :

https://github.com/Genymobile/scrcpy/blob/master/FAQ.md#exception

If I understand well, this commit is potentially "correcting" this problem by lowering the definition. Am I right ?
I'll try the new server if you think this can correct this issue, and I'll be able to test your commit this way.

Thanks

@rom1v
Copy link
Collaborator Author

rom1v commented Jan 20, 2022

I'll try the new server if you think this can correct this issue

The change is mainly in the server (which will retry), so yes, it will help (you need both the client and server) :D

rom1v added 11 commits January 21, 2022 18:36
Use the actual rotation and size values directly.

This will allow to automatically change the maxSize value on MediaCodec
error.

PR #2947 <#2947>
This will allow to reuse them to recreate a ScreenInfo instance in order
to change the maxSize value on MediaCodec error.

PR #2947 <#2947>
Some devices are not able to encode at the device screen definition.

Instead of just failing, try with a lower definition on any MediaCodec
error.

PR #2947 <#2947>
Add --no-downsize-on-error option to disable attempts to use a lower
definition on MediaCodec error.

PR #2947 <#2947>
Now that scrcpy attempts with a lower definition on any MediaCodec
error (or the user explicitly requests to disable auto-downsizing), the
suggestion is unnecessary.

PR #2947 <#2947>
The position fields accept SC_WINDOW_POSITION_UNDEFINED, not the size
fields.

PR #2947 <#2947>
Show the window only after the actual frame size is known (and if no
error has occurred).

This will allow to properly position and size the window when the size
of the first frame is different from the size initially announced by the
server.

PR #2947 <#2947>
The optimal initial size was computed from the expected dimensions, sent
immediately by the server before encoding any video frame.

However, the actual frame size may be different, for example when the
device encoder does not support the requested size.

To always handle this case properly, position and size the window only
once the first frame size is known.

PR #2947 <#2947>
V4L2 device is created with the initial device size, it does not support
resizing.

PR #2947 <#2947>
The purpose of automatic downscaling on error is to make mirroring work
by just starting scrcpy without an explicit -m value, even if the
encoder could not encode at the screen definition.

It is only useful when we detect an encoding failure before the first
frame. Downsizing later could be surprising, so disable it.

PR #2947 <#2947>
@rom1v rom1v force-pushed the downsize_on_error branch from 8af00e8 to 2eb6fe7 Compare January 21, 2022 17:46
@rom1v rom1v merged commit 2eb6fe7 into dev Jan 21, 2022
@rom1v rom1v changed the title Automatically try with a lower definition on MediaCodec error Automatically retry with a lower definition on MediaCodec error Jan 29, 2022
@rom1v rom1v mentioned this pull request Jan 29, 2022
2 tasks
@AndroidDeveloperLB
Copy link

This change has fixed an issue with Galaxy A32 that always failed to mirror.
Thank you guys for adding it!

rom1v added a commit that referenced this pull request Jan 30, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

ERROR: Exception on thread Thread[main,5,main]
    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
rom1v added a commit that referenced this pull request Jan 30, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
rom1v added a commit that referenced this pull request Jan 30, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
rom1v added a commit that referenced this pull request Jan 30, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
PR #2990 <#2990>
rom1v added a commit that referenced this pull request Jan 30, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
PR #2990 <#2990>
rom1v added a commit that referenced this pull request Feb 2, 2022
The new retry mechanism with a lower definition only worked if the error
occurred during encode(). For example:

    java.lang.IllegalStateException
        at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
        at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:3452)
        at com.genymobile.scrcpy.ScreenEncoder.encode(ScreenEncoder.java:114)
        at com.genymobile.scrcpy.ScreenEncoder.internalStreamScreen(ScreenEncoder.java:95)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:61)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:80)
        at com.genymobile.scrcpy.Server.main(Server.java:255)

However, MediaCodec may also fail before encoding, during configure() or
start(). For example:

    android.media.MediaCodec$CodecException: Error 0xfffffc0e
        at android.media.MediaCodec.native_configure(Native Method)
        at android.media.MediaCodec.configure(MediaCodec.java:1956)
        at android.media.MediaCodec.configure(MediaCodec.java:1885)
        at com.genymobile.scrcpy.ScreenEncoder.configure(ScreenEncoder.java:158)
        at com.genymobile.scrcpy.ScreenEncoder.streamScreen(ScreenEncoder.java:68)
        at com.genymobile.scrcpy.Server.scrcpy(Server.java:28)
        at com.genymobile.scrcpy.Server.main(Server.java:110)

Also downscale and retry in these cases.

Refs #2947 <#2947>
Refs #2988 <#2988>
PR #2990 <#2990>
rom1v added a commit that referenced this pull request Feb 20, 2022
MediaCodec.configure() may throw an IllegalArgumentException if it does
not support the requested size. Also retry on this exception.

Fixes #2993 <#2993>
Refs #2947 <#2947>
Refs #2990 <#2990>
rom1v added a commit that referenced this pull request Feb 20, 2022
MediaCodec.configure() may throw an IllegalArgumentException if it does
not support the requested size. Also retry on this exception.

Fixes #2993 <#2993>
Refs #2947 <#2947>
Refs #2990 <#2990>
PR #3043 <#3043>
rom1v added a commit that referenced this pull request Feb 22, 2022
MediaCodec.configure() may throw an IllegalArgumentException if it does
not support the requested size. Also retry on this exception.

Fixes #2993 <#2993>
Refs #2947 <#2947>
Refs #2990 <#2990>
PR #3043 <#3043>
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.

3 participants