X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fvideo_output%2Fvout_pictures.c;h=427ce00f79fbecfb760c1b5ec6a0b25a1743d701;hb=62fb058cf20e03deab925bbcc89bd7524a6c10bc;hp=fd44cad8b0693f8650b5fea9498f51fff8060da3;hpb=be8ca6e9a9924ccdf8c72449b85bdb97e05e87a6;p=vlc diff --git a/src/video_output/vout_pictures.c b/src/video_output/vout_pictures.c index fd44cad8b0..427ce00f79 100644 --- a/src/video_output/vout_pictures.c +++ b/src/video_output/vout_pictures.c @@ -1,8 +1,8 @@ /***************************************************************************** * vout_pictures.c : picture management functions ***************************************************************************** - * Copyright (C) 2000 VideoLAN - * $Id: vout_pictures.c,v 1.30 2002/11/10 18:04:24 sam Exp $ + * Copyright (C) 2000-2004 VideoLAN + * $Id: vout_pictures.c,v 1.47 2004/02/27 14:01:35 fenrir Exp $ * * Authors: Vincent Seguin * Samuel Hocevar @@ -31,7 +31,7 @@ #include -#include "video.h" +#include "vlc_video.h" #include "video_output.h" #include "vout_pictures.h" @@ -44,8 +44,8 @@ static void CopyPicture( vout_thread_t *, picture_t *, picture_t * ); /***************************************************************************** * vout_DisplayPicture: display a picture ***************************************************************************** - * Remove the reservation flag of a picture, which will cause it to be ready for - * display. The picture won't be displayed until vout_DatePicture has been + * Remove the reservation flag of a picture, which will cause it to be ready + * for display. The picture won't be displayed until vout_DatePicture has been * called. *****************************************************************************/ void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ) @@ -102,13 +102,14 @@ void vout_DatePicture( vout_thread_t *p_vout, ***************************************************************************** * This function creates a reserved image in the video output heap. * A null pointer is returned if the function fails. This method provides an - * already allocated zone of memory in the picture data fields. It needs locking - * since several pictures can be created by several producers threads. + * already allocated zone of memory in the picture data fields. + * It needs locking since several pictures can be created by several producers + * threads. *****************************************************************************/ picture_t *vout_CreatePicture( vout_thread_t *p_vout, vlc_bool_t b_progressive, vlc_bool_t b_top_field_first, - vlc_bool_t b_repeat_first_field ) + unsigned int i_nb_fields ) { int i_pic; /* picture index */ picture_t * p_pic; @@ -118,22 +119,12 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, vlc_mutex_lock( &p_vout->picture_lock ); /* - * Look for an empty place. We start at 1 because the first - * directbuffer is reserved for memcpy()ed pictures. + * Look for an empty place in the picture heap. */ - for( i_pic = 0; i_pic < I_RENDERPICTURES && p_freepic == NULL; i_pic++ ) + for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ ) { - p_pic = PP_RENDERPICTURE[ i_pic ]; - - /* If the picture we found is a memory buffer, and we have enough - * pictures in the stack, and we might have enough room later for - * a direct buffer, skip it. If no other pictures are found, the - * video decoder will try again later. */ - if( p_vout->b_direct && ( p_vout->output.i_pictures > 5 ) - && ( p_pic->i_type != DIRECT_PICTURE ) ) - { - break; - } + p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1) + % I_RENDERPICTURES]; switch( p_pic->i_status ) { @@ -146,15 +137,21 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, p_pic->b_force = 0; p_pic->b_progressive = b_progressive; - p_pic->b_repeat_first_field = b_repeat_first_field; + p_pic->i_nb_fields = i_nb_fields; p_pic->b_top_field_first = b_top_field_first; p_vout->i_heap_size++; + p_vout->render.i_last_used_pic = + ( p_vout->render.i_last_used_pic + i_pic + 1 ) + % I_RENDERPICTURES; vlc_mutex_unlock( &p_vout->picture_lock ); return( p_pic ); case FREE_PICTURE: /* Picture is empty and ready for allocation */ + p_vout->render.i_last_used_pic = + ( p_vout->render.i_last_used_pic + i_pic + 1 ) + % I_RENDERPICTURES; p_freepic = p_pic; break; @@ -168,9 +165,10 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, */ if( p_freepic != NULL ) { - vout_AllocatePicture( p_vout, p_freepic, + vout_AllocatePicture( VLC_OBJECT(p_vout), + p_freepic, p_vout->render.i_chroma, p_vout->render.i_width, p_vout->render.i_height, - p_vout->render.i_chroma ); + p_vout->render.i_aspect ); if( p_freepic->i_planes ) { @@ -182,7 +180,7 @@ picture_t *vout_CreatePicture( vout_thread_t *p_vout, p_freepic->b_force = 0; p_freepic->b_progressive = b_progressive; - p_freepic->b_repeat_first_field = b_repeat_first_field; + p_freepic->i_nb_fields = i_nb_fields; p_freepic->b_top_field_first = b_top_field_first; p_freepic->i_matrix_coefficients = 1; @@ -254,7 +252,7 @@ void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) /***************************************************************************** * vout_UnlinkPicture: decrement reference counter of a picture ***************************************************************************** - * This function decrement the reference counter of a picture in the video heap. + * This function decrement the reference counter of a picture in the video heap *****************************************************************************/ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) { @@ -263,7 +261,8 @@ void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic ) if( p_pic->i_refcount < 0 ) { - msg_Err( p_vout, "picture refcount is %i", p_pic->i_refcount ); + msg_Err( p_vout, "picture %p refcount is %i", + p_pic, p_pic->i_refcount ); p_pic->i_refcount = 0; } @@ -296,7 +295,7 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, if( p_pic->i_type == DIRECT_PICTURE ) { - if( p_pic->i_refcount ) + if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount ) { /* Picture is in a direct buffer and is still in use, * we need to copy it to another direct buffer before @@ -334,10 +333,23 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, /* Picture is not in a direct buffer, but is exactly the * same size as the direct buffers. A memcpy() is enough, * then render the subtitles. */ + + if( PP_OUTPUTPICTURE[0]->pf_lock ) + if( PP_OUTPUTPICTURE[0]->pf_lock( p_vout, PP_OUTPUTPICTURE[0] ) ) + { + if( PP_OUTPUTPICTURE[0]->pf_unlock ) + PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] ); + + return NULL; + } + CopyPicture( p_vout, p_pic, PP_OUTPUTPICTURE[0] ); vout_RenderSubPictures( p_vout, PP_OUTPUTPICTURE[0], p_subpic ); + if( PP_OUTPUTPICTURE[0]->pf_unlock ) + PP_OUTPUTPICTURE[0]->pf_unlock( p_vout, PP_OUTPUTPICTURE[0] ); + return PP_OUTPUTPICTURE[0]; } @@ -346,12 +358,19 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, * well. This usually means software YUV, or hardware YUV with a * different chroma. */ + if( p_vout->p_picture[0].pf_lock ) + if( p_vout->p_picture[0].pf_lock( p_vout, &p_vout->p_picture[0] ) ) + return NULL; + /* Convert image to the first direct buffer */ p_vout->chroma.pf_convert( p_vout, p_pic, &p_vout->p_picture[0] ); /* Render subpictures on the first direct buffer */ vout_RenderSubPictures( p_vout, &p_vout->p_picture[0], p_subpic ); + if( p_vout->p_picture[0].pf_unlock ) + p_vout->p_picture[0].pf_unlock( p_vout, &p_vout->p_picture[0] ); + return &p_vout->p_picture[0]; } @@ -361,8 +380,10 @@ picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, * This function will be accessed by plugins. It calculates the relative * position of the output window and the image window. *****************************************************************************/ -void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height, - int *pi_x, int *pi_y, int *pi_width, int *pi_height ) +void vout_PlacePicture( vout_thread_t *p_vout, + unsigned int i_width, unsigned int i_height, + unsigned int *pi_x, unsigned int *pi_y, + unsigned int *pi_width, unsigned int *pi_height ) { if( (i_width <= 0) || (i_height <=0) ) { @@ -403,8 +424,29 @@ void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height, *pi_width = *pi_height * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR; } - *pi_x = ( i_width - *pi_width ) / 2; - *pi_y = ( i_height - *pi_height ) / 2; + switch( p_vout->i_alignment & VOUT_ALIGN_HMASK ) + { + case VOUT_ALIGN_LEFT: + *pi_x = 0; + break; + case VOUT_ALIGN_RIGHT: + *pi_x = i_width - *pi_width; + break; + default: + *pi_x = ( i_width - *pi_width ) / 2; + } + + switch( p_vout->i_alignment & VOUT_ALIGN_VMASK ) + { + case VOUT_ALIGN_TOP: + *pi_y = 0; + break; + case VOUT_ALIGN_BOTTOM: + *pi_y = i_height - *pi_height; + break; + default: + *pi_y = ( i_height - *pi_height ) / 2; + } } /***************************************************************************** @@ -414,11 +456,121 @@ void vout_PlacePicture( vout_thread_t *p_vout, int i_width, int i_height, * used exactly like a video buffer. The video output thread then manages * how it gets displayed. *****************************************************************************/ -void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic, - int i_width, int i_height, vlc_fourcc_t i_chroma ) +void vout_AllocatePicture( vlc_object_t *p_this, picture_t *p_pic, + vlc_fourcc_t i_chroma, + int i_width, int i_height, int i_aspect ) { int i_bytes, i_index; + vout_InitPicture( p_this, p_pic, i_chroma, + i_width, i_height, i_aspect ); + + /* Calculate how big the new image should be */ + i_bytes = p_pic->format.i_bits_per_pixel * + p_pic->format.i_width * p_pic->format.i_height / 8; + + p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes ); + + if( p_pic->p_data == NULL ) + { + p_pic->i_planes = 0; + return; + } + + /* Fill the p_pixels field for each plane */ + p_pic->p[ 0 ].p_pixels = p_pic->p_data; + + for( i_index = 1; i_index < p_pic->i_planes; i_index++ ) + { + p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels + + p_pic->p[i_index-1].i_lines + * p_pic->p[i_index-1].i_pitch; + } +} + +/***************************************************************************** + * vout_InitFormat: initialise the video format fields given chroma/size. + ***************************************************************************** + * This function initializes all the video_frame_format_t fields given the + * static properties of a picture (chroma and size). + *****************************************************************************/ +void vout_InitFormat( video_frame_format_t *p_format, vlc_fourcc_t i_chroma, + int i_width, int i_height, int i_aspect ) +{ + p_format->i_chroma = i_chroma; + p_format->i_width = p_format->i_visible_width = i_width; + p_format->i_height = p_format->i_visible_height = i_height; + p_format->i_x_offset = p_format->i_y_offset = 0; + p_format->i_aspect = i_aspect; + +#if 0 + /* Assume we have square pixels */ + if( i_width && i_height ) + p_format->i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height; + else + p_format->i_aspect = 0; +#endif + + switch( i_chroma ) + { + case FOURCC_I444: + p_format->i_bits_per_pixel = 24; + break; + case FOURCC_I422: + case FOURCC_YUY2: + p_format->i_bits_per_pixel = 16; + p_format->i_bits_per_pixel = 16; + break; + case FOURCC_I411: + case FOURCC_YV12: + case FOURCC_I420: + case FOURCC_IYUV: + p_format->i_bits_per_pixel = 12; + break; + case FOURCC_I410: + case FOURCC_YVU9: + p_format->i_bits_per_pixel = 9; + break; + case FOURCC_Y211: + p_format->i_bits_per_pixel = 8; + break; + case FOURCC_RV32: + p_format->i_bits_per_pixel = 32; + break; + case FOURCC_RV24: + /* FIXME: Should be 24 here but x11 and our chroma conversion + * routines assume 32. */ +#ifdef WIN32 + p_format->i_bits_per_pixel = 24; +#else + p_format->i_bits_per_pixel = 32; +#endif + break; + case FOURCC_RV15: + case FOURCC_RV16: + p_format->i_bits_per_pixel = 16; + break; + case FOURCC_RGB2: + p_format->i_bits_per_pixel = 8; + break; + default: + p_format->i_bits_per_pixel = 0; + break; + } +} + +/***************************************************************************** + * vout_InitPicture: initialise the picture_t fields given chroma/size. + ***************************************************************************** + * This function initializes most of the picture_t fields given a chroma and + * size. It makes the assumption that stride == width. + *****************************************************************************/ +void vout_InitPicture( vlc_object_t *p_this, picture_t *p_pic, + vlc_fourcc_t i_chroma, + int i_width, int i_height, int i_aspect ) +{ + int i_index; + /* Store default values */ for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ ) { @@ -426,10 +578,26 @@ void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic, p_pic->p[i_index].i_pixel_pitch = 1; } + vout_InitFormat( &p_pic->format, i_chroma, i_width, i_height, i_aspect ); + /* Calculate coordinates */ switch( i_chroma ) { + case FOURCC_I411: + p_pic->p[ Y_PLANE ].i_lines = i_height; + p_pic->p[ Y_PLANE ].i_pitch = i_width; + p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch; + p_pic->p[ U_PLANE ].i_lines = i_height; + p_pic->p[ U_PLANE ].i_pitch = i_width / 4; + p_pic->p[ U_PLANE ].i_visible_pitch = p_pic->p[ U_PLANE ].i_pitch; + p_pic->p[ V_PLANE ].i_lines = i_height; + p_pic->p[ V_PLANE ].i_pitch = i_width / 4; + p_pic->p[ V_PLANE ].i_visible_pitch = p_pic->p[ V_PLANE ].i_pitch; + p_pic->i_planes = 3; + break; + case FOURCC_I410: + case FOURCC_YVU9: p_pic->p[ Y_PLANE ].i_lines = i_height; p_pic->p[ Y_PLANE ].i_pitch = i_width; p_pic->p[ Y_PLANE ].i_visible_pitch = p_pic->p[ Y_PLANE ].i_pitch; @@ -531,6 +699,26 @@ void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic, p_pic->i_planes = 1; break; + case FOURCC_RV24: + p_pic->p->i_lines = i_height; + + /* FIXME: Should be 3 here but x11 and our chroma conversion + * routines assume 4. */ +#ifdef WIN32 + p_pic->p->i_pitch = i_width * 3; + p_pic->p->i_pixel_pitch = 3; +#else + p_pic->p->i_pitch = i_width * 4; + p_pic->p->i_pixel_pitch = 4; +#endif + p_pic->p->i_visible_pitch = p_pic->p->i_pitch; +/* FIXME: p_heap isn't always reachable + p_pic->p_heap->i_rmask = 0xff0000; + p_pic->p_heap->i_gmask = 0x00ff00; + p_pic->p_heap->i_bmask = 0x0000ff; */ + p_pic->i_planes = 1; + break; + case FOURCC_RV32: p_pic->p->i_lines = i_height; p_pic->p->i_pitch = i_width * 4; @@ -544,42 +732,18 @@ void vout_AllocatePicture( vout_thread_t *p_vout, picture_t *p_pic, break; default: - msg_Err( p_vout, "unknown chroma type 0x%.8x (%4.4s)", + msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma ); p_pic->i_planes = 0; return; } - - /* Calculate how big the new image should be */ - for( i_bytes = 0, i_index = 0; i_index < p_pic->i_planes; i_index++ ) - { - i_bytes += p_pic->p[ i_index ].i_lines * p_pic->p[ i_index ].i_pitch; - } - - p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes ); - - if( p_pic->p_data == NULL ) - { - p_pic->i_planes = 0; - return; - } - - /* Fill the p_pixels field for each plane */ - p_pic->p[ 0 ].p_pixels = p_pic->p_data; - - for( i_index = 1; i_index < p_pic->i_planes; i_index++ ) - { - p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels - + p_pic->p[i_index-1].i_lines - * p_pic->p[i_index-1].i_pitch; - } } /***************************************************************************** * vout_ChromaCmp: compare two chroma values ***************************************************************************** * This function returns 1 if the two fourcc values given as argument are - * the same format (eg. UYVY / UYNV) or almost the same format (eg. I420/YV12) + * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12) *****************************************************************************/ int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc ) { @@ -663,7 +827,8 @@ static void CopyPicture( vout_thread_t * p_vout, else { /* We need to proceed line by line */ - u8 *p_in = p_src->p[i].p_pixels, *p_out = p_dest->p[i].p_pixels; + uint8_t *p_in = p_src->p[i].p_pixels; + uint8_t *p_out = p_dest->p[i].p_pixels; int i_line; for( i_line = p_src->p[i].i_lines; i_line--; ) @@ -675,5 +840,5 @@ static void CopyPicture( vout_thread_t * p_vout, } } } + p_dest->date = p_src->date; } -