diff --git a/Makefile.in b/Makefile.in index a7f5172ed..98b1a8426 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,7 +5,7 @@ CC = @CC@ CXX = @CXX@ QMAKE = @QMAKE@ LINKER = @LINKER@ -COMMON_FLAGS = @COMMON_FLAGS@ -g @DEFS@ -DPATH_PREFIX=@prefix@ -DLIB_DIR=@libdir@ -Wall -Wextra -Wpointer-arith -msse2 +COMMON_FLAGS = @COMMON_FLAGS@ -g @DEFS@ -DPATH_PREFIX=@prefix@ -DLIB_DIR=@libdir@ -Wall -Wextra -Wpointer-arith CFLAGS = @CFLAGS@ @X_CFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE CPPFLAGS = @CPPFLAGS@ -D_GNU_SOURCE CXXFLAGS = @CXXFLAGS@ $(COMMON_FLAGS) -D_GNU_SOURCE @AJA_CXXFLAGS@ diff --git a/configure.ac b/configure.ac index 091757d06..1ea56ab29 100644 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,11 @@ then fi fi +if test $host_cpu = x86_64 -o $host_cpu = i686 +then + COMMON_FLAGS="$COMMON_FLAGS -msse2" +fi + AC_MSG_CHECKING([OS family]) if expr "$host_os" : ".*darwin.*" > /dev/null; then diff --git a/ldgm b/ldgm index 664c7846e..6fa7e0506 160000 --- a/ldgm +++ b/ldgm @@ -1 +1 @@ -Subproject commit 664c7846e187a2e6595757e4f5d65939513ce9e6 +Subproject commit 6fa7e0506e08a70e213877378c44b05c9ddfdf16 diff --git a/src/config_win32.h b/src/config_win32.h index d4ba34db8..ab738e1df 100644 --- a/src/config_win32.h +++ b/src/config_win32.h @@ -265,4 +265,10 @@ void ShowMessage(int level, char *msg); #define inet_ntop InetNtopA #endif + +#if _M_IX86_FP == 2 +#undef __SSE2__ +#define __SSE2__ +#endif + #endif diff --git a/src/control_socket.cpp b/src/control_socket.cpp index 83c14386a..8c7544a0c 100644 --- a/src/control_socket.cpp +++ b/src/control_socket.cpp @@ -53,6 +53,7 @@ #include "control_socket.h" #include +#include #include #include @@ -104,7 +105,7 @@ struct control_state { multimap stats; // first member is ID of stream if applicable std::map stats_id_port_mapping; // this maps ID from above to index 0..n - pthread_mutex_t stats_lock; + std::mutex stats_lock; enum connection_type connection_type; @@ -153,19 +154,19 @@ static ssize_t write_all(fd_t fd, const void *buf, size_t count) static fd_t create_internal_port(int *port) { fd_t sock; - sock = socket(AF_INET6, SOCK_STREAM, 0); + sock = socket(AF_INET, SOCK_STREAM, 0); assert(sock != INVALID_SOCKET); - struct sockaddr_in6 s_in; + struct sockaddr_in s_in; memset(&s_in, 0, sizeof(s_in)); - s_in.sin6_family = AF_INET6; - s_in.sin6_addr = in6addr_any; - s_in.sin6_port = htons(0); + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = htonl(INADDR_ANY); + s_in.sin_port = htons(0); assert(::bind(sock, (const struct sockaddr *) &s_in, sizeof(s_in)) == 0); assert(listen(sock, 10) == 0); socklen_t len = sizeof(s_in); assert(getsockname(sock, (struct sockaddr *) &s_in, &len) == 0); - *port = ntohs(s_in.sin6_port); + *port = ntohs(s_in.sin_port); return sock; } @@ -177,8 +178,6 @@ int control_init(int port, int connection_type, struct control_state **state, st s->root_module = root_module; s->started = false; - pthread_mutex_init(&s->stats_lock, NULL); - module_init_default(&s->mod); s->mod.cls = MODULE_CLASS_CONTROL; s->mod.priv_data = s; @@ -193,29 +192,33 @@ int control_init(int port, int connection_type, struct control_state **state, st if(s->connection_type == SERVER) { s->socket_fd = socket(AF_INET6, SOCK_STREAM, 0); - assert(s->socket_fd != INVALID_SOCKET); - int val = 1; - int rc; - rc = setsockopt(s->socket_fd, SOL_SOCKET, SO_REUSEADDR, - (sso_val_type) &val, sizeof(val)); - if (rc != 0) { - perror("Control socket - setsockopt"); - } + if (s->socket_fd == INVALID_SOCKET) { + perror("socket"); + fprintf(stderr, "Remote control will be disabled!\n"); + } else { + int val = 1; + int rc; + rc = setsockopt(s->socket_fd, SOL_SOCKET, SO_REUSEADDR, + (sso_val_type) &val, sizeof(val)); + if (rc != 0) { + perror("Control socket - setsockopt"); + } - /* setting address to in6addr_any allows connections to be established - * from both IPv4 and IPv6 hosts. This behavior can be modified - * using the IPPROTO_IPV6 level socket option IPV6_V6ONLY if required.*/ - struct sockaddr_in6 s_in; - memset(&s_in, 0, sizeof(s_in)); - s_in.sin6_family = AF_INET6; - s_in.sin6_addr = in6addr_any; - s_in.sin6_port = htons(s->network_port); + /* setting address to in6addr_any allows connections to be established + * from both IPv4 and IPv6 hosts. This behavior can be modified + * using the IPPROTO_IPV6 level socket option IPV6_V6ONLY if required.*/ + struct sockaddr_in6 s_in; + memset(&s_in, 0, sizeof(s_in)); + s_in.sin6_family = AF_INET6; + s_in.sin6_addr = in6addr_any; + s_in.sin6_port = htons(s->network_port); - rc = ::bind(s->socket_fd, (const struct sockaddr *) &s_in, sizeof(s_in)); - if (rc != 0) { - perror("Control socket - bind"); + rc = ::bind(s->socket_fd, (const struct sockaddr *) &s_in, sizeof(s_in)); + if (rc != 0) { + perror("Control socket - bind"); + } + listen(s->socket_fd, MAX_CLIENTS); } - listen(s->socket_fd, MAX_CLIENTS); } else { s->socket_fd = socket(AF_INET, SOCK_STREAM, 0); assert(s->socket_fd != INVALID_SOCKET); @@ -495,12 +498,12 @@ static bool parse_msg(char *buffer, int buffer_len, /* out */ char *message, int */ static fd_t connect_to_internal_channel(int local_port) { - struct sockaddr_in6 s_in; + struct sockaddr_in s_in; memset(&s_in, 0, sizeof(s_in)); - s_in.sin6_family = AF_INET6; - s_in.sin6_addr = in6addr_loopback; - s_in.sin6_port = htons(local_port); - fd_t fd = socket(AF_INET6, SOCK_STREAM, 0); + s_in.sin_family = AF_INET; + s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + s_in.sin_port = htons(local_port); + fd_t fd = socket(AF_INET, SOCK_STREAM, 0); assert(fd != INVALID_SOCKET); int ret; ret = connect(fd, (struct sockaddr *) &s_in, @@ -552,7 +555,7 @@ static void * control_thread(void *args) fd_set fds; FD_ZERO(&fds); - if(s->connection_type == SERVER) { + if(s->connection_type == SERVER && s->socket_fd != INVALID_SOCKET) { FD_SET(s->socket_fd, &fds); max_fd = s->socket_fd + 1; } @@ -639,7 +642,7 @@ static void * control_thread(void *args) int32_t last_id = -1; ostringstream buffer; buffer << "stats"; - pthread_mutex_lock(&s->stats_lock); + std::unique_lock lk(s->stats_lock); for(auto it = s->stats.begin(); it != s->stats.end(); ++it) { int32_t id = it->first; @@ -656,7 +659,7 @@ static void * control_thread(void *args) buffer << " " + it->second->get_stat(); } - pthread_mutex_unlock(&s->stats_lock); + lk.unlock(); buffer << "\r\n"; if (!first) { // are there any stats to report? @@ -705,40 +708,35 @@ void control_done(struct control_state *s) fprintf(stderr, "Cannot exit control thread!\n"); } } - if(s->connection_type == SERVER) { + if(s->connection_type == SERVER && s->socket_fd != INVALID_SOCKET) { // for client, the socket has already been closed // by the time of control_thread exit CLOSESOCKET(s->socket_fd); } - pthread_mutex_destroy(&s->stats_lock); - delete s; } void control_add_stats(struct control_state *s, struct stats_reportable *stats, int32_t port_id) { - pthread_mutex_lock(&s->stats_lock); + std::unique_lock lk(s->stats_lock); s->stats.emplace(port_id, stats); - pthread_mutex_unlock(&s->stats_lock); } void control_remove_stats(struct control_state *s, struct stats_reportable *stats) { - pthread_mutex_lock(&s->stats_lock); + std::unique_lock lk(s->stats_lock); for (auto it = s->stats.begin(); it != s->stats.end(); ++it) { if (it->second == stats) { s->stats.erase(it); break; } } - pthread_mutex_unlock(&s->stats_lock); } void control_replace_port_mapping(struct control_state *s, std::map &&m) { - pthread_mutex_lock(&s->stats_lock); + std::unique_lock lk(s->stats_lock); s->stats_id_port_mapping = move(m); - pthread_mutex_unlock(&s->stats_lock); } diff --git a/src/video_codec.c b/src/video_codec.c index e80776dd5..2578fb774 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -84,8 +84,10 @@ using std::min; #define min(a, b) (((a) < (b))? (a): (b)) #endif +#ifdef __SSE2__ static void vc_deinterlace_aligned(unsigned char *src, long src_linesize, int lines); static void vc_deinterlace_unaligned(unsigned char *src, long src_linesize, int lines); +#endif static void vc_copylineToUYVY709(unsigned char *dst, const unsigned char *src, int dst_len, int rshift, int gshift, int bshift, int pix_size) __attribute__((unused)); static void vc_copylineToUYVY601(unsigned char *dst, const unsigned char *src, int dst_len, @@ -419,13 +421,25 @@ int get_pf_block_size(codec_t codec) */ void vc_deinterlace(unsigned char *src, long src_linesize, int lines) { +#ifdef __SSE2__ if(((long int) src & 0x0F) == 0 && src_linesize % 16 == 0) { vc_deinterlace_aligned(src, src_linesize, lines); } else { vc_deinterlace_unaligned(src, src_linesize, lines); } +#else + for (int y = 0; y < lines; y += 2) { + for (int x = 0; x < src_linesize; ++x) { + int val = (*src + src[src_linesize] + 1) >> 1; + *src = src[src_linesize] = val; + src++; + } + src += src_linesize; + } +#endif } +#ifdef __SSE2__ /** * Aligned version of deinterlace filter * @@ -520,6 +534,7 @@ static void vc_deinterlace_unaligned(unsigned char *src, long src_linesize, int bline3 += 16; } } +#endif /** * @brief Converts v210 to UYVY @@ -576,7 +591,7 @@ void vc_copylinev210(unsigned char *dst, const unsigned char *src, int dst_len) */ void vc_copylineYUYV(unsigned char *dst, const unsigned char *src, int dst_len) { -#if WORD_LEN == 64 +#if defined __SSE2__ register uint32_t *d; register const uint32_t *s; const uint32_t * const end = (uint32_t *)(void *) dst + dst_len / 4; diff --git a/src/vo_postprocess/3d-interlaced.c b/src/vo_postprocess/3d-interlaced.c index 3c8377650..f9e9d020c 100644 --- a/src/vo_postprocess/3d-interlaced.c +++ b/src/vo_postprocess/3d-interlaced.c @@ -143,6 +143,7 @@ bool interlaced_3d_postprocess(void *state, struct video_frame *in, struct video char *line1 = vf_get_tile(in, x % 2)->data + (x / 2) * 2 * linesize; char *line2 = vf_get_tile(in, x % 2)->data + ((x / 2) * 2 + 1) * linesize; +#ifdef __SSE2__ for(linepos = 0; linepos < linesize; linepos += 16) { asm volatile ("movdqu (%0), %%xmm0\n" "pavgb (%1), %%xmm0\n" @@ -155,6 +156,9 @@ bool interlaced_3d_postprocess(void *state, struct video_frame *in, struct video line1 += 16; line2 += 16; } +#else + fprintf(stderr, "SSE2 not supported on this platform!\n"); +#endif } return true;