/* Internal video allocator functions */ static picture_t *VideoBufferNew( filter_t *p_filter ) { const video_format_t *p_fmt = &p_filter->fmt_out.video; picture_t *p_picture = picture_New( p_fmt->i_chroma, p_fmt->i_width, p_fmt->i_height, p_fmt->i_aspect ); if( !p_picture ) msg_Err( p_filter, "Failed to allocate picture" ); return p_picture; }
static picture_t *video_new_buffer( vlc_object_t *p_this, decoder_owner_sys_t *p_sys, es_format_t *fmt_out ) { if( fmt_out->video.i_width != p_sys->video.i_width || fmt_out->video.i_height != p_sys->video.i_height || fmt_out->video.i_chroma != p_sys->video.i_chroma || fmt_out->video.i_aspect != p_sys->video.i_aspect ) { if( !fmt_out->video.i_sar_num || !fmt_out->video.i_sar_den ) { fmt_out->video.i_sar_num = fmt_out->video.i_aspect * fmt_out->video.i_height; fmt_out->video.i_sar_den = VOUT_ASPECT_FACTOR * fmt_out->video.i_width; } vlc_ureduce( &fmt_out->video.i_sar_num, &fmt_out->video.i_sar_den, fmt_out->video.i_sar_num, fmt_out->video.i_sar_den, 0 ); if( !fmt_out->video.i_visible_width || !fmt_out->video.i_visible_height ) { fmt_out->video.i_visible_width = fmt_out->video.i_width; fmt_out->video.i_visible_height = fmt_out->video.i_height; } fmt_out->video.i_chroma = fmt_out->i_codec; p_sys->video = fmt_out->video; } /* */ fmt_out->video.i_chroma = fmt_out->i_codec; return picture_New( fmt_out->video.i_chroma, fmt_out->video.i_width, fmt_out->video.i_height, fmt_out->video.i_aspect ); }
/***************************************************************************** * Command functions *****************************************************************************/ static int exec_DataSharedMem( filter_t *p_filter, const commandparams_t *p_params, commandparams_t *p_results ) { #if defined(HAVE_SYS_SHM_H) filter_sys_t *p_sys = (filter_sys_t*) p_filter->p_sys; struct shmid_ds shminfo; overlay_t *p_ovl; size_t i_size; VLC_UNUSED(p_results); p_ovl = ListGet( &p_sys->overlays, p_params->i_id ); if( p_ovl == NULL ) { msg_Err( p_filter, "Invalid overlay: %d", p_params->i_id ); return VLC_EGENERIC; } if( shmctl( p_params->i_shmid, IPC_STAT, &shminfo ) == -1 ) { msg_Err( p_filter, "Unable to access shared memory" ); return VLC_EGENERIC; } i_size = shminfo.shm_segsz; if( p_params->fourcc == VLC_CODEC_TEXT ) { char *p_data; if( (p_params->i_height != 1) || (p_params->i_width < 1) ) { msg_Err( p_filter, "Invalid width and/or height. when specifying text height " "must be 1 and width the number of bytes in the string, " "including the null terminator" ); return VLC_EGENERIC; } if( (size_t)p_params->i_width > i_size ) { msg_Err( p_filter, "Insufficient data in shared memory. need %d, got %zu", p_params->i_width, i_size ); return VLC_EGENERIC; } p_ovl->data.p_text = malloc( p_params->i_width ); if( p_ovl->data.p_text == NULL ) { msg_Err( p_filter, "Unable to allocate string storage" ); return VLC_ENOMEM; } video_format_Setup( &p_ovl->format, VLC_CODEC_TEXT, 0, 0, 0, 1 ); p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY ); if( p_data == NULL ) { msg_Err( p_filter, "Unable to attach to shared memory" ); free( p_ovl->data.p_text ); p_ovl->data.p_text = NULL; return VLC_ENOMEM; } memcpy( p_ovl->data.p_text, p_data, p_params->i_width ); shmdt( p_data ); } else { uint8_t *p_data, *p_in; size_t i_neededsize = 0; p_ovl->data.p_pic = picture_New( p_params->fourcc, p_params->i_width, p_params->i_height, 1, 1 ); if( p_ovl->data.p_pic == NULL ) return VLC_ENOMEM; p_ovl->format = p_ovl->data.p_pic->format; for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes; ++i_plane ) { i_neededsize += p_ovl->data.p_pic->p[i_plane].i_visible_lines * p_ovl->data.p_pic->p[i_plane].i_visible_pitch; } if( i_neededsize > i_size ) { msg_Err( p_filter, "Insufficient data in shared memory. need %zu, got %zu", i_neededsize, i_size ); picture_Release( p_ovl->data.p_pic ); p_ovl->data.p_pic = NULL; return VLC_EGENERIC; } p_data = shmat( p_params->i_shmid, NULL, SHM_RDONLY ); if( p_data == NULL ) { msg_Err( p_filter, "Unable to attach to shared memory" ); picture_Release( p_ovl->data.p_pic ); p_ovl->data.p_pic = NULL; return VLC_ENOMEM; } p_in = p_data; for( size_t i_plane = 0; i_plane < (size_t)p_ovl->data.p_pic->i_planes; ++i_plane ) { uint8_t *p_out = p_ovl->data.p_pic->p[i_plane].p_pixels; for( size_t i_line = 0; i_line < (size_t)p_ovl->data.p_pic->p[i_plane].i_visible_lines; ++i_line ) { memcpy( p_out, p_in, p_ovl->data.p_pic->p[i_plane].i_visible_pitch ); p_out += p_ovl->data.p_pic->p[i_plane].i_pitch; p_in += p_ovl->data.p_pic->p[i_plane].i_visible_pitch; } } shmdt( p_data ); } p_sys->b_updated = p_ovl->b_active; return VLC_SUCCESS; #else VLC_UNUSED(p_params); VLC_UNUSED(p_results); msg_Err( p_filter, "system doesn't support shared memory" ); return VLC_EGENERIC; #endif }
static int Init( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; const video_format_t *p_fmti = &p_filter->fmt_in.video; video_format_t *p_fmto = &p_filter->fmt_out.video; if( IsFmtSimilar( p_fmti, &p_sys->fmt_in ) && IsFmtSimilar( p_fmto, &p_sys->fmt_out ) && p_sys->ctx ) { return VLC_SUCCESS; } Clean( p_filter ); /* Init with new parameters */ ScalerConfiguration cfg; if( GetParameters( &cfg, p_fmti, p_fmto, p_sys->i_sws_flags ) ) { msg_Err( p_filter, "format not supported" ); return VLC_EGENERIC; } if( p_fmti->i_width <= 0 || p_fmto->i_width <= 0 ) { msg_Err( p_filter, "0 width not supported" ); return VLC_EGENERIC; } /* swscale does not like too small width */ p_sys->i_extend_factor = 1; while( __MIN( p_fmti->i_width, p_fmto->i_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH) p_sys->i_extend_factor++; const unsigned i_fmti_width = p_fmti->i_width * p_sys->i_extend_factor; const unsigned i_fmto_width = p_fmto->i_width * p_sys->i_extend_factor; for( int n = 0; n < (cfg.b_has_a ? 2 : 1); n++ ) { const int i_fmti = n == 0 ? cfg.i_fmti : PIX_FMT_GRAY8; const int i_fmto = n == 0 ? cfg.i_fmto : PIX_FMT_GRAY8; struct SwsContext *ctx; ctx = sws_getContext( i_fmti_width, p_fmti->i_height, i_fmti, i_fmto_width, p_fmto->i_height, i_fmto, cfg.i_sws_flags | p_sys->i_cpu_mask, p_sys->p_src_filter, p_sys->p_dst_filter, 0 ); if( n == 0 ) p_sys->ctx = ctx; else p_sys->ctxA = ctx; } if( p_sys->ctxA ) { p_sys->p_src_a = picture_New( VLC_CODEC_GREY, i_fmti_width, p_fmti->i_height, 0, 1 ); p_sys->p_dst_a = picture_New( VLC_CODEC_GREY, i_fmto_width, p_fmto->i_height, 0, 1 ); } if( p_sys->i_extend_factor != 1 ) { p_sys->p_src_e = picture_New( p_fmti->i_chroma, i_fmti_width, p_fmti->i_height, 0, 1 ); p_sys->p_dst_e = picture_New( p_fmto->i_chroma, i_fmto_width, p_fmto->i_height, 0, 1 ); if( p_sys->p_src_e ) memset( p_sys->p_src_e->p[0].p_pixels, 0, p_sys->p_src_e->p[0].i_pitch * p_sys->p_src_e->p[0].i_lines ); if( p_sys->p_dst_e ) memset( p_sys->p_dst_e->p[0].p_pixels, 0, p_sys->p_dst_e->p[0].i_pitch * p_sys->p_dst_e->p[0].i_lines ); } if( !p_sys->ctx || ( cfg.b_has_a && ( !p_sys->ctxA || !p_sys->p_src_a || !p_sys->p_dst_a ) ) || ( p_sys->i_extend_factor != 1 && ( !p_sys->p_src_e || !p_sys->p_dst_e ) ) ) { msg_Err( p_filter, "could not init SwScaler and/or allocate memory" ); Clean( p_filter ); return VLC_EGENERIC; } p_sys->b_add_a = cfg.b_add_a; p_sys->b_copy = cfg.b_copy; p_sys->fmt_in = *p_fmti; p_sys->fmt_out = *p_fmto; p_sys->b_swap_uvi = cfg.b_swap_uvi; p_sys->b_swap_uvo = cfg.b_swap_uvo; video_format_ScaleCropAr( p_fmto, p_fmti ); #if 0 msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s extend by %d", p_fmti->i_width, p_fmti->i_height, (char *)&p_fmti->i_chroma, p_fmto->i_width, p_fmto->i_height, (char *)&p_fmto->i_chroma, p_sys->i_extend_factor ); #endif return VLC_SUCCESS; }
/***************************************************************************** * LoadImage: creates and returns the bar graph image *****************************************************************************/ static picture_t *LoadImage( vlc_object_t *p_this, int nbChannels, int* i_values, int scale, int alarm, int barWidth) { VLC_UNUSED(p_this); picture_t *p_pic; int i,j; int i_width = 0; int i_line; int moinsTrois, moinsCinq, moinsSept, moinsDix, moinsVingt; if (nbChannels == 0) { i_width = 20; } else { i_width = 2 * nbChannels * barWidth + 10; } moinsTrois = 0.71*scale + 20; moinsCinq = 0.56*scale + 20; moinsSept = 0.45*scale + 20; moinsDix = 0.32*scale + 20; moinsVingt = 0.1*scale + 20; p_pic = picture_New(VLC_FOURCC('Y','U','V','A'), i_width+20, scale+30, 1, 1); // blacken the whole picture for( i = 0 ; i < p_pic->i_planes ; i++ ) { memset( p_pic->p[i].p_pixels, 0x00, p_pic->p[i].i_visible_lines * p_pic->p[i].i_pitch ); } // side bar for ( i_line = 20; i_line < scale+20; i_line++ ) { #define DrawPointsBlack(a,b) {\ for (i=a; i<b; i++) {\ *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 0x00; \ *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 128; \ *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 128; \ *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; \ }\ } #define DrawPointsWhite(a,b) {\ for (i=a; i<b; i++) {\ *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 0xFF;\ *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 128;\ *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 128;\ *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; \ }\ } // vertical line DrawPointsBlack(20,22); DrawPointsWhite(22,24); // -3dB if (i_line == moinsTrois - 2) { // 3 DrawPointsBlack(16,19); } if (i_line == moinsTrois - 1) { // 3 DrawPointsBlack(18,19); // limit DrawPointsWhite(24,27); } if (i_line == moinsTrois) { // 3 DrawPointsBlack(16,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsTrois + 1) { // 3 DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsTrois + 2) { // 3 DrawPointsBlack(16,19); } // -5dB if (i_line == moinsCinq - 2) { // 5 DrawPointsBlack(16,19); } if (i_line == moinsCinq - 1) { // 5 DrawPointsBlack(18,19); // limit DrawPointsWhite(24,27); } if (i_line == moinsCinq) { // 5 DrawPointsBlack(16,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsCinq + 1) { // 5 DrawPointsBlack(16,17); // limit DrawPointsBlack(24,27); } if (i_line == moinsCinq + 2) { // 5 DrawPointsBlack(16,19); } // -7dB if (i_line == moinsSept - 2) { // 7 DrawPointsBlack(18,19); } if (i_line == moinsSept - 1) { // 7 DrawPointsBlack(18,19); // limit DrawPointsWhite(24,27); } if (i_line == moinsSept) { // 7 DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsSept + 1) { // 7 DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsSept + 2) { // 7 DrawPointsBlack(16,19); } // -10dB if (i_line == moinsDix - 2) { // 1 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,19); } if (i_line == moinsDix - 1) { // 1 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsWhite(24,27); } if (i_line == moinsDix) { // 1 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsDix + 1) { // 1 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsDix + 2) { // 1 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,19); } // -20dB if (i_line == moinsVingt - 2) { // 2 DrawPointsBlack(12,15); // 0 DrawPointsBlack(16,19); } if (i_line == moinsVingt - 1) { // 2 DrawPointsBlack(12,13); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsWhite(24,27); } if (i_line == moinsVingt) { // 2 DrawPointsBlack(12,15); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsVingt + 1) { // 2 DrawPointsBlack(14,15); // 0 DrawPointsBlack(16,17); DrawPointsBlack(18,19); // limit DrawPointsBlack(24,27); } if (i_line == moinsVingt + 2) { // 2 DrawPointsBlack(12,15); // 0 DrawPointsBlack(16,19); } } // draw the bars and channel indicators for (i=0; i<nbChannels; i++) { for( j = barWidth+20 ; j < 2*barWidth+20; j++) { // channel indicators for ( i_line = 12; i_line < 18; i_line++ ) { // white *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + ( (2*i*barWidth)+j ) ) = 255; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + ( (2*i*barWidth)+j ) ) = 128; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + ( (2*i*barWidth)+j ) ) = 128; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + ( (2*i*barWidth)+j )) = 0xFF; } // bars for( i_line = 20; i_line < i_values[i]+20; i_line++ ) { if (i_line < moinsDix) { // green if < -10 dB *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + ( (2*i*barWidth)+j ) ) = 150; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + ( (2*i*barWidth)+j ) ) = 44; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + ( (2*i*barWidth)+j ) ) = 21; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + ( (2*i*barWidth)+j )) = 0xFF; } else if (i_line < moinsTrois) { // yellow if > -10dB and < -3dB *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + ( (2*i*barWidth)+j ) ) = 226; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + ( (2*i*barWidth)+j ) ) = 1; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + ( (2*i*barWidth)+j ) ) = 148; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + ( (2*i*barWidth)+j )) = 0xFF; } else { // red if > -3 dB *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + ( (2*i*barWidth)+j ) ) = 76; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + ( (2*i*barWidth)+j ) ) = 85; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + ( (2*i*barWidth)+j ) ) = 0xFF; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + ( (2*i*barWidth)+j )) = 0xFF; } } } } if (alarm) {// draw the alarm square // bottom for ( i_line = 0; i_line < 10; i_line++ ) { for (i=0; i<i_width+20; i++) { *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 76; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 85; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 0xFF; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; } } // top for ( i_line = scale+21; i_line < scale+30; i_line++ ) { for (i=0; i<i_width+20; i++) { *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 76; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 85; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 0xFF; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; } } // sides for ( i_line = 9; i_line < scale+21; i_line++ ) { for (i=0; i<10; i++) { *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 76; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 85; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 0xFF; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; } for (i=i_width+11; i<i_width+20; i++) { *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = 76; *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = 85; *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = 0xFF; *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = 0xFF; } } } return p_pic; }
static void* vnc_worker_thread( void *obj ) { filter_t* p_filter = (filter_t*)obj; filter_sys_t *p_sys = p_filter->p_sys; vlc_thread_t update_thread; int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC worker thread started" ); int fd = vnc_connect( p_filter ); if( fd == -1 ) { msg_Err( p_filter, "Error occurred while handshaking VNC host" ); return NULL; } /* Create an empty picture for VNC the data */ picture_t *pic = picture_New( VLC_CODEC_YUVA, p_sys->i_vnc_width, p_sys->i_vnc_height, 1, 1 ); if( likely(pic != NULL) ) { vlc_mutex_lock( &p_sys->lock ); p_sys->i_socket = fd; p_sys->p_pic = pic; vlc_mutex_unlock( &p_sys->lock ); } else { net_Close( fd ); return NULL; } write_update_request( p_filter, false ); /* create the update request thread */ bool polling = var_InheritBool( p_filter, RMTOSD_CFG "vnc-polling" ); if( polling && vlc_clone( &update_thread, update_request_thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_filter, "cannot spawn VNC update request thread" ); polling = false; } vlc_cleanup_push( polling ? update_thread_cleanup : dummy_cleanup, &update_thread ); /* connection is initialized, now read and handle server messages */ for( ;; ) { rfbServerToClientMsg msg; int i_msgSize; memset( &msg, 0, sizeof(msg) ); vlc_restorecancel (canc); if( !read_exact(p_filter, fd, &msg, 1 ) ) { msg_Err( p_filter, "Error while waiting for next server message"); break; } switch (msg.type) { case rfbFramebufferUpdate: i_msgSize = sz_rfbFramebufferUpdateMsg; break; case rfbSetColourMapEntries: i_msgSize = sz_rfbSetColourMapEntriesMsg; break; case rfbBell: i_msgSize = sz_rfbBellMsg; break; case rfbServerCutText: i_msgSize = sz_rfbServerCutTextMsg; break; case rfbReSizeFrameBuffer: i_msgSize = sz_rfbReSizeFrameBufferMsg; break; default: i_msgSize = 0; msg_Err( p_filter, "Invalid message %u received", msg.type ); break; } if( i_msgSize <= 0 ) break; if( --i_msgSize > 0 ) { if ( !read_exact( p_filter, fd, ((char *)&msg) + 1, i_msgSize ) ) { msg_Err( p_filter, "Error while reading message of type %u", msg.type ); break; } } canc = vlc_savecancel (); process_server_message( p_filter, &msg); } vlc_cleanup_pop(); if( polling ) update_thread_cleanup( &update_thread ); msg_Dbg( p_filter, "VNC message reader thread ended" ); vlc_restorecancel (canc); return NULL; }
static int Init( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; const video_format_t *p_fmti = &p_filter->fmt_in.video; video_format_t *p_fmto = &p_filter->fmt_out.video; if( p_fmti->orientation != p_fmto->orientation ) return VLC_EGENERIC; if( video_format_IsSimilar( p_fmti, &p_sys->fmt_in ) && video_format_IsSimilar( p_fmto, &p_sys->fmt_out ) && p_sys->ctx ) { return VLC_SUCCESS; } Clean( p_filter ); /* Init with new parameters */ ScalerConfiguration cfg; if( GetParameters( &cfg, p_fmti, p_fmto, p_sys->i_sws_flags ) ) { msg_Err( p_filter, "format not supported" ); return VLC_EGENERIC; } if( p_fmti->i_visible_width <= 0 || p_fmti->i_visible_height <= 0 || p_fmto->i_visible_width <= 0 || p_fmto->i_visible_height <= 0 ) { msg_Err( p_filter, "invalid scaling: %ix%i -> %ix%i", p_fmti->i_visible_width, p_fmti->i_visible_height, p_fmto->i_visible_width, p_fmto->i_visible_height); return VLC_EGENERIC; } p_sys->desc_in = vlc_fourcc_GetChromaDescription( p_fmti->i_chroma ); p_sys->desc_out = vlc_fourcc_GetChromaDescription( p_fmto->i_chroma ); if( p_sys->desc_in == NULL || p_sys->desc_out == NULL ) return VLC_EGENERIC; /* swscale does not like too small width */ p_sys->i_extend_factor = 1; while( __MIN( p_fmti->i_visible_width, p_fmto->i_visible_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH) p_sys->i_extend_factor++; const unsigned i_fmti_visible_width = p_fmti->i_visible_width * p_sys->i_extend_factor; const unsigned i_fmto_visible_width = p_fmto->i_visible_width * p_sys->i_extend_factor; for( int n = 0; n < (cfg.b_has_a ? 2 : 1); n++ ) { const int i_fmti = n == 0 ? cfg.i_fmti : PIX_FMT_GRAY8; const int i_fmto = n == 0 ? cfg.i_fmto : PIX_FMT_GRAY8; struct SwsContext *ctx; ctx = sws_getContext( i_fmti_visible_width, p_fmti->i_visible_height, i_fmti, i_fmto_visible_width, p_fmto->i_visible_height, i_fmto, cfg.i_sws_flags | p_sys->i_cpu_mask, p_sys->p_src_filter, p_sys->p_dst_filter, 0 ); if( n == 0 ) p_sys->ctx = ctx; else p_sys->ctxA = ctx; } if( p_sys->ctxA ) { p_sys->p_src_a = picture_New( VLC_CODEC_GREY, i_fmti_visible_width, p_fmti->i_visible_height, 0, 1 ); p_sys->p_dst_a = picture_New( VLC_CODEC_GREY, i_fmto_visible_width, p_fmto->i_visible_height, 0, 1 ); } if( p_sys->i_extend_factor != 1 ) { p_sys->p_src_e = picture_New( p_fmti->i_chroma, i_fmti_visible_width, p_fmti->i_visible_height, 0, 1 ); p_sys->p_dst_e = picture_New( p_fmto->i_chroma, i_fmto_visible_width, p_fmto->i_visible_height, 0, 1 ); if( p_sys->p_src_e ) memset( p_sys->p_src_e->p[0].p_pixels, 0, p_sys->p_src_e->p[0].i_pitch * p_sys->p_src_e->p[0].i_lines ); if( p_sys->p_dst_e ) memset( p_sys->p_dst_e->p[0].p_pixels, 0, p_sys->p_dst_e->p[0].i_pitch * p_sys->p_dst_e->p[0].i_lines ); } if( !p_sys->ctx || ( cfg.b_has_a && ( !p_sys->ctxA || !p_sys->p_src_a || !p_sys->p_dst_a ) ) || ( p_sys->i_extend_factor != 1 && ( !p_sys->p_src_e || !p_sys->p_dst_e ) ) ) { msg_Err( p_filter, "could not init SwScaler and/or allocate memory" ); Clean( p_filter ); return VLC_EGENERIC; } if (p_filter->b_allow_fmt_out_change) { /* * If the transformation is not homothetic we must modify the * aspect ratio of the output format in order to have the * output picture displayed correctly and not stretched * horizontally or vertically. * WARNING: this is a hack, ideally this should not be needed * and the vout should update its video format instead. */ unsigned i_sar_num = p_fmti->i_sar_num * p_fmti->i_visible_width; unsigned i_sar_den = p_fmti->i_sar_den * p_fmto->i_visible_width; vlc_ureduce(&i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 65536); i_sar_num *= p_fmto->i_visible_height; i_sar_den *= p_fmti->i_visible_height; vlc_ureduce(&i_sar_num, &i_sar_den, i_sar_num, i_sar_den, 65536); p_fmto->i_sar_num = i_sar_num; p_fmto->i_sar_den = i_sar_den; } p_sys->b_add_a = cfg.b_add_a; p_sys->b_copy = cfg.b_copy; p_sys->fmt_in = *p_fmti; p_sys->fmt_out = *p_fmto; p_sys->b_swap_uvi = cfg.b_swap_uvi; p_sys->b_swap_uvo = cfg.b_swap_uvo; #if 0 msg_Dbg( p_filter, "%ix%i (%ix%i) chroma: %4.4s -> %ix%i (%ix%i) chroma: %4.4s extend by %d", p_fmti->i_visible_width, p_fmti->i_visible_height, p_fmti->i_width, p_fmti->i_height, (char *)&p_fmti->i_chroma, p_fmto->i_visible_width, p_fmto->i_visible_height, p_fmto->i_width, p_fmto->i_height, (char *)&p_fmto->i_chroma, p_sys->i_extend_factor ); #endif return VLC_SUCCESS; }
static void* vnc_worker_thread( void *obj ) { filter_t* p_filter = (filter_t*)obj; filter_sys_t *p_sys = p_filter->p_sys; vlc_thread_t update_request_thread_handle; int canc = vlc_savecancel (); msg_Dbg( p_filter, "VNC worker thread started" ); if( !open_vnc_connection ( p_filter ) ) { msg_Err( p_filter, "Could not connect to vnc host" ); goto exit; } if( !handshaking ( p_filter ) ) { msg_Err( p_filter, "Error occured while handshaking vnc host" ); goto exit; } p_sys->b_connection_active = true; /* to enable sending key * and mouse events to host */ /* Create an empty picture for VNC the data */ vlc_mutex_lock( &p_sys->lock ); p_sys->p_pic = picture_New( VLC_CODEC_YUVA, p_sys->i_vnc_width, p_sys->i_vnc_height, 1, 1 ); if( !p_sys->p_pic ) { vlc_mutex_unlock( &p_sys->lock ); goto exit; } p_sys->i_vnc_pixels = p_sys->i_vnc_width * p_sys->i_vnc_height; vlc_mutex_unlock( &p_sys->lock ); /* create the update request thread */ if( vlc_clone( &update_request_thread_handle, update_request_thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_filter, "cannot spawn vnc update request thread" ); goto exit; } /* connection is initialized, now read and handle server messages */ vlc_restorecancel (canc); for( ;; ) { rfbServerToClientMsg msg; int i_msgSize; memset( &msg, 0, sizeof(msg) ); if( !read_exact(p_filter, p_sys->i_socket, (char*)&msg, 1 ) ) { msg_Err( p_filter, "Error while waiting for next server message"); break; } switch (msg.type) { case rfbFramebufferUpdate: i_msgSize = sz_rfbFramebufferUpdateMsg; break; case rfbSetColourMapEntries: i_msgSize = sz_rfbSetColourMapEntriesMsg; break; case rfbBell: i_msgSize = sz_rfbBellMsg; break; case rfbServerCutText: i_msgSize = sz_rfbServerCutTextMsg; break; case rfbReSizeFrameBuffer: i_msgSize = sz_rfbReSizeFrameBufferMsg; break; default: i_msgSize = 0; msg_Err( p_filter, "Invalid message %u received", msg.type ); break; } if( i_msgSize <= 0 ) break; if( --i_msgSize > 0 ) { if ( !read_exact( p_filter, p_sys->i_socket, ((char*)&msg)+1, i_msgSize ) ) { msg_Err( p_filter, "Error while reading message of type %u", msg.type ); break; } } canc = vlc_savecancel (); process_server_message( p_filter, &msg); vlc_restorecancel (canc); } canc = vlc_savecancel (); msg_Dbg( p_filter, "joining update_request_thread" ); vlc_cancel( update_request_thread_handle ); vlc_join( update_request_thread_handle, NULL ); msg_Dbg( p_filter, "released update_request_thread" ); exit: vlc_mutex_lock( &p_sys->lock ); p_sys->b_connection_active = false; if (p_sys->i_socket >= 0) net_Close(p_sys->i_socket); if( p_sys->p_pic ) picture_Release( p_sys->p_pic ); /* It will hide the subtitle */ p_sys->b_continue = false; p_sys->b_need_update = true; vlc_mutex_unlock( &p_sys->lock ); msg_Dbg( p_filter, "VNC message reader thread ended" ); vlc_restorecancel (canc); return NULL; }
/***************************************************************************** * Draw: creates and returns the bar graph image *****************************************************************************/ static void Draw(BarGraph_t *b) { int nbChannels = b->nbChannels; int scale = b->scale; int barWidth = b->barWidth; int w = 40; if (nbChannels > 0) w = 2 * nbChannels * barWidth + 30; int h = scale + 30; int level[6]; for (int i = 0; i < 6; i++) level[i] = iec_scale(-(i+1) * 10) * scale + 20; if (b->p_pic) picture_Release(b->p_pic); b->p_pic = picture_New(VLC_FOURCC('Y','U','V','A'), w, h, 1, 1); if (!b->p_pic) return; picture_t *p_pic = b->p_pic; plane_t *p = p_pic->p; for (int i = 0 ; i < p_pic->i_planes ; i++) memset(p[i].p_pixels, 0x00, p[i].i_visible_lines * p[i].i_pitch); Draw2VLines(p, scale, 20, black); Draw2VLines(p, scale, 22, white); static const uint8_t pixmap[6][5] = { { 0x17, 0x15, 0x15, 0x15, 0x17 }, { 0x77, 0x45, 0x75, 0x15, 0x77 }, { 0x77, 0x15, 0x75, 0x15, 0x77 }, { 0x17, 0x15, 0x75, 0x55, 0x57 }, { 0x77, 0x15, 0x75, 0x45, 0x77 }, { 0x77, 0x55, 0x75, 0x45, 0x77 }, }; for (int i = 0; i < 6; i++) { DrawHLines(p, h - 1 - level[i] - 1, 24, white, 1, 3); DrawHLines(p, h - 1 - level[i], 24, black, 2, 3); DrawNumber(p, h, pixmap[i], level[i]); } int minus8 = iec_scale(- 8) * scale + 20; int minus18 = iec_scale(-18) * scale + 20; int *i_values = b->i_values; const uint8_t *indicator_color = b->alarm ? bright_red : black; for (int i = 0; i < nbChannels; i++) { int pi = 30 + i * (5 + barWidth); DrawHLines(p, h - 20 - 1, pi, indicator_color, 8, barWidth); for (int line = 20; line < i_values[i] + 20; line++) { if (line < minus18) DrawHLines(p, h - line - 1, pi, bright_green, 1, barWidth); else if (line < minus8) DrawHLines(p, h - line - 1, pi, bright_yellow, 1, barWidth); else DrawHLines(p, h - line - 1, pi, bright_red, 1, barWidth); } for (int line = i_values[i] + 20; line < scale + 20; line++) { if (line < minus18) DrawHLines(p, h - line - 1, pi, green, 1, barWidth); else if (line < minus8) DrawHLines(p, h - line - 1, pi, yellow, 1, barWidth); else DrawHLines(p, h - line - 1, pi, red, 1, barWidth); } } }
static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *p_buffer ) { sout_stream_sys_t *p_sys = p_stream->p_sys; picture_t *p_pic; if ( (sout_stream_sys_t *)id != p_sys ) { block_ChainRelease( p_buffer ); return VLC_SUCCESS; } while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder, &p_buffer )) ) { picture_t *p_new_pic; if( p_sys->i_height || p_sys->i_width ) { video_format_t fmt_out, fmt_in; memset( &fmt_in, 0, sizeof(video_format_t) ); memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_in = p_sys->p_decoder->fmt_out.video; if( p_sys->i_chroma ) fmt_out.i_chroma = p_sys->i_chroma; else fmt_out.i_chroma = VLC_CODEC_I420; const unsigned i_fmt_in_aspect = (int64_t)VOUT_ASPECT_FACTOR * fmt_in.i_sar_num * fmt_in.i_width / (fmt_in.i_sar_den * fmt_in.i_height); if ( !p_sys->i_height ) { fmt_out.i_width = p_sys->i_width; fmt_out.i_height = (p_sys->i_width * VOUT_ASPECT_FACTOR * p_sys->i_sar_num / p_sys->i_sar_den / i_fmt_in_aspect) & ~0x1; } else if ( !p_sys->i_width ) { fmt_out.i_height = p_sys->i_height; fmt_out.i_width = (p_sys->i_height * i_fmt_in_aspect * p_sys->i_sar_den / p_sys->i_sar_num / VOUT_ASPECT_FACTOR) & ~0x1; } else { fmt_out.i_width = p_sys->i_width; fmt_out.i_height = p_sys->i_height; } fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; p_new_pic = image_Convert( p_sys->p_image, p_pic, &fmt_in, &fmt_out ); if( p_new_pic == NULL ) { msg_Err( p_stream, "image conversion failed" ); picture_Release( p_pic ); continue; } } else { /* TODO: chroma conversion if needed */ p_new_pic = picture_New( p_pic->format.i_chroma, p_pic->format.i_width, p_pic->format.i_height, p_sys->p_decoder->fmt_out.video.i_sar_num, p_sys->p_decoder->fmt_out.video.i_sar_den ); if( !p_new_pic ) { picture_Release( p_pic ); msg_Err( p_stream, "image allocation failed" ); continue; } picture_Copy( p_new_pic, p_pic ); } picture_Release( p_pic ); if( p_sys->p_vf2 ) p_new_pic = filter_chain_VideoFilter( p_sys->p_vf2, p_new_pic ); PushPicture( p_stream, p_new_pic ); } return VLC_SUCCESS; }
/***************************************************************************** * LoadImage: creates and returns the bar graph image *****************************************************************************/ static picture_t *LoadImage( vlc_object_t *p_this, int nbChannels, int* i_values, int scale, int alarm, int barWidth) { VLC_UNUSED(p_this); picture_t *p_pic; int i, j, pi; int i_width = 0; int i_line; int minus8, minus10, minus18, minus20, minus30, minus40, minus50, minus60; if (nbChannels == 0) { i_width = 20; } else { i_width = 2 * nbChannels * barWidth + 10; } minus8 = iec_scale(-8)*scale + 20; minus10 = iec_scale(-10)*scale + 20; minus18 = iec_scale(-18)*scale + 20; minus20 = iec_scale(-20)*scale + 20; minus30 = iec_scale(-30)*scale + 20; minus40 = iec_scale(-40)*scale + 20; minus50 = iec_scale(-50)*scale + 20; minus60 = iec_scale(-60)*scale + 20; p_pic = picture_New(VLC_FOURCC('Y','U','V','A'), i_width+20, scale+30, 1, 1); #define DrawLine(a,b,Y,U,V,A) \ for (i=a; i<b; i++) {\ *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + i ) = Y;\ *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + i ) = U;\ *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + i ) = V;\ *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + i ) = A; \ } #define DrawLineBlack(a,b) DrawLine(a,b,0,128,128,0xFF) #define DrawLineWhite(a,b) DrawLine(a,b,255,128,128,0xFF) // blacken the whole picture for( i = 0 ; i < p_pic->i_planes ; i++ ) { memset( p_pic->p[i].p_pixels, 0x00, p_pic->p[i].i_visible_lines * p_pic->p[i].i_pitch ); } // side bar for ( i_line = 20; i_line < scale+20; i_line++ ) { // vertical line DrawLineBlack(20,22); DrawLineWhite(22,24); // -10dB if (i_line == minus10 - 2) { // 1 DrawLineBlack(14,15); // 0 DrawLineBlack(16,19); } if (i_line == minus10 - 1) { // 1 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); //White } if (i_line == minus10) { // 1 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus10 + 1) { // 1 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus10 + 2) { // 1 DrawLineBlack(14,15); // 0 DrawLineBlack(16,19); } // -20dB if (i_line == minus20 - 2) { // 2 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } if (i_line == minus20 - 1) { // 2 DrawLineBlack(12,13); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); //White } if (i_line == minus20) { // 2 DrawLineBlack(12,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus20 + 1) { // 2 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus20 + 2) { // 2 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } // -30dB if (i_line == minus30 - 2) { // 3 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } if (i_line == minus30 - 1) { // 3 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); //White } if (i_line == minus30) { // 3 DrawLineBlack(12,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus30 + 1) { // 3 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus30 + 2) { // 3 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } // -40dB if (i_line == minus40 - 2) { // 4 DrawLineBlack(14,15); // 0 DrawLineBlack(16,19); } if (i_line == minus40 - 1) { // 4 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); // white } if (i_line == minus40) { // 4 DrawLineBlack(12,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus40 + 1) { // 4 DrawLineBlack(12,13); DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus40 + 2) { // 4 DrawLineBlack(12,13); DrawLineBlack(14,15); // 0 DrawLineBlack(16,19); } // -50dB if (i_line == minus50 - 2) { // 5 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } if (i_line == minus50 - 1) { // 5 DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); //White } if (i_line == minus50) { // 5 DrawLineBlack(12,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus50 + 1) { // 5 DrawLineBlack(12,13); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus50 + 2) { // 2 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } // -60dB if (i_line == minus60 - 2) { // 6 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } if (i_line == minus60 - 1) { // 6 DrawLineBlack(12,13); DrawLineBlack(14,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineWhite(24,27); //White } if (i_line == minus60) { // 6 DrawLineBlack(12,15); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus60 + 1) { // 6 DrawLineBlack(12,13); // 0 DrawLineBlack(16,17); DrawLineBlack(18,19); // limit DrawLineBlack(24,27); } if (i_line == minus60 + 2) { // 6 DrawLineBlack(12,15); // 0 DrawLineBlack(16,19); } } #define drawPoint(offset,y,u,v,a) \ *(p_pic->p[0].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[0].i_pitch + offset ) = y; \ *(p_pic->p[1].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[1].i_pitch + offset ) = u; \ *(p_pic->p[2].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[2].i_pitch + offset ) = v; \ *(p_pic->p[3].p_pixels + (scale + 30 - i_line - 1) * p_pic->p[3].i_pitch + offset ) = a; // draw the bars and channel indicators for (i=0; i<nbChannels; i++) { pi = 25 + ((i+1)*5) + (i*barWidth) ; // 25 separació amb indicador, 5 separació entre barres for( j = pi; j < pi + barWidth; j++) { // channel indicators for ( i_line = 12; i_line < 20; i_line++ ) { if( alarm ) { drawPoint(j,76,85,0xFF,0xFF); // red } else { drawPoint(j,0,128,128,0xFF); // black DrawLine(pi,pf,0xFF,128,128,0xFF); } } // bars for( i_line = 20; i_line < i_values[i]+20; i_line++ ) { if (i_line < minus18) { // green if < -18 dB drawPoint(j,150,44,21,0xFF); //DrawLine(pi,pf,150,44,21,0xFF); } else if (i_line < minus8) { // yellow if > -18dB and < -8dB drawPoint(j,226,1,148,0xFF); //DrawLine(pi,pf,226,1,148,0xFF); } else { // red if > -8 dB drawPoint(j,76,85,0xFF,0xFF); //DrawLine(pi,pf,76,85,255,0xFF); } } // bars no signal for( ; i_line < scale+20; i_line++ ) { if (i_line < minus18) { // green if < -18 dB drawPoint(j,74,85,74,0xFF); //DrawLine(pi,pf,74,85,74,0xFF); } else if (i_line < minus8) { // yellow if > -18dB and < -8dB drawPoint(j,112,64,138,0xFF); //DrawLine(pi,pf,112,64,138,0xFF); } else { // red if > -8 dB drawPoint(j,37,106,191,0xFF); //DrawLine(pi,pf,37,106,191,0xFF); } } } } return p_pic; }