Quit on audio configuration failure
When audio capture fails on the device, scrcpy continues mirroring the video stream. This allows to enable audio by default only when supported. However, if an audio configuration occurs (for example the user explicitly selected an unknown audio encoder), this must be treated as an error and scrcpy must exit. PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
This commit is contained in:
parent
9196dc1563
commit
50d56a9a2b
4 changed files with 32 additions and 8 deletions
|
@ -195,6 +195,12 @@ run_demuxer(void *data) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (raw_codec_id == 1) {
|
||||||
|
LOGE("Demuxer '%s': stream configuration error on the device",
|
||||||
|
demuxer->name);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
enum AVCodecID codec_id = sc_demuxer_to_avcodec_id(raw_codec_id);
|
enum AVCodecID codec_id = sc_demuxer_to_avcodec_id(raw_codec_id);
|
||||||
if (codec_id == AV_CODEC_ID_NONE) {
|
if (codec_id == AV_CODEC_ID_NONE) {
|
||||||
LOGE("Demuxer '%s': stream disabled due to unsupported codec",
|
LOGE("Demuxer '%s': stream disabled due to unsupported codec",
|
||||||
|
|
|
@ -231,10 +231,19 @@ static void
|
||||||
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
|
sc_audio_demuxer_on_ended(struct sc_demuxer *demuxer, bool eos,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
(void) demuxer;
|
(void) demuxer;
|
||||||
(void) eos;
|
|
||||||
(void) userdata;
|
(void) userdata;
|
||||||
|
|
||||||
// Contrary to the video demuxer, keep mirroring if only the audio fails
|
// Contrary to the video demuxer, keep mirroring if only the audio fails.
|
||||||
|
// 'eos' is true on end-of-stream, including when audio capture is not
|
||||||
|
// possible on the device (so that scrcpy continue to mirror video without
|
||||||
|
// failing).
|
||||||
|
// However, if an audio configuration failure occurs (for example the user
|
||||||
|
// explicitly selected an unknown audio encoder), 'eos' is false and scrcpy
|
||||||
|
// must exit.
|
||||||
|
|
||||||
|
if (!eos) {
|
||||||
|
PUSH_EVENT(SC_EVENT_DEMUXER_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -222,7 +222,7 @@ public final class AudioEncoder {
|
||||||
public void encode() throws IOException, ConfigurationException {
|
public void encode() throws IOException, ConfigurationException {
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||||
Ln.w("Audio disabled: it is not supported before Android 11");
|
Ln.w("Audio disabled: it is not supported before Android 11");
|
||||||
streamer.writeDisableStream();
|
streamer.writeDisableStream(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,9 +279,13 @@ public final class AudioEncoder {
|
||||||
outputThread.start();
|
outputThread.start();
|
||||||
|
|
||||||
waitEnded();
|
waitEnded();
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
// Notify the error to make scrcpy exit
|
||||||
|
streamer.writeDisableStream(true);
|
||||||
|
throw e;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// Notify the client that the audio could not be captured
|
// Notify the client that the audio could not be captured
|
||||||
streamer.writeDisableStream();
|
streamer.writeDisableStream(false);
|
||||||
throw e;
|
throw e;
|
||||||
} finally {
|
} finally {
|
||||||
// Cleanup everything (either at the end or on error at any step of the initialization)
|
// Cleanup everything (either at the end or on error at any step of the initialization)
|
||||||
|
|
|
@ -40,10 +40,15 @@ public final class Streamer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeDisableStream() throws IOException {
|
public void writeDisableStream(boolean error) throws IOException {
|
||||||
// Writing 0 (32-bit) as codec-id means that the device disables the stream (because it could not capture)
|
// Writing a specific code as codec-id means that the device disables the stream
|
||||||
byte[] zeros = new byte[4];
|
// code 0: it explicitly disables the stream (because it could not capture audio), scrcpy should continue mirroring video only
|
||||||
IO.writeFully(fd, zeros, 0, zeros.length);
|
// code 1: a configuration error occurred, scrcpy must be stopped
|
||||||
|
byte[] code = new byte[4];
|
||||||
|
if (error) {
|
||||||
|
code[3] = 1;
|
||||||
|
}
|
||||||
|
IO.writeFully(fd, code, 0, code.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writePacket(ByteBuffer buffer, long pts, boolean config, boolean keyFrame) throws IOException {
|
public void writePacket(ByteBuffer buffer, long pts, boolean config, boolean keyFrame) throws IOException {
|
||||||
|
|
Loading…
Reference in a new issue