mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
add the -f videoflip option, modeled on flip and rotate in RPiPlay
This commit is contained in:
@@ -4,13 +4,16 @@ project(uxplay)
|
|||||||
|
|
||||||
set (CMAKE_CXX_STANDARD 11)
|
set (CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
add_definitions(-DAVAHI_COMPAT_NOWARN)
|
|
||||||
|
|
||||||
|
if (ZOOMFIX)
|
||||||
add_definitions(-DX_DISPLAY_FIX)
|
add_definitions(-DX_DISPLAY_FIX)
|
||||||
find_package(X11 REQUIRED)
|
find_package(X11 REQUIRED)
|
||||||
link_libraries(${X11_LIBRARIES})
|
link_libraries(${X11_LIBRARIES})
|
||||||
include_directories(${X11_INCLUDE_DIR})
|
include_directories(${X11_INCLUDE_DIR})
|
||||||
# link_directories(${X11_LIBRARIES})
|
# link_directories(${X11_LIBRARIES})
|
||||||
|
endif (ZOOMFIX)
|
||||||
|
|
||||||
|
add_definitions(-DAVAHI_COMPAT_NOWARN)
|
||||||
|
|
||||||
add_subdirectory(lib/llhttp)
|
add_subdirectory(lib/llhttp)
|
||||||
add_subdirectory(lib/playfair)
|
add_subdirectory(lib/playfair)
|
||||||
@@ -20,5 +23,5 @@ add_subdirectory(renderers)
|
|||||||
add_executable( uxplay uxplay.cpp)
|
add_executable( uxplay uxplay.cpp)
|
||||||
target_link_libraries ( uxplay renderers airplay ${X11_LIBRARIES})
|
target_link_libraries ( uxplay renderers airplay ${X11_LIBRARIES})
|
||||||
|
|
||||||
install(PROGRAMS uxplay DESTINATION bin)
|
install(TARGETS uxplay RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,18 @@ extern "C" {
|
|||||||
#include "../lib/logger.h"
|
#include "../lib/logger.h"
|
||||||
#include "../lib/raop_ntp.h"
|
#include "../lib/raop_ntp.h"
|
||||||
|
|
||||||
|
typedef enum videoflip_e {
|
||||||
|
NONE,
|
||||||
|
LEFT,
|
||||||
|
RIGHT,
|
||||||
|
INVERT,
|
||||||
|
VFLIP,
|
||||||
|
HFLIP,
|
||||||
|
} videoflip_t;
|
||||||
|
|
||||||
typedef struct video_renderer_s video_renderer_t;
|
typedef struct video_renderer_s video_renderer_t;
|
||||||
|
|
||||||
video_renderer_t *video_renderer_init(logger_t *logger, const char *server_name);
|
video_renderer_t *video_renderer_init(logger_t *logger, const char *server_name, videoflip_t videoflip);
|
||||||
void video_renderer_start(video_renderer_t *renderer);
|
void video_renderer_start(video_renderer_t *renderer);
|
||||||
void video_renderer_render_buffer(video_renderer_t *renderer, raop_ntp_t *ntp, unsigned char* data, int data_len, uint64_t pts, int type);
|
void video_renderer_render_buffer(video_renderer_t *renderer, raop_ntp_t *ntp, unsigned char* data, int data_len, uint64_t pts, int type);
|
||||||
void video_renderer_flush(video_renderer_t *renderer);
|
void video_renderer_flush(video_renderer_t *renderer);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static gboolean check_plugins (void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
video_renderer_t *video_renderer_init(logger_t *logger, const char *server_name) {
|
video_renderer_t *video_renderer_init(logger_t *logger, const char *server_name, videoflip_t videoflip) {
|
||||||
video_renderer_t *renderer;
|
video_renderer_t *renderer;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
@@ -71,8 +71,29 @@ video_renderer_t *video_renderer_init(logger_t *logger, const char *server_name)
|
|||||||
|
|
||||||
assert(check_plugins ());
|
assert(check_plugins ());
|
||||||
|
|
||||||
renderer->pipeline = gst_parse_launch("appsrc name=video_source stream-type=0 format=GST_FORMAT_TIME is-live=true !"
|
GString *launch = g_string_new("appsrc name=video_source stream-type=0 format=GST_FORMAT_TIME is-live=true !"
|
||||||
"queue ! decodebin ! videoconvert ! autovideosink name=video_sink sync=false", &error);
|
"queue ! decodebin ! videoconvert ! ");
|
||||||
|
|
||||||
|
/* image transform */
|
||||||
|
switch (videoflip) {
|
||||||
|
case LEFT:
|
||||||
|
g_string_append(launch, "videoflip method=counterclockwise ! ");
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
g_string_append(launch, "videoflip method=clockwise ! ");
|
||||||
|
break;
|
||||||
|
case INVERT:
|
||||||
|
g_string_append(launch, "videoflip method=rotate-180 ! ");
|
||||||
|
break;
|
||||||
|
case HFLIP:
|
||||||
|
g_string_append(launch, "videoflip method=horizontal-flip ! ");
|
||||||
|
break;
|
||||||
|
case VFLIP:
|
||||||
|
g_string_append(launch, "videoflip method=vertical-flip ! ");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_append(launch, "autovideosink name=video_sink sync=false");
|
||||||
|
renderer->pipeline = gst_parse_launch(launch->str, &error);
|
||||||
g_assert (renderer->pipeline);
|
g_assert (renderer->pipeline);
|
||||||
|
|
||||||
renderer->appsrc = gst_bin_get_by_name (GST_BIN (renderer->pipeline), "video_source");
|
renderer->appsrc = gst_bin_get_by_name (GST_BIN (renderer->pipeline), "video_source");
|
||||||
|
|||||||
59
uxplay.cpp
59
uxplay.cpp
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
|
|
||||||
int start_server(std::vector<char> hw_addr, std::string name, unsigned short display_size[2],
|
int start_server(std::vector<char> hw_addr, std::string name, unsigned short display_size[2],
|
||||||
unsigned short tcp[2], unsigned short udp[3],
|
unsigned short tcp[2], unsigned short udp[3], videoflip_t videoflip,
|
||||||
bool use_audio, bool debug_log);
|
bool use_audio, bool debug_log);
|
||||||
|
|
||||||
int stop_server();
|
int stop_server();
|
||||||
@@ -120,8 +120,9 @@ void print_info(char *name) {
|
|||||||
printf("UxPlay %s: An open-source AirPlay mirroring server based on RPiPlay\n", VERSION);
|
printf("UxPlay %s: An open-source AirPlay mirroring server based on RPiPlay\n", VERSION);
|
||||||
printf("Usage: %s [-n name] [-s wxh] [-p [n]]\n", name);
|
printf("Usage: %s [-n name] [-s wxh] [-p [n]]\n", name);
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf("-n name Specify the network name of the AirPlay server\n");
|
printf("-n name Specify the network name of the AirPlay server\n");
|
||||||
printf("-s wxh Set display size: width w height h default 1920x1080\n");
|
printf("-s wxh Set display size: width w height h default 1920x1080\n");
|
||||||
|
printf("-f {H|V|R|L|I} horizontal/vertical flip; rotate 90R/90L/180 deg\n");
|
||||||
printf("-p n Use fixed UDP+TCP network ports n:n+1:n+2 > 1023\n");
|
printf("-p n Use fixed UDP+TCP network ports n:n+1:n+2 > 1023\n");
|
||||||
printf("-p Use legacy UDP 6000:6001:7011 TCP 7000:7001:7100\n");
|
printf("-p Use legacy UDP 6000:6001:7011 TCP 7000:7001:7100\n");
|
||||||
printf("-r use random MAC address (use for concurrent UxPlay's)\n");
|
printf("-r use random MAC address (use for concurrent UxPlay's)\n");
|
||||||
@@ -159,6 +160,33 @@ bool get_lowest_port(char *str, unsigned short *n) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_videoflip(char *str, videoflip_t *videoflip) {
|
||||||
|
char c = str[0];
|
||||||
|
printf(" %c |%s| %d\n",c, str, strlen(str));
|
||||||
|
|
||||||
|
if(strlen(str) > 1) return false;
|
||||||
|
printf(" %c |%s| %d\n",c, str, strlen(str));
|
||||||
|
switch (c) {
|
||||||
|
case 'L':
|
||||||
|
*videoflip = LEFT;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
*videoflip = RIGHT;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
*videoflip = INVERT;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
*videoflip = HFLIP;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
*videoflip = VFLIP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
init_signals();
|
init_signals();
|
||||||
|
|
||||||
@@ -169,7 +197,8 @@ int main(int argc, char *argv[]) {
|
|||||||
bool debug_log = DEFAULT_DEBUG_LOG;
|
bool debug_log = DEFAULT_DEBUG_LOG;
|
||||||
unsigned short display_size[2] = { (unsigned short) DEFAULT_DISPLAY_WIDTH, (unsigned short) DEFAULT_DISPLAY_HEIGHT };
|
unsigned short display_size[2] = { (unsigned short) DEFAULT_DISPLAY_WIDTH, (unsigned short) DEFAULT_DISPLAY_HEIGHT };
|
||||||
unsigned short tcp[2] = {0}, udp[3] = {0};
|
unsigned short tcp[2] = {0}, udp[3] = {0};
|
||||||
|
videoflip_t videoflip = NONE;
|
||||||
|
|
||||||
#ifdef AVAHI_COMPAT_NOWARN
|
#ifdef AVAHI_COMPAT_NOWARN
|
||||||
//suppress avahi_compat nag message
|
//suppress avahi_compat nag message
|
||||||
char avahi_compat_nowarn[] = "AVAHI_COMPAT_NOWARN==1";
|
char avahi_compat_nowarn[] = "AVAHI_COMPAT_NOWARN==1";
|
||||||
@@ -187,12 +216,21 @@ int main(int argc, char *argv[]) {
|
|||||||
fprintf(stderr,"invalid \"-s\" had no argument\n");
|
fprintf(stderr,"invalid \"-s\" had no argument\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
std::string value(argv[++i]);
|
std::string value(argv[++i]);
|
||||||
if (!get_display_size(argv[i], &display_size[0], &display_size[1])) {
|
if (!get_display_size(argv[i], &display_size[0], &display_size[1])) {
|
||||||
fprintf(stderr, "invalid \"-s %s\"; default is \"-s 1920x1080\" (< 5 digits)\n",
|
fprintf(stderr, "invalid \"-s %s\"; default is \"-s 1920x1080\" (< 5 digits)\n",
|
||||||
value.c_str());
|
value.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
} else if (arg == "-f") {
|
||||||
|
if (i == argc - 1 || argv[i + 1][0] == '-') {
|
||||||
|
fprintf(stderr,"invalid \"f\" had no argument\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!get_videoflip(argv[++i], &videoflip)) {
|
||||||
|
fprintf(stderr,"invalid \"-f %s\" , unknown videoflip type\n",argv[i]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
} else if (arg == "-p") {
|
} else if (arg == "-p") {
|
||||||
if (i == argc - 1 || argv[i + 1][0] == '-') {
|
if (i == argc - 1 || argv[i + 1][0] == '-') {
|
||||||
tcp[0] = 7100; tcp[1] = 7000;
|
tcp[0] = 7100; tcp[1] = 7000;
|
||||||
@@ -220,7 +258,7 @@ int main(int argc, char *argv[]) {
|
|||||||
print_info(argv[0]);
|
print_info(argv[0]);
|
||||||
exit(0);
|
exit(0);
|
||||||
} else {
|
} else {
|
||||||
LOGI("unknown option %s, skipping\n",argv[i]);
|
LOGI("unknown option %s, skipping\n",argv[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +275,8 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
parse_hw_addr(mac_address, server_hw_addr);
|
parse_hw_addr(mac_address, server_hw_addr);
|
||||||
|
|
||||||
if (start_server(server_hw_addr, server_name, display_size, tcp, udp, use_audio, debug_log) != 0) {
|
if (start_server(server_hw_addr, server_name, display_size, tcp, udp, videoflip,
|
||||||
|
use_audio, debug_log) != 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
running = true;
|
running = true;
|
||||||
@@ -307,7 +346,7 @@ extern "C" void log_callback(void *cls, int level, const char *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start_server(std::vector<char> hw_addr, std::string name, unsigned short display_size[2],
|
int start_server(std::vector<char> hw_addr, std::string name, unsigned short display_size[2],
|
||||||
unsigned short tcp[2], unsigned short udp[3],
|
unsigned short tcp[2], unsigned short udp[3], videoflip_t videoflip,
|
||||||
bool use_audio, bool debug_log) {
|
bool use_audio, bool debug_log) {
|
||||||
raop_callbacks_t raop_cbs;
|
raop_callbacks_t raop_cbs;
|
||||||
memset(&raop_cbs, 0, sizeof(raop_cbs));
|
memset(&raop_cbs, 0, sizeof(raop_cbs));
|
||||||
@@ -332,7 +371,7 @@ int start_server(std::vector<char> hw_addr, std::string name, unsigned short dis
|
|||||||
logger_set_callback(render_logger, log_callback, NULL);
|
logger_set_callback(render_logger, log_callback, NULL);
|
||||||
logger_set_level(render_logger, debug_log ? LOGGER_DEBUG : LOGGER_INFO);
|
logger_set_level(render_logger, debug_log ? LOGGER_DEBUG : LOGGER_INFO);
|
||||||
|
|
||||||
if ((video_renderer = video_renderer_init(render_logger, name.c_str())) == NULL) {
|
if ((video_renderer = video_renderer_init(render_logger, name.c_str(), videoflip)) == NULL) {
|
||||||
LOGE("Could not init video renderer");
|
LOGE("Could not init video renderer");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -351,7 +390,7 @@ int start_server(std::vector<char> hw_addr, std::string name, unsigned short dis
|
|||||||
/* write desired display pixel width, pixel height to raop (use 0 for default values) */
|
/* write desired display pixel width, pixel height to raop (use 0 for default values) */
|
||||||
raop_set_display_size(raop, display_size[0], display_size[1]);
|
raop_set_display_size(raop, display_size[0], display_size[1]);
|
||||||
|
|
||||||
/* network port selection (use value 0 for dynamic assignment) */
|
/* network port selection (ports listed as "0" will dynamically assigned) */
|
||||||
raop_set_tcp_ports(raop, tcp);
|
raop_set_tcp_ports(raop, tcp);
|
||||||
raop_set_udp_ports(raop, udp);
|
raop_set_udp_ports(raop, udp);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user