Compare commits

..

1 Commits

Author SHA1 Message Date
Romain Vimont
60b7281cbc Fix compatibility with old FFmpeg
V4L2 sink used a "url" field format AVFormatContext which has been
introduced in lavf 58.7.100.

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

Refs <ea3672b7d6>
Refs <fa8308d3d4>
2021-06-13 18:31:48 +02:00
13 changed files with 15 additions and 160 deletions

View File

@@ -80,13 +80,6 @@ control_msg_serialize(const struct control_msg *msg, unsigned char *buf) {
case CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE:
buf[1] = msg->set_screen_power_mode.mode;
return 2;
case CONTROL_MSG_TYPE_SCAN_MEDIA:
{
size_t len = write_string(msg->scan_media.path,
CONTROL_MSG_SCAN_MEDIA_PATH_MAX_LENGTH,
&buf[1]);
return 1 + len;
}
case CONTROL_MSG_TYPE_EXPAND_NOTIFICATION_PANEL:
case CONTROL_MSG_TYPE_EXPAND_SETTINGS_PANEL:
case CONTROL_MSG_TYPE_COLLAPSE_PANELS:
@@ -109,9 +102,6 @@ control_msg_destroy(struct control_msg *msg) {
case CONTROL_MSG_TYPE_SET_CLIPBOARD:
free(msg->set_clipboard.text);
break;
case CONTROL_MSG_TYPE_SCAN_MEDIA:
free(msg->scan_media.path);
break;
default:
// do nothing
break;

View File

@@ -17,8 +17,6 @@
// type: 1 byte; paste flag: 1 byte; length: 4 bytes
#define CONTROL_MSG_CLIPBOARD_TEXT_MAX_LENGTH (CONTROL_MSG_MAX_SIZE - 6)
#define CONTROL_MSG_SCAN_MEDIA_PATH_MAX_LENGTH 256
#define POINTER_ID_MOUSE UINT64_C(-1);
#define POINTER_ID_VIRTUAL_FINGER UINT64_C(-2);
@@ -35,7 +33,6 @@ enum control_msg_type {
CONTROL_MSG_TYPE_SET_CLIPBOARD,
CONTROL_MSG_TYPE_SET_SCREEN_POWER_MODE,
CONTROL_MSG_TYPE_ROTATE_DEVICE,
CONTROL_MSG_TYPE_SCAN_MEDIA,
};
enum screen_power_mode {
@@ -79,9 +76,6 @@ struct control_msg {
struct {
enum screen_power_mode mode;
} set_screen_power_mode;
struct {
char *path; // owned, to be freed by free()
} scan_media;
};
};

View File

@@ -4,8 +4,6 @@
#include <string.h>
#include "adb.h"
#include "control_msg.h"
#include "controller.h"
#include "util/log.h"
#define DEFAULT_PUSH_TARGET "/sdcard/"
@@ -16,8 +14,7 @@ file_handler_request_destroy(struct file_handler_request *req) {
}
bool
file_handler_init(struct file_handler *file_handler,
struct controller *controller, const char *serial,
file_handler_init(struct file_handler *file_handler, const char *serial,
const char *push_target) {
cbuf_init(&file_handler->queue);
@@ -53,8 +50,6 @@ file_handler_init(struct file_handler *file_handler,
file_handler->push_target = push_target ? push_target : DEFAULT_PUSH_TARGET;
file_handler->controller = controller;
return true;
}
@@ -108,24 +103,6 @@ file_handler_request(struct file_handler *file_handler,
return res;
}
static bool
request_scan_media(struct file_handler *file_handler) {
struct control_msg msg;
msg.type = CONTROL_MSG_TYPE_SCAN_MEDIA;
msg.scan_media.path = strdup(file_handler->push_target);
if (!msg.scan_media.path) {
LOGW("Could not strdup() media path");
return false;
}
if (!controller_push_msg(file_handler->controller, &msg)) {
LOGW("Could not request 'scan media'");
return false;
}
return true;
}
static int
run_file_handler(void *data) {
struct file_handler *file_handler = data;
@@ -168,7 +145,6 @@ run_file_handler(void *data) {
if (process_check_success(process, "adb push", false)) {
LOGI("%s successfully pushed to %s", req.file,
file_handler->push_target);
request_scan_media(file_handler);
} else {
LOGE("Failed to push %s to %s", req.file,
file_handler->push_target);

View File

@@ -22,7 +22,6 @@ struct file_handler_request {
struct file_handler_request_queue CBUF(struct file_handler_request, 16);
struct file_handler {
struct controller *controller;
char *serial;
const char *push_target;
sc_thread thread;
@@ -35,8 +34,7 @@ struct file_handler {
};
bool
file_handler_init(struct file_handler *file_handler,
struct controller *controller, const char *serial,
file_handler_init(struct file_handler *file_handler, const char *serial,
const char *push_target);
void

View File

@@ -297,6 +297,14 @@ scrcpy(const struct scrcpy_options *options) {
goto end;
}
if (options->display && options->control) {
if (!file_handler_init(&s->file_handler, s->server.serial,
options->push_target)) {
goto end;
}
file_handler_initialized = true;
}
struct decoder *dec = NULL;
bool needs_decoder = options->display;
#ifdef HAVE_V4L2
@@ -345,12 +353,6 @@ scrcpy(const struct scrcpy_options *options) {
goto end;
}
controller_started = true;
if (!file_handler_init(&s->file_handler, &s->controller,
s->server.serial, options->push_target)) {
goto end;
}
file_handler_initialized = true;
}
const char *window_title =

View File

@@ -181,16 +181,16 @@ sc_v4l2_sink_open(struct sc_v4l2_sink *vs) {
// <https://github.com/FFmpeg/FFmpeg/commit/0694d8702421e7aff1340038559c438b61bb30dd>
vs->format_ctx->oformat = (AVOutputFormat *) format;
#ifdef SCRCPY_LAVF_HAS_AVFORMATCONTEXT_URL
vs->format_ctx->url = strdup(vs->device_name);
# define CTX_URL_FIELD url
#else
# define CTX_URL_FIELD filename
#endif
vs->format_ctx->CTX_URL_FIELD = strdup(vs->device_name);
if (!vs->format_ctx->url) {
LOGE("Could not strdup v4l2 device name");
goto error_avformat_free_context;
return false;
}
#else
strncpy(vs->format_ctx->filename, vs->device_name,
sizeof(vs->format_ctx->filename));
#endif
AVStream *ostream = avformat_new_stream(vs->format_ctx, encoder);
if (!ostream) {

View File

@@ -278,28 +278,6 @@ static void test_serialize_rotate_device(void) {
assert(!memcmp(buf, expected, sizeof(expected)));
}
static void test_serialize_scan_media(void) {
struct control_msg msg = {
.type = CONTROL_MSG_TYPE_SCAN_MEDIA,
.scan_media = {
.path = "/sdcard/Download/",
},
};
unsigned char buf[CONTROL_MSG_MAX_SIZE];
size_t size = control_msg_serialize(&msg, buf);
assert(size == 22);
const unsigned char expected[] = {
CONTROL_MSG_TYPE_SCAN_MEDIA,
0x00, 0x00, 0x00, 0x11, // path length
'/', 's', 'd', 'c', 'a', 'r', 'd', '/',
'D', 'o', 'w', 'n', 'l', 'o', 'a', 'd',
'/' // path
};
assert(!memcmp(buf, expected, sizeof(expected)));
}
int main(int argc, char *argv[]) {
(void) argc;
(void) argv;
@@ -317,6 +295,5 @@ int main(int argc, char *argv[]) {
test_serialize_set_clipboard();
test_serialize_set_screen_power_mode();
test_serialize_rotate_device();
test_serialize_scan_media();
return 0;
}

View File

@@ -17,7 +17,6 @@ public final class ControlMessage {
public static final int TYPE_SET_CLIPBOARD = 9;
public static final int TYPE_SET_SCREEN_POWER_MODE = 10;
public static final int TYPE_ROTATE_DEVICE = 11;
public static final int TYPE_SCAN_MEDIA = 12;
private int type;
private String text;
@@ -98,13 +97,6 @@ public final class ControlMessage {
return msg;
}
public static ControlMessage createScanMedia(String path) {
ControlMessage msg = new ControlMessage();
msg.type = TYPE_SCAN_MEDIA;
msg.text = path;
return msg;
}
public static ControlMessage createEmpty(int type) {
ControlMessage msg = new ControlMessage();
msg.type = type;

View File

@@ -76,9 +76,6 @@ public class ControlMessageReader {
case ControlMessage.TYPE_SET_SCREEN_POWER_MODE:
msg = parseSetScreenPowerMode();
break;
case ControlMessage.TYPE_SCAN_MEDIA:
msg = parseScanMedia();
break;
case ControlMessage.TYPE_EXPAND_NOTIFICATION_PANEL:
case ControlMessage.TYPE_EXPAND_SETTINGS_PANEL:
case ControlMessage.TYPE_COLLAPSE_PANELS:
@@ -185,14 +182,6 @@ public class ControlMessageReader {
return ControlMessage.createSetScreenPowerMode(mode);
}
private ControlMessage parseScanMedia() {
String path = parseString();
if (path == null) {
return null;
}
return ControlMessage.createScanMedia(path);
}
private static Position readPosition(ByteBuffer buffer) {
int x = buffer.getInt();
int y = buffer.getInt();

View File

@@ -1,7 +1,5 @@
package com.genymobile.scrcpy;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.view.InputDevice;
@@ -9,7 +7,6 @@ import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -138,13 +135,6 @@ public class Controller {
case ControlMessage.TYPE_ROTATE_DEVICE:
Device.rotateDevice();
break;
case ControlMessage.TYPE_SCAN_MEDIA:
String path = msg.getText();
@SuppressWarnings("deprecation")
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(new File(path)));
Device.sendBroadcast(intent);
break;
default:
// do nothing
}

View File

@@ -8,7 +8,6 @@ import com.genymobile.scrcpy.wrappers.SurfaceControl;
import com.genymobile.scrcpy.wrappers.WindowManager;
import android.content.IOnPrimaryClipChangedListener;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.os.IBinder;
@@ -300,8 +299,4 @@ public final class Device {
public static ContentProvider createSettingsProvider() {
return SERVICE_MANAGER.getActivityManager().createSettingsProvider();
}
public static void sendBroadcast(Intent intent) {
SERVICE_MANAGER.getActivityManager().sendBroadcast(intent);
}
}

View File

@@ -2,9 +2,7 @@ package com.genymobile.scrcpy.wrappers;
import com.genymobile.scrcpy.Ln;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
@@ -18,7 +16,6 @@ public class ActivityManager {
private Method getContentProviderExternalMethod;
private boolean getContentProviderExternalMethodNewVersion = true;
private Method removeContentProviderExternalMethod;
private Method broadcastIntentMethod;
public ActivityManager(IInterface manager) {
this.manager = manager;
@@ -45,22 +42,6 @@ public class ActivityManager {
return removeContentProviderExternalMethod;
}
private Method getBroadcastIntentMethod() throws NoSuchMethodException {
if (broadcastIntentMethod == null) {
try {
Class<?> iApplicationThreadClass = Class.forName("android.app.IApplicationThread");
Class<?> iIntentReceiverClass = Class.forName("android.content.IIntentReceiver");
broadcastIntentMethod = manager.getClass()
.getMethod("broadcastIntent", iApplicationThreadClass, Intent.class, String.class, iIntentReceiverClass, int.class,
String.class, Bundle.class, String[].class, int.class, Bundle.class, boolean.class, boolean.class, int.class);
return broadcastIntentMethod;
} catch (ClassNotFoundException e) {
throw new AssertionError(e);
}
}
return broadcastIntentMethod;
}
private ContentProvider getContentProviderExternal(String name, IBinder token) {
try {
Method method = getGetContentProviderExternalMethod();
@@ -103,13 +84,4 @@ public class ActivityManager {
public ContentProvider createSettingsProvider() {
return getContentProviderExternal("settings", new Binder());
}
public void sendBroadcast(Intent intent) {
try {
Method method = getBroadcastIntentMethod();
method.invoke(manager, null, intent, null, null, 0, null, null, null, -1, null, true, false, ServiceManager.USER_ID);
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
Ln.e("Could not invoke method", e);
}
}
}

View File

@@ -314,26 +314,6 @@ public class ControlMessageReaderTest {
Assert.assertEquals(ControlMessage.TYPE_ROTATE_DEVICE, event.getType());
}
@Test
public void testScanMedia() throws IOException {
ControlMessageReader reader = new ControlMessageReader();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
dos.writeByte(ControlMessage.TYPE_SCAN_MEDIA);
byte[] text = "/sdcard/Download/".getBytes(StandardCharsets.UTF_8);
dos.writeInt(text.length);
dos.write(text);
byte[] packet = bos.toByteArray();
reader.readFrom(new ByteArrayInputStream(packet));
ControlMessage event = reader.next();
Assert.assertEquals(ControlMessage.TYPE_SCAN_MEDIA, event.getType());
Assert.assertEquals("/sdcard/Download/", event.getText());
}
@Test
public void testMultiEvents() throws IOException {
ControlMessageReader reader = new ControlMessageReader();