X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Frawvideo.c;h=41d1c32524a7382b0135550d5c9e5452f769dddf;hb=771b937a13ca042391530236f79f9a52e27e095d;hp=83fc9bf69a8ed77bfc3b195b46cc56f86b6c2ef5;hpb=1a67448183a9c5ab7b5b427fb80d2d1a2e34ff8d;p=vlc diff --git a/modules/codec/rawvideo.c b/modules/codec/rawvideo.c index 83fc9bf69a..41d1c32524 100644 --- a/modules/codec/rawvideo.c +++ b/modules/codec/rawvideo.c @@ -1,8 +1,8 @@ /***************************************************************************** * rawvideo.c: Pseudo video decoder/packetizer for raw video data ***************************************************************************** - * Copyright (C) 2001, 2002 VideoLAN - * $Id: rawvideo.c,v 1.7 2003/10/24 21:27:06 gbazin Exp $ + * Copyright (C) 2001, 2002 the VideoLAN team + * $Id$ * * Authors: Laurent Aimar * @@ -18,22 +18,15 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include /* strdup() */ - #include -#include -#include -#include -#include - -#include "codecs.h" +#include +#include /***************************************************************************** * decoder_sys_t : raw video decoder descriptor @@ -47,17 +40,7 @@ struct decoder_sys_t * Input properties */ int i_raw_size; - - /* - * Output properties - */ - vout_thread_t *p_vout; - - /* - * Packetizer output properties - */ - sout_packetizer_input_t *p_sout_input; - sout_format_t sout_format; + vlc_bool_t b_invert; /* * Common properties @@ -69,41 +52,40 @@ struct decoder_sys_t /**************************************************************************** * Local prototypes ****************************************************************************/ -static int OpenDecoder ( vlc_object_t * ); -static int OpenPacketizer( vlc_object_t * ); +static int OpenDecoder ( vlc_object_t * ); +static int OpenPacketizer( vlc_object_t * ); +static void CloseDecoder ( vlc_object_t * ); -static int InitDecoder ( decoder_t * ); -static int RunDecoder ( decoder_t *, block_t * ); -static int EndDecoder ( decoder_t * ); +static void *DecodeBlock ( decoder_t *, block_t ** ); -static int DecodeFrame ( decoder_t *, block_t * ); -static int SendFrame ( decoder_t *, block_t * ); +static picture_t *DecodeFrame( decoder_t *, block_t * ); +static block_t *SendFrame ( decoder_t *, block_t * ); /***************************************************************************** * Module descriptor *****************************************************************************/ vlc_module_begin(); - set_description( _("Pseudo Raw Video decoder") ); + set_description( _("Pseudo raw video decoder") ); set_capability( "decoder", 50 ); - set_callbacks( OpenDecoder, NULL ); + set_category( CAT_INPUT ); + set_subcategory( SUBCAT_INPUT_VCODEC ); + set_callbacks( OpenDecoder, CloseDecoder ); add_submodule(); - set_description( _("Pseudo Raw Video packetizer") ); + set_description( _("Pseudo raw video packetizer") ); set_capability( "packetizer", 100 ); - set_callbacks( OpenPacketizer, NULL ); + set_callbacks( OpenPacketizer, CloseDecoder ); vlc_module_end(); /***************************************************************************** * OpenDecoder: probe the decoder and return score - ***************************************************************************** - * Tries to launch a decoder and return score so that the interface is able - * to choose. *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; + decoder_sys_t *p_sys; - switch( p_dec->p_fifo->i_fourcc ) + switch( p_dec->fmt_in.i_codec ) { /* Planar YUV */ case VLC_FOURCC('I','4','4','4'): @@ -113,6 +95,7 @@ static int OpenDecoder( vlc_object_t *p_this ) case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('I','4','1','1'): case VLC_FOURCC('I','4','1','0'): + case VLC_FOURCC('Y','V','U','9'): /* Packed YUV */ case VLC_FOURCC('Y','U','Y','2'): @@ -124,133 +107,117 @@ static int OpenDecoder( vlc_object_t *p_this ) case VLC_FOURCC('R','V','1','6'): case VLC_FOURCC('R','V','1','5'): break; + case VLC_FOURCC('2','V','u','y'): + case VLC_FOURCC('2','v','u','y'): + p_dec->fmt_in.i_codec = VLC_FOURCC('U','Y','V','Y'); + break; + case VLC_FOURCC('y','v','1','2'): + p_dec->fmt_in.i_codec = VLC_FOURCC('Y','V','1','2'); + break; default: return VLC_EGENERIC; } - p_dec->pf_init = InitDecoder; - p_dec->pf_decode = RunDecoder; - p_dec->pf_end = EndDecoder; - /* Allocate the memory needed to store the decoder's structure */ - if( ( p_dec->p_sys = + if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } + /* Misc init */ p_dec->p_sys->b_packetizer = VLC_FALSE; - - return VLC_SUCCESS; -} - -static int OpenPacketizer( vlc_object_t *p_this ) -{ - decoder_t *p_dec = (decoder_t*)p_this; - - int i_ret = OpenDecoder( p_this ); - - if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE; - - return i_ret; -} - -/***************************************************************************** - * InitDecoder: Initalize the decoder - *****************************************************************************/ -static int InitDecoder( decoder_t *p_dec ) -{ - decoder_sys_t *p_sys = p_dec->p_sys; - video_frame_format_t format; - p_sys->i_pts = 0; + p_sys->b_invert = 0; - p_sys->p_sout_input = NULL; - p_sys->sout_format.i_cat = VIDEO_ES; - p_sys->sout_format.i_block_align = 0; - p_sys->sout_format.i_bitrate = 0; - p_sys->sout_format.i_extra_data = 0; - p_sys->sout_format.p_extra_data = NULL; - -#define bih ((BITMAPINFOHEADER*)p_dec->p_fifo->p_bitmapinfoheader) - if( bih == NULL ) + if( (int)p_dec->fmt_in.video.i_height < 0 ) { - msg_Err( p_dec, "info missing, fatal" ); - return VLC_EGENERIC; + /* Frames are coded from bottom to top */ + p_dec->fmt_in.video.i_height = + (unsigned int)(-(int)p_dec->fmt_in.video.i_height); + p_sys->b_invert = VLC_TRUE; } - if( bih->biWidth <= 0 || bih->biHeight <= 0 ) + + if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", - bih->biWidth, bih->biHeight ); + p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } - if( p_sys->b_packetizer ) + /* Find out p_vdec->i_raw_size */ + vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, + p_dec->fmt_in.video.i_width, + p_dec->fmt_in.video.i_height, + p_dec->fmt_in.video.i_aspect ); + p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel * + p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8; + + /* Set output properties */ + p_dec->fmt_out.i_cat = VIDEO_ES; + p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec; + if( !p_dec->fmt_in.video.i_aspect ) { - /* add an input for the stream ouput */ - p_sys->sout_format.i_width = bih->biWidth; - p_sys->sout_format.i_height = bih->biHeight; - p_sys->sout_format.i_fourcc = p_dec->p_fifo->i_fourcc; - - p_sys->p_sout_input = - sout_InputNew( p_dec, &p_sys->sout_format ); - - if( !p_sys->p_sout_input ) - { - msg_Err( p_dec, "cannot add a new stream" ); - return VLC_EGENERIC; - } - } - else - { - /* Initialize video output */ - p_sys->p_vout = vout_Request( p_dec, NULL, - bih->biWidth, bih->biHeight, - p_dec->p_fifo->i_fourcc, - VOUT_ASPECT_FACTOR * bih->biWidth / - bih->biHeight ); - if( p_sys->p_vout == NULL ) - { - msg_Err( p_dec, "failed to create vout" ); - return VLC_EGENERIC; - } + p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * + p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; } + else p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect; - /* Find out p_vdec->i_raw_size */ - vout_InitFormat( &format, p_dec->p_fifo->i_fourcc, - bih->biWidth, bih->biHeight, - bih->biWidth * VOUT_ASPECT_FACTOR / bih->biHeight ); - p_sys->i_raw_size = format.i_bits_per_pixel * - format.i_width * format.i_height / 8; -#undef bih + if( p_dec->fmt_in.video.i_rmask ) + p_dec->fmt_out.video.i_rmask = p_dec->fmt_in.video.i_rmask; + if( p_dec->fmt_in.video.i_gmask ) + p_dec->fmt_out.video.i_gmask = p_dec->fmt_in.video.i_gmask; + if( p_dec->fmt_in.video.i_bmask ) + p_dec->fmt_out.video.i_bmask = p_dec->fmt_in.video.i_bmask; + + /* Set callbacks */ + p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) + DecodeBlock; + p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) + DecodeBlock; return VLC_SUCCESS; } +static int OpenPacketizer( vlc_object_t *p_this ) +{ + decoder_t *p_dec = (decoder_t*)p_this; + + int i_ret = OpenDecoder( p_this ); + + if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE; + + return i_ret; +} + /**************************************************************************** - * RunDecoder: the whole thing + * DecodeBlock: the whole thing **************************************************************************** - * This function must be fed with ogg packets. + * This function must be fed with complete frames. ****************************************************************************/ -static int RunDecoder( decoder_t *p_dec, block_t *p_block ) +static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_ret; + block_t *p_block; + void *p_buf; + + if( !pp_block || !*pp_block ) return NULL; -#if 0 - if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts ) + p_block = *pp_block; + + if( !p_sys->i_pts && !p_block->i_pts && !p_block->i_dts ) { /* We've just started the stream, wait for the first PTS. */ block_Release( p_block ); - return VLC_SUCCESS; + return NULL; } -#endif /* Date management */ - if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts ) + if( p_block->i_pts > 0 || p_block->i_dts > 0 ) { - p_sys->i_pts = p_block->i_pts; + if( p_block->i_pts > 0 ) p_sys->i_pts = p_block->i_pts; + else if( p_block->i_dts > 0 ) p_sys->i_pts = p_block->i_dts; } if( p_block->i_buffer < p_sys->i_raw_size ) @@ -259,23 +226,23 @@ static int RunDecoder( decoder_t *p_dec, block_t *p_block ) p_block->i_buffer, p_sys->i_raw_size ); block_Release( p_block ); - return VLC_EGENERIC; + return NULL; } if( p_sys->b_packetizer ) { - i_ret = SendFrame( p_dec, p_block ); + p_buf = SendFrame( p_dec, p_block ); } else { - i_ret = DecodeFrame( p_dec, p_block ); + p_buf = DecodeFrame( p_dec, p_block ); } /* Date management: 1 frame per packet */ p_sys->i_pts += ( I64C(1000000) * 1.0 / 25 /*FIXME*/ ); + *pp_block = NULL; - block_Release( p_block ); - return i_ret; + return p_buf; } /***************************************************************************** @@ -285,91 +252,115 @@ static void FillPicture( decoder_t *p_dec, block_t *p_block, picture_t *p_pic ) { uint8_t *p_src, *p_dst; int i_src, i_plane, i_line, i_width; + decoder_sys_t *p_sys = p_dec->p_sys; - p_src = p_block->p_buffer; + p_src = p_block->p_buffer; i_src = p_block->i_buffer; for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { p_dst = p_pic->p[i_plane].p_pixels; - i_width = p_pic->p[i_plane].i_visible_pitch; + i_width = p_pic->p[i_plane].i_pitch; + + if( p_sys->b_invert ) + p_src += (i_width * (p_pic->p[i_plane].i_visible_lines - 1)); - for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ ) + for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ ) { - p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width ); - p_src += i_width; - p_dst += p_pic->p[i_plane].i_pitch; + p_dec->p_libvlc->pf_memcpy( p_dst, p_src, i_width ); + p_src += p_sys->b_invert ? -i_width : i_width; + p_dst += i_width; } + + if( p_sys->b_invert ) + p_src += (i_width * (p_pic->p[i_plane].i_visible_lines + 1)); } } /***************************************************************************** * DecodeFrame: decodes a video frame. *****************************************************************************/ -static int DecodeFrame( decoder_t *p_dec, block_t *p_block ) +static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; picture_t *p_pic; /* Get a new picture */ - while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) ) + p_pic = p_dec->pf_vout_buffer_new( p_dec ); + if( !p_pic ) { - if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error ) - { - return VLC_EGENERIC; - } - msleep( VOUT_OUTMEM_SLEEP ); + block_Release( p_block ); + return NULL; } - if( !p_pic ) return VLC_EGENERIC; FillPicture( p_dec, p_block, p_pic ); - vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts ); - vout_DisplayPicture( p_sys->p_vout, p_pic ); + p_pic->date = p_sys->i_pts; - return VLC_SUCCESS; + block_Release( p_block ); + return p_pic; } /***************************************************************************** * SendFrame: send a video frame to the stream output. *****************************************************************************/ -static int SendFrame( decoder_t *p_dec, block_t *p_block ) +static block_t *SendFrame( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; - sout_buffer_t *p_sout_buffer = - sout_BufferNew( p_sys->p_sout_input->p_sout, p_block->i_buffer ); + p_block->i_dts = p_block->i_pts = p_sys->i_pts; - if( !p_sout_buffer ) return VLC_EGENERIC; + if( p_sys->b_invert ) + { + picture_t pic; + uint8_t *p_tmp, *p_pixels; + int i, j; - p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer, - p_block->p_buffer, p_block->i_buffer ); + /* Fill in picture_t fields */ + vout_InitPicture( VLC_OBJECT(p_dec), &pic, p_dec->fmt_out.i_codec, + p_dec->fmt_out.video.i_width, + p_dec->fmt_out.video.i_height, VOUT_ASPECT_FACTOR ); - p_sout_buffer->i_dts = p_sout_buffer->i_pts = p_sys->i_pts; + if( !pic.i_planes ) + { + msg_Err( p_dec, "unsupported chroma" ); + return p_block; + } - sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer ); + p_tmp = malloc( pic.p[0].i_pitch ); + p_pixels = p_block->p_buffer; + for( i = 0; i < pic.i_planes; i++ ) + { + int i_pitch = pic.p[i].i_pitch; + uint8_t *p_top = p_pixels; + uint8_t *p_bottom = p_pixels + i_pitch * + (pic.p[i].i_visible_lines - 1); + + for( j = 0; j < pic.p[i].i_visible_lines / 2; j++ ) + { + p_dec->p_libvlc->pf_memcpy( p_tmp, p_bottom, + pic.p[i].i_visible_pitch ); + p_dec->p_libvlc->pf_memcpy( p_bottom, p_top, + pic.p[i].i_visible_pitch ); + p_dec->p_libvlc->pf_memcpy( p_top, p_tmp, + pic.p[i].i_visible_pitch ); + p_top += i_pitch; + p_bottom -= i_pitch; + } + + p_pixels += i_pitch * pic.p[i].i_lines; + } + free( p_tmp ); + } - return VLC_SUCCESS; + return p_block; } /***************************************************************************** - * EndDecoder: decoder destruction + * CloseDecoder: decoder destruction *****************************************************************************/ -static int EndDecoder( decoder_t *p_dec ) +static void CloseDecoder( vlc_object_t *p_this ) { - decoder_sys_t *p_sys = p_dec->p_sys; - - if( !p_sys->b_packetizer ) - { - vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 ); - } - - if( p_sys->p_sout_input != NULL ) - { - sout_InputDelete( p_sys->p_sout_input ); - } - - free( p_sys ); - - return VLC_SUCCESS; + decoder_t *p_dec = (decoder_t*)p_this; + free( p_dec->p_sys ); }