Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

rawvideo.c

00001 /*****************************************************************************
00002  * rawvideo.c: Pseudo video decoder/packetizer for raw video data
00003  *****************************************************************************
00004  * Copyright (C) 2001, 2002 the VideoLAN team
00005  * $Id: rawvideo.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <vlc/vlc.h>
00028 #include <vlc/decoder.h>
00029 #include <vlc/vout.h>
00030 
00031 /*****************************************************************************
00032  * decoder_sys_t : raw video decoder descriptor
00033  *****************************************************************************/
00034 struct decoder_sys_t
00035 {
00036     /* Module mode */
00037     vlc_bool_t b_packetizer;
00038 
00039     /*
00040      * Input properties
00041      */
00042     int i_raw_size;
00043     vlc_bool_t b_invert;
00044 
00045     /*
00046      * Common properties
00047      */
00048     mtime_t i_pts;
00049 
00050 };
00051 
00052 /****************************************************************************
00053  * Local prototypes
00054  ****************************************************************************/
00055 static int  OpenDecoder   ( vlc_object_t * );
00056 static int  OpenPacketizer( vlc_object_t * );
00057 static void CloseDecoder  ( vlc_object_t * );
00058 
00059 static void *DecodeBlock  ( decoder_t *, block_t ** );
00060 
00061 static picture_t *DecodeFrame( decoder_t *, block_t * );
00062 static block_t   *SendFrame  ( decoder_t *, block_t * );
00063 
00064 /*****************************************************************************
00065  * Module descriptor
00066  *****************************************************************************/
00067 vlc_module_begin();
00068     set_description( _("Pseudo raw video decoder") );
00069     set_capability( "decoder", 50 );
00070     set_category( CAT_INPUT );
00071     set_subcategory( SUBCAT_INPUT_VCODEC );
00072     set_callbacks( OpenDecoder, CloseDecoder );
00073 
00074     add_submodule();
00075     set_description( _("Pseudo raw video packetizer") );
00076     set_capability( "packetizer", 100 );
00077     set_callbacks( OpenPacketizer, CloseDecoder );
00078 vlc_module_end();
00079 
00080 /*****************************************************************************
00081  * OpenDecoder: probe the decoder and return score
00082  *****************************************************************************/
00083 static int OpenDecoder( vlc_object_t *p_this )
00084 {
00085     decoder_t *p_dec = (decoder_t*)p_this;
00086     decoder_sys_t *p_sys;
00087 
00088     switch( p_dec->fmt_in.i_codec )
00089     {
00090         /* Planar YUV */
00091         case VLC_FOURCC('I','4','4','4'):
00092         case VLC_FOURCC('I','4','2','2'):
00093         case VLC_FOURCC('I','4','2','0'):
00094         case VLC_FOURCC('Y','V','1','2'):
00095         case VLC_FOURCC('I','Y','U','V'):
00096         case VLC_FOURCC('I','4','1','1'):
00097         case VLC_FOURCC('I','4','1','0'):
00098         case VLC_FOURCC('Y','V','U','9'):
00099 
00100         /* Packed YUV */
00101         case VLC_FOURCC('Y','U','Y','2'):
00102         case VLC_FOURCC('U','Y','V','Y'):
00103 
00104         /* RGB */
00105         case VLC_FOURCC('R','V','3','2'):
00106         case VLC_FOURCC('R','V','2','4'):
00107         case VLC_FOURCC('R','V','1','6'):
00108         case VLC_FOURCC('R','V','1','5'):
00109             break;
00110 
00111         case VLC_FOURCC('y','v','1','2'):
00112             p_dec->fmt_in.i_codec = VLC_FOURCC('Y','V','1','2');
00113             break;
00114 
00115         default:
00116             return VLC_EGENERIC;
00117     }
00118 
00119     /* Allocate the memory needed to store the decoder's structure */
00120     if( ( p_dec->p_sys = p_sys =
00121           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00122     {
00123         msg_Err( p_dec, "out of memory" );
00124         return VLC_EGENERIC;
00125     }
00126     /* Misc init */
00127     p_dec->p_sys->b_packetizer = VLC_FALSE;
00128     p_sys->i_pts = 0;
00129     p_sys->b_invert = 0;
00130 
00131     if( (int)p_dec->fmt_in.video.i_height < 0 )
00132     {
00133         /* Frames are coded from bottom to top */
00134         p_dec->fmt_in.video.i_height =
00135             (unsigned int)(-(int)p_dec->fmt_in.video.i_height);
00136         p_sys->b_invert = VLC_TRUE;
00137     }
00138 
00139     if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height <= 0 )
00140     {
00141         msg_Err( p_dec, "invalid display size %dx%d",
00142                  p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );
00143         return VLC_EGENERIC;
00144     }
00145 
00146     /* Find out p_vdec->i_raw_size */
00147     vout_InitFormat( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec,
00148                      p_dec->fmt_in.video.i_width,
00149                      p_dec->fmt_in.video.i_height,
00150                      p_dec->fmt_in.video.i_aspect );
00151     p_sys->i_raw_size = p_dec->fmt_out.video.i_bits_per_pixel *
00152         p_dec->fmt_out.video.i_width * p_dec->fmt_out.video.i_height / 8;
00153 
00154     /* Set output properties */
00155     p_dec->fmt_out.i_cat = VIDEO_ES;
00156     p_dec->fmt_out.i_codec = p_dec->fmt_in.i_codec;
00157     if( !p_dec->fmt_in.video.i_aspect )
00158     {
00159         p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
00160             p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
00161     }
00162     else p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
00163 
00164     if( p_dec->fmt_in.video.i_rmask )
00165         p_dec->fmt_out.video.i_rmask = p_dec->fmt_in.video.i_rmask;
00166     if( p_dec->fmt_in.video.i_gmask )
00167         p_dec->fmt_out.video.i_gmask = p_dec->fmt_in.video.i_gmask;
00168     if( p_dec->fmt_in.video.i_bmask )
00169         p_dec->fmt_out.video.i_bmask = p_dec->fmt_in.video.i_bmask;
00170 
00171     /* Set callbacks */
00172     p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
00173         DecodeBlock;
00174     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
00175         DecodeBlock;
00176 
00177     return VLC_SUCCESS;
00178 }
00179 
00180 static int OpenPacketizer( vlc_object_t *p_this )
00181 {
00182     decoder_t *p_dec = (decoder_t*)p_this;
00183 
00184     int i_ret = OpenDecoder( p_this );
00185 
00186     if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
00187 
00188     return i_ret;
00189 }
00190 
00191 /****************************************************************************
00192  * DecodeBlock: the whole thing
00193  ****************************************************************************
00194  * This function must be fed with complete frames.
00195  ****************************************************************************/
00196 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00197 {
00198     decoder_sys_t *p_sys = p_dec->p_sys;
00199     block_t *p_block;
00200     void *p_buf;
00201 
00202     if( !pp_block || !*pp_block ) return NULL;
00203 
00204     p_block = *pp_block;
00205 
00206     if( !p_sys->i_pts && !p_block->i_pts && !p_block->i_dts )
00207     {
00208         /* We've just started the stream, wait for the first PTS. */
00209         block_Release( p_block );
00210         return NULL;
00211     }
00212 
00213     /* Date management */
00214     if( p_block->i_pts > 0 || p_block->i_dts > 0 )
00215     {
00216         if( p_block->i_pts > 0 ) p_sys->i_pts = p_block->i_pts;
00217         else if( p_block->i_dts > 0 ) p_sys->i_pts = p_block->i_dts;
00218     }
00219 
00220     if( p_block->i_buffer < p_sys->i_raw_size )
00221     {
00222         msg_Warn( p_dec, "invalid frame size (%d < %d)",
00223                   p_block->i_buffer, p_sys->i_raw_size );
00224 
00225         block_Release( p_block );
00226         return NULL;
00227     }
00228 
00229     if( p_sys->b_packetizer )
00230     {
00231         p_buf = SendFrame( p_dec, p_block );
00232     }
00233     else
00234     {
00235         p_buf = DecodeFrame( p_dec, p_block );
00236     }
00237 
00238     /* Date management: 1 frame per packet */
00239     p_sys->i_pts += ( I64C(1000000) * 1.0 / 25 /*FIXME*/ );
00240     *pp_block = NULL;
00241 
00242     return p_buf;
00243 }
00244 
00245 /*****************************************************************************
00246  * FillPicture:
00247  *****************************************************************************/
00248 static void FillPicture( decoder_t *p_dec, block_t *p_block, picture_t *p_pic )
00249 {
00250     uint8_t *p_src, *p_dst;
00251     int i_src, i_plane, i_line, i_width;
00252     decoder_sys_t *p_sys = p_dec->p_sys;
00253 
00254     p_src = p_block->p_buffer;
00255     i_src = p_block->i_buffer;
00256 
00257     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
00258     {
00259         p_dst = p_pic->p[i_plane].p_pixels;
00260         i_width = p_pic->p[i_plane].i_visible_pitch;
00261 
00262         if( p_sys->b_invert )
00263             p_src += (i_width * (p_pic->p[i_plane].i_visible_lines - 1));
00264 
00265         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
00266         {
00267             p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
00268             p_src += p_sys->b_invert ? -i_width : i_width;
00269             p_dst += p_pic->p[i_plane].i_pitch;
00270         }
00271 
00272         if( p_sys->b_invert )
00273             p_src += (i_width * (p_pic->p[i_plane].i_visible_lines + 1));
00274     }
00275 }
00276 
00277 /*****************************************************************************
00278  * DecodeFrame: decodes a video frame.
00279  *****************************************************************************/
00280 static picture_t *DecodeFrame( decoder_t *p_dec, block_t *p_block )
00281 {
00282     decoder_sys_t *p_sys = p_dec->p_sys;
00283     picture_t *p_pic;
00284 
00285     /* Get a new picture */
00286     p_pic = p_dec->pf_vout_buffer_new( p_dec );
00287     if( !p_pic )
00288     {
00289         block_Release( p_block );
00290         return NULL;
00291     }
00292 
00293     FillPicture( p_dec, p_block, p_pic );
00294 
00295     p_pic->date = p_sys->i_pts;
00296 
00297     block_Release( p_block );
00298     return p_pic;
00299 }
00300 
00301 /*****************************************************************************
00302  * SendFrame: send a video frame to the stream output.
00303  *****************************************************************************/
00304 static block_t *SendFrame( decoder_t *p_dec, block_t *p_block )
00305 {
00306     decoder_sys_t *p_sys = p_dec->p_sys;
00307 
00308     p_block->i_dts = p_block->i_pts = p_sys->i_pts;
00309 
00310     if( p_sys->b_invert )
00311     {
00312         picture_t pic;
00313         uint8_t *p_tmp, *p_pixels;
00314         int i, j;
00315 
00316         /* Fill in picture_t fields */
00317         vout_InitPicture( VLC_OBJECT(p_dec), &pic, p_dec->fmt_out.i_codec,
00318                           p_dec->fmt_out.video.i_width,
00319                           p_dec->fmt_out.video.i_height, VOUT_ASPECT_FACTOR );
00320 
00321         if( !pic.i_planes )
00322         {
00323             msg_Err( p_dec, "unsupported chroma" );
00324             return p_block;
00325         }
00326 
00327         p_tmp = malloc( pic.p[0].i_visible_pitch );
00328         p_pixels = p_block->p_buffer;
00329         for( i = 0; i < pic.i_planes; i++ )
00330         {
00331             int i_pitch = pic.p[i].i_visible_pitch;
00332             uint8_t *p_top = p_pixels;
00333             uint8_t *p_bottom = p_pixels + i_pitch *
00334                 (pic.p[i].i_visible_lines - 1);
00335 
00336             for( j = 0; j < pic.p[i].i_visible_lines / 2; j++ )
00337             {
00338                 p_dec->p_vlc->pf_memcpy( p_tmp, p_bottom,
00339                                          pic.p[i].i_visible_pitch  );
00340                 p_dec->p_vlc->pf_memcpy( p_bottom, p_top,
00341                                          pic.p[i].i_visible_pitch  );
00342                 p_dec->p_vlc->pf_memcpy( p_top, p_tmp,
00343                                          pic.p[i].i_visible_pitch  );
00344                 p_top += i_pitch;
00345                 p_bottom -= i_pitch;
00346             }
00347 
00348             p_pixels += i_pitch * pic.p[i].i_lines;
00349         }
00350         free( p_tmp );
00351     }
00352 
00353     return p_block;
00354 }
00355 
00356 /*****************************************************************************
00357  * CloseDecoder: decoder destruction
00358  *****************************************************************************/
00359 static void CloseDecoder( vlc_object_t *p_this )
00360 {
00361     decoder_t *p_dec = (decoder_t*)p_this;
00362     free( p_dec->p_sys );
00363 }

Generated on Tue Dec 20 10:14:29 2005 for vlc-0.8.4a by  doxygen 1.4.2