Compare commits

..

5 Commits

Author SHA1 Message Date
Romain Vimont
a9c8fa305d Fix segfault on recording with old FFmpeg
The AVPacket fields side_data and side_data_elems were not initialized
by av_packet_ref() in old FFmpeg versions (prior to [1]).

As a consequence, on av_packet_unref(), side_data was freed, causing a
segfault.

Fixes <https://github.com/Genymobile/scrcpy/issues/707>

[1]: <http://git.videolan.org/gitweb.cgi/ffmpeg.git/?p=ffmpeg.git;a=commitdiff;h=3b4026e15110547892d5d770b6b43c9e34df458f>
2019-08-13 18:58:36 +02:00
Romain Vimont
20b3f101a4 Print gradle output on compiling
Enable the attribute "console" of custom_target() introduced in meson
0.48. This allows to get a feedback of what gradle does (which can takes
a very long time).

This produces warnings because we declare to support meson >= 0.37, but
we don't want to stop supporting older versions for that. Older versions
just ignore the option:

> WARNING: Unknown keyword arguments in target scrcpy-server: console

Newer meson versions use it, but warn because we declare supporting
older versions:

> WARNING: Project targetting '>= 0.37' but tried to use feature
> introduced in '0.48.0': console arg in custom_target

Meson does not support conditional branches to suppress such warnings,
so just keep the warnings.
2019-08-09 15:15:28 +02:00
Romain Vimont
686733023b Merge pull request #708 from toddsierens/patch-1
Update WindowManager.java
2019-08-08 23:24:47 +02:00
toddsierens
27eacc3c11 Update WindowManager.java 2019-08-08 17:17:48 -04:00
Romain Vimont
8507fea271 Record a packet with its duration
Record a packet only once the following has been received, so that we
can set its duration before muxing it.

Fixes <https://github.com/Genymobile/scrcpy/issues/702>
2019-08-08 18:57:52 +02:00
5 changed files with 67 additions and 5 deletions

View File

@@ -33,6 +33,11 @@ record_packet_new(const AVPacket *packet) {
if (!rec) {
return NULL;
}
// av_packet_ref() does not initialize all fields in old FFmpeg versions
// See <https://github.com/Genymobile/scrcpy/issues/707>
av_init_packet(&rec->packet);
if (av_packet_ref(&rec->packet, packet)) {
SDL_free(rec);
return NULL;
@@ -87,6 +92,7 @@ recorder_init(struct recorder *recorder,
recorder->format = format;
recorder->declared_frame_size = declared_frame_size;
recorder->header_written = false;
recorder->previous = NULL;
return true;
}
@@ -219,13 +225,22 @@ recorder_rescale_packet(struct recorder *recorder, AVPacket *packet) {
bool
recorder_write(struct recorder *recorder, AVPacket *packet) {
SDL_assert(packet->pts != AV_NOPTS_VALUE);
if (!recorder->header_written) {
if (packet->pts != AV_NOPTS_VALUE) {
LOGE("The first packet is not a config packet");
return false;
}
bool ok = recorder_write_header(recorder, packet);
if (!ok) {
return false;
}
recorder->header_written = true;
return true;
}
if (packet->pts == AV_NOPTS_VALUE) {
// ignore config packets
return true;
}
recorder_rescale_packet(recorder, packet);
@@ -248,6 +263,19 @@ run_recorder(void *data) {
if (recorder->stopped && queue_is_empty(&recorder->queue)) {
mutex_unlock(recorder->mutex);
struct record_packet *last = recorder->previous;
if (last) {
// assign an arbitrary duration to the last packet
last->packet.duration = 100000;
bool ok = recorder_write(recorder, &last->packet);
if (!ok) {
// failing to write the last frame is not very serious, no
// future frame may depend on it, so the resulting file
// will still be valid
LOGW("Could not record last packet");
}
record_packet_delete(last);
}
break;
}
@@ -256,8 +284,20 @@ run_recorder(void *data) {
mutex_unlock(recorder->mutex);
bool ok = recorder_write(recorder, &rec->packet);
record_packet_delete(rec);
// recorder->previous is only written from this thread, no need to lock
struct record_packet *previous = recorder->previous;
recorder->previous = rec;
if (!previous) {
// we just received the first packet
continue;
}
// we now know the duration of the previous packet
previous->packet.duration = rec->packet.pts - previous->packet.pts;
bool ok = recorder_write(recorder, &previous->packet);
record_packet_delete(previous);
if (!ok) {
LOGE("Could not record packet");

View File

@@ -34,6 +34,12 @@ struct recorder {
bool stopped; // set on recorder_stop() by the stream reader
bool failed; // set on packet write failure
struct recorder_queue queue;
// we can write a packet only once we received the next one so that we can
// set its duration (next_pts - current_pts)
// "previous" is only accessed from the recorder thread, so it does not
// need to be protected by the mutex
struct record_packet *previous;
};
bool

View File

@@ -69,6 +69,15 @@ notify_stopped(void) {
SDL_PushEvent(&stop_event);
}
static bool
process_config_packet(struct stream *stream, AVPacket *packet) {
if (stream->recorder && !recorder_push(stream->recorder, packet)) {
LOGE("Could not send config packet to recorder");
return false;
}
return true;
}
static bool
process_frame(struct stream *stream, AVPacket *packet) {
if (stream->decoder && !decoder_push(stream->decoder, packet)) {
@@ -148,7 +157,13 @@ stream_push_packet(struct stream *stream, AVPacket *packet) {
}
}
if (!is_config) {
if (is_config) {
// config packet
bool ok = process_config_packet(stream, packet);
if (!ok) {
return false;
}
} else {
// data packet
bool ok = stream_parse(stream, packet);

View File

@@ -6,6 +6,7 @@ if prebuilt_server == ''
build_always: true, # gradle is responsible for tracking source changes
output: 'scrcpy-server.jar',
command: [find_program('./scripts/build-wrapper.sh'), meson.current_source_dir(), '@OUTPUT@', get_option('buildtype')],
console: true,
install: true,
install_dir: 'share/scrcpy')
else

View File

@@ -14,7 +14,7 @@ public final class WindowManager {
try {
Class<?> cls = manager.getClass();
try {
return (Integer) manager.getClass().getMethod("getRotation").invoke(manager);
return (Integer) cls.getMethod("getRotation").invoke(manager);
} catch (NoSuchMethodException e) {
// method changed since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/8ee7285128c3843401d4c4d0412cd66e86ba49e3%5E%21/#F2