| | 44 | * Local prototypes |
|---|
| | 45 | */ |
|---|
| | 46 | static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *, const char *, config_chain_t *, const es_format_t *, const es_format_t * ); |
|---|
| | 47 | static int filter_chain_AppendFromStringInternal( filter_chain_t *, const char * ); |
|---|
| | 48 | static int filter_chain_DeleteFilterInternal( filter_chain_t *, filter_t * ); |
|---|
| | 49 | |
|---|
| | 50 | static int UpdateBufferFunctions( filter_chain_t * ); |
|---|
| | 51 | static picture_t *VideoBufferNew( filter_t * ); |
|---|
| | 52 | static void VideoBufferRelease( picture_t * ); |
|---|
| | 53 | |
|---|
| | 54 | /** |
|---|
| 178 | | int filter_chain_AppendFromString( filter_chain_t *p_chain, |
|---|
| 179 | | const char *psz_string ) |
|---|
| | 189 | filter_t *filter_chain_AppendFilter( filter_chain_t *p_chain, |
|---|
| | 190 | const char *psz_name, |
|---|
| | 191 | config_chain_t *p_cfg, |
|---|
| | 192 | const es_format_t *p_fmt_in, |
|---|
| | 193 | const es_format_t *p_fmt_out ) |
|---|
| | 194 | { |
|---|
| | 195 | filter_t *p_filter = filter_chain_AppendFilterInternal( p_chain, psz_name, |
|---|
| | 196 | p_cfg, p_fmt_in, |
|---|
| | 197 | p_fmt_out ); |
|---|
| | 198 | if( UpdateBufferFunctions( p_chain ) < 0 ) |
|---|
| | 199 | msg_Err( p_filter, "Woah! This doesn't look good." ); |
|---|
| | 200 | return p_filter; |
|---|
| | 201 | } |
|---|
| | 202 | |
|---|
| | 203 | static int filter_chain_AppendFromStringInternal( filter_chain_t *p_chain, |
|---|
| | 204 | const char *psz_string ) |
|---|
| 209 | | int filter_chain_DeleteFilter( filter_chain_t *p_chain, filter_t *p_filter ) |
|---|
| | 234 | int filter_chain_AppendFromString( filter_chain_t *p_chain, |
|---|
| | 235 | const char *psz_string ) |
|---|
| | 236 | { |
|---|
| | 237 | int i_ret = filter_chain_AppendFromStringInternal( p_chain, psz_string ); |
|---|
| | 238 | if( i_ret < 0 ) return i_ret; |
|---|
| | 239 | int i_ret2 = UpdateBufferFunctions( p_chain ); |
|---|
| | 240 | if( i_ret2 < 0 ) return i_ret2; |
|---|
| | 241 | return i_ret; |
|---|
| | 242 | } |
|---|
| | 243 | |
|---|
| | 244 | static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain, |
|---|
| | 245 | filter_t *p_filter ) |
|---|
| | 388 | |
|---|
| | 389 | /** |
|---|
| | 390 | * Internal chain buffer handling |
|---|
| | 391 | */ |
|---|
| | 392 | |
|---|
| | 393 | /** |
|---|
| | 394 | * This function should be called after every filter chain change |
|---|
| | 395 | */ |
|---|
| | 396 | static int UpdateBufferFunctions( filter_chain_t *p_chain ) |
|---|
| | 397 | { |
|---|
| | 398 | if( !strcmp( p_chain->psz_capability, "video filter2" ) ) |
|---|
| | 399 | { |
|---|
| | 400 | /** |
|---|
| | 401 | * Last filter uses the filter chain's parent buffer allocation |
|---|
| | 402 | * functions. All the other filters use internal functions. |
|---|
| | 403 | * This makes it possible to have format changes between each |
|---|
| | 404 | * filter without having to worry about the parent's picture |
|---|
| | 405 | * heap format. |
|---|
| | 406 | */ |
|---|
| | 407 | int i; |
|---|
| | 408 | filter_t **pp_filter = (filter_t **)p_chain->filters.pp_elems; |
|---|
| | 409 | filter_t *p_filter; |
|---|
| | 410 | for( i = 0; i < p_chain->filters.i_count - 1; i++ ) |
|---|
| | 411 | { |
|---|
| | 412 | p_filter = pp_filter[i]; |
|---|
| | 413 | if( p_filter->pf_vout_buffer_new != VideoBufferNew ) |
|---|
| | 414 | { |
|---|
| | 415 | if( p_chain->pf_buffer_allocation_clear ) |
|---|
| | 416 | p_chain->pf_buffer_allocation_clear( p_filter ); |
|---|
| | 417 | p_filter->pf_vout_buffer_new = VideoBufferNew; |
|---|
| | 418 | p_filter->pf_vout_buffer_del = NULL; |
|---|
| | 419 | } |
|---|
| | 420 | } |
|---|
| | 421 | if( p_chain->filters.i_count >= 1 ) |
|---|
| | 422 | { |
|---|
| | 423 | p_filter = pp_filter[i]; |
|---|
| | 424 | if( p_filter->pf_vout_buffer_new == VideoBufferNew ) |
|---|
| | 425 | { |
|---|
| | 426 | p_filter->pf_vout_buffer_new = NULL; |
|---|
| | 427 | if( p_chain->pf_buffer_allocation_init( p_filter, |
|---|
| | 428 | p_chain->p_buffer_allocation_data ) != VLC_SUCCESS ) |
|---|
| | 429 | return VLC_EGENERIC; |
|---|
| | 430 | } |
|---|
| | 431 | } |
|---|
| | 432 | } |
|---|
| | 433 | return VLC_SUCCESS; |
|---|
| | 434 | } |
|---|
| | 435 | |
|---|
| | 436 | static picture_t *VideoBufferNew( filter_t *p_filter ) |
|---|
| | 437 | { |
|---|
| | 438 | picture_t *p_pic = malloc( sizeof( picture_t ) ); |
|---|
| | 439 | if( !p_pic ) return NULL; |
|---|
| | 440 | memset( p_pic, 0, sizeof( picture_t * ) ); |
|---|
| | 441 | int i_ret = vout_AllocatePicture( VLC_OBJECT( p_filter ), p_pic, |
|---|
| | 442 | p_filter->fmt_out.video.i_chroma, |
|---|
| | 443 | p_filter->fmt_out.video.i_width, |
|---|
| | 444 | p_filter->fmt_out.video.i_height, |
|---|
| | 445 | p_filter->fmt_out.video.i_aspect ); |
|---|
| | 446 | if( i_ret != VLC_SUCCESS ) |
|---|
| | 447 | { |
|---|
| | 448 | msg_Err( p_filter, "Failed to allocate picture: %s", |
|---|
| | 449 | vlc_error( i_ret ) ); |
|---|
| | 450 | free( p_pic ); |
|---|
| | 451 | return NULL; |
|---|
| | 452 | } |
|---|
| | 453 | p_pic->pf_release = VideoBufferRelease; |
|---|
| | 454 | p_pic->i_type = MEMORY_PICTURE; |
|---|
| | 455 | p_pic->i_status = RESERVED_PICTURE; |
|---|
| | 456 | return p_pic; |
|---|
| | 457 | } |
|---|
| | 458 | |
|---|
| | 459 | static void VideoBufferRelease( picture_t *p_pic ) |
|---|
| | 460 | { |
|---|
| | 461 | free( p_pic->p_data_orig ); |
|---|
| | 462 | free( p_pic ); |
|---|
| | 463 | } |
|---|