📄 vout_pictures.c
字号:
/***************************************************************************** * vout_pictures.c : picture management functions ***************************************************************************** * Copyright (C) 2000-2004 VideoLAN * $Id: vout_pictures.c 10184 2005-03-07 17:52:05Z gbazin $ * * Authors: Vincent Seguin <seguin@via.ecp.fr> * Samuel Hocevar <sam@zoy.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* free() */#include <stdio.h> /* sprintf() */#include <string.h> /* strerror() */#include <vlc/vlc.h>#include "vlc_video.h"#include "video_output.h"#include "vlc_spu.h"#include "vout_pictures.h"/** * 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 * called. */void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic ){ vlc_mutex_lock( &p_vout->picture_lock ); switch( p_pic->i_status ) { case RESERVED_PICTURE: p_pic->i_status = RESERVED_DISP_PICTURE; break; case RESERVED_DATED_PICTURE: p_pic->i_status = READY_PICTURE; break; default: msg_Err( p_vout, "picture to display %p has invalid status %d", p_pic, p_pic->i_status ); break; } vlc_mutex_unlock( &p_vout->picture_lock );}/** * Date 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_DisplayPicture has * been called. * \param p_vout The vout in question * \param p_pic The picture to date * \param date The date to display the picture */void vout_DatePicture( vout_thread_t *p_vout, picture_t *p_pic, mtime_t date ){ vlc_mutex_lock( &p_vout->picture_lock ); p_pic->date = date; switch( p_pic->i_status ) { case RESERVED_PICTURE: p_pic->i_status = RESERVED_DATED_PICTURE; break; case RESERVED_DISP_PICTURE: p_pic->i_status = READY_PICTURE; break; default: msg_Err( p_vout, "picture to date %p has invalid status %d", p_pic, p_pic->i_status ); break; } vlc_mutex_unlock( &p_vout->picture_lock );}/** * Allocate a picture in the video output heap. * * 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. */picture_t *vout_CreatePicture( vout_thread_t *p_vout, vlc_bool_t b_progressive, vlc_bool_t b_top_field_first, unsigned int i_nb_fields ){ int i_pic; /* picture index */ picture_t * p_pic; picture_t * p_freepic = NULL; /* first free picture */ /* Get lock */ vlc_mutex_lock( &p_vout->picture_lock ); /* * Look for an empty place in the picture heap. */ for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ ) { p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1) % I_RENDERPICTURES]; switch( p_pic->i_status ) { case DESTROYED_PICTURE: /* Memory will not be reallocated, and function can end * immediately - this is the best possible case, since no * memory allocation needs to be done */ p_pic->i_status = RESERVED_PICTURE; p_pic->i_refcount = 0; p_pic->b_force = 0; p_pic->b_progressive = b_progressive; 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; default: break; } } /* * Prepare picture */ if( p_freepic != NULL ) { 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_aspect ); if( p_freepic->i_planes ) { /* Copy picture information, set some default values */ p_freepic->i_status = RESERVED_PICTURE; p_freepic->i_type = MEMORY_PICTURE; p_freepic->b_slow = 0; p_freepic->i_refcount = 0; p_freepic->b_force = 0; p_freepic->b_progressive = b_progressive; p_freepic->i_nb_fields = i_nb_fields; p_freepic->b_top_field_first = b_top_field_first; p_freepic->i_matrix_coefficients = 1; p_vout->i_heap_size++; } else { /* Memory allocation failed : set picture as empty */ p_freepic->i_status = FREE_PICTURE; p_freepic = NULL; msg_Err( p_vout, "picture allocation failed" ); } vlc_mutex_unlock( &p_vout->picture_lock ); return( p_freepic ); } /* No free or destroyed picture could be found, but the decoder * will try again in a while. */ vlc_mutex_unlock( &p_vout->picture_lock ); return( NULL );}/** * Remove a permanent or reserved picture from the heap * * This function frees a previously reserved picture or a permanent * picture. It is meant to be used when the construction of a picture aborted. * Note that the picture will be destroyed even if it is linked ! */void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic ){ vlc_mutex_lock( &p_vout->picture_lock );#ifdef DEBUG /* Check if picture status is valid */ if( (p_pic->i_status != RESERVED_PICTURE) && (p_pic->i_status != RESERVED_DATED_PICTURE) && (p_pic->i_status != RESERVED_DISP_PICTURE) ) { msg_Err( p_vout, "picture to destroy %p has invalid status %d", p_pic, p_pic->i_status ); }#endif p_pic->i_status = DESTROYED_PICTURE; p_vout->i_heap_size--; vlc_mutex_unlock( &p_vout->picture_lock );}/** * Increment reference counter of a picture * * This function increments the reference counter of a picture in the video * heap. It needs a lock since several producer threads can access the picture. */void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic ){ vlc_mutex_lock( &p_vout->picture_lock ); p_pic->i_refcount++; vlc_mutex_unlock( &p_vout->picture_lock );}/** * Decrement reference counter of a picture * * 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 ){ vlc_mutex_lock( &p_vout->picture_lock ); p_pic->i_refcount--; if( p_pic->i_refcount < 0 ) { msg_Err( p_vout, "picture %p refcount is %i", p_pic, p_pic->i_refcount ); p_pic->i_refcount = 0; } if( ( p_pic->i_refcount == 0 ) && ( p_pic->i_status == DISPLAYED_PICTURE ) ) { p_pic->i_status = DESTROYED_PICTURE; p_vout->i_heap_size--; } vlc_mutex_unlock( &p_vout->picture_lock );}/** * Render a picture * * This function chooses whether the current picture needs to be copied * before rendering, does the subpicture magic, and tells the video output * thread which direct buffer needs to be displayed. */picture_t * vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic, subpicture_t *p_subpic ){ int i_scale_width, i_scale_height; if( p_pic == NULL ) { /* XXX: subtitles */ return NULL; } i_scale_width = p_vout->fmt_out.i_visible_width * 1000 / p_vout->fmt_in.i_visible_width; i_scale_height = p_vout->fmt_out.i_visible_height * 1000 / p_vout->fmt_in.i_visible_height; if( p_pic->i_type == DIRECT_PICTURE ) { if( !p_vout->render.b_allow_modify_pics || p_pic->i_refcount || p_pic->b_force ) { /* Picture is in a direct buffer and is still in use, * we need to copy it to another direct buffer before * displaying it if there are subtitles. */ if( p_subpic != NULL ) { /* We have subtitles. First copy the picture to * the spare direct buffer, then render the * subtitles. */ vout_CopyPicture( p_vout, PP_OUTPUTPICTURE[0], p_pic ); spu_RenderSubpictures( p_vout->p_spu, &p_vout->fmt_out, PP_OUTPUTPICTURE[0], p_pic, p_subpic, i_scale_width, i_scale_height );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -