subpicture_t *subpicture_NewFromPicture( vlc_object_t *p_obj, picture_t *p_picture, vlc_fourcc_t i_chroma ) { /* */ video_format_t fmt_in = p_picture->format; /* */ video_format_t fmt_out; fmt_out = fmt_in; fmt_out.i_chroma = i_chroma; /* */ image_handler_t *p_image = image_HandlerCreate( p_obj ); if( !p_image ) return NULL; picture_t *p_pip = image_Convert( p_image, p_picture, &fmt_in, &fmt_out ); image_HandlerDelete( p_image ); if( !p_pip ) return NULL; subpicture_t *p_subpic = subpicture_New( NULL ); if( !p_subpic ) { picture_Release( p_pip ); return NULL; } p_subpic->i_original_picture_width = fmt_out.i_width; p_subpic->i_original_picture_height = fmt_out.i_height; fmt_out.i_sar_num = fmt_out.i_sar_den = 0; p_subpic->p_region = subpicture_region_New( &fmt_out ); if( p_subpic->p_region ) { picture_Release( p_subpic->p_region->p_picture ); p_subpic->p_region->p_picture = p_pip; } else { picture_Release( p_pip ); } return p_subpic; }
/**************************************************************************** * download and resize image located at psz_url ***************************************************************************/ static picture_t *LoadImage( filter_t *p_filter, const char *psz_url ) { filter_sys_t *p_sys = p_filter->p_sys; video_format_t fmt_in; video_format_t fmt_out; picture_t *p_orig; picture_t *p_pic = NULL; image_handler_t *p_handler = image_HandlerCreate( p_filter ); memset( &fmt_in, 0, sizeof(video_format_t) ); memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out.i_chroma = VLC_CODEC_YUVA; p_orig = image_ReadUrl( p_handler, psz_url, &fmt_in, &fmt_out ); if( !p_orig ) { msg_Warn( p_filter, "Unable to read image %s", psz_url ); } else if( p_sys->p_style->i_font_size > 0 ) { fmt_in.i_chroma = VLC_CODEC_YUVA; fmt_in.i_height = p_orig->p[Y_PLANE].i_visible_lines; fmt_in.i_width = p_orig->p[Y_PLANE].i_visible_pitch; fmt_out.i_width = p_orig->p[Y_PLANE].i_visible_pitch *p_sys->p_style->i_font_size/p_orig->p[Y_PLANE].i_visible_lines; fmt_out.i_height = p_sys->p_style->i_font_size; p_pic = image_Convert( p_handler, p_orig, &fmt_in, &fmt_out ); picture_Release( p_orig ); if( !p_pic ) { msg_Warn( p_filter, "Error while converting %s", psz_url ); } } else { p_pic = p_orig; } image_HandlerDelete( p_handler ); return p_pic; }
/** * This function will inject a subpicture into the vout with the provided * picture */ static int VoutSnapshotPip( vout_thread_t *p_vout, image_handler_t *p_image, picture_t *p_pic, const video_format_t *p_fmt_in ) { video_format_t fmt_in = *p_fmt_in; video_format_t fmt_out; picture_t *p_pip; subpicture_t *p_subpic; /* */ memset( &fmt_out, 0, sizeof(fmt_out) ); fmt_out = fmt_in; fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A'); /* */ p_pip = image_Convert( p_image, p_pic, &fmt_in, &fmt_out ); if( !p_pip ) return VLC_EGENERIC; p_subpic = spu_CreateSubpicture( p_vout->p_spu ); if( p_subpic == NULL ) { picture_Release( p_pip ); return VLC_EGENERIC; } p_subpic->i_channel = 0; p_subpic->i_start = mdate(); p_subpic->i_stop = mdate() + 4000000; p_subpic->b_ephemer = true; p_subpic->b_fade = true; p_subpic->i_original_picture_width = fmt_out.i_width * 4; p_subpic->i_original_picture_height = fmt_out.i_height * 4; fmt_out.i_aspect = 0; fmt_out.i_sar_num = fmt_out.i_sar_den = 0; p_subpic->p_region = spu_CreateRegion( p_vout->p_spu, &fmt_out ); if( p_subpic->p_region ) vout_CopyPicture( p_image->p_parent, &p_subpic->p_region->picture, p_pip ); picture_Release( p_pip ); spu_DisplaySubpicture( p_vout->p_spu, p_subpic ); return VLC_SUCCESS; }
/***************************************************************************** * Render: displays previously rendered output ***************************************************************************** * This function send the currently rendered image to Distort image, waits * until it is displayed and switch the two rendering buffers, preparing next * frame. *****************************************************************************/ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) { picture_t *p_outpic; unsigned int w, h; int x,y; uint8_t u,v; picture_t *p_converted; video_format_t fmt_out; memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out.p_palette = NULL; if( !p_pic ) return NULL; p_outpic = filter_NewPicture( p_filter ); if( !p_outpic ) { picture_Release( p_pic ); return NULL; } if( !p_filter->p_sys->p_image ) p_filter->p_sys->p_image = image_HandlerCreate( p_filter ); /* chrominance */ u = p_filter->p_sys->u; v = p_filter->p_sys->v; for( y = 0; y<p_outpic->p[U_PLANE].i_lines; y++) { vlc_memset( p_outpic->p[U_PLANE].p_pixels+y*p_outpic->p[U_PLANE].i_pitch, u, p_outpic->p[U_PLANE].i_pitch ); vlc_memset( p_outpic->p[V_PLANE].p_pixels+y*p_outpic->p[V_PLANE].i_pitch, v, p_outpic->p[V_PLANE].i_pitch ); if( v == 0 && u != 0 ) u --; else if( u == 0xff ) v --; else if( v == 0xff ) u ++; else if( u == 0 ) v ++; } /* luminance */ vlc_memcpy( p_outpic->p[Y_PLANE].p_pixels, p_pic->p[Y_PLANE].p_pixels, p_outpic->p[Y_PLANE].i_lines * p_outpic->p[Y_PLANE].i_pitch ); /* image visualization */ fmt_out = p_filter->fmt_out.video; fmt_out.i_width = p_filter->fmt_out.video.i_width*p_filter->p_sys->scale/150; fmt_out.i_height = p_filter->fmt_out.video.i_height*p_filter->p_sys->scale/150; p_converted = image_Convert( p_filter->p_sys->p_image, p_pic, &(p_pic->format), &fmt_out ); if( p_converted ) { #define copyimage( plane, b ) \ for( y=0; y<p_converted->p[plane].i_visible_lines; y++) { \ for( x=0; x<p_converted->p[plane].i_visible_pitch; x++) { \ int nx, ny; \ if( p_filter->p_sys->yinc == 1 ) \ ny= y; \ else \ ny = p_converted->p[plane].i_visible_lines-y; \ if( p_filter->p_sys->xinc == 1 ) \ nx = x; \ else \ nx = p_converted->p[plane].i_visible_pitch-x; \ p_outpic->p[plane].p_pixels[(p_filter->p_sys->x*b+nx)+(ny+p_filter->p_sys->y*b)*p_outpic->p[plane].i_pitch ] = p_converted->p[plane].p_pixels[y*p_converted->p[plane].i_pitch+x]; \ } } copyimage( Y_PLANE, 2 ); copyimage( U_PLANE, 1 ); copyimage( V_PLANE, 1 ); #undef copyimage picture_Release( p_converted ); } else { msg_Err( p_filter, "Image scaling failed miserably." ); } p_filter->p_sys->x += p_filter->p_sys->xinc; p_filter->p_sys->y += p_filter->p_sys->yinc; p_filter->p_sys->scale += p_filter->p_sys->scaleinc; if( p_filter->p_sys->scale >= 50 ) p_filter->p_sys->scaleinc = -1; if( p_filter->p_sys->scale <= 1 ) p_filter->p_sys->scaleinc = 1; w = p_filter->fmt_out.video.i_width*p_filter->p_sys->scale/150; h = p_filter->fmt_out.video.i_height*p_filter->p_sys->scale/150; if( p_filter->p_sys->x*2 + w >= p_filter->fmt_out.video.i_width ) p_filter->p_sys->xinc = -1; if( p_filter->p_sys->x <= 0 ) p_filter->p_sys->xinc = 1; if( p_filter->p_sys->x*2 + w >= p_filter->fmt_out.video.i_width ) p_filter->p_sys->x = (p_filter->fmt_out.video.i_width-w)/2; if( p_filter->p_sys->y*2 + h >= p_filter->fmt_out.video.i_height ) p_filter->p_sys->y = (p_filter->fmt_out.video.i_height-h)/2; if( p_filter->p_sys->y*2 + h >= p_filter->fmt_out.video.i_height ) p_filter->p_sys->yinc = -1; if( p_filter->p_sys->y <= 0 ) p_filter->p_sys->yinc = 1; for( y = 0; y< 16; y++ ) { if( p_filter->p_sys->v == 0 && p_filter->p_sys->u != 0 ) p_filter->p_sys->u -= 1; else if( p_filter->p_sys->u == 0xff ) p_filter->p_sys->v -= 1; else if( p_filter->p_sys->v == 0xff ) p_filter->p_sys->u += 1; else if( p_filter->p_sys->u == 0 ) p_filter->p_sys->v += 1; } return CopyInfoAndRelease( p_outpic, p_pic ); }
/***************************************************************************** * Filter *****************************************************************************/ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) { filter_sys_t *p_sys = p_filter->p_sys; bridge_t *p_bridge; subpicture_t *p_spu; int i_index, i_real_index, i_row, i_col; int i_greatest_real_index_used = p_sys->i_order_length - 1; unsigned int col_inner_width, row_inner_height; subpicture_region_t *p_region; subpicture_region_t *p_region_prev = NULL; /* Allocate the subpicture internal data. */ p_spu = filter_NewSubpicture( p_filter ); if( !p_spu ) return NULL; /* Initialize subpicture */ p_spu->i_channel = 0; p_spu->i_start = date; p_spu->i_stop = 0; p_spu->b_ephemer = true; p_spu->i_alpha = p_sys->i_alpha; p_spu->b_absolute = false; vlc_mutex_lock( &p_sys->lock ); vlc_global_lock( VLC_MOSAIC_MUTEX ); p_bridge = GetBridge( p_filter ); if ( p_bridge == NULL ) { vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; } if ( p_sys->i_position == position_offsets ) { /* If we have either too much or not enough offsets, fall-back * to automatic positioning. */ if ( p_sys->i_offsets_length != p_sys->i_order_length ) { msg_Err( p_filter, "Number of specified offsets (%d) does not match number " "of input substreams in mosaic-order (%d), falling back " "to mosaic-position=0", p_sys->i_offsets_length, p_sys->i_order_length ); p_sys->i_position = position_auto; } } if ( p_sys->i_position == position_auto ) { int i_numpics = p_sys->i_order_length; /* keep slots and all */ for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; if ( !p_es->b_empty ) { i_numpics ++; if( p_sys->i_order_length && p_es->psz_id != NULL ) { /* We also want to leave slots for images given in * mosaic-order that are not available in p_vout_picture */ int i; for( i = 0; i < p_sys->i_order_length ; i++ ) { if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) ) { i_numpics--; break; } } } } } p_sys->i_rows = ceil(sqrt( (double)i_numpics )); p_sys->i_cols = ( i_numpics % p_sys->i_rows == 0 ? i_numpics / p_sys->i_rows : i_numpics / p_sys->i_rows + 1 ); } col_inner_width = ( ( p_sys->i_width - ( p_sys->i_cols - 1 ) * p_sys->i_borderw ) / p_sys->i_cols ); row_inner_height = ( ( p_sys->i_height - ( p_sys->i_rows - 1 ) * p_sys->i_borderh ) / p_sys->i_rows ); i_real_index = 0; for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; video_format_t fmt_in, fmt_out; picture_t *p_converted; memset( &fmt_in, 0, sizeof( video_format_t ) ); memset( &fmt_out, 0, sizeof( video_format_t ) ); if ( p_es->b_empty ) continue; while ( p_es->p_picture != NULL && p_es->p_picture->date + p_sys->i_delay < date ) { if ( p_es->p_picture->p_next != NULL ) { picture_t *p_next = p_es->p_picture->p_next; picture_Release( p_es->p_picture ); p_es->p_picture = p_next; } else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY < date ) { /* Display blank */ picture_Release( p_es->p_picture ); p_es->p_picture = NULL; p_es->pp_last = &p_es->p_picture; break; } else { msg_Dbg( p_filter, "too late picture for %s (%"PRId64 ")", p_es->psz_id, date - p_es->p_picture->date - p_sys->i_delay ); break; } } if ( p_es->p_picture == NULL ) continue; if ( p_sys->i_order_length == 0 ) { i_real_index++; } else { int i; for ( i = 0; i <= p_sys->i_order_length; i++ ) { if ( i == p_sys->i_order_length ) break; if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 ) { i_real_index = i; break; } } if ( i == p_sys->i_order_length ) i_real_index = ++i_greatest_real_index_used; } i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows; i_col = i_real_index % p_sys->i_cols ; if ( !p_sys->b_keep ) { /* Convert the images */ fmt_in.i_chroma = p_es->p_picture->format.i_chroma; fmt_in.i_height = p_es->p_picture->format.i_height; fmt_in.i_width = p_es->p_picture->format.i_width; if( fmt_in.i_chroma == VLC_CODEC_YUVA || fmt_in.i_chroma == VLC_CODEC_RGBA ) fmt_out.i_chroma = VLC_CODEC_YUVA; else fmt_out.i_chroma = VLC_CODEC_I420; fmt_out.i_width = col_inner_width; fmt_out.i_height = row_inner_height; if( p_sys->b_ar ) /* keep aspect ratio */ { if( (float)fmt_out.i_width / (float)fmt_out.i_height > (float)fmt_in.i_width / (float)fmt_in.i_height ) { fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width ) / fmt_in.i_height; } else { fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height ) / fmt_in.i_width; } } fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; p_converted = image_Convert( p_sys->p_image, p_es->p_picture, &fmt_in, &fmt_out ); if( !p_converted ) { msg_Warn( p_filter, "image resizing and chroma conversion failed" ); continue; } } else { p_converted = p_es->p_picture; fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width; fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height; fmt_in.i_chroma = fmt_out.i_chroma = p_converted->format.i_chroma; fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; } p_region = subpicture_region_New( &fmt_out ); /* FIXME the copy is probably not needed anymore */ if( p_region ) picture_Copy( p_region->p_picture, p_converted ); if( !p_sys->b_keep ) picture_Release( p_converted ); if( !p_region ) { msg_Err( p_filter, "cannot allocate SPU region" ); p_filter->pf_sub_buffer_del( p_filter, p_spu ); vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; } if( p_es->i_x >= 0 && p_es->i_y >= 0 ) { p_region->i_x = p_es->i_x; p_region->i_y = p_es->i_y; } else if( p_sys->i_position == position_offsets ) { p_region->i_x = p_sys->pi_x_offsets[i_real_index]; p_region->i_y = p_sys->pi_y_offsets[i_real_index]; } else { if( fmt_out.i_width > col_inner_width || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's larger than the rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols; } else { /* center the video in the dedicated rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols + ( col_inner_width - fmt_out.i_width ) / 2; } if( fmt_out.i_height > row_inner_height || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's taller than the rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows; } else { /* center the video in the dedicated rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows + ( row_inner_height - fmt_out.i_height ) / 2; } } p_region->i_align = p_sys->i_align; p_region->i_alpha = p_es->i_alpha; if( p_region_prev == NULL ) { p_spu->p_region = p_region; } else { p_region_prev->p_next = p_region; } p_region_prev = p_region; } vlc_global_unlock( VLC_MOSAIC_MUTEX ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; }
/***************************************************************************** * Filter: displays previously rendered output ***************************************************************************** * This function send the currently rendered image to the internal opencv * filter for processing. *****************************************************************************/ static picture_t* Filter( filter_t* p_filter, picture_t* p_pic ) { picture_t* p_outpic = filter_NewPicture( p_filter ); if( p_outpic == NULL ) { msg_Err( p_filter, "couldn't get a p_outpic!" ); picture_Release( p_pic ); return NULL; } video_format_t fmt_out; // Make a copy if we want to show the original input if (p_filter->p_sys->i_wrapper_output == VINPUT) picture_Copy( p_outpic, p_pic ); VlcPictureToIplImage( p_filter, p_pic ); // Pass the image (as a pointer to the first IplImage*) to the // internal OpenCV filter for processing. p_filter->p_sys->p_opencv->pf_video_filter( p_filter->p_sys->p_opencv, (picture_t*)&(p_filter->p_sys->p_cv_image[0]) ); if(p_filter->p_sys->i_wrapper_output == PROCESSED) { // Processed video if( (p_filter->p_sys->p_proc_image) && (p_filter->p_sys->p_proc_image->i_planes > 0) && (p_filter->p_sys->i_internal_chroma != CINPUT) ) { //p_filter->p_sys->p_proc_image->format.i_chroma = VLC_CODEC_RGB24; memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_out = p_pic->format; //picture_Release( p_outpic ); /* * We have to copy out the image from image_Convert(), otherwise * you leak pictures for some reason: * main video output error: pictures leaked, trying to workaround */ picture_t* p_outpic_tmp = image_Convert( p_filter->p_sys->p_image, p_filter->p_sys->p_proc_image, &(p_filter->p_sys->p_proc_image->format), &fmt_out ); picture_CopyPixels( p_outpic, p_outpic_tmp ); CopyInfoAndRelease( p_outpic, p_outpic_tmp ); } else if( p_filter->p_sys->i_internal_chroma == CINPUT ) { picture_CopyPixels( p_outpic, p_filter->p_sys->p_proc_image ); picture_CopyProperties( p_outpic, p_filter->p_sys->p_proc_image ); } } ReleaseImages( p_filter ); picture_Release( p_pic ); #ifndef NDEBUG msg_Dbg( p_filter, "Filter() done" ); #endif if( p_filter->p_sys->i_wrapper_output != NONE ) { return p_outpic; } else { // NONE picture_Release( p_outpic ); return NULL; } }
static int OpenVideo(vlc_object_t *p_this) { vout_display_t *vd = (vout_display_t *)p_this; vout_display_sys_t *sys; struct decklink_sys_t *decklink_sys; vd->sys = sys = (vout_display_sys_t*)malloc(sizeof(*sys)); if (!sys) return VLC_ENOMEM; sys->tenbits = var_InheritBool(p_this, VIDEO_CFG_PREFIX "tenbits"); sys->nosignal_delay = var_InheritInteger(p_this, VIDEO_CFG_PREFIX "nosignal-delay"); sys->pic_nosignal = NULL; decklink_sys = OpenDecklink(vd); if (!decklink_sys) { if (sys->pic_nosignal) picture_Release(sys->pic_nosignal); free(sys); return VLC_EGENERIC; } sys->pool = NULL; vd->fmt.i_chroma = sys->tenbits ? VLC_CODEC_I422_10L /* we will convert to v210 */ : VLC_CODEC_UYVY; //video_format_FixRgb(&(vd->fmt)); vd->fmt.i_width = decklink_sys->i_width; vd->fmt.i_height = decklink_sys->i_height; char *pic_file = var_InheritString(p_this, VIDEO_CFG_PREFIX "nosignal-image"); if (pic_file) { image_handler_t *img = image_HandlerCreate(p_this); if (!img) { msg_Err(p_this, "Could not create image converter"); } else { video_format_t in, dummy; video_format_Init(&in, 0); video_format_Setup(&in, 0, vd->fmt.i_width, vd->fmt.i_height, vd->fmt.i_width, vd->fmt.i_height, 1, 1); video_format_Init(&dummy, 0); picture_t *png = image_ReadUrl(img, pic_file, &dummy, &in); if (png) { msg_Err(p_this, "Converting"); sys->pic_nosignal = image_Convert(img, png, &in, &vd->fmt); picture_Release(png); } image_HandlerDelete(img); } free(pic_file); if (!sys->pic_nosignal) { CloseVideo(p_this); msg_Err(p_this, "Could not create no signal picture"); return VLC_EGENERIC; } } vd->info.has_hide_mouse = true; vd->pool = PoolVideo; vd->prepare = NULL; vd->display = DisplayVideo; vd->control = ControlVideo; vd->manage = NULL; vout_display_SendEventFullscreen(vd, false); return VLC_SUCCESS; }
/***************************************************************************** * VlcPictureToIplImage: Convert picture_t to IplImage ***************************************************************************** * Converts given picture_t into IplImage(s) according to module config. * IplImage(s) are stored in vout_sys_t. *****************************************************************************/ static void VlcPictureToIplImage( filter_t* p_filter, picture_t* p_in ) { int planes = p_in->i_planes; //num input video planes // input video size CvSize sz = cvSize(abs(p_in->format.i_width), abs(p_in->format.i_height)); video_format_t fmt_out; filter_sys_t* p_sys = p_filter->p_sys; memset( &fmt_out, 0, sizeof(video_format_t) ); //do scale / color conversion according to p_sys config if ((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { fmt_out = p_in->format; //calc the scaled video size fmt_out.i_width = p_in->format.i_width * p_sys->f_scale; fmt_out.i_height = p_in->format.i_height * p_sys->f_scale; if (p_sys->i_internal_chroma == RGB) { //rgb2 gives 3 separate planes, this gives 1 interleaved plane //rv24 gives is about 20% faster but gives r&b the wrong way round //and I can't think of an easy way to fix this fmt_out.i_chroma = VLC_CODEC_RGB24; } else if (p_sys->i_internal_chroma == GREY) { //take the I (gray) plane (video seems to commonly be in this fmt so usually the //conversion does nothing) fmt_out.i_chroma = VLC_CODEC_I420; } //convert from the input image p_sys->p_proc_image = image_Convert( p_sys->p_image, p_in, &(p_in->format), &fmt_out ); if (!p_sys->p_proc_image) { msg_Err(p_filter, "can't convert (unsupported formats?), aborting..."); return; } p_sys->p_to_be_freed = p_sys->p_proc_image; //remember this so we can free it later } else //((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { // In theory, you could use the input image without conversion, // but it seems to cause weird picture effects (like repeated // image filtering) and picture leaking. p_sys->p_proc_image = filter_NewPicture( p_filter ); //p_in picture_Copy( p_sys->p_proc_image, p_in ); p_sys->p_to_be_freed = p_sys->p_proc_image; } //Convert to the IplImage array that is to be processed. //If there are multiple planes in p_sys->p_proc_image, then 1 IplImage //is created for each plane. planes = p_sys->p_proc_image->i_planes; p_sys->i_cv_image_size = planes; for( int i = 0; i < planes; i++ ) { sz = cvSize(abs(p_sys->p_proc_image->p[i].i_visible_pitch / p_sys->p_proc_image->p[i].i_pixel_pitch), abs(p_sys->p_proc_image->p[i].i_visible_lines)); p_sys->p_cv_image[i] = cvCreateImageHeader(sz, IPL_DEPTH_8U, p_sys->p_proc_image->p[i].i_pixel_pitch); cvSetData( p_sys->p_cv_image[i], (char*)(p_sys->p_proc_image->p[i].p_pixels), p_sys->p_proc_image->p[i].i_pitch ); } //Hack the above opencv image array into a picture_t so that it can be sent to //another video filter p_sys->hacked_pic.i_planes = planes; p_sys->hacked_pic.format.i_chroma = fmt_out.i_chroma; #ifndef NDEBUG msg_Dbg( p_filter, "VlcPictureToIplImageRgb() completed" ); #endif }
/***************************************************************************** * Filter *****************************************************************************/ static subpicture_t *Filter( filter_t *p_filter, mtime_t date ) { filter_sys_t *p_sys = p_filter->p_sys; bridge_t *p_bridge; subpicture_t *p_spu; int i_index, i_real_index, i_row, i_col; int i_greatest_real_index_used = p_sys->i_order_length - 1; unsigned int col_inner_width, row_inner_height; subpicture_region_t *p_region; subpicture_region_t *p_region_prev = NULL; /* Allocate the subpicture internal data. */ p_spu = p_filter->pf_sub_buffer_new( p_filter ); if( !p_spu ) { return NULL; } /* Initialize subpicture */ p_spu->i_channel = 0; p_spu->i_start = date; p_spu->i_stop = 0; p_spu->b_ephemer = VLC_TRUE; p_spu->i_alpha = p_sys->i_alpha; p_spu->i_flags = p_sys->i_align; p_spu->b_absolute = VLC_FALSE; vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( p_sys->p_lock ); p_bridge = GetBridge( p_filter ); if ( p_bridge == NULL ) { vlc_mutex_unlock( p_sys->p_lock ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; } if ( p_sys->i_position == 0 ) /* use automatic positioning */ { int i_numpics = p_sys->i_order_length; /* keep slots and all */ for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; if ( !p_es->b_empty ) { i_numpics ++; if( p_sys->i_order_length && p_es->psz_id != 0 ) { /* We also want to leave slots for images given in * mosaic-order that are not available in p_vout_picture */ int i; for( i = 0; i < p_sys->i_order_length ; i++ ) { if( !strcmp( p_sys->ppsz_order[i], p_es->psz_id ) ) { i_numpics--; break; } } } } } p_sys->i_rows = ((int)ceil(sqrt( (float)i_numpics ))); p_sys->i_cols = ( i_numpics % p_sys->i_rows == 0 ? i_numpics / p_sys->i_rows : i_numpics / p_sys->i_rows + 1 ); } col_inner_width = ( ( p_sys->i_width - ( p_sys->i_cols - 1 ) * p_sys->i_borderw ) / p_sys->i_cols ); row_inner_height = ( ( p_sys->i_height - ( p_sys->i_rows - 1 ) * p_sys->i_borderh ) / p_sys->i_rows ); i_real_index = 0; for ( i_index = 0; i_index < p_bridge->i_es_num; i_index++ ) { bridged_es_t *p_es = p_bridge->pp_es[i_index]; video_format_t fmt_in = {0}, fmt_out = {0}; picture_t *p_converted; if ( p_es->b_empty ) continue; while ( p_es->p_picture != NULL && p_es->p_picture->date + p_sys->i_delay < date ) { if ( p_es->p_picture->p_next != NULL ) { picture_t *p_next = p_es->p_picture->p_next; p_es->p_picture->pf_release( p_es->p_picture ); p_es->p_picture = p_next; } else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY < date ) { /* Display blank */ p_es->p_picture->pf_release( p_es->p_picture ); p_es->p_picture = NULL; p_es->pp_last = &p_es->p_picture; break; } else { msg_Dbg( p_filter, "too late picture for %s (" I64Fd ")", p_es->psz_id, date - p_es->p_picture->date - p_sys->i_delay ); break; } } if ( p_es->p_picture == NULL ) continue; if ( p_sys->i_order_length == 0 ) { i_real_index++; } else { int i; for ( i = 0; i <= p_sys->i_order_length; i++ ) { if ( i == p_sys->i_order_length ) break; if ( strcmp( p_es->psz_id, p_sys->ppsz_order[i] ) == 0 ) { i_real_index = i; break; } } if ( i == p_sys->i_order_length ) i_real_index = ++i_greatest_real_index_used; } i_row = ( i_real_index / p_sys->i_cols ) % p_sys->i_rows; i_col = i_real_index % p_sys->i_cols ; if ( !p_sys->b_keep ) { /* Convert the images */ fmt_in.i_chroma = p_es->p_picture->format.i_chroma; fmt_in.i_height = p_es->p_picture->format.i_height; fmt_in.i_width = p_es->p_picture->format.i_width; fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A'); fmt_out.i_width = col_inner_width; fmt_out.i_height = row_inner_height; if( p_sys->b_ar ) /* keep aspect ratio */ { if( (float)fmt_out.i_width / (float)fmt_out.i_height > (float)fmt_in.i_width / (float)fmt_in.i_height ) { fmt_out.i_width = ( fmt_out.i_height * fmt_in.i_width ) / fmt_in.i_height; } else { fmt_out.i_height = ( fmt_out.i_width * fmt_in.i_height ) / fmt_in.i_width; } } fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; p_converted = image_Convert( p_sys->p_image, p_es->p_picture, &fmt_in, &fmt_out ); if( !p_converted ) { msg_Warn( p_filter, "image resizing and chroma conversion failed" ); continue; } /* Bluescreen stuff */ if( p_sys->b_bs ) { int i,j; int i_lines = p_converted->p[ A_PLANE ].i_lines; int i_pitch = p_converted->p[ A_PLANE ].i_pitch; uint8_t *p_a = p_converted->p[ A_PLANE ].p_pixels; uint8_t *p_at = malloc( i_lines * i_pitch * sizeof( uint8_t ) ); uint8_t *p_u = p_converted->p[ U_PLANE ].p_pixels; uint8_t *p_v = p_converted->p[ V_PLANE ].p_pixels; uint8_t umin, umax, vmin, vmax; umin = p_sys->i_bsu - p_sys->i_bsut >= 0x00 ? p_sys->i_bsu - p_sys->i_bsut : 0x00; umax = p_sys->i_bsu + p_sys->i_bsut <= 0xff ? p_sys->i_bsu + p_sys->i_bsut : 0xff; vmin = p_sys->i_bsv - p_sys->i_bsvt >= 0x00 ? p_sys->i_bsv - p_sys->i_bsvt : 0x00; vmax = p_sys->i_bsv + p_sys->i_bsvt <= 0xff ? p_sys->i_bsv + p_sys->i_bsvt : 0xff; for( i = 0; i < i_lines*i_pitch; i++ ) { if( p_u[i] < umax && p_u[i] > umin && p_v[i] < vmax && p_v[i] > vmin ) { p_at[i] = 0x00; } else { p_at[i] = 0xff; } } /* Gaussian convolution to make it look cleaner */ memset( p_a, 0, 2 * i_pitch ); for( i = 2; i < i_lines - 2; i++ ) { p_a[i*i_pitch] = 0x00; p_a[i*i_pitch+1] = 0x00; for( j = 2; j < i_pitch - 2; j ++ ) { p_a[i*i_pitch+j] = (uint8_t)(( /* 2 rows up */ ( p_at[(i-2)*i_pitch+j-2]<<1 ) + ( p_at[(i-2)*i_pitch+j-1]<<2 ) + ( p_at[(i-2)*i_pitch+j]<<2 ) + ( p_at[(i-2)*i_pitch+j+1]<<2 ) + ( p_at[(i-2)*i_pitch+j+2]<<1 ) /* 1 row up */ + ( p_at[(i-1)*i_pitch+j-1]<<3 ) + ( p_at[(i-1)*i_pitch+j-2]<<2 ) + ( p_at[(i-1)*i_pitch+j]*12 ) + ( p_at[(i-1)*i_pitch+j+1]<<3 ) + ( p_at[(i-1)*i_pitch+j+2]<<2 ) /* */ + ( p_at[i*i_pitch+j-2]<<2 ) + ( p_at[i*i_pitch+j-1]*12 ) + ( p_at[i*i_pitch+j]<<4 ) + ( p_at[i*i_pitch+j+1]*12 ) + ( p_at[i*i_pitch+j+2]<<2 ) /* 1 row down */ + ( p_at[(i+1)*i_pitch+j-2]<<2 ) + ( p_at[(i+1)*i_pitch+j-1]<<3 ) + ( p_at[(i+1)*i_pitch+j]*12 ) + ( p_at[(i+1)*i_pitch+j+1]<<3 ) + ( p_at[(i+1)*i_pitch+j+2]<<2 ) /* 2 rows down */ + ( p_at[(i+2)*i_pitch+j-2]<<1 ) + ( p_at[(i+2)*i_pitch+j-1]<<2 ) + ( p_at[(i+2)*i_pitch+j]<<2 ) + ( p_at[(i+2)*i_pitch+j+1]<<2 ) + ( p_at[(i+2)*i_pitch+j+2]<<1 ) )/152); if( p_a[i*i_pitch+j] < 0xbf ) p_a[i*i_pitch+j] = 0x00; } } free( p_at ); } } else { p_converted = p_es->p_picture; p_converted->i_refcount++; fmt_in.i_width = fmt_out.i_width = p_converted->format.i_width; fmt_in.i_height = fmt_out.i_height = p_converted->format.i_height; fmt_in.i_chroma = fmt_out.i_chroma = p_converted->format.i_chroma; fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; } p_region = p_spu->pf_make_region( VLC_OBJECT(p_filter), &fmt_out, p_converted ); if( !p_region ) { msg_Err( p_filter, "cannot allocate SPU region" ); p_filter->pf_sub_buffer_del( p_filter, p_spu ); vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( p_sys->p_lock ); return p_spu; } /* HACK ALERT : let's fix the pointers to avoid picture duplication. * This is necessary because p_region->picture is not a pointer * as it ought to be. */ if( !p_sys->b_keep ) { free( p_converted ); } else { /* Keep a pointer to the original picture (and its refcount...). */ p_region->picture.p_sys = (picture_sys_t *)p_converted; p_region->picture.pf_release = MosaicReleasePicture; } if( fmt_out.i_width > col_inner_width || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's larger than the rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols; } else { /* center the video in the dedicated rectangle */ p_region->i_x = p_sys->i_xoffset + i_col * ( p_sys->i_width / p_sys->i_cols ) + ( i_col * p_sys->i_borderw ) / p_sys->i_cols + ( col_inner_width - fmt_out.i_width ) / 2; } if( fmt_out.i_height < row_inner_height || p_sys->b_ar || p_sys->b_keep ) { /* we don't have to center the video since it takes the whole rectangle area or it's taller than the rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows; } else { /* center the video in the dedicated rectangle */ p_region->i_y = p_sys->i_yoffset + i_row * ( p_sys->i_height / p_sys->i_rows ) + ( i_row * p_sys->i_borderh ) / p_sys->i_rows + ( row_inner_height - fmt_out.i_height ) / 2; } if( p_region_prev == NULL ) { p_spu->p_region = p_region; } else { p_region_prev->p_next = p_region; } p_region_prev = p_region; } vlc_mutex_unlock( p_sys->p_lock ); vlc_mutex_unlock( &p_sys->lock ); return p_spu; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; vlc_value_t val; image_handler_t *p_handler; video_format_t fmt_in, fmt_out; picture_t *p_image; char *psz_file, *psz_chroma; bool b_keep_ar; int i_aspect = 0; if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e') ) { return VLC_EGENERIC; } p_dec->p_sys = calloc( 1, sizeof( *p_dec->p_sys ) ); if( !p_dec->p_sys ) return VLC_ENOMEM; psz_file = var_CreateGetNonEmptyStringCommand( p_dec, "fake-file" ); if( !psz_file ) { msg_Err( p_dec, "specify a file with --fake-file=..." ); free( p_dec->p_sys ); return VLC_EGENERIC; } var_AddCallback( p_dec, "fake-file", FakeCallback, p_dec ); memset( &fmt_in, 0, sizeof(fmt_in) ); memset( &fmt_out, 0, sizeof(fmt_out) ); val.i_int = var_CreateGetIntegerCommand( p_dec, "fake-file-reload" ); if( val.i_int > 0) { p_dec->p_sys->b_reload = true; p_dec->p_sys->i_reload = (mtime_t)(val.i_int * 1000000); p_dec->p_sys->i_next = (mtime_t)(p_dec->p_sys->i_reload + mdate()); } var_AddCallback( p_dec, "fake-file-reload", FakeCallback , p_dec ); psz_chroma = var_CreateGetString( p_dec, "fake-chroma" ); fmt_out.i_chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, psz_chroma ); if( !fmt_out.i_chroma ) { msg_Warn( p_dec, "Invalid chroma (%s). Using I420.", psz_chroma ); fmt_out.i_chroma = VLC_CODEC_I420; } free( psz_chroma ); var_Create( p_dec, "fake-keep-ar", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "fake-keep-ar", &val ); b_keep_ar = val.b_bool; var_Create( p_dec, "fake-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_dec, "fake-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_dec, "fake-aspect-ratio", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_dec, "fake-aspect-ratio", &val ); if ( val.psz_string ) { char *psz_parser = strchr( val.psz_string, ':' ); if( psz_parser ) { *psz_parser++ = '\0'; i_aspect = atoi( val.psz_string ) * VOUT_ASPECT_FACTOR / atoi( psz_parser ); } free( val.psz_string ); } if ( !b_keep_ar ) { var_Get( p_dec, "fake-width", &val ); fmt_out.i_width = val.i_int; var_Get( p_dec, "fake-height", &val ); fmt_out.i_height = val.i_int; } p_handler = image_HandlerCreate( p_dec ); p_image = image_ReadUrl( p_handler, psz_file, &fmt_in, &fmt_out ); image_HandlerDelete( p_handler ); if ( p_image == NULL ) { msg_Err( p_dec, "unable to read image file %s", psz_file ); free( psz_file ); free( p_dec->p_sys ); return VLC_EGENERIC; } msg_Dbg( p_dec, "file %s loaded successfully", psz_file ); free( psz_file ); if ( b_keep_ar ) { picture_t *p_old = p_image; int i_width, i_height; var_Get( p_dec, "fake-width", &val ); i_width = val.i_int; var_Get( p_dec, "fake-height", &val ); i_height = val.i_int; if ( i_width && i_height ) { int i_image_ar = fmt_out.i_width * VOUT_ASPECT_FACTOR / fmt_out.i_height; int i_region_ar = i_width * VOUT_ASPECT_FACTOR / i_height; fmt_in = fmt_out; if ( i_aspect == i_image_ar ) { fmt_out.i_width = i_width; fmt_out.i_height = i_height; } else if ( i_image_ar > i_region_ar ) { fmt_out.i_width = i_width; fmt_out.i_height = i_width * VOUT_ASPECT_FACTOR / i_image_ar; i_aspect = i_image_ar; } else { fmt_out.i_height = i_height; fmt_out.i_width = i_height * i_image_ar / VOUT_ASPECT_FACTOR; i_aspect = i_image_ar; } p_handler = image_HandlerCreate( p_dec ); p_image = image_Convert( p_handler, p_old, &fmt_in, &fmt_out ); image_HandlerDelete( p_handler ); if ( p_image == NULL ) { msg_Warn( p_dec, "couldn't load resizing module" ); p_image = p_old; fmt_out = fmt_in; } else { picture_Release( p_old ); } } } if ( i_aspect ) { fmt_out.i_aspect = i_aspect; } else { fmt_out.i_aspect = fmt_out.i_width * VOUT_ASPECT_FACTOR / fmt_out.i_height; } var_Create( p_dec, "fake-deinterlace", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "fake-deinterlace", &val ); if ( val.b_bool ) { picture_t *p_old = p_image; var_Create( p_dec, "fake-deinterlace-module", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Get( p_dec, "fake-deinterlace-module", &val ); p_handler = image_HandlerCreate( p_dec ); p_image = image_Filter( p_handler, p_old, &fmt_out, val.psz_string ); image_HandlerDelete( p_handler ); free( val.psz_string ); if ( p_image == NULL ) { msg_Warn( p_dec, "couldn't load deinterlace module" ); p_image = p_old; } else { picture_Release( p_old ); } } /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = fmt_out.i_chroma; p_dec->fmt_out.video = fmt_out; /* Set callbacks */ p_dec->pf_decode_video = DecodeBlock; p_dec->p_sys->p_image = p_image; vlc_mutex_init( &p_dec->p_sys->lock ); return VLC_SUCCESS; }
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; }
/***************************************************************************** * VlcPictureToIplImage: Convert picture_t to IplImage ***************************************************************************** * Converts given picture_t into IplImage(s) according to module config. * IplImage(s) are stored in vout_sys_t. *****************************************************************************/ static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ) { int planes = p_in->i_planes; //num input video planes // input video size CvSize sz = cvSize(abs(p_in->format.i_width), abs(p_in->format.i_height)); video_format_t fmt_out; clock_t start, finish; //performance measures double duration; int i = 0; vout_sys_t* p_sys = p_vout->p_sys; memset( &fmt_out, 0, sizeof(video_format_t) ); start = clock(); //do scale / color conversion according to p_sys config if ((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { fmt_out = p_in->format; //calc the scaled video size fmt_out.i_width = p_in->format.i_width * p_sys->f_scale; fmt_out.i_height = p_in->format.i_height * p_sys->f_scale; if (p_sys->i_internal_chroma == RGB) { //rgb2 gives 3 separate planes, this gives 1 interleaved plane //rv24 gives is about 20% faster but gives r&b the wrong way round //and I cant think of an easy way to fix this fmt_out.i_chroma = VLC_CODEC_RGB32; } else if (p_sys->i_internal_chroma == GREY) { //take the I (gray) plane (video seems to commonly be in this fmt so usually the //conversion does nothing) fmt_out.i_chroma = VLC_CODEC_I420; } //convert from the input image p_sys->p_proc_image = image_Convert( p_sys->p_image, p_in, &(p_in->format), &fmt_out ); if (!p_sys->p_proc_image) { msg_Err(p_vout, "can't convert (unsupported formats?), aborting..."); return; } p_sys->p_to_be_freed = p_sys->p_proc_image; //remember this so we can free it later } else //((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { //use the input image without conversion p_sys->p_proc_image = p_in; } //Convert to the IplImage array that is to be processed. //If there are multiple planes in p_sys->p_proc_image, then 1 IplImage //is created for each plane. planes = p_sys->p_proc_image->i_planes; p_sys->i_cv_image_size = planes; for ( i = 0; i < planes; i++ ) { sz = cvSize(abs(p_sys->p_proc_image->p[i].i_visible_pitch / p_sys->p_proc_image->p[i].i_pixel_pitch), abs(p_sys->p_proc_image->p[i].i_visible_lines)); p_sys->p_cv_image[i] = cvCreateImageHeader(sz, IPL_DEPTH_8U, p_sys->p_proc_image->p[i].i_pixel_pitch); cvSetData( p_sys->p_cv_image[i], (char*)(p_sys->p_proc_image->p[i].p_pixels), p_sys->p_proc_image->p[i].i_pitch ); } //Hack the above opencv image array into a picture_t so that it can be sent to //another video filter p_sys->hacked_pic.i_planes = planes; p_sys->hacked_pic.format.i_chroma = fmt_out.i_chroma; //calculate duration of conversion finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; if (p_sys->i_verbosity > VERB_WARN) msg_Dbg( p_vout, "VlcPictureToIplImageRgb took %2.4f seconds", duration ); }