From 5ba58034617fbf27e6fd2151c4b33164b4eabe9f Mon Sep 17 00:00:00 2001 From: "Castillo, Gerard" Date: Thu, 7 Aug 2014 21:55:32 +0200 Subject: [PATCH] merge and improvements: resize filter refactor and YUYV color scheme resize support, control socket port refactor for setting any possible port when connection type is server, double free corruption when flushing many capture filters solved in video frame data deleter --- Makefile.in | 4 -- configure.ac | 3 +- src/capture_filter.cpp | 6 +++ src/capture_filter/resize.cpp | 24 +++++------ src/capture_filter/resize.h | 51 +++++++++++++++++++++++ src/capture_filter/resize_utils.cpp | 8 +++- src/control_socket.cpp | 6 +-- src/control_socket.h | 4 +- src/hd-rum-translator/hd-rum-translator.c | 2 +- src/main.cpp | 23 +++++++++- src/video_frame.c | 1 + 11 files changed, 105 insertions(+), 27 deletions(-) create mode 100644 src/capture_filter/resize.h diff --git a/Makefile.in b/Makefile.in index 925603369..3cf50d050 100644 --- a/Makefile.in +++ b/Makefile.in @@ -655,10 +655,6 @@ rtsp_server: @RTSP_SERVER_LIB_TARGET@ mkdir -p lib/ultragrid $(LINKER) $(LDFLAGS) -shared -Wl,-soname,video_rxtx_h264.so.@video_rxtx_abi_version@ $^ @RTSP_SERVER_LIB@ -o $@ -@VCAPTURE_FILTER_RESIZE_LIB_TARGET@: @RESIZE_OBJ@ - mkdir -p lib/ultragrid - $(LINKER) $(LDFLAGS) -shared -Wl,-soname,vidcap_resize.so.@vcapture_filter_abi_version@ $^ @RESIZE_LIB@ -o $@ - install: all $(INSTALL) -d -m 755 $(DESTDIR)/$(bindir) $(INSTALL) -m 755 bin/uv $(DESTDIR)/$(bindir) diff --git a/configure.ac b/configure.ac index 66dfea1b9..ffc47fb3c 100644 --- a/configure.ac +++ b/configure.ac @@ -1343,9 +1343,8 @@ case $host in OPENCV_INC= RESIZE_LIB="${OPENCV_LIBS}" RESIZE_OBJ="src/capture_filter/resize.o src/capture_filter/resize_utils.o" - AC_SUBST(VCAPTURE_FILTER_RESIZE_LIB_TARGET, "lib/ultragrid/vcapfilter_resize.so.$vcapture_filter_abi_version") - LIB_TARGETS="$LIB_TARGETS $VCAPTURE_FILTER_RESIZE_LIB_TARGET" + LIB_TARGETS="$LIB_TARGETS" LIB_OBJS="$LIB_OBJS $RESIZE_OBJ" opencv=yes diff --git a/src/capture_filter.cpp b/src/capture_filter.cpp index d4b859f19..e876ce27e 100644 --- a/src/capture_filter.cpp +++ b/src/capture_filter.cpp @@ -55,6 +55,9 @@ #include "capture_filter/logo.h" #include "capture_filter/none.h" #include "capture_filter/scale.h" +#ifdef HAVE_OPENCV +#include "capture_filter/resize.h" +#endif #include @@ -76,6 +79,9 @@ struct init_capture_filters { &capture_filter_logo, &capture_filter_none, &capture_filter_scale, +#ifdef HAVE_OPENCV + &capture_filter_resize, +#endif }; } } diff --git a/src/capture_filter/resize.cpp b/src/capture_filter/resize.cpp index 3a5725933..dca03e990 100644 --- a/src/capture_filter/resize.cpp +++ b/src/capture_filter/resize.cpp @@ -91,7 +91,7 @@ static int init(struct module *parent, const char *cfg, void **state) UNUSED(parent); int n; - int denom = 1;; + int denom = 1; if(cfg) { if(strcasecmp(cfg, "help") == 0) { usage(); @@ -107,15 +107,20 @@ static int init(struct module *parent, const char *cfg, void **state) } if(n <= 0 || denom <= 0){ - printf("\n[RESIZE ERROR] numerator and denominator resize factors must be greater than zero!\n"); + printf("\n[RESIZE ERROR] resize factors must be greater than zero!\n"); usage(); return -1; } if(n/denom > 1.0){ - printf("\n[RESIZE ERROR] numerator and denominator resize factors must be lower than 1 (only downscaling is supported)\n"); + printf("\n[RESIZE ERROR] resize factors must be lower than 1 (only downscaling is supported)\n"); usage(); return -1; } + if(n == denom){ + printf("\n[RESIZE ERROR] resize factors must be lower than 1 (only downscaling is supported)\n"); + usage(); + return -1; + } struct state_resize *s = (state_resize*) calloc(1, sizeof(struct state_resize)); s->reinit = 1; @@ -150,7 +155,7 @@ static struct video_frame *filter(void *state, struct video_frame *in) for(i=0; iframe->tile_count;i++){ if(s->reinit==1){ - //TODO: all tiles could have different sizes and other color specs different than UYVY and RGB + //TODO: all tiles could have different sizes and other color specs different than UYVY, YUYV and RGB s->orig_width = s->frame->tiles[i].width; s->orig_height = s->frame->tiles[i].height; s->frame->tiles[i].width *= s->num; @@ -175,23 +180,18 @@ static struct video_frame *filter(void *state, struct video_frame *in) } } + VIDEO_FRAME_DISPOSE(in); + return s->frame; } -static struct capture_filter_info capture_filter_resize = { +struct capture_filter_info capture_filter_resize = { "resize", init, done, filter, }; -static void init(void) __attribute__((constructor)); - -static void init(void) -{ - register_video_capture_filter(&capture_filter_resize); -} - #ifdef __cplusplus } #endif diff --git a/src/capture_filter/resize.h b/src/capture_filter/resize.h new file mode 100644 index 000000000..cbad20e54 --- /dev/null +++ b/src/capture_filter/resize.h @@ -0,0 +1,51 @@ +/* + * FILE: capture_filter/resize.h + * AUTHORS: Gerard Castillo + * Marc Palau + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by the Fundació i2CAT, + * Internet I Innovació Digital a Catalunya. This product also includes + * software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the University nor of the Institute may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CAPTURE_FILTER_RESIZE_H_ +#define CAPTURE_FILTER_RESIZE_H_ + +struct capture_filter_info; +extern struct capture_filter_info capture_filter_resize; + +#endif // CAPTURE_FILTER_RESIZE_H_ diff --git a/src/capture_filter/resize_utils.cpp b/src/capture_filter/resize_utils.cpp index a35885891..dfd720fd1 100644 --- a/src/capture_filter/resize_utils.cpp +++ b/src/capture_filter/resize_utils.cpp @@ -47,7 +47,7 @@ using namespace cv; int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *data_len, unsigned int width, unsigned int height, double scale_factor){ - assert(in_color == UYVY || in_color == RGB); + assert(in_color == UYVY || in_color == YUYV || in_color == RGB); int res = 0; Mat out, in, rgb; @@ -63,6 +63,12 @@ int resize_frame(char *indata, codec_t in_color, char *outdata, unsigned int *da cvtColor(in, rgb, CV_YUV2RGB_UYVY); resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); break; + case YUYV: + in.create(height, width, CV_8UC2); + in.data = (uchar*)indata; + cvtColor(in, rgb, CV_YUV2RGB_YUYV); + resize(rgb, out, Size(0,0), scale_factor, scale_factor, INTER_LINEAR); + break; case RGB: in.create(height, width, CV_8UC3); in.data = (uchar*)indata; diff --git a/src/control_socket.cpp b/src/control_socket.cpp index b22070d05..50d8e5e9a 100644 --- a/src/control_socket.cpp +++ b/src/control_socket.cpp @@ -161,7 +161,7 @@ static fd_t create_internal_port(int *port) } -int control_init(int port, struct control_state **state, struct module *root_module) +int control_init(int port, int connection_type, struct control_state **state, struct module *root_module) { control_state *s = new control_state; @@ -174,8 +174,8 @@ int control_init(int port, struct control_state **state, struct module *root_mod s->mod.cls = MODULE_CLASS_CONTROL; s->mod.priv_data = s; - if(port == -1) { - s->network_port = DEFAULT_CONTROL_PORT; + if(connection_type == 0) { + s->network_port = port; s->connection_type = SERVER; } else { s->network_port = port; diff --git a/src/control_socket.h b/src/control_socket.h index 1284e326a..c22969b83 100644 --- a/src/control_socket.h +++ b/src/control_socket.h @@ -53,12 +53,12 @@ struct control_state; struct module; struct stats; -#define CONTROL_DEFAULT_PORT -1 +#define CONTROL_DEFAULT_PORT 5054 /** * @retval 0 if success */ -int control_init(int port, struct control_state **state, struct module *root_module); +int control_init(int port, int connection_type, struct control_state **state, struct module *root_module); void control_start(struct control_state *state); void control_done(struct control_state *s); void control_add_stats(struct control_state *state, struct stats *stats); diff --git a/src/hd-rum-translator/hd-rum-translator.c b/src/hd-rum-translator/hd-rum-translator.c index 44a02a6fc..a01c927d9 100644 --- a/src/hd-rum-translator/hd-rum-translator.c +++ b/src/hd-rum-translator/hd-rum-translator.c @@ -547,7 +547,7 @@ int main(int argc, char **argv) module_register(&state.replicas[i].mod, &state.mod); } - if(control_init(control_port, &control_state, &state.mod) != 0) { + if(control_init(control_port, 0, &control_state, &state.mod) != 0) { fprintf(stderr, "Warning: Unable to create remote control.\n"); if(control_port != CONTROL_DEFAULT_PORT) { return EXIT_FAILURE; diff --git a/src/main.cpp b/src/main.cpp index ed111a83f..de686947b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -201,6 +201,9 @@ static void usage(void) printf(" address(es)\n\n"); printf("\t--verbose \tprint verbose messages\n"); printf("\n"); + printf("\t--control-port [:0|1] \tset control port (default port: 5054)\n"); + printf("\t \tconnection types: 0- Server (default), 1- Client\n"); + printf("\n"); printf ("\t-d \tselect display device, use '-d help'\n"); printf("\t \tto get list of supported devices\n"); @@ -448,6 +451,7 @@ int main(int argc, char *argv[]) char *sage_opts = NULL; int control_port = CONTROL_DEFAULT_PORT; + int connection_type = 0; struct control_state *control = NULL; const char *audio_host = NULL; @@ -779,7 +783,22 @@ int main(int argc, char *argv[]) requested_encryption = optarg; break; case OPT_CONTROL_PORT: - control_port = atoi(optarg); + if (strchr(optarg, ':')) { + char *save_ptr = NULL; + char *tok; + control_port = atoi(strtok_r(optarg, ":", &save_ptr)); + connection_type = atoi(strtok_r(NULL, ":", &save_ptr)); + if(connection_type < 0 || connection_type > 1){ + usage(); + return EXIT_FAIL_USAGE; + } + if ((tok = strtok_r(NULL, ":", &save_ptr))) { + usage(); + return EXIT_FAIL_USAGE; + } + } else { + control_port = atoi(optarg); + } break; case OPT_VERBOSE: verbose = true; @@ -863,7 +882,7 @@ int main(int argc, char *argv[]) } #endif - if(control_init(control_port, &control, &root_mod) != 0) { + if(control_init(control_port, connection_type, &control, &root_mod) != 0) { fprintf(stderr, "%s Unable to initialize remote control!\n", control_port != CONTROL_DEFAULT_PORT ? "Warning:" : "Error:"); if(control_port != CONTROL_DEFAULT_PORT) { diff --git a/src/video_frame.c b/src/video_frame.c index fe823d08a..6443c1212 100644 --- a/src/video_frame.c +++ b/src/video_frame.c @@ -133,6 +133,7 @@ void vf_data_deleter(struct video_frame *buf) return; for(unsigned int i = 0u; i < buf->tile_count; ++i) { + if(!buf->tiles[i].data) free(buf->tiles[i].data); } }