diff --git a/veejay-current/veejay-client/AUTHORS b/veejay-current/veejay-client/AUTHORS index 52b83b23..eb78d521 100644 --- a/veejay-current/veejay-client/AUTHORS +++ b/veejay-current/veejay-client/AUTHORS @@ -20,3 +20,10 @@ Contributions by: d/j/a/y (reloaded interface improvements) + + +Icons: + + share/multicast.ico + + icons8.com as Creative Commons Attribution-NoDerivs 3.0 Unported diff --git a/veejay-current/veejay-client/configure.ac b/veejay-current/veejay-client/configure.ac index 60463592..0830877a 100644 --- a/veejay-current/veejay-client/configure.ac +++ b/veejay-current/veejay-client/configure.ac @@ -1,12 +1,12 @@ dnl Process this file with autoconf to produce a configure script. dnl AC_INIT -AC_INIT([reloaded],[1.5.58],[nwelburg@gmail.com]) +AC_INIT([reloaded],[1.5.60],[nwelburg@gmail.com]) AC_PREREQ(2.57) AC_CONFIG_SRCDIR([src/gveejay.c]) RELOADED_MAJOR_VERSION=1 RELOADED_MINOR_VERSION=5 -RELOADED_MICRO_VERSION=58 +RELOADED_MICRO_VERSION=60 RELOADED_VERSION=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION.$VEEJAY_MICRO_VERSION RELOADED_CODENAME="Reloaded - build $RELOADED_MAJOR_VERSION $RELOADED_MINOR_VERSION $RELOADED_MICRO_VERSION" AC_CONFIG_HEADERS([config.h]) @@ -184,17 +184,17 @@ fi dnl Check for Veejay have_veejay=false -PKG_CHECK_MODULES( VEEJAY, [veejay >= 1.5.50 ], +PKG_CHECK_MODULES( VEEJAY, [veejay >= 1.5.60 ], [ AC_SUBST(VEEJAY_CFLAGS) AC_SUBST(VEEJAY_LIBS) have_veejay=true - AC_DEFINE(HAVE_VEEJAY,1, [Veejay 1.5.50 installed])] + AC_DEFINE(HAVE_VEEJAY,1, [Veejay 1.5.60 installed])] , [have_veejay=false]) if test x$have_veejay != xtrue ; then - AC_MSG_ERROR([Cannot find veejay 1.5.50 or later]) + AC_MSG_ERROR([Cannot find veejay 1.5.60 or later]) fi have_pixbuf=false diff --git a/veejay-current/veejay-client/share/gveejay.reloaded.glade b/veejay-current/veejay-client/share/gveejay.reloaded.glade index 436098e9..0a05507e 100644 --- a/veejay-current/veejay-client/share/gveejay.reloaded.glade +++ b/veejay-current/veejay-client/share/gveejay.reloaded.glade @@ -11911,6 +11911,28 @@ YUV (current) 1 + + + True + True + True + True + Enable Multicast frame sender + + + + True + False + multicast.ico + + + + + False + False + 2 + + @@ -15353,6 +15375,24 @@ YUV (current) + + + + + + + + + + + + + + + + + + True diff --git a/veejay-current/veejay-client/share/multicast.ico b/veejay-current/veejay-client/share/multicast.ico new file mode 100644 index 00000000..aad528c8 Binary files /dev/null and b/veejay-current/veejay-client/share/multicast.ico differ diff --git a/veejay-current/veejay-client/src/callback.c b/veejay-current/veejay-client/src/callback.c index df360413..ce8af29f 100644 --- a/veejay-current/veejay-client/src/callback.c +++ b/veejay-current/veejay-client/src/callback.c @@ -1797,9 +1797,9 @@ void on_new_colorstream_clicked(GtkWidget *widget, gpointer user_data) ¤t_color ); // scale to 0 - 255 - gint red = current_color.red / 256.0; -gint green = current_color.green / 256.0; - gint blue = current_color.blue / 256.0; + gint red = current_color.red / 255.0; + gint green = current_color.green / 255.0; + gint blue = current_color.blue / 255.0; multi_vims( VIMS_STREAM_NEW_COLOR, "%d %d %d", red,green,blue ); gveejay_new_slot(MODE_STREAM); @@ -4521,7 +4521,6 @@ void on_midievent_toggled( GtkWidget *w, gpointer data ) vj_midi_play( info->midi ); } - void on_load_midi_layout1_activate( GtkWidget *w , gpointer data ) { gchar *filename = dialog_open_file( "Select MIDI configuration file to load",0); @@ -4552,3 +4551,12 @@ void on_button_vloop_start_clicked(GtkWidget *widget, gpointer user_data) multi_vims( VIMS_VLOOPBACK_START, "%d", get_nums( "spin_vloop" ) ); } +void on_toggle_multicast_toggled(GtkWidget *widget, gpointer user_data) +{ + if( is_button_toggled( "toggle_multicast" ) ) { + multi_vims( VIMS_VIDEO_MCAST_START, "%d", 0 ); + } + else { + single_vims( VIMS_VIDEO_MCAST_STOP ); + } +} diff --git a/veejay-current/veejay-client/src/vj-api.c b/veejay-current/veejay-client/src/vj-api.c index 584ce197..be5c0596 100644 --- a/veejay-current/veejay-client/src/vj-api.c +++ b/veejay-current/veejay-client/src/vj-api.c @@ -116,6 +116,7 @@ static struct #define MAX_SLOW 25 static int beta__ = 0; +static int use_vims_mcast = 0; static struct { @@ -5627,10 +5628,10 @@ static void load_editlist_info() #endif return; } - sscanf(res, "%d %d %d %c %f %d %d %ld %d %ld %ld %d", + sscanf(res, "%d %d %d %c %f %d %d %ld %d %ld %ld %d %d", &values[0], &values[1], &values[2], &norm,&fps, &values[4], &values[5], &rate, &values[7], - &dum[0], &dum[1], &values[8]); + &dum[0], &dum[1], &values[8], &use_vims_mcast); snprintf( tmp, sizeof(tmp)-1, "%dx%d", values[0],values[1]); info->el.width = values[0]; @@ -5667,6 +5668,13 @@ static void load_editlist_info() enable_widget( "button_5_4" ); } + if( use_vims_mcast ) { + enable_widget( "toggle_multicast" ); + } + else { + disable_widget( "toggle_multicast" ); + } + free(res); } @@ -8668,10 +8676,7 @@ static void remove_sample_from_slot() VIMS_STREAM_DELETE ), "%d", info->selection_slot->sample_id ); - // decrement history of delete type - int *his = info->history_tokens[ (info->status_tokens[PLAY_MODE]) ]; - his[TOTAL_SLOTS] = his[TOTAL_SLOTS] - 1; update_sample_slot_data( bank_nr, slot_nr, 0, -1, NULL, NULL); sample_gui_slot_t *gui_slot = info->sample_banks[bank_nr]->gui_slot[slot_nr]; @@ -8679,8 +8684,12 @@ static void remove_sample_from_slot() gtk_image_clear( GTK_IMAGE( gui_slot->image) ); set_selection_of_slot_in_samplebank( FALSE ); + info->selection_gui_slot = NULL; info->selection_slot = NULL; + + info->uc.reload_hint[HINT_SLIST] = 2; + } diff --git a/veejay-current/veejay-server/configure.ac b/veejay-current/veejay-server/configure.ac index eb4e54ef..446da4ed 100644 --- a/veejay-current/veejay-server/configure.ac +++ b/veejay-current/veejay-server/configure.ac @@ -1,12 +1,12 @@ dnl Process this file with autoconf to produce a configure script. dnl AC_INIT -AC_INIT([veejay],[1.5.59],[http://www.veejayhq.net]) +AC_INIT([veejay],[1.5.60],[http://www.veejayhq.net]) AC_PREREQ(2.57) AC_CONFIG_SRCDIR([veejay/veejay.c]) VEEJAY_MAJOR_VERSION=1 VEEJAY_MINOR_VERSION=5 -VEEJAY_MICRO_VERSION=59 +VEEJAY_MICRO_VERSION=60 VEEJAY_VERSION=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION.$VEEJAY_MICRO_VERSION VEEJAY_CODENAME="Veejay Classic - build $VEEJAY_MINOR_VERSION $VEEJAY_MICRO_VERSION" AC_CONFIG_HEADERS([config.h]) diff --git a/veejay-current/veejay-server/libel/vj-avcodec.c b/veejay-current/veejay-server/libel/vj-avcodec.c index 5d233891..0544d1a6 100644 --- a/veejay-current/veejay-server/libel/vj-avcodec.c +++ b/veejay-current/veejay-server/libel/vj-avcodec.c @@ -410,9 +410,9 @@ int vj_avcodec_init( int pixel_format, int verbose) { out_pixel_format = pixel_format; - av_log_set_level( AV_LOG_QUIET); + //av_log_set_level( AV_LOG_QUIET); - //av_log_set_level( AV_LOG_VERBOSE ); + av_log_set_level( AV_LOG_VERBOSE ); #if LIBAVCODEC_BUILD < 5400 avcodec_register_all(); diff --git a/veejay-current/veejay-server/libstream/vj-net.c b/veejay-current/veejay-server/libstream/vj-net.c index f285b202..d2d26530 100644 --- a/veejay-current/veejay-server/libstream/vj-net.c +++ b/veejay-current/veejay-server/libstream/vj-net.c @@ -1,7 +1,7 @@ /* * Linux VeeJay * - * Copyright(C)2002-2006 Niels Elburg + * Copyright(C)2002-2016 Niels Elburg * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -35,8 +35,7 @@ #include #include #include - -#define RUP8(num)(((num)+8)&~8) +#include typedef struct { @@ -96,7 +95,6 @@ static void *reader_thread(void *data) char buf[16]; int retrieve = 0; int success = 0; - int is_mcast = (tag->source_type == VJ_TAG_TYPE_MCAST ? 1: 0 ); vj_client *v = vj_client_alloc( t->w, t->h, t->af ); if( v == NULL ) @@ -108,15 +106,9 @@ static void *reader_thread(void *data) return NULL; } - if( is_mcast ) { - success = vj_client_connect( v, NULL, tag->source_name, tag->video_channel ); - snprintf(buf,sizeof(buf), "%03d:%d;", VIMS_VIDEO_MCAST_START, 0 ); - } - else { - snprintf(buf,sizeof(buf), "%03d:%d;", VIMS_GET_FRAME, my_screen_id); - success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); - } - + snprintf(buf,sizeof(buf), "%03d:%d;", VIMS_GET_FRAME, my_screen_id); + success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); + if( success > 0 ) { veejay_msg(VEEJAY_MSG_INFO, "Connecton established with %s:%d",tag->source_name, tag->video_channel + 5); } @@ -130,50 +122,36 @@ static void *reader_thread(void *data) t->state = STATE_RUNNING; unlock(t); -/* if( is_mcast ) { - vj_client_send( v, V_CMD, (unsigned char*) buf ); - } -*/ for( ;; ) { - int error = 0; - int res = 0; + int error = 0; + int res = 0; int ret = 0; - - if( !is_mcast ) { - if( retrieve == 0 && t->have_frame == 0 ) { - ret = vj_client_send( v, V_CMD,(unsigned char*) buf ); - if( ret <= 0 ) { - error = 1; - } - else { - retrieve = 1; - } + + if( retrieve == 0 && t->have_frame == 0 ) { + ret = vj_client_send( v, V_CMD,(unsigned char*) buf ); + if( ret <= 0 ) { + error = 1; } + else { + retrieve = 1; + } + } - if(!error && retrieve == 1 ) { - res = vj_client_poll(v, V_CMD ); - if( res ) { - if(vj_client_link_can_read( v, V_CMD ) ) { - retrieve = 2; - } - } - else if ( res < 0 ) { - error = 1; - } else if ( res == 0 ) { - net_delay(10,0); - continue; + if(!error && retrieve == 1 ) { + res = vj_client_poll(v, V_CMD ); + if( res ) { + if(vj_client_link_can_read( v, V_CMD ) ) { + retrieve = 2; } + } + else if ( res < 0 ) { + error = 1; + } else if ( res == 0 ) { + net_delay(10,0); + continue; } } - else { - error = 0; - retrieve = 2; - res = 1; - } - -//FIXME multicast stream has its own header, it is not compressed. -//FIXME compressing it before sending requires to modify header -//FIXME + if(!error && retrieve == 2) { int strides[3] = { 0,0,0}; int compr_len = 0; @@ -203,30 +181,25 @@ static void *reader_thread(void *data) vj_client_decompress_frame_data( v, t->buf, t->in_fmt, t->in_w, t->in_h, compr_len, strides[0],strides[1],strides[2] ); unlock(t); } - } + } if( need_rlock ) { unlock(t); } } - - // lock(t); - //t->buf = vj_client_read_i( v, t->buf,&(t->bufsize), &ret ); + if(ret && t->buf) { t->have_frame = 1; - t->in_fmt = v->in_fmt; - t->in_w = v->in_width; - t->in_h = v->in_height; + t->in_fmt = v->in_fmt; + t->in_w = v->in_width; + t->in_h = v->in_height; retrieve = 0; } + if( ret <= 0 || t->buf == NULL ) { - if( tag->source_type == VJ_TAG_TYPE_NET ) - { - veejay_msg(VEEJAY_MSG_DEBUG,"Error reading video frame from %s:%d",tag->source_name,tag->video_channel ); - error = 1; - } + veejay_msg(VEEJAY_MSG_DEBUG,"Error reading video frame from %s:%d",tag->source_name,tag->video_channel ); + error = 1; } - // unlock(t); } NETTHREADRETRY: @@ -237,10 +210,7 @@ NETTHREADRETRY: veejay_msg(VEEJAY_MSG_INFO, " ZZzzzzz ... waiting for Link %s:%d to become ready", tag->source_name, tag->video_channel ); net_delay( 0, 5 ); - if( is_mcast ) - success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); - else - success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); + success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); if( t->state == 0 ) { @@ -269,23 +239,147 @@ NETTHREADRETRY: } NETTHREADEXIT: -/* - if( is_mcast ) { - snprintf(buf,sizeof(buf), "%03d:;", VIMS_VIDEO_MCAST_STOP ); - vj_client_send( v, V_CMD, (unsigned char*) buf ); - } -*/ + if(t->buf) free(t->buf); t->buf = NULL; if(v) { - vj_client_close(v); + vj_client_close(v); vj_client_free(v); v = NULL; } veejay_msg(VEEJAY_MSG_INFO, "Network thread with %s: %d has exited",tag->source_name,tag->video_channel+5); - //pthread_exit( &(t->thread)); + + return NULL; +} + + +static void *mcast_reader_thread(void *data) +{ + vj_tag *tag = (vj_tag*) data; + threaded_t *t = tag->priv; + char buf[16]; + int retrieve = 0; + int success = 0; + + vj_client *v = vj_client_alloc( t->w, t->h, t->af ); + if( v == NULL ) + return NULL; + + v->lzo = lzo_new(); + if( v->lzo == NULL ) { + vj_client_free(v); + return NULL; + } + + success = vj_client_connect( v, NULL, tag->source_name, tag->video_channel ); + snprintf(buf,sizeof(buf), "%03d:%d;", VIMS_VIDEO_MCAST_START, 0 ); + + if( success > 0 ) { + veejay_msg(VEEJAY_MSG_INFO, "Multicast connecton established with %s:%d",tag->source_name, tag->video_channel + 5); + } + else + { + veejay_msg(0, "Unable to connect to %s: %d", tag->source_name, tag->video_channel+5); + goto NETTHREADEXIT; + } + + lock(t); + t->state = STATE_RUNNING; + unlock(t); + + const int padded = 256; + int max_len = padded + RUP8( 1920 * 1080 * 3 ); + + t->buf = (uint8_t*) vj_malloc( sizeof(uint8_t) * max_len ); + + for( ;; ) { + int error = 0; + int res = 0; + int ret = 0; + int strides[3] = { 0,0,0}; + int compr_len = 0; + + t->bufsize = padded + RUP8(t->in_w * t->in_h * 3); + if( t->bufsize <= padded ) + t->bufsize = max_len; + else + max_len = t->bufsize; + + if( t->bufsize != max_len ) { + free(t->buf); + t->buf = (uint8_t*) vj_malloc( sizeof(uint8_t) * t->bufsize ); + } + + if( vj_client_read_mcast_data( v, &compr_len, &strides[0], &strides[1], &strides[2], &(t->in_w), &(t->in_h), &(t->in_fmt), NULL, max_len ) == 0 ) { + error = 1; + } + + if( compr_len > 0 ) { + lock(t); + vj_client_decompress_frame_data( v, t->buf, t->in_fmt, t->in_w, t->in_h, compr_len, strides[0],strides[1],strides[2] ); + unlock(t); + } + else { + lock(t); + veejay_memcpy( t->buf, v->space + 44, strides[0] + strides[1] + strides[2] ); + unlock(t); + } + + if(error == 0) { + t->have_frame = 1; + t->in_fmt = v->in_fmt; + t->in_w = v->in_width; + t->in_h = v->in_height; + } + +NETTHREADRETRY: + + if( error ) + { + vj_client_close(v); + + veejay_msg(VEEJAY_MSG_INFO, " ZZzzzzz ... waiting for multicast server %s:%d to become ready", tag->source_name, tag->video_channel ); + net_delay( 0, 5 ); + + success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); + + if( t->state == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Multicast receiver %s: %d was told to stop",tag->source_name,tag->video_channel+5); + goto NETTHREADEXIT; + } + + if( success <= 0 ) + { + goto NETTHREADRETRY; + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Multicast receiver has re-established with %s:%d",tag->source_name,tag->video_channel + 5); + } + } + + if( t->state == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Multicast receiver %s: %d was told to stop",tag->source_name,tag->video_channel+5); + goto NETTHREADEXIT; + } + } + +NETTHREADEXIT: + + if(t->buf) + free(t->buf); + t->buf = NULL; + if(v) { + vj_client_close(v); + vj_client_free(v); + v = NULL; + } + + veejay_msg(VEEJAY_MSG_INFO, "Multicast receiver %s: %d has stopped",tag->source_name,tag->video_channel+5); return NULL; } @@ -322,7 +416,7 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) /* frame ready ? */ lock(t); state = t->state; - if( state == 0 || t->bufsize == 0 || t->buf == NULL ) { + if( state == 0 || t->bufsize == 0 || t->buf == NULL || t->have_frame == 0 ) { unlock(t); return 1; // not active or no frame } // just continue when t->have_frame == 0 @@ -332,6 +426,7 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) int buvlen = b_len; //FIXME alpha channel not yet supported in unicast/mcast streaming, work arround. refactor in libvevosample + // bad image source points (alpha channel pointer is never set) if( t->in_fmt == PIX_FMT_YUVA420P ) { t->in_fmt = PIX_FMT_YUVJ420P; } else if (t->in_fmt == PIX_FMT_YUVA422P ) { @@ -340,7 +435,7 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) t->in_fmt = PIX_FMT_YUVJ444P; } - switch( t->in_fmt ) { /* fixme alpha channel support */ + switch( t->in_fmt ) { case PIX_FMT_YUV420P: case PIX_FMT_YUVJ420P: buvlen = b_len / 4; @@ -367,7 +462,6 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) t->scaler = yuv_init_swscaler( t->a,t->b, &sws_templ, yuv_sws_get_cpu_flags() ); } - // bad image src points if t->b is set to yuv alpha yuv_convert_and_scale( t->scaler, t->a,t->b ); t->have_frame = 0; @@ -379,6 +473,7 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat) { threaded_t *t = (threaded_t*)tag->priv; + int p_err = 0; pthread_mutex_init( &(t->mutex), NULL ); t->w = wid; @@ -387,14 +482,19 @@ int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat) t->f = get_ffmpeg_pixfmt(pixelformat); t->have_frame = 0; - int p_err = pthread_create( &(t->thread), NULL, &reader_thread, (void*) tag ); - if( p_err ==0) - - { + if( tag->source_type == VJ_TAG_TYPE_MCAST ) { + p_err = pthread_create( &(t->thread), NULL, &mcast_reader_thread, (void*) tag ); + } + else { + p_err = pthread_create( &(t->thread), NULL, &reader_thread, (void*) tag ); + } + + if( p_err ==0) { veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream to veejay host %s port %d", tag->source_type == VJ_TAG_TYPE_MCAST ? "multicast" : "unicast", tag->source_name,tag->video_channel); } + return 1; } @@ -426,22 +526,22 @@ int net_already_opened(const char *filename, int n, int channel) { if (vj_tag_exists(i) ) { - vj_tag_get_source_name(i, sourcename); - if (strcasecmp(sourcename, filename) == 0) - { - vj_tag *tt = vj_tag_get( i ); - if( tt->source_type == VJ_TAG_TYPE_NET || tt->source_type == VJ_TAG_TYPE_MCAST ) + vj_tag_get_source_name(i, sourcename); + if (strcasecmp(sourcename, filename) == 0) { - if( tt->video_channel == channel ) + vj_tag *tt = vj_tag_get( i ); + if( tt->source_type == VJ_TAG_TYPE_NET || tt->source_type == VJ_TAG_TYPE_MCAST ) { - veejay_msg(VEEJAY_MSG_WARNING, "Already streaming from %s:%p in stream %d", - filename,channel, tt->id); - return 1; + if( tt->video_channel == channel ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Already streaming from %s:%p in stream %d", + filename,channel, tt->id); + return 1; + } } } - } } - } + } return 0; } diff --git a/veejay-current/veejay-server/libvjnet/mcastreceiver.c b/veejay-current/veejay-server/libvjnet/mcastreceiver.c index 9fc9a69f..6147f66f 100644 --- a/veejay-current/veejay-server/libvjnet/mcastreceiver.c +++ b/veejay-current/veejay-server/libvjnet/mcastreceiver.c @@ -1,6 +1,6 @@ /* vjnet - low level network I/O for VeeJay * - * (C) 2005-2007 Niels Elburg + * (C) 2005-2016 Niels Elburg * * * This program is free software; you can redistribute it and/or modify @@ -31,31 +31,33 @@ #include #include #include +#include #include -#include "mcastreceiver.h" +#include #include #include -#include #include -#include "packet.h" #include +#include "mcastreceiver.h" +#include "packet.h" typedef struct { packet_header_t hdr; - frame_info_t inf; - uint8_t *buf; - int len; - int count; - int rdy; + uint8_t *ref; + int len; + int count; + int rdy; } packet_buffer_t; #define PACKET_SLOTS 3 + typedef struct { packet_buffer_t **slot; - int in_slot; - long last; + int in_slot; + long last; + uint8_t *buf; } packet_slot_t; mcast_receiver *mcast_new_receiver( const char *group_name, int port ) @@ -143,8 +145,8 @@ int mcast_receiver_set_peer( mcast_receiver *v, const char *hostname ) v->addr.sin_family = AF_INET; if( !inet_aton( hostname, &(v->addr.sin_addr) ) ) { - veejay_msg(0, "Invalid host '%s'", hostname ); - return 0; + veejay_msg(0, "Invalid host '%s'", hostname ); + return 0; } } return 1; @@ -172,24 +174,32 @@ int mcast_recv( mcast_receiver *v, void *buf, int len ) return n; } +static void mcast_clear_slot( packet_buffer_t *packet ) +{ + packet->ref = NULL; + packet->count = 0; + packet->rdy = 0; + veejay_memset( &(packet->hdr), 0, PACKET_HEADER_LENGTH ); +} + int mcast_recv_packet_frame( mcast_receiver *v ) { - uint8_t chunk[PACKET_PAYLOAD_SIZE]; + uint8_t chunk[PACKET_PAYLOAD_SIZE]; packet_slot_t *q = (packet_slot_t*) v->next; - - packet_header_t hdr; - frame_info_t inf; - + int res = recv(v->sock_fd, chunk, PACKET_PAYLOAD_SIZE, 0 ); - if( res <= 0 ) - { + if( res <= 0 ) { if(res == - 1) - veejay_msg(VEEJAY_MSG_ERROR, "Error receiving multicast packet:%s", strerror(errno)); + veejay_msg(VEEJAY_MSG_ERROR, "Error receiving multicast packet:%s", strerror(errno)); - return 0; - } - hdr = packet_get_header(chunk); - packet_get_info( &inf, chunk ); + return 0; + } + if( res != PACKET_PAYLOAD_SIZE ) { + veejay_msg(VEEJAY_MSG_ERROR, "Multicast receive error, expected %d bytes got %d bytes", + PACKET_PAYLOAD_SIZE, res ); + } + + packet_header_t *hdr = packet_get_hdr(chunk); //@ choose slot to fill int i; @@ -197,7 +207,8 @@ int mcast_recv_packet_frame( mcast_receiver *v ) for(i = 0; i < PACKET_SLOTS; i ++ ) { - if( q->slot[i]->hdr.usec == hdr.usec ) { + const packet_buffer_t *packet = q->slot[i]; + if( packet->hdr.usec == hdr->usec ) { d_slot = i; break; } @@ -215,10 +226,10 @@ int mcast_recv_packet_frame( mcast_receiver *v ) //@ no slots available if( d_slot == -1) { - veejay_msg(VEEJAY_MSG_WARNING, "All packet slots in use, cannot keep pace! Dropping oldest in queue."); + veejay_msg(VEEJAY_MSG_DEBUG, "All packet slots in use, cannot keep pace! Dropping oldest in queue."); //@ drop oldest packet in slot long oldest = LONG_MAX; - int o = 0; + int o = 0; for(i = 0; i < PACKET_SLOTS; i ++ ) { if(q->slot[i]->hdr.usec < oldest ) { o = i; @@ -227,60 +238,46 @@ int mcast_recv_packet_frame( mcast_receiver *v ) } d_slot = o; - free(q->slot[d_slot]->buf); - q->slot[d_slot]->buf = NULL; - q->slot[d_slot]->count = 0; - veejay_memset( &(q->slot[d_slot]->hdr), 0,sizeof(packet_header_t)); - veejay_memset( &(q->slot[d_slot]->inf), 0,sizeof(frame_info_t)); - q->slot[d_slot]->rdy = 0; + mcast_clear_slot( q->slot[d_slot] ); } //@ destination slot packet_buffer_t *pb = q->slot[d_slot]; - if(pb->buf == NULL) { //@ allocate buffer if needed - pb->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * inf.width * inf.height * 3); - } - - pb->len = inf.len; - uint8_t *dst = pb->buf + (CHUNK_SIZE * hdr.seq_num ); - packet_get_data( &hdr, chunk, dst ); + + uint8_t *dst = q->buf + (CHUNK_SIZE * hdr->seq_num ); + + packet_get_data( hdr, chunk, dst ); + pb->count ++; + pb->ref = dst; - //@ save info/hdr - veejay_memcpy( &(pb->hdr), &hdr, sizeof(packet_header_t)); - veejay_memcpy( &(pb->inf), &inf, sizeof(frame_info_t)); + veejay_memcpy( &(pb->hdr), hdr, sizeof(packet_header_t)); - if( pb->count >= hdr.length ) + if( pb->count >= hdr->length ) { pb->rdy = 1; - q->last = hdr.usec; + q->last = hdr->usec; return 2; } return 1; } -uint8_t *mcast_recv_frame( mcast_receiver *v, int *dw, int *dh, int *dfmt, int *len ) +uint8_t *mcast_recv_frame( mcast_receiver *v, int *len, int *hdrlen, uint8_t *recvbuf ) { packet_slot_t *q = (packet_slot_t*) v->next; int i,n; + + q->buf = recvbuf; + for(i = 0; i < PACKET_SLOTS; i ++ ) { //@ find rdy frames or too-old-frames and free them if( q->slot[i]->rdy == 1 || q->slot[i]->hdr.usec < q->last ) { - free(q->slot[i]->buf); - q->slot[i]->buf = NULL; - q->slot[i]->count = 0; - veejay_memset( &(q->slot[i]->hdr), 0,sizeof(packet_header_t)); - veejay_memset( &(q->slot[i]->inf), 0,sizeof(frame_info_t)); - q->slot[i]->rdy = 0; + mcast_clear_slot( q->slot[i] ); } } - //@ is there something todo -// if( mcast_poll_timeout( v, 1000 ) == 0 ) -// return NULL; - while( (n = mcast_recv_packet_frame(v) ) ) { if( n == 2 ) { @@ -308,18 +305,16 @@ uint8_t *mcast_recv_frame( mcast_receiver *v, int *dw, int *dh, int *dfmt, int * if( q->slot[i]->rdy == 1 && q->slot[i]->hdr.usec > t1) { full_frame = 1; d_slot = i; + break; } } - /* - */ + //@ return newest full frame if( full_frame ) { packet_buffer_t *pb = q->slot[d_slot]; - *dw = pb->inf.width; - *dh = pb->inf.height; - *dfmt=pb->inf.fmt; - *len =pb->len; - return pb->buf; + *len = pb->len; + *hdrlen = 0; + return q->buf; } return NULL; @@ -338,13 +333,12 @@ void mcast_close_receiver( mcast_receiver *v ) if( q ) { for( i = 0; i < PACKET_SLOTS; i ++ ){ packet_buffer_t *r = q->slot[i]; - if( r->buf ) { - free(r->buf); - } free(r); } free(q->slot); free(q); } + free(v); + v = NULL; } } diff --git a/veejay-current/veejay-server/libvjnet/mcastreceiver.h b/veejay-current/veejay-server/libvjnet/mcastreceiver.h index 19e53580..428e04de 100644 --- a/veejay-current/veejay-server/libvjnet/mcastreceiver.h +++ b/veejay-current/veejay-server/libvjnet/mcastreceiver.h @@ -19,41 +19,22 @@ */ #ifndef MCASTRECEIVER_H #define MCASTRECEIVER_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include typedef struct { char *group; int addr_len; - struct sockaddr_in addr; + struct sockaddr_in addr; int port; int sock_fd; - int recv_buf_size; uint8_t *space; - int space_len; - void *next; + int space_len; + void *next; } mcast_receiver; mcast_receiver *mcast_new_receiver( const char *group_name, int port ); - -int mcast_poll( mcast_receiver *v ); - -int mcast_recv( mcast_receiver *v, void *dst, int len ); - -uint8_t *mcast_recv_frame( mcast_receiver *v, int *dw, int *dh, int *dfmt, int *len ); - -void mcast_close_receiver( mcast_receiver *v ); - -int mcast_receiver_set_peer( mcast_receiver *v, const char *hostname ); - +int mcast_poll( mcast_receiver *v ); +int mcast_recv( mcast_receiver *v, void *dst, int len ); +uint8_t *mcast_recv_frame( mcast_receiver *v, int *len, int *hdrlen, uint8_t *recvbuf ); +void mcast_close_receiver( mcast_receiver *v ); +int mcast_receiver_set_peer( mcast_receiver *v, const char *hostname ); #endif diff --git a/veejay-current/veejay-server/libvjnet/mcastsender.c b/veejay-current/veejay-server/libvjnet/mcastsender.c index 7aa3f14b..190138de 100644 --- a/veejay-current/veejay-server/libvjnet/mcastsender.c +++ b/veejay-current/veejay-server/libvjnet/mcastsender.c @@ -22,13 +22,21 @@ #include #include #include -#include -#include "mcastsender.h" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include "packet.h" +#include "mcastsender.h" static void print_error(char *msg) { @@ -46,7 +54,6 @@ mcast_sender *mcast_new_sender( const char *group_name ) v->addr.sin_port = htons( 0 ); v->addr_len = sizeof( struct sockaddr_in ); v->sock_fd = socket( AF_INET, SOCK_DGRAM, 0 ); - v->send_buf_size = 240 * 1024; v->stamp = 1; if( v->sock_fd == -1 ) { @@ -78,15 +85,6 @@ mcast_sender *mcast_new_sender( const char *group_name ) return NULL; } -// if( setsockopt( v->sock_fd, SOL_SOCKET, SO_SNDBUF, &(v->send_buf_size), sizeof(int)) < 0 ) -// { -// print_error("so_sndbuf"); -// } - -// if( getsockopt( v->sock_fd, SOL_SOCKET, SO_SNDBUF, &(v->send_buf_size), -// sizeof(int)) < 0 ) -// print_error(); - char *eth = getenv("VEEJAY_MCAST_INTERFACE"); if( eth != NULL ) { mcast_set_interface(v, eth ); @@ -127,33 +125,19 @@ void mcast_set_interface( mcast_sender *v, const char *interface ) if( setsockopt( v->sock_fd, IPPROTO_IP, IP_MULTICAST_IF, &if_addr, sizeof(if_addr) ) < 0 ) print_error("IP_MULTICAST_IF"); + else + veejay_msg(VEEJAY_MSG_INFO, "Multicast interface set to %s", interface ); } int mcast_send( mcast_sender *v, const void *buf, int len, int port_num ) { - int n ; v->addr.sin_port = htons( port_num ); v->addr.sin_family = AF_INET; - n = sendto( v->sock_fd, buf, len, 0, (struct sockaddr*) &(v->addr), v->addr_len ); - - if( n == -1 ) - { - char msg[100]; - sprintf(msg, "mcast send -> %d", - port_num ); - print_error(msg); - } - - return n; + return sendto( v->sock_fd, buf, len, 0, (struct sockaddr*) &(v->addr), v->addr_len ); } -static void stamp_reset( mcast_sender *v ) -{ - v->stamp = 1; -} - -static uint32_t stamp_make( mcast_sender *v ) +static long stamp_make( mcast_sender *v ) { v->stamp ++; return v->stamp; @@ -163,35 +147,28 @@ int mcast_send_frame( mcast_sender *v, const VJFrame *frame, uint8_t *buf, int total_len, long ms,int port_num, int mode) { int i; - packet_header_t header = packet_construct_header( 1 ); - frame_info_t info; - info.fmt = frame->format; - info.width = frame->width; - info.height = frame->height; - info.len = total_len; - info.mode = mode; - uint32_t frame_num = stamp_make(v); - - header.timeout = ms * 1000; - header.usec = frame_num; - - uint8_t chunk[PACKET_PAYLOAD_SIZE]; int res = 0; + uint8_t chunk[PACKET_PAYLOAD_SIZE]; + long frame_num = stamp_make(v); + + packet_header_t header = packet_construct_header( 1 ); + + header.timeout = (uint32_t) (ms * 1000); + header.usec = frame_num; veejay_memset( chunk, 0,sizeof(chunk)); //@ If we can send in a single packet: if( total_len <= CHUNK_SIZE ) { - header.seq_num = 0; header.flag = 1; header.length = 1; - packet_put_padded_data( &header,&info, chunk, buf, total_len); + header.seq_num = 0; header.length = 1; + packet_put_padded_data( &header,chunk, buf, total_len); res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); if(res <= 0 ) return -1; return 1; } - int pred_chunks = (total_len / CHUNK_SIZE); int bytes_left = (total_len % CHUNK_SIZE); @@ -201,8 +178,8 @@ int mcast_send_frame( mcast_sender *v, const VJFrame *frame, { const uint8_t *data = buf + (i * CHUNK_SIZE); header.seq_num = i; - header.flag = 1; - packet_put_data( &header, &info, chunk, data ); + packet_put_data( &header, chunk, data ); + res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); if(res <= 0 ) { @@ -212,22 +189,18 @@ int mcast_send_frame( mcast_sender *v, const VJFrame *frame, if( bytes_left ) { - i = header.length-1; + i = header.length - 1; header.seq_num = i; - header.flag = 1; - int bytes_done = packet_put_padded_data( &header, &info, chunk, buf + (i * CHUNK_SIZE), bytes_left ); + int bytes_done = packet_put_padded_data( &header, chunk, buf + (i * CHUNK_SIZE), bytes_left ); + veejay_memset( chunk + bytes_done, 0, (PACKET_PAYLOAD_SIZE-bytes_done)); res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); if( res <= 0 ) { - veejay_msg(0, "Unable to send last packet"); return -1; } } - if( frame_num == 0xffff ) - stamp_reset(v); - return 1; } @@ -238,5 +211,7 @@ void mcast_close_sender( mcast_sender *v ) close(v->sock_fd); if(v->group) free(v->group); v->group = NULL; + free(v); + v = NULL; } } diff --git a/veejay-current/veejay-server/libvjnet/mcastsender.h b/veejay-current/veejay-server/libvjnet/mcastsender.h index d04fbc45..3db5c2b3 100644 --- a/veejay-current/veejay-server/libvjnet/mcastsender.h +++ b/veejay-current/veejay-server/libvjnet/mcastsender.h @@ -19,36 +19,19 @@ */ #ifndef MCASTSENDER_HH #define MCASTSENDER_HH -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include typedef struct { - char *group; + char *group; int sock_fd; int addr_len; - struct sockaddr_in addr; - int send_buf_size; - uint32_t stamp; + struct sockaddr_in addr; + long stamp; } mcast_sender; mcast_sender *mcast_new_sender( const char *group_name ); -void mcast_set_interface( mcast_sender *s, const char *interface ); - +void mcast_set_interface( mcast_sender *s, const char *interface ); int mcast_send( mcast_sender *s, const void *buf, int len, int port_num ); - int mcast_send_frame( mcast_sender *s, const VJFrame *frame , uint8_t *buf, int total_len,long ms, int port_num ,int mode); - -void mcast_close_sender(mcast_sender *s ); - +void mcast_close_sender(mcast_sender *s ); int mcast_sender_set_peer( mcast_sender *v, const char *hostname ); - #endif diff --git a/veejay-current/veejay-server/libvjnet/packet.c b/veejay-current/veejay-server/libvjnet/packet.c index 20db0f2a..b8fbabdd 100644 --- a/veejay-current/veejay-server/libvjnet/packet.c +++ b/veejay-current/veejay-server/libvjnet/packet.c @@ -1,6 +1,6 @@ /* vjnet - low level network I/O for VeeJay * - * (C) 2005 Niels Elburg + * (C) 2005-2016 Niels Elburg * * * This program is free software; you can redistribute it and/or modify @@ -26,14 +26,8 @@ void packet_dump_header( packet_header_t *h) { - veejay_msg(VEEJAY_MSG_DEBUG, "Flag: %x, Sequence Num %d/%d, Timestamp %x Timeout : %ld", - h->flag, h->seq_num,h->length, h->usec,h->timeout ); -} - -void packet_dump_info( frame_info_t *i ) -{ - veejay_msg(VEEJAY_MSG_DEBUG, "Frame: %dx%d, fmt %d, data_len=%d", - i->width,i->height,i->fmt, i->len ); + veejay_msg(VEEJAY_MSG_DEBUG, "Flag: %x, Sequence Num %d/%d, Timestamp %ld Timeout : %d", + h->seq_num,h->length, h->usec,h->timeout ); } packet_header_t packet_construct_header(uint8_t flag) @@ -41,8 +35,7 @@ packet_header_t packet_construct_header(uint8_t flag) struct timeval tv; gettimeofday(&tv, NULL); packet_header_t header; - header.flag = flag; - header.seq_num = 0; // not set + header.seq_num = 0; header.usec = tv.tv_usec; header.timeout = 0; header.length = 0; @@ -52,8 +45,7 @@ packet_header_t packet_construct_header(uint8_t flag) packet_header_t packet_get_header(const void *data) { packet_header_t h,tmp; - veejay_memcpy( &tmp, data, sizeof(packet_header_t) ); - h.flag = tmp.flag; + veejay_memcpy( &tmp, data, PACKET_HEADER_LENGTH ); h.seq_num = tmp.seq_num; h.length = tmp.length; h.usec = tmp.usec; @@ -61,40 +53,32 @@ packet_header_t packet_get_header(const void *data) return h; } +packet_header_t *packet_get_hdr(const void *data) +{ + return (packet_header_t*) data; +} + int packet_get_data(packet_header_t *h, const void *data, uint8_t *plane ) { - const char *addr = (const char*) data; - size_t len = sizeof(packet_header_t); - len += sizeof( frame_info_t ); - veejay_memcpy( plane , addr + len, CHUNK_SIZE ); + uint8_t *addr = (uint8_t*) data; + veejay_memcpy( plane , addr + PACKET_HEADER_LENGTH, CHUNK_SIZE ); return 1; } -int packet_get_info(frame_info_t *i, const void *data ) +int packet_put_padded_data(packet_header_t *h, void *payload, const uint8_t *plane, int bytes ) { - const char *dst = (const char*) data; - veejay_memcpy(i, dst + sizeof(packet_header_t), sizeof(frame_info_t)); - return 1; -} - -int packet_put_padded_data(packet_header_t *h, frame_info_t *i , void *payload, const uint8_t *plane, int bytes ) -{ - char *dst = (char*) payload; - size_t len = sizeof( packet_header_t ); + uint8_t *dst = (uint8_t*) payload; + size_t len = PACKET_HEADER_LENGTH; veejay_memcpy( dst, h , len ); - veejay_memcpy( dst + len, i , sizeof( frame_info_t )); - len += sizeof(frame_info_t ); veejay_memcpy( dst + len, plane, bytes ); return (len + bytes); } -int packet_put_data(packet_header_t *h, frame_info_t *i , void *payload, const uint8_t *plane ) + +int packet_put_data(packet_header_t *h, void *payload, const uint8_t *plane ) { - size_t len = sizeof( packet_header_t ); - char *dst = (char*) payload; - veejay_memcpy( dst, h , len ); - veejay_memcpy( dst + len, i , sizeof( frame_info_t )); - len += sizeof(frame_info_t ); - veejay_memcpy( dst + len, plane, CHUNK_SIZE ); + uint8_t *dst = (uint8_t*) payload; + veejay_memcpy( dst, h , PACKET_HEADER_LENGTH ); + veejay_memcpy( dst + PACKET_HEADER_LENGTH, plane, CHUNK_SIZE ); return 1; } diff --git a/veejay-current/veejay-server/libvjnet/packet.h b/veejay-current/veejay-server/libvjnet/packet.h index f7928a1e..ceba6f4c 100644 --- a/veejay-current/veejay-server/libvjnet/packet.h +++ b/veejay-current/veejay-server/libvjnet/packet.h @@ -1,6 +1,6 @@ /* vjnet - low level network I/O for VeeJay * - * (C) 2005-2007 Niels Elburg + * (C) 2005-2016 Niels Elburg * * * This program is free software; you can redistribute it and/or modify @@ -36,41 +36,28 @@ Ignoring machine byte order. Fix it yourself typedef struct { - uint8_t flag; - uint8_t seq_num; - uint32_t usec; + uint32_t seq_num; + long usec; uint32_t timeout; - uint8_t length; + uint32_t length; } packet_header_t; -typedef struct -{ - uint16_t width; - uint16_t height; - uint8_t fmt; - uint32_t len; - uint8_t mode; -} frame_info_t; +#define MCAST_PACKET_SIZE 1500 +#define PACKET_HEADER_LENGTH ( sizeof(packet_header_t) ) +#define CHUNK_SIZE ( MCAST_PACKET_SIZE - PACKET_HEADER_LENGTH ) +#define PACKET_PAYLOAD_SIZE ( CHUNK_SIZE + PACKET_HEADER_LENGTH ) -#define PACKET_HEADER_LENGTH ( sizeof(packet_header_t) ) -#define PACKET_APP_HEADER_LENGTH ( sizeof(frame_info_t) ) -#define CHUNK_SIZE ( 1500 - 32 ) -#define PACKET_PAYLOAD_SIZE (CHUNK_SIZE + PACKET_HEADER_LENGTH + PACKET_APP_HEADER_LENGTH ) +packet_header_t packet_construct_header(uint8_t flag); -void packet_dump_header( packet_header_t *h); +packet_header_t packet_get_header(const void *data); -void packet_dump_info( frame_info_t * i ); +packet_header_t *packet_get_hdr(const void *data); -packet_header_t packet_construct_header(uint8_t flag); +int packet_get_data( packet_header_t *h, const void *data, uint8_t *plane); -packet_header_t packet_get_header(const void *data); +int packet_put_data( packet_header_t *h, void *payload, const uint8_t *plane ); -int packet_get_data( packet_header_t *h, const void *data, uint8_t *plane); +int packet_put_padded_data( packet_header_t *h, void *payload, const uint8_t *plane, int bytes ); -int packet_put_data( packet_header_t *h, frame_info_t *i, void *payload, const uint8_t *plane ); - -int packet_put_padded_data( packet_header_t *h, frame_info_t *i, void *payload, const uint8_t *plane, int bytes ); - -int packet_get_info(frame_info_t *i, const void *data ); #endif diff --git a/veejay-current/veejay-server/libvjnet/vj-client.c b/veejay-current/veejay-server/libvjnet/vj-client.c index e6161439..a0f0621f 100644 --- a/veejay-current/veejay-server/libvjnet/vj-client.c +++ b/veejay-current/veejay-server/libvjnet/vj-client.c @@ -1,5 +1,5 @@ /* libvjnet - Linux VeeJay - * (C) 2002-2007 Niels Elburg + * (C) 2002-2016 Niels Elburg * * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -194,9 +195,6 @@ int vj_client_connect(vj_client *v, char *host, char *group_name, int port_id ) mcast_sender_set_peer( v->s , group_name ); v->mcast = 1; -// mcast_receiver_set_peer( v->c[0]->r, group_name); - veejay_msg(VEEJAY_MSG_DEBUG, "Client is interested in packets from group %s : %d, send to %d", - group_name, port_id + VJ_CMD_MCAST , port_id + VJ_CMD_MCAST_IN); return 1; } @@ -213,6 +211,9 @@ int vj_client_link_can_read( vj_client *v, int sock_type ) { int vj_client_poll( vj_client *v, int sock_type ) { + if( v->mcast ) + return mcast_poll( v->r ); + return sock_t_poll( v->fd[sock_type ]); } @@ -237,23 +238,28 @@ static long vj_client_decompress( vj_client *t,uint8_t *in, uint8_t *out, int da * and try to identify which software is sending frames * */ - +#define FRAMEINFO_LENGTH 44 static int vj_client_packet_negotiate( vj_client *v, int *tokens ) { - uint8_t line[44]; - + uint8_t line[64]; veejay_memset( line,0, sizeof(line)); - int plen = sock_t_recv( v->fd[0], line, 44 ); - + + int plen = sock_t_recv( v->fd[0], line, FRAMEINFO_LENGTH ); + if( plen == 0 ) { veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); - return -1; + return 0; } if( plen < 0 ) { - veejay_msg(VEEJAY_MSG_ERROR, "Network I/O Error while reading header: %s", strerror(errno)); - return -1; + veejay_msg(VEEJAY_MSG_ERROR, "Error while reading header: %s", strerror(errno)); + return 0; + } + + if( plen != FRAMEINFO_LENGTH ) { + veejay_msg(VEEJAY_MSG_ERROR, "Error reading frame header, only got %d bytes.", plen ); + return 0; } int n = sscanf( (char*) line, "%04d%04d%04d%08d%08d%08d%08d", @@ -291,6 +297,7 @@ int vj_client_read_frame_header( vj_client *v, int *w, int *h, int *fmt, int *co } if( tokens[0] <= 0 || tokens[1] <= 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Frame packet does not contain any data" ); return 0; } @@ -308,6 +315,36 @@ int vj_client_read_frame_header( vj_client *v, int *w, int *h, int *fmt, int *co return 1; } +int vj_client_read_mcast_data( vj_client *v, int *compr_len, int *stride1, int *stride2, int *stride3, int *w, int *h, int *fmt, uint8_t *dst, int buflen ) +{ + if( v->space == NULL ) { + v->space = vj_calloc( sizeof(uint8_t) * RUP8( buflen )); + if(v->space == NULL) + return 0; + } + + int space_len = 0; + int hdr_len = 0; + uint8_t *space = mcast_recv_frame( v->r, &space_len, &hdr_len, v->space ); + if( space == NULL ) { + free(v->space); + return 0; + } + + int n_tokens = sscanf( (char*) v->space, "%04d%04d%04d%08d%08d%08d%08d",w,h,fmt,compr_len,stride1,stride2,stride3 ); + if( n_tokens != 7 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Frame header error in mcast frame, only parsed %d tokens", n_tokens ); + free(v->space); + return 0; + } + + v->in_width = *w; + v->in_height = *h; + v->in_fmt = *fmt; + + return 1; +} + int vj_client_read_frame_data( vj_client *v, int compr_len, int stride1,int stride2, int stride3, uint8_t *dst ) { int datalen = (compr_len > 0 ? compr_len : stride1+stride2+stride3); @@ -326,6 +363,7 @@ int vj_client_read_frame_data( vj_client *v, int compr_len, int stride1,int stri if( compr_len > 0 ) { int n = sock_t_recv( v->fd[0],v->space,datalen ); + if( n <= 0 ) { if( n == -1 ) { veejay_msg(VEEJAY_MSG_ERROR, "Error '%s' while reading socket", strerror(errno)); @@ -340,11 +378,11 @@ int vj_client_read_frame_data( vj_client *v, int compr_len, int stride1,int stri veejay_msg(VEEJAY_MSG_ERROR, "Broken video packet , got %d out of %d bytes",n, compr_len ); return 0; } - return 2; } else { int n = sock_t_recv( v->fd[0], dst, datalen ); + if( n != (stride1 + stride2 + stride3) ) { return 0; @@ -375,14 +413,15 @@ void vj_client_decompress_frame_data( vj_client *v, uint8_t *dst, int fmt, int w uv_len = y_len; break; } - - //@ decompress YUV buffer - vj_client_decompress( v, v->space, dst, compr_len, y_len, uv_len ,0, stride1,stride2,stride3); + uint8_t *addr = v->space; + + if( v->mcast ) + addr = v->space + FRAMEINFO_LENGTH; + + vj_client_decompress( v, addr, dst, compr_len, y_len, uv_len ,0, stride1,stride2,stride3); } - - uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret ) { uint32_t p[4] = {0, 0,0,0 }; @@ -397,7 +436,6 @@ uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret int result = vj_client_packet_negotiate( v, tokens ); if( result == 0 ) { - veejay_msg(0, "Unable to read frame header."); *ret = -1; return dst; } @@ -502,7 +540,7 @@ uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret if( v->in_fmt == v->cur_fmt && v->cur_width == p[0] && v->cur_height == p[1] ) { *ret = 1; - return dst; + return dst; } *ret = 2; @@ -514,11 +552,17 @@ uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret int vj_client_read_no_wait(vj_client *v, int sock_type, uint8_t *dst, int bytes ) { + if( v->mcast ) + return mcast_recv( v->r, dst, bytes ); + return sock_t_recv( v->fd[ sock_type ], dst, bytes ); } int vj_client_read(vj_client *v, int sock_type, uint8_t *dst, int bytes ) { + if( v->mcast ) + return mcast_recv( v->r, dst, bytes ); + return sock_t_recv( v->fd[ sock_type ], dst, bytes ); } diff --git a/veejay-current/veejay-server/libvjnet/vj-client.h b/veejay-current/veejay-server/libvjnet/vj-client.h index fefa4be4..82eb0176 100644 --- a/veejay-current/veejay-server/libvjnet/vj-client.h +++ b/veejay-current/veejay-server/libvjnet/vj-client.h @@ -78,6 +78,8 @@ int vj_client_window_sizes( int socket_fd, int *r, int *s ); int vj_client_connect_dat(vj_client *v, char *host, int port_id ); +int vj_client_read_mcast_data( vj_client *v, int *compr_len, int *stride1, int *stride2, int *stride3, int *w, int *h, int *fmt, uint8_t *dst, int buflen ); + void vj_client_decompress_frame_data( vj_client *v, uint8_t *dst, int fmt, int w, int h, int compr_len, int stride1, int stride2, int stride3 ); diff --git a/veejay-current/veejay-server/libvjnet/vj-server.c b/veejay-current/veejay-server/libvjnet/vj-server.c index 6b8302a6..b31d2ed0 100644 --- a/veejay-current/veejay-server/libvjnet/vj-server.c +++ b/veejay-current/veejay-server/libvjnet/vj-server.c @@ -23,16 +23,22 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include -#include -#include #include -#include -#include + #define RUP8(num)(((num)+8)&~8) #define __INVALID 0 @@ -426,7 +432,7 @@ vj_server *vj_server_alloc(int port_offset, char *mcast_group_name, int type, si else { veejay_msg(VEEJAY_MSG_DEBUG,"env VEEJAY_NET_TIMEOUT=seconds not set"); } - + if( mcast_group_name != NULL ) { /* setup multicast socket */ vjs->use_mcast = 1; @@ -536,7 +542,7 @@ static int vj_server_send_frame_now( vj_server *vje, int link_id, uint8_t *buf, return 0; } - return total; + return total; } int vj_server_send_frame( vj_server *vje, int link_id, uint8_t *buf, int len, @@ -946,7 +952,8 @@ int vj_server_update( vj_server *vje, int id ) if(!Link[id]->in_use) return 0; - _vj_server_empty_queue(vje, id); + if( Link[id]->pool ) + _vj_server_empty_queue(vje, id); if(!vje->use_mcast) { diff --git a/veejay-current/veejay-server/veejay/liblavplayvj.c b/veejay-current/veejay-server/veejay/liblavplayvj.c index 3a837d59..4b21bc94 100644 --- a/veejay-current/veejay-server/veejay/liblavplayvj.c +++ b/veejay-current/veejay-server/veejay/liblavplayvj.c @@ -918,7 +918,6 @@ static int veejay_screen_update(veejay_t * info ) if( info->settings->mcast_frame_sender && info->settings->use_vims_mcast ) { vj_perform_send_primary_frame_s2(info, 1, info->uc->current_link); - vj_perform_done_s2(info); } vj_perform_get_primary_frame(info,frame); @@ -2657,7 +2656,7 @@ int vj_server_setup(veejay_t * info) } info->vjs[VEEJAY_PORT_MAT] = NULL; - if( info->settings->use_vims_mcast ) //FIXME mcast + if( info->settings->use_vims_mcast ) { info->vjs[VEEJAY_PORT_MAT] = vj_server_alloc(info->uc->port, info->settings->vims_group_name, V_CMD, recv_len ); diff --git a/veejay-current/veejay-server/veejay/veejay.c b/veejay-current/veejay-server/veejay/veejay.c index 98d2ef5a..e70fb2b9 100644 --- a/veejay-current/veejay-server/veejay/veejay.c +++ b/veejay-current/veejay-server/veejay/veejay.c @@ -202,9 +202,9 @@ static void Usage(char *progname) fprintf(stderr, " -p/--port \t\tTCP port to accept/send messages (default: 3490)\n"); fprintf(stderr, - " -M/--multicast-osc \t\tmulticast OSC\n"); + " -M/--multicast-osc \t\tmulticast OSC\n"); fprintf(stderr, - " -T/--multicast-vims \t\tmulticast VIMS\n"); + " -T/--multicast-vims \t\tmulticast VIMS\n"); fprintf(stderr, " -m/--memory \t\tMaximum memory to use for cache (0=disable, default=0 max=100)\n"); fprintf(stderr, @@ -321,15 +321,11 @@ static void Usage(char *progname) #define OUT_OF_RANGE_ERR(val) if(OUT_OF_RANGE(val)) { fprintf(stderr,"\tValue must be 0-100\n"); exit(1); } #define check_val(val,msg) {\ -char *v = strdup(val);\ -if(v==NULL){\ +if(val==NULL){\ fprintf(stderr, " Invalid argument given for %s\n",msg);\ }\ -else\ -{\ -free(v);\ -}\ } + static int set_option(const char *name, char *value) { /* return 1 means error, return 0 means okay */ diff --git a/veejay-current/veejay-server/veejay/vims.h b/veejay-current/veejay-server/veejay/vims.h index 5f47e7a8..df07c765 100644 --- a/veejay-current/veejay-server/veejay/vims.h +++ b/veejay-current/veejay-server/veejay/vims.h @@ -320,6 +320,7 @@ enum { #define VEEJAY_PORT_STA 1 #define VEEJAY_PORT_DAT 3 #define VEEJAY_PORT_MAT 2 +#define VEEJAY_PORT_OSC 6 #define FMT_RGB24 2 #define FMT_RGB32 1 diff --git a/veejay-current/veejay-server/veejay/vj-event.c b/veejay-current/veejay-server/veejay/vj-event.c index c82041b2..546a1a10 100644 --- a/veejay-current/veejay-server/veejay/vj-event.c +++ b/veejay-current/veejay-server/veejay/vj-event.c @@ -1544,18 +1544,20 @@ void vj_event_update_remote(void *ptr) if( v->settings->use_vims_mcast ) { - int res = vj_server_update(v->vjs[VEEJAY_PORT_MAT],0 ); - if(res > 0) - { - v->uc->current_link = 0; - char *buf = NULL; - int len =0; - while( ( buf = vj_server_retrieve_msg( v->vjs[VEEJAY_PORT_MAT], 0, buf,&len )) != NULL ) - { - vj_event_parse_msg( v, buf,len ); + int res = vj_server_poll( v->vjs[VEEJAY_PORT_MAT] ); + if( res > 0 ) { + res = vj_server_update(v->vjs[VEEJAY_PORT_MAT],0 ); + if(res > 0) + { + v->uc->current_link = 0; + char *buf = NULL; + int len =0; + while( ( buf = vj_server_retrieve_msg( v->vjs[VEEJAY_PORT_MAT], 0, buf,&len )) != NULL ) + { + vj_event_parse_msg( v, buf,len ); + } } } - } v->settings->is_dat = 0; @@ -9128,7 +9130,7 @@ void vj_event_send_video_information ( void *ptr, const char format[], va_lis if( SAMPLE_PLAYING(v)) n_frames = sample_max_video_length( v->uc->sample_id ); char *s_print_buf = get_print_buf(200); - snprintf(info_msg,sizeof(info_msg)-1, "%04d %04d %01d %c %02.3f %1d %04d %06ld %02d %03ld %08ld %1d", + snprintf(info_msg,sizeof(info_msg)-1, "%04d %04d %01d %c %02.3f %1d %04d %06ld %02d %03ld %08ld %1d %d", el->video_width, el->video_height, el->video_inter, @@ -9140,7 +9142,8 @@ void vj_event_send_video_information ( void *ptr, const char format[], va_lis el->audio_chans, el->num_video_files, n_frames, - v->audio + v->audio, + v->settings->use_vims_mcast ); sprintf(s_print_buf, "%03zu%s",strlen(info_msg), info_msg); SEND_MSG(v,s_print_buf); diff --git a/veejay-current/veejay-server/veejay/vj-perform.c b/veejay-current/veejay-server/veejay/vj-perform.c index a5973370..a477526b 100644 --- a/veejay-current/veejay-server/veejay/vj-perform.c +++ b/veejay-current/veejay-server/veejay/vj-perform.c @@ -1247,8 +1247,8 @@ void vj_perform_done_s2( veejay_t *info ) { static int vj_perform_compress_primary_frame_s2(veejay_t *info,VJFrame *frame ) { - char info_line[128]; - int data_len = 44; + char info_line[64]; + int data_len = 44; int sp_w = frame->width; int sp_h = frame->height; int sp_uvlen = frame->uv_len; @@ -1285,24 +1285,24 @@ static int vj_perform_compress_primary_frame_s2(veejay_t *info,VJFrame *frame ) planes[1], planes[2] ); - veejay_memcpy( socket_buffer, info_line, 44 ); - + veejay_memcpy( socket_buffer, info_line, data_len ); + if( compr_ok == 0 ) { if(!info->splitter) { - veejay_memcpy( socket_buffer + 44 , frame->data[0], sp_len); - veejay_memcpy( socket_buffer + 44 + sp_len,frame->data[1], sp_uvlen ); - veejay_memcpy( socket_buffer + 44 + sp_len + sp_uvlen,frame->data[2],sp_uvlen ); + veejay_memcpy( socket_buffer + data_len , frame->data[0], sp_len); + veejay_memcpy( socket_buffer + data_len + sp_len,frame->data[1], sp_uvlen ); + veejay_memcpy( socket_buffer + data_len + sp_len + sp_uvlen,frame->data[2],sp_uvlen ); } else { - veejay_memcpy( socket_buffer + 44, frame->data[0], sp_len + sp_uvlen + sp_uvlen); + veejay_memcpy( socket_buffer + data_len, frame->data[0], sp_len + sp_uvlen + sp_uvlen); } - data_len += 16 + sp_len + sp_uvlen + sp_uvlen; + data_len += 16 + sp_len + sp_uvlen + sp_uvlen; // 16 is compression data header } else { - data_len += 16 + planes[0] + planes[1] + planes[2]; + data_len += total; } return data_len; @@ -1352,8 +1352,7 @@ int vj_perform_send_primary_frame_s2(veejay_t *info, int mcast, int to_mcast_lin { for( i = 0; i < VJ_MAX_CONNECTIONS; i++ ) { if( info->rlinks[i] != -1 ) { - if(vj_server_send_frame( info->vjs[id], info->rlinks[i], socket_buffer, data_len, - frame, info->real_fps )<=0) + if(vj_server_send_frame( info->vjs[id], info->rlinks[i], socket_buffer, data_len, frame, info->real_fps )<=0) { _vj_server_del_client( info->vjs[id], info->rlinks[i] ); } @@ -1363,8 +1362,7 @@ int vj_perform_send_primary_frame_s2(veejay_t *info, int mcast, int to_mcast_lin } else { - if(vj_server_send_frame( info->vjs[id], to_mcast_link_id, socket_buffer, data_len, - frame, info->real_fps )<=0) + if(vj_server_send_frame( info->vjs[id], to_mcast_link_id, socket_buffer, data_len, frame, info->real_fps )<=0) { veejay_msg(VEEJAY_MSG_DEBUG, "Error sending multicast frame."); } diff --git a/veejay-current/veejay-utils/src/sayVIMS.c b/veejay-current/veejay-utils/src/sayVIMS.c index 13e282dc..d0a943ad 100644 --- a/veejay-current/veejay-utils/src/sayVIMS.c +++ b/veejay-current/veejay-utils/src/sayVIMS.c @@ -126,15 +126,17 @@ static void reconnect(void) static int vjsend( int cmd, unsigned char *buf ) { /* bad-check if connection is still up */ - int foobar = vj_client_poll(sayvims, V_CMD ); - if( foobar && vj_client_link_can_read(sayvims, V_CMD) ) - { - unsigned char dummy[8]; - /* read one byte will fail if connection is closed */ - /* nb: only vims query messages write something to V_CMD (vims 400-499)*/ - int res = vj_client_read(sayvims, V_CMD, dummy, 1); - if( res <= 0 ) { - reconnect(); + if(!sayvims->mcast) { + int foobar = vj_client_poll(sayvims, V_CMD ); + if( foobar && vj_client_link_can_read(sayvims, V_CMD) ) + { + unsigned char dummy[8]; + /* read one byte will fail if connection is closed */ + /* nb: only vims query messages write something to V_CMD (vims 400-499)*/ + int res = vj_client_read(sayvims, V_CMD, dummy, 1); + if( res <= 0 ) { + reconnect(); + } } }