mirror of
https://github.com/Genymobile/scrcpy.git
synced 2025-08-03 06:39:39 +00:00
[app] add --serve option on v1.16
This commit combines the following commits: - Adding --serve option on README - Adding --serve option : Add current working files - Update --serve option with scrcpy v1.13 + Cleaning code. - Fix missing char and error - Allowing other ip address by converting it to hex Rebased on top of the v1.16 source
This commit is contained in:
parent
479d10dc22
commit
c22cf77227
11 changed files with 363 additions and 5 deletions
11
app/.project
Normal file
11
app/.project
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>app</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -17,6 +17,7 @@ src = [
|
||||||
'src/scrcpy.c',
|
'src/scrcpy.c',
|
||||||
'src/screen.c',
|
'src/screen.c',
|
||||||
'src/server.c',
|
'src/server.c',
|
||||||
|
'src/serve.c',
|
||||||
'src/stream.c',
|
'src/stream.c',
|
||||||
'src/tiny_xpm.c',
|
'src/tiny_xpm.c',
|
||||||
'src/video_buffer.c',
|
'src/video_buffer.c',
|
||||||
|
|
183
app/src/cli.c
183
app/src/cli.c
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "scrcpy.h"
|
#include "scrcpy.h"
|
||||||
|
#include "serve.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/str_util.h"
|
#include "util/str_util.h"
|
||||||
|
|
||||||
|
@ -119,6 +120,11 @@ scrcpy_print_usage(const char *arg0) {
|
||||||
" --record-format format\n"
|
" --record-format format\n"
|
||||||
" Force recording format (either mp4 or mkv).\n"
|
" Force recording format (either mp4 or mkv).\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
" --serve tcp:localhost:1234\n"
|
||||||
|
" Open a socket to redirect video stream.\n"
|
||||||
|
" It will wait for a client to connect before starting the mirroring,\n"
|
||||||
|
" then it would forward the video stream.\n"
|
||||||
|
"\n"
|
||||||
" --render-driver name\n"
|
" --render-driver name\n"
|
||||||
" Request SDL to use the given render driver (this is just a\n"
|
" Request SDL to use the given render driver (this is just a\n"
|
||||||
" hint).\n"
|
" hint).\n"
|
||||||
|
@ -626,6 +632,169 @@ guess_record_format(const char *filename) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char**
|
||||||
|
str_split(const char *a_str, const char a_delim) {
|
||||||
|
char** result = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
char* tmp = (char*)a_str;
|
||||||
|
char str[50];
|
||||||
|
strncpy(str, a_str, sizeof(str));
|
||||||
|
char* last_comma = 0;
|
||||||
|
char delim[2];
|
||||||
|
delim[0] = a_delim;
|
||||||
|
delim[1] = 0;
|
||||||
|
|
||||||
|
/* Count how many elements will be extracted. */
|
||||||
|
while (*tmp) {
|
||||||
|
if (a_delim == *tmp) {
|
||||||
|
count++;
|
||||||
|
last_comma = tmp;
|
||||||
|
}
|
||||||
|
tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add space for trailing token. */
|
||||||
|
count += last_comma < (str + strlen(str) - 1);
|
||||||
|
|
||||||
|
/* Add space for terminating null string so caller
|
||||||
|
knows where the list of returned strings ends. */
|
||||||
|
count++;
|
||||||
|
|
||||||
|
result = malloc(sizeof(char*) * count);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
size_t idx = 0;
|
||||||
|
char* token = strtok(str, delim);
|
||||||
|
|
||||||
|
while (token) {
|
||||||
|
assert(idx < count);
|
||||||
|
*(result + idx++) = strdup(token);
|
||||||
|
token = strtok(0, delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(idx == count - 1);
|
||||||
|
*(result + idx) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
check_if_ip_valid(char *ip) {
|
||||||
|
int num, dots = 0;
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
if (ip == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptr = strtok(ip, "."); //Cut the string using dot as delimiter
|
||||||
|
|
||||||
|
if (ptr == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (ptr) {
|
||||||
|
long value;
|
||||||
|
if (!parse_integer(ptr, &value)) //Check whether the substring is holding only number or not
|
||||||
|
return false;
|
||||||
|
num = atoi(ptr); //Convert substring to number
|
||||||
|
if (num >= 0 && num <= 255) {
|
||||||
|
ptr = strtok(NULL, "."); //Cut the next part of the string
|
||||||
|
if (ptr != NULL)
|
||||||
|
dots++; //Increase the dot count
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dots != 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
convert_ip_to_int(char* ip_string) {
|
||||||
|
int num, dots = 0;
|
||||||
|
char* ptr;
|
||||||
|
|
||||||
|
char* ip = "0x";
|
||||||
|
|
||||||
|
ptr = strtok(ip_string, "."); //Cut the string using dot as delimiter
|
||||||
|
|
||||||
|
while (ptr) {
|
||||||
|
num = atoi(ptr); //Convert substring to number
|
||||||
|
if (num >= 0 && num <= 255) {
|
||||||
|
char hex[3];
|
||||||
|
sprintf(hex, "%X", num);
|
||||||
|
strcat(ip, hex);
|
||||||
|
ptr = strtok(NULL, "."); //Cut the next part of the string
|
||||||
|
if (ptr != NULL)
|
||||||
|
dots++; //Increase the dot count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return atoi(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
parse_serve_args(const char *optarg, const char **s_protocol, uint32_t *s_ip, uint16_t *s_port) {
|
||||||
|
bool protocol_valid = false;
|
||||||
|
bool ip_valid = false;
|
||||||
|
bool port_valid = false;
|
||||||
|
|
||||||
|
char* protocol = NULL;
|
||||||
|
char* ip = NULL;
|
||||||
|
uint32_t ip_value;
|
||||||
|
char* port = NULL;
|
||||||
|
|
||||||
|
char** values;
|
||||||
|
values = str_split(optarg, ':');
|
||||||
|
|
||||||
|
if (values) {
|
||||||
|
protocol = *values;
|
||||||
|
ip = *(values + 1);
|
||||||
|
port = *(values + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(values);
|
||||||
|
|
||||||
|
//Check if the choosen protocol is allowed
|
||||||
|
if (!strcmp(protocol, "tcp")) {
|
||||||
|
protocol_valid = true;
|
||||||
|
} else {
|
||||||
|
LOGE("Unexpected protocol (expected tcp)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the choosen ip is valid
|
||||||
|
if (!strcmp(ip, "localhost")) {
|
||||||
|
ip_value = 0x7F000001;
|
||||||
|
ip_valid = true;
|
||||||
|
} else if (check_if_ip_valid(ip)) {
|
||||||
|
ip_value = convert_ip_to_int(ip);
|
||||||
|
ip_valid = true;
|
||||||
|
} else {
|
||||||
|
LOGE("Unexpected ip address (expected \"localhost\" or 255.255.255.255 format)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the choosen port is valid
|
||||||
|
long port_value = 0;
|
||||||
|
port_valid = parse_integer_arg(port, &port_value, false, 0, 0xFFFF, "port");
|
||||||
|
|
||||||
|
//Check if everything is valid
|
||||||
|
if (!protocol_valid || !ip_valid || !port_valid) {
|
||||||
|
LOGE("Unexpected argument format (expected [tcp]:[ip or \"localhost\"]:[port])");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*s_protocol = protocol;
|
||||||
|
*s_ip = (uint32_t)ip_value;
|
||||||
|
*s_port = (uint16_t)port_value;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#define OPT_RENDER_EXPIRED_FRAMES 1000
|
#define OPT_RENDER_EXPIRED_FRAMES 1000
|
||||||
#define OPT_WINDOW_TITLE 1001
|
#define OPT_WINDOW_TITLE 1001
|
||||||
#define OPT_PUSH_TARGET 1002
|
#define OPT_PUSH_TARGET 1002
|
||||||
|
@ -649,6 +818,7 @@ guess_record_format(const char *filename) {
|
||||||
#define OPT_DISABLE_SCREENSAVER 1020
|
#define OPT_DISABLE_SCREENSAVER 1020
|
||||||
#define OPT_SHORTCUT_MOD 1021
|
#define OPT_SHORTCUT_MOD 1021
|
||||||
#define OPT_NO_KEY_REPEAT 1022
|
#define OPT_NO_KEY_REPEAT 1022
|
||||||
|
#define OPT_SERVE 1023
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
|
@ -683,6 +853,7 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
{"rotation", required_argument, NULL, OPT_ROTATION},
|
{"rotation", required_argument, NULL, OPT_ROTATION},
|
||||||
{"serial", required_argument, NULL, 's'},
|
{"serial", required_argument, NULL, 's'},
|
||||||
{"shortcut-mod", required_argument, NULL, OPT_SHORTCUT_MOD},
|
{"shortcut-mod", required_argument, NULL, OPT_SHORTCUT_MOD},
|
||||||
|
{"serve", required_argument, NULL, OPT_SERVE},
|
||||||
{"show-touches", no_argument, NULL, 't'},
|
{"show-touches", no_argument, NULL, 't'},
|
||||||
{"stay-awake", no_argument, NULL, 'w'},
|
{"stay-awake", no_argument, NULL, 'w'},
|
||||||
{"turn-screen-off", no_argument, NULL, 'S'},
|
{"turn-screen-off", no_argument, NULL, 'S'},
|
||||||
|
@ -771,6 +942,14 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
case 'S':
|
case 'S':
|
||||||
opts->turn_screen_off = true;
|
opts->turn_screen_off = true;
|
||||||
break;
|
break;
|
||||||
|
case OPT_SERVE:
|
||||||
|
if (!parse_serve_args(optarg, &opts->serve_protocol, &opts->serve_ip, &opts->serve_port)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
opts->serve = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
opts->show_touches = true;
|
opts->show_touches = true;
|
||||||
break;
|
break;
|
||||||
|
@ -860,8 +1039,8 @@ scrcpy_parse_args(struct scrcpy_cli_args *args, int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts->display && !opts->record_filename) {
|
if (!opts->display && !opts->record_filename && !opts->serve) {
|
||||||
LOGE("-N/--no-display requires screen recording (-r/--record)");
|
LOGE("-N/--no-display requires screen recording (-r/--record) or to serve to another client (--serve)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "recorder.h"
|
#include "recorder.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "serve.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "tiny_xpm.h"
|
#include "tiny_xpm.h"
|
||||||
#include "video_buffer.h"
|
#include "video_buffer.h"
|
||||||
|
@ -41,6 +42,7 @@ static struct video_buffer video_buffer;
|
||||||
static struct stream stream;
|
static struct stream stream;
|
||||||
static struct decoder decoder;
|
static struct decoder decoder;
|
||||||
static struct recorder recorder;
|
static struct recorder recorder;
|
||||||
|
static struct serve serve;
|
||||||
static struct controller controller;
|
static struct controller controller;
|
||||||
static struct file_handler file_handler;
|
static struct file_handler file_handler;
|
||||||
|
|
||||||
|
@ -390,9 +392,19 @@ scrcpy(const struct scrcpy_options *options) {
|
||||||
recorder_initialized = true;
|
recorder_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct serve* serv = NULL;
|
||||||
|
if (options->serve) {
|
||||||
|
serve_init(&serve, options->serve_protocol, options->serve_ip, options->serve_port);
|
||||||
|
|
||||||
|
if (!serve_start(&serve)) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
serv = &serve;
|
||||||
|
}
|
||||||
|
|
||||||
av_log_set_callback(av_log_callback);
|
av_log_set_callback(av_log_callback);
|
||||||
|
|
||||||
stream_init(&stream, server.video_socket, dec, rec);
|
stream_init(&stream, server.video_socket, dec, rec, serv);
|
||||||
|
|
||||||
// now we consumed the header values, the socket receives the video stream
|
// now we consumed the header values, the socket receives the video stream
|
||||||
// start the stream
|
// start the stream
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct scrcpy_options {
|
||||||
const char *window_title;
|
const char *window_title;
|
||||||
const char *push_target;
|
const char *push_target;
|
||||||
const char *render_driver;
|
const char *render_driver;
|
||||||
|
const char *serve_protocol;
|
||||||
const char *codec_options;
|
const char *codec_options;
|
||||||
enum sc_log_level log_level;
|
enum sc_log_level log_level;
|
||||||
enum sc_record_format record_format;
|
enum sc_record_format record_format;
|
||||||
|
@ -65,6 +66,8 @@ struct scrcpy_options {
|
||||||
uint16_t window_width;
|
uint16_t window_width;
|
||||||
uint16_t window_height;
|
uint16_t window_height;
|
||||||
uint16_t display_id;
|
uint16_t display_id;
|
||||||
|
uint32_t serve_ip;
|
||||||
|
uint16_t serve_port;
|
||||||
bool show_touches;
|
bool show_touches;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool always_on_top;
|
bool always_on_top;
|
||||||
|
@ -75,6 +78,7 @@ struct scrcpy_options {
|
||||||
bool prefer_text;
|
bool prefer_text;
|
||||||
bool window_borderless;
|
bool window_borderless;
|
||||||
bool mipmaps;
|
bool mipmaps;
|
||||||
|
bool serve;
|
||||||
bool stay_awake;
|
bool stay_awake;
|
||||||
bool force_adb_forward;
|
bool force_adb_forward;
|
||||||
bool disable_screensaver;
|
bool disable_screensaver;
|
||||||
|
@ -88,6 +92,7 @@ struct scrcpy_options {
|
||||||
.window_title = NULL, \
|
.window_title = NULL, \
|
||||||
.push_target = NULL, \
|
.push_target = NULL, \
|
||||||
.render_driver = NULL, \
|
.render_driver = NULL, \
|
||||||
|
.serve_protocol = NULL, \
|
||||||
.codec_options = NULL, \
|
.codec_options = NULL, \
|
||||||
.log_level = SC_LOG_LEVEL_INFO, \
|
.log_level = SC_LOG_LEVEL_INFO, \
|
||||||
.record_format = SC_RECORD_FORMAT_AUTO, \
|
.record_format = SC_RECORD_FORMAT_AUTO, \
|
||||||
|
@ -109,6 +114,8 @@ struct scrcpy_options {
|
||||||
.window_width = 0, \
|
.window_width = 0, \
|
||||||
.window_height = 0, \
|
.window_height = 0, \
|
||||||
.display_id = 0, \
|
.display_id = 0, \
|
||||||
|
.serve_ip = 0, \
|
||||||
|
.serve_port = 0, \
|
||||||
.show_touches = false, \
|
.show_touches = false, \
|
||||||
.fullscreen = false, \
|
.fullscreen = false, \
|
||||||
.always_on_top = false, \
|
.always_on_top = false, \
|
||||||
|
@ -119,6 +126,7 @@ struct scrcpy_options {
|
||||||
.prefer_text = false, \
|
.prefer_text = false, \
|
||||||
.window_borderless = false, \
|
.window_borderless = false, \
|
||||||
.mipmaps = true, \
|
.mipmaps = true, \
|
||||||
|
.serve = false, \
|
||||||
.stay_awake = false, \
|
.stay_awake = false, \
|
||||||
.force_adb_forward = false, \
|
.force_adb_forward = false, \
|
||||||
.disable_screensaver = false, \
|
.disable_screensaver = false, \
|
||||||
|
|
61
app/src/serve.c
Normal file
61
app/src/serve.c
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#include "serve.h"
|
||||||
|
|
||||||
|
#include <SDL2/SDL_events.h>
|
||||||
|
#include <SDL2/SDL_mutex.h>
|
||||||
|
#include <SDL2/SDL_thread.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "events.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
#include "util/net.h"
|
||||||
|
|
||||||
|
# define SOCKET_ERROR (-1)
|
||||||
|
|
||||||
|
void
|
||||||
|
serve_init(struct serve* serve, char *protocol, uint32_t ip, uint16_t port) {
|
||||||
|
serve->protocol = protocol;
|
||||||
|
serve->ip = ip;
|
||||||
|
serve->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
serve_start(struct serve* serve) {
|
||||||
|
LOGD("Starting serve thread");
|
||||||
|
|
||||||
|
socket_t Listensocket;
|
||||||
|
socket_t ClientSocket;
|
||||||
|
|
||||||
|
Listensocket = net_listen(serve->ip, serve->port, 1);
|
||||||
|
if (Listensocket == INVALID_SOCKET) {
|
||||||
|
LOGI("Listen error");
|
||||||
|
net_close(Listensocket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGI("Waiting for a client to connect");
|
||||||
|
|
||||||
|
ClientSocket = net_accept(Listensocket);
|
||||||
|
if (ClientSocket == INVALID_SOCKET) {
|
||||||
|
LOGI("Client error");
|
||||||
|
net_close(Listensocket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGI("Client found");
|
||||||
|
|
||||||
|
net_close(Listensocket);
|
||||||
|
|
||||||
|
serve->socket = ClientSocket;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
serve_push(struct serve* serve, const AVPacket *packet) {
|
||||||
|
if (net_send(serve->socket, packet->data, packet->size) == SOCKET_ERROR) {
|
||||||
|
LOGI("Client lost");
|
||||||
|
net_close(serve->socket);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
28
app/src/serve.h
Normal file
28
app/src/serve.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef SERVE_H
|
||||||
|
#define SERVE_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <SDL2/SDL_atomic.h>
|
||||||
|
#include <SDL2/SDL_thread.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "util/net.h"
|
||||||
|
|
||||||
|
struct serve {
|
||||||
|
socket_t socket;
|
||||||
|
char *protocol;
|
||||||
|
uint32_t ip;
|
||||||
|
uint16_t port;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
serve_init(struct serve* serve, char* protocol, uint32_t ip, uint16_t port);
|
||||||
|
|
||||||
|
bool
|
||||||
|
serve_start(struct serve* serve);
|
||||||
|
|
||||||
|
bool
|
||||||
|
serve_push(struct serve* serve, const AVPacket *packet);
|
||||||
|
#endif
|
|
@ -13,6 +13,7 @@
|
||||||
#include "decoder.h"
|
#include "decoder.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "recorder.h"
|
#include "recorder.h"
|
||||||
|
#include "serve.h"
|
||||||
#include "util/buffer_util.h"
|
#include "util/buffer_util.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
|
@ -93,6 +94,15 @@ process_frame(struct stream *stream, AVPacket *packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->serve) {
|
||||||
|
packet->dts = packet->pts;
|
||||||
|
|
||||||
|
if (!serve_push(stream->serve, packet)) {
|
||||||
|
LOGE("Could not serve packet");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,10 +280,11 @@ end:
|
||||||
|
|
||||||
void
|
void
|
||||||
stream_init(struct stream *stream, socket_t socket,
|
stream_init(struct stream *stream, socket_t socket,
|
||||||
struct decoder *decoder, struct recorder *recorder) {
|
struct decoder *decoder, struct recorder *recorder, struct serve *serve) {
|
||||||
stream->socket = socket;
|
stream->socket = socket;
|
||||||
stream->decoder = decoder,
|
stream->decoder = decoder,
|
||||||
stream->recorder = recorder;
|
stream->recorder = recorder;
|
||||||
|
stream->serve = serve;
|
||||||
stream->has_pending = false;
|
stream->has_pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct stream {
|
||||||
SDL_Thread *thread;
|
SDL_Thread *thread;
|
||||||
struct decoder *decoder;
|
struct decoder *decoder;
|
||||||
struct recorder *recorder;
|
struct recorder *recorder;
|
||||||
|
struct serve *serve;
|
||||||
AVCodecContext *codec_ctx;
|
AVCodecContext *codec_ctx;
|
||||||
AVCodecParserContext *parser;
|
AVCodecParserContext *parser;
|
||||||
// successive packets may need to be concatenated, until a non-config
|
// successive packets may need to be concatenated, until a non-config
|
||||||
|
@ -28,7 +29,7 @@ struct stream {
|
||||||
|
|
||||||
void
|
void
|
||||||
stream_init(struct stream *stream, socket_t socket,
|
stream_init(struct stream *stream, socket_t socket,
|
||||||
struct decoder *decoder, struct recorder *recorder);
|
struct decoder *decoder, struct recorder *recorder, struct serve *serve);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
stream_start(struct stream *stream);
|
stream_start(struct stream *stream);
|
||||||
|
|
21
app/src/sys/unix/net.c
Normal file
21
app/src/sys/unix/net.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include "util/net.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_init(void) {
|
||||||
|
// do nothing
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_cleanup(void) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_close(socket_t socket) {
|
||||||
|
return !close(socket);
|
||||||
|
}
|
25
app/src/sys/win/net.c
Normal file
25
app/src/sys/win/net.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "util/net.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_init(void) {
|
||||||
|
WSADATA wsa;
|
||||||
|
int res = WSAStartup(MAKEWORD(2, 2), &wsa) < 0;
|
||||||
|
if (res < 0) {
|
||||||
|
LOGC("WSAStartup failed with error %d", res);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
net_cleanup(void) {
|
||||||
|
WSACleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
net_close(socket_t socket) {
|
||||||
|
return !closesocket(socket);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue