Compare commits

..

6 Commits

Author SHA1 Message Date
77ebafd96c Retrieve icon decoder directly
The call to av_find_best_stream() gives the decoder directly, there is
no need to retrieve it afterwards in a separate step.
2024-06-11 08:58:19 +02:00
9ea4446369 Release the audio lock early
The final write from the writer thread does not require a lock: it is
guaranteed that enough space is available since the reader thread never
writes.
2024-06-09 19:25:32 +02:00
5d1d5bdc16 Fix thread leak on Windows
Fixes #4973 <https://github.com/Genymobile/scrcpy/issues/4973>
2024-06-09 18:27:30 +02:00
fd9498e07c Avoid zero-length copies
Return early if there is nothing to read/write.
2024-05-30 15:56:37 +02:00
09e8c20168 Rename streamScreen() to streamCapture()
The capture source may be either the screen or the camera.
2024-05-14 08:23:57 +02:00
da484b7ab9 Reject recording with control only
If video and audio are disabled, there is nothing to record.
2024-05-12 10:44:27 +02:00
6 changed files with 23 additions and 11 deletions

View File

@ -194,7 +194,11 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
// Still insufficient, drop old samples to make space // Still insufficient, drop old samples to make space
skipped_samples = sc_audiobuf_read(&ap->buf, NULL, remaining); skipped_samples = sc_audiobuf_read(&ap->buf, NULL, remaining);
assert(skipped_samples == remaining); assert(skipped_samples == remaining);
}
SDL_UnlockAudioDevice(ap->device);
if (written < samples) {
// Now there is enough space // Now there is enough space
uint32_t w = sc_audiobuf_write(&ap->buf, uint32_t w = sc_audiobuf_write(&ap->buf,
swr_buf + TO_BYTES(written), swr_buf + TO_BYTES(written),
@ -202,8 +206,6 @@ sc_audio_player_frame_sink_push(struct sc_frame_sink *sink,
assert(w == remaining); assert(w == remaining);
(void) w; (void) w;
} }
SDL_UnlockAudioDevice(ap->device);
} }
uint32_t underflow = 0; uint32_t underflow = 0;

View File

@ -2738,6 +2738,11 @@ parse_args_with_getopt(struct scrcpy_cli_args *args, int argc, char *argv[],
} }
if (opts->record_filename) { if (opts->record_filename) {
if (!opts->video && !opts->audio) {
LOGE("Video and audio disabled, nothing to record");
return false;
}
if (!opts->record_format) { if (!opts->record_format) {
opts->record_format = guess_record_format(opts->record_filename); opts->record_format = guess_record_format(opts->record_filename);
if (!opts->record_format) { if (!opts->record_format) {

View File

@ -78,7 +78,10 @@ decode_image(const char *path) {
goto close_input; goto close_input;
} }
int stream = av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); const AVCodec *codec;
int stream =
av_find_best_stream(ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0);
if (stream < 0 ) { if (stream < 0 ) {
LOGE("Could not find best image stream"); LOGE("Could not find best image stream");
goto close_input; goto close_input;
@ -86,12 +89,6 @@ decode_image(const char *path) {
AVCodecParameters *params = ctx->streams[stream]->codecpar; AVCodecParameters *params = ctx->streams[stream]->codecpar;
const AVCodec *codec = avcodec_find_decoder(params->codec_id);
if (!codec) {
LOGE("Could not find image decoder");
goto close_input;
}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) { if (!codec_ctx) {
LOG_OOM(); LOG_OOM();

View File

@ -176,6 +176,8 @@ sc_process_execute_p(const char *const argv[], HANDLE *handle, unsigned flags,
free(lpAttributeList); free(lpAttributeList);
} }
CloseHandle(pi.hThread);
// These handles are used by the child process, close them for this process // These handles are used by the child process, close them for this process
if (pin) { if (pin) {
CloseHandle(stdin_read_handle); CloseHandle(stdin_read_handle);

View File

@ -46,6 +46,9 @@ sc_audiobuf_read(struct sc_audiobuf *buf, void *to_, uint32_t samples_count) {
uint32_t head = atomic_load_explicit(&buf->head, memory_order_acquire); uint32_t head = atomic_load_explicit(&buf->head, memory_order_acquire);
uint32_t can_read = (buf->alloc_size + head - tail) % buf->alloc_size; uint32_t can_read = (buf->alloc_size + head - tail) % buf->alloc_size;
if (!can_read) {
return 0;
}
if (samples_count > can_read) { if (samples_count > can_read) {
samples_count = can_read; samples_count = can_read;
} }
@ -86,6 +89,9 @@ sc_audiobuf_write(struct sc_audiobuf *buf, const void *from_,
uint32_t tail = atomic_load_explicit(&buf->tail, memory_order_acquire); uint32_t tail = atomic_load_explicit(&buf->tail, memory_order_acquire);
uint32_t can_write = (buf->alloc_size + tail - head - 1) % buf->alloc_size; uint32_t can_write = (buf->alloc_size + tail - head - 1) % buf->alloc_size;
if (!can_write) {
return 0;
}
if (samples_count > can_write) { if (samples_count > can_write) {
samples_count = can_write; samples_count = can_write;
} }

View File

@ -48,7 +48,7 @@ public class SurfaceEncoder implements AsyncProcessor {
this.downsizeOnError = downsizeOnError; this.downsizeOnError = downsizeOnError;
} }
private void streamScreen() throws IOException, ConfigurationException { private void streamCapture() throws IOException, ConfigurationException {
Codec codec = streamer.getCodec(); Codec codec = streamer.getCodec();
MediaCodec mediaCodec = createMediaCodec(codec, encoderName); MediaCodec mediaCodec = createMediaCodec(codec, encoderName);
MediaFormat format = createFormat(codec.getMimeType(), videoBitRate, maxFps, codecOptions); MediaFormat format = createFormat(codec.getMimeType(), videoBitRate, maxFps, codecOptions);
@ -254,7 +254,7 @@ public class SurfaceEncoder implements AsyncProcessor {
Looper.prepare(); Looper.prepare();
try { try {
streamScreen(); streamCapture();
} catch (ConfigurationException e) { } catch (ConfigurationException e) {
// Do not print stack trace, a user-friendly error-message has already been logged // Do not print stack trace, a user-friendly error-message has already been logged
} catch (IOException e) { } catch (IOException e) {