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

video.c

00001 /*****************************************************************************
00002  * video.c: video decoder using the ffmpeg library
00003  *****************************************************************************
00004  * Copyright (C) 1999-2001 the VideoLAN team
00005  * $Id: video.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 /*****************************************************************************
00026  * Preamble
00027  *****************************************************************************/
00028 #include <vlc/vlc.h>
00029 #include <vlc/decoder.h>
00030 #include <vlc/input.h>                  /* hmmm, just for INPUT_RATE_DEFAULT */
00031 
00032 /* ffmpeg header */
00033 #ifdef HAVE_FFMPEG_AVCODEC_H
00034 #   include <ffmpeg/avcodec.h>
00035 #else
00036 #   include <avcodec.h>
00037 #endif
00038 
00039 #include "ffmpeg.h"
00040 
00041 /*****************************************************************************
00042  * decoder_sys_t : decoder descriptor
00043  *****************************************************************************/
00044 struct decoder_sys_t
00045 {
00046     /* Common part between video and audio decoder */
00047     int i_cat;
00048     int i_codec_id;
00049     char *psz_namecodec;
00050 
00051     AVCodecContext      *p_context;
00052     AVCodec             *p_codec;
00053 
00054     /* Video decoder specific part */
00055     mtime_t input_pts;
00056     mtime_t input_dts;
00057     mtime_t i_pts;
00058 
00059     AVFrame          *p_ff_pic;
00060     BITMAPINFOHEADER *p_format;
00061 
00062     /* for frame skipping algo */
00063     int b_hurry_up;
00064     int i_frame_skip;
00065 
00066     /* how many decoded frames are late */
00067     int     i_late_frames;
00068     mtime_t i_late_frames_start;
00069 
00070     /* for direct rendering */
00071     int b_direct_rendering;
00072 
00073     vlc_bool_t b_has_b_frames;
00074 
00075     /* Hack to force display of still pictures */
00076     vlc_bool_t b_first_frame;
00077 
00078     int i_buffer_orig, i_buffer;
00079     char *p_buffer_orig, *p_buffer;
00080 
00081     /* Postprocessing handle */
00082     void *p_pp;
00083     vlc_bool_t b_pp;
00084     vlc_bool_t b_pp_async;
00085     vlc_bool_t b_pp_init;
00086 };
00087 
00088 /* FIXME (dummy palette for now) */
00089 static AVPaletteControl palette_control;
00090 
00091 /*****************************************************************************
00092  * Local prototypes
00093  *****************************************************************************/
00094 static void ffmpeg_InitCodec      ( decoder_t * );
00095 static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );
00096 static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );
00097 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
00098 
00099 static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
00100 {
00101     uint8_t *p = (uint8_t*)&fcc;
00102     return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
00103 }
00104 
00105 /*****************************************************************************
00106  * Local Functions
00107  *****************************************************************************/
00108 static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma )
00109 {
00110     switch( i_ff_chroma )
00111     {
00112     case PIX_FMT_YUV420P:
00113     case PIX_FMT_YUVJ420P: /* Hacky but better then chroma conversion */
00114         return VLC_FOURCC('I','4','2','0');
00115     case PIX_FMT_YUV422P:
00116     case PIX_FMT_YUVJ422P: /* Hacky but better then chroma conversion */
00117         return VLC_FOURCC('I','4','2','2');
00118     case PIX_FMT_YUV444P:
00119     case PIX_FMT_YUVJ444P: /* Hacky but better then chroma conversion */
00120         return VLC_FOURCC('I','4','4','4');
00121 
00122     case PIX_FMT_YUV422:
00123         return VLC_FOURCC('Y','U','Y','2');
00124 
00125     case PIX_FMT_RGB555:
00126         return VLC_FOURCC('R','V','1','5');
00127     case PIX_FMT_RGB565:
00128         return VLC_FOURCC('R','V','1','6');
00129     case PIX_FMT_RGB24:
00130         return VLC_FOURCC('R','V','2','4');
00131     case PIX_FMT_RGBA32:
00132         return VLC_FOURCC('R','V','3','2');
00133     case PIX_FMT_GRAY8:
00134         return VLC_FOURCC('G','R','E','Y');
00135 
00136     case PIX_FMT_YUV410P:
00137     case PIX_FMT_YUV411P:
00138     case PIX_FMT_BGR24:
00139     default:
00140         return 0;
00141     }
00142 }
00143 
00144 /* Returns a new picture buffer */
00145 static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,
00146                                             AVCodecContext *p_context )
00147 {
00148     decoder_sys_t *p_sys = p_dec->p_sys;
00149     picture_t *p_pic;
00150 
00151     p_dec->fmt_out.video.i_width = p_context->width;
00152     p_dec->fmt_out.video.i_height = p_context->height;
00153     p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
00154 
00155     if( !p_context->width || !p_context->height )
00156     {
00157         return NULL; /* invalid display size */
00158     }
00159 
00160     if( !p_dec->fmt_out.i_codec )
00161     {
00162         /* we make conversion if possible*/
00163         p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
00164     }
00165 
00166     /* If an aspect-ratio was specified in the input format then force it */
00167     if( p_dec->fmt_in.video.i_aspect )
00168     {
00169         p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
00170     }
00171     else
00172     {
00173 #if LIBAVCODEC_BUILD >= 4687
00174         p_dec->fmt_out.video.i_aspect =
00175             VOUT_ASPECT_FACTOR * ( av_q2d(p_context->sample_aspect_ratio) *
00176                 p_context->width / p_context->height );
00177         p_dec->fmt_out.video.i_sar_num = p_context->sample_aspect_ratio.num;
00178         p_dec->fmt_out.video.i_sar_den = p_context->sample_aspect_ratio.den;
00179 #else
00180         p_dec->fmt_out.video.i_aspect =
00181             VOUT_ASPECT_FACTOR * p_context->aspect_ratio;
00182 #endif
00183         if( p_dec->fmt_out.video.i_aspect == 0 )
00184         {
00185             p_dec->fmt_out.video.i_aspect =
00186                 VOUT_ASPECT_FACTOR * p_context->width / p_context->height;
00187         }
00188     }
00189 
00190 #if LIBAVCODEC_BUILD >= 4754
00191     if( p_context->time_base.num > 0 && p_context->time_base.den > 0 )
00192     {
00193         p_dec->fmt_out.video.i_frame_rate = p_context->time_base.den;
00194         p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num;
00195     }
00196 #else
00197     if( p_context->frame_rate > 0 && p_context->frame_rate_base > 0 )
00198     {
00199         p_dec->fmt_out.video.i_frame_rate = p_context->frame_rate;
00200         p_dec->fmt_out.video.i_frame_rate_base = p_context->frame_rate_base;
00201     }
00202 #endif
00203 
00204     p_pic = p_dec->pf_vout_buffer_new( p_dec );
00205 
00206 #ifdef LIBAVCODEC_PP
00207     if( p_sys->p_pp && p_sys->b_pp && !p_sys->b_pp_init )
00208     {
00209         E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width,
00210                           p_context->height, p_context->pix_fmt );
00211         p_sys->b_pp_init = VLC_TRUE;
00212     }
00213 #endif
00214 
00215     return p_pic;
00216 }
00217 
00218 /*****************************************************************************
00219  * InitVideo: initialize the video decoder
00220  *****************************************************************************
00221  * the ffmpeg codec will be opened, some memory allocated. The vout is not yet
00222  * opened (done after the first decoded frame).
00223  *****************************************************************************/
00224 int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
00225                       AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
00226 {
00227     decoder_sys_t *p_sys;
00228     vlc_value_t lockval;
00229     vlc_value_t val;
00230 
00231     var_Get( p_dec->p_libvlc, "avcodec", &lockval );
00232 
00233     /* Allocate the memory needed to store the decoder's structure */
00234     if( ( p_dec->p_sys = p_sys =
00235           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00236     {
00237         msg_Err( p_dec, "out of memory" );
00238         return VLC_EGENERIC;
00239     }
00240 
00241     p_dec->p_sys->p_context = p_context;
00242     p_dec->p_sys->p_codec = p_codec;
00243     p_dec->p_sys->i_codec_id = i_codec_id;
00244     p_dec->p_sys->psz_namecodec = psz_namecodec;
00245     p_sys->p_ff_pic = avcodec_alloc_frame();
00246 
00247     /* ***** Fill p_context with init values ***** */
00248     /* FIXME: remove when ffmpeg deals properly with avc1 */
00249     if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','v','c','1') )
00250     /* End FIXME */
00251     p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec );
00252     p_sys->p_context->width  = p_dec->fmt_in.video.i_width;
00253     p_sys->p_context->height = p_dec->fmt_in.video.i_height;
00254     p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel;
00255 
00256     /*  ***** Get configuration of ffmpeg plugin ***** */
00257     p_sys->p_context->workaround_bugs =
00258         config_GetInt( p_dec, "ffmpeg-workaround-bugs" );
00259     p_sys->p_context->error_resilience =
00260         config_GetInt( p_dec, "ffmpeg-error-resilience" );
00261 
00262     var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00263     var_Get( p_dec, "grayscale", &val );
00264     if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY;
00265 
00266     var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00267     var_Get( p_dec, "ffmpeg-vismv", &val );
00268 #if LIBAVCODEC_BUILD >= 4698
00269     if( val.i_int ) p_sys->p_context->debug_mv = val.i_int;
00270 #endif
00271 
00272     var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
00273     var_Get( p_dec, "ffmpeg-lowres", &val );
00274 #if LIBAVCODEC_BUILD >= 4723
00275     if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int;
00276 #endif
00277 
00278     /* ***** ffmpeg frame skipping ***** */
00279     var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00280     var_Get( p_dec, "ffmpeg-hurry-up", &val );
00281     p_sys->b_hurry_up = val.b_bool;
00282 
00283     /* ***** ffmpeg direct rendering ***** */
00284     p_sys->b_direct_rendering = 0;
00285     var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00286     var_Get( p_dec, "ffmpeg-dr", &val );
00287     if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
00288         ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) &&
00289         /* Apparently direct rendering doesn't work with YUV422P */
00290         p_sys->p_context->pix_fmt != PIX_FMT_YUV422P &&
00291         /* H264 uses too many reference frames */
00292         p_sys->i_codec_id != CODEC_ID_H264 &&
00293         !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) &&
00294 #if LIBAVCODEC_BUILD >= 4698
00295         !p_sys->p_context->debug_mv )
00296 #else
00297         1 )
00298 #endif
00299     {
00300         /* Some codecs set pix_fmt only after the 1st frame has been decoded,
00301          * so we need to do another check in ffmpeg_GetFrameBuf() */
00302         p_sys->b_direct_rendering = 1;
00303     }
00304 
00305 #ifdef LIBAVCODEC_PP
00306     p_sys->p_pp = NULL;
00307     p_sys->b_pp = p_sys->b_pp_async = p_sys->b_pp_init = VLC_FALSE;
00308     p_sys->p_pp = E_(OpenPostproc)( p_dec, &p_sys->b_pp_async );
00309 #endif
00310 
00311     /* ffmpeg doesn't properly release old pictures when frames are skipped */
00312     //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0;
00313     if( p_sys->b_direct_rendering )
00314     {
00315         msg_Dbg( p_dec, "using direct rendering" );
00316         p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
00317     }
00318 
00319     /* Always use our get_buffer wrapper so we can calculate the
00320      * PTS correctly */
00321     p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
00322     p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
00323     p_sys->p_context->opaque = p_dec;
00324 
00325     /* ***** init this codec with special data ***** */
00326     ffmpeg_InitCodec( p_dec );
00327 
00328     /* ***** misc init ***** */
00329     p_sys->input_pts = p_sys->input_dts = 0;
00330     p_sys->i_pts = 0;
00331     p_sys->b_has_b_frames = VLC_FALSE;
00332     p_sys->b_first_frame = VLC_TRUE;
00333     p_sys->i_late_frames = 0;
00334     p_sys->i_buffer = 0;
00335     p_sys->i_buffer_orig = 1;
00336     p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig );
00337 
00338     /* Set output properties */
00339     p_dec->fmt_out.i_cat = VIDEO_ES;
00340     p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );
00341 
00342     /* Setup palette */
00343 #if LIBAVCODEC_BUILD >= 4688
00344     if( p_dec->fmt_in.video.p_palette )
00345         p_sys->p_context->palctrl =
00346             (AVPaletteControl *)p_dec->fmt_in.video.p_palette;
00347     else
00348         p_sys->p_context->palctrl = &palette_control;
00349 #endif
00350 
00351     /* ***** Open the codec ***** */
00352     vlc_mutex_lock( lockval.p_address );
00353     if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 )
00354     {
00355         vlc_mutex_unlock( lockval.p_address );
00356         msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
00357         free( p_sys );
00358         return VLC_EGENERIC;
00359     }
00360     vlc_mutex_unlock( lockval.p_address );
00361     msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
00362 
00363 
00364     return VLC_SUCCESS;
00365 }
00366 
00367 /*****************************************************************************
00368  * DecodeVideo: Called to decode one or more frames
00369  *****************************************************************************/
00370 picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block )
00371 {
00372     decoder_sys_t *p_sys = p_dec->p_sys;
00373     int b_drawpicture;
00374     int b_null_size = VLC_FALSE;
00375     block_t *p_block;
00376 
00377     if( !pp_block || !*pp_block ) return NULL;
00378 
00379     if( !p_sys->p_context->extradata_size && p_dec->fmt_in.i_extra )
00380         ffmpeg_InitCodec( p_dec );
00381 
00382     p_block = *pp_block;
00383 
00384     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
00385     {
00386         p_sys->i_buffer = 0;
00387         p_sys->i_pts = 0; /* To make sure we recover properly */
00388 
00389         p_sys->input_pts = p_sys->input_dts = 0;
00390         p_sys->i_late_frames = 0;
00391 
00392         block_Release( p_block );
00393         return NULL;
00394     }
00395 
00396     if( p_block->i_flags & BLOCK_FLAG_PREROLL )
00397     {
00398         /* Do not care about late frames when prerolling
00399          * TODO avoid decoding of non reference frame
00400          * (ie all B except for H264 where it depends only on nal_ref_idc) */
00401         p_sys->i_late_frames = 0;
00402     }
00403 
00404     if( !p_dec->b_pace_control && p_sys->i_late_frames > 0 &&
00405         mdate() - p_sys->i_late_frames_start > I64C(5000000) )
00406     {
00407         if( p_sys->i_pts )
00408         {
00409             msg_Err( p_dec, "more than 5 seconds of late video -> "
00410                      "dropping frame (computer too slow ?)" );
00411             p_sys->i_pts = 0; /* To make sure we recover properly */
00412         }
00413         block_Release( p_block );
00414         p_sys->i_late_frames--;
00415         return NULL;
00416     }
00417 
00418     if( p_block->i_pts > 0 || p_block->i_dts > 0 )
00419     {
00420         p_sys->input_pts = p_block->i_pts;
00421         p_sys->input_dts = p_block->i_dts;
00422 
00423         /* Make sure we don't reuse the same timestamps twice */
00424         p_block->i_pts = p_block->i_dts = 0;
00425     }
00426 
00427     /* TODO implement it in a better way */
00428     /* A good idea could be to decode all I pictures and see for the other */
00429     if( !p_dec->b_pace_control &&
00430         p_sys->b_hurry_up && p_sys->i_late_frames > 4 )
00431     {
00432         b_drawpicture = 0;
00433         if( p_sys->i_late_frames < 8 )
00434         {
00435             p_sys->p_context->hurry_up = 2;
00436         }
00437         else
00438         {
00439             /* picture too late, won't decode
00440              * but break picture until a new I, and for mpeg4 ...*/
00441 
00442             p_sys->i_late_frames--; /* needed else it will never be decrease */
00443             block_Release( p_block );
00444             p_sys->i_buffer = 0;
00445             return NULL;
00446         }
00447     }
00448     else
00449     {
00450         if (!(p_block->i_flags & BLOCK_FLAG_PREROLL))
00451         {
00452             b_drawpicture = 1;
00453             p_sys->p_context->hurry_up = 0;
00454         }
00455         else
00456         {
00457             b_drawpicture = 0;
00458             p_sys->p_context->hurry_up = 1;
00459         }
00460     }
00461 
00462 
00463     if( p_sys->p_context->width <= 0 || p_sys->p_context->height <= 0 )
00464     {
00465         p_sys->p_context->hurry_up = 5;
00466         b_null_size = VLC_TRUE;
00467     }
00468 
00469     /*
00470      * Do the actual decoding now
00471      */
00472 
00473     /* Check if post-processing was enabled */
00474     p_sys->b_pp = p_sys->b_pp_async;
00475 
00476     /* Don't forget that ffmpeg requires a little more bytes
00477      * that the real frame size */
00478     if( p_block->i_buffer > 0 )
00479     {
00480         p_sys->i_buffer = p_block->i_buffer;
00481         if( p_sys->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE >
00482             p_sys->i_buffer_orig )
00483         {
00484             free( p_sys->p_buffer_orig );
00485             p_sys->i_buffer_orig =
00486                 p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE;
00487             p_sys->p_buffer_orig = malloc( p_sys->i_buffer_orig );
00488         }
00489         p_sys->p_buffer = p_sys->p_buffer_orig;
00490         p_sys->i_buffer = p_block->i_buffer;
00491         p_dec->p_vlc->pf_memcpy( p_sys->p_buffer, p_block->p_buffer,
00492                                  p_block->i_buffer );
00493         memset( p_sys->p_buffer + p_block->i_buffer, 0,
00494                 FF_INPUT_BUFFER_PADDING_SIZE );
00495 
00496         p_block->i_buffer = 0;
00497     }
00498 
00499     while( p_sys->i_buffer > 0 )
00500     {
00501         int i_used, b_gotpicture;
00502         picture_t *p_pic;
00503 
00504         i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
00505                                        &b_gotpicture,
00506                                        p_sys->p_buffer, p_sys->i_buffer );
00507         if( b_null_size && p_sys->p_context->width > 0 &&
00508             p_sys->p_context->height > 0 )
00509         {
00510             /* Reparse it to not drop the I frame */
00511             b_null_size = VLC_FALSE;
00512             p_sys->p_context->hurry_up = 0;
00513             i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
00514                                            &b_gotpicture,
00515                                            p_sys->p_buffer, p_sys->i_buffer );
00516         }
00517 
00518         if( i_used < 0 )
00519         {
00520             msg_Warn( p_dec, "cannot decode one frame (%d bytes)",
00521                       p_sys->i_buffer );
00522             block_Release( p_block );
00523             return NULL;
00524         }
00525         else if( i_used > p_sys->i_buffer )
00526         {
00527             i_used = p_sys->i_buffer;
00528         }
00529 
00530         /* Consumed bytes */
00531         p_sys->i_buffer -= i_used;
00532         p_sys->p_buffer += i_used;
00533 
00534         /* Nothing to display */
00535         if( !b_gotpicture )
00536         {
00537             if( i_used == 0 ) break;
00538             continue;
00539         }
00540 
00541         /* Update frame late count (except when doing preroll) */
00542         if( p_sys->i_pts && p_sys->i_pts <= mdate() &&
00543             !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
00544         {
00545             p_sys->i_late_frames++;
00546             if( p_sys->i_late_frames == 1 )
00547                 p_sys->i_late_frames_start = mdate();
00548         }
00549         else
00550         {
00551             p_sys->i_late_frames = 0;
00552         }
00553 
00554         if( !b_drawpicture || !p_sys->p_ff_pic->linesize[0] )
00555         {
00556             /* Do not display the picture */
00557             continue;
00558         }
00559 
00560         if( !p_sys->p_ff_pic->opaque )
00561         {
00562             /* Get a new picture */
00563             p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
00564             if( !p_pic )
00565             {
00566                 block_Release( p_block );
00567                 return NULL;
00568             }
00569 
00570             /* Fill p_picture_t from AVVideoFrame and do chroma conversion
00571              * if needed */
00572             ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic );
00573         }
00574         else
00575         {
00576             p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
00577         }
00578 
00579         /* Set the PTS */
00580         if( p_sys->p_ff_pic->pts ) p_sys->i_pts = p_sys->p_ff_pic->pts;
00581 
00582         /* Sanity check (seems to be needed for some streams) */
00583         if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
00584         {
00585             p_sys->b_has_b_frames = VLC_TRUE;
00586         }
00587 
00588         if( !p_dec->fmt_in.video.i_aspect )
00589         {
00590             /* Fetch again the aspect ratio in case it changed */
00591 #if LIBAVCODEC_BUILD >= 4687
00592             p_dec->fmt_out.video.i_aspect =
00593                 VOUT_ASPECT_FACTOR
00594                     * ( av_q2d(p_sys->p_context->sample_aspect_ratio)
00595                     * p_sys->p_context->width / p_sys->p_context->height );
00596             p_dec->fmt_out.video.i_sar_num
00597                 = p_sys->p_context->sample_aspect_ratio.num;
00598             p_dec->fmt_out.video.i_sar_den
00599                 = p_sys->p_context->sample_aspect_ratio.den;
00600 #else
00601             p_dec->fmt_out.video.i_aspect =
00602                 VOUT_ASPECT_FACTOR * p_sys->p_context->aspect_ratio;
00603 #endif
00604             if( p_dec->fmt_out.video.i_aspect == 0 )
00605             {
00606                 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR
00607                     * p_sys->p_context->width / p_sys->p_context->height;
00608             }
00609         }
00610 
00611         /* Send decoded frame to vout */
00612         if( p_sys->i_pts )
00613         {
00614             p_pic->date = p_sys->i_pts;
00615 
00616             /* interpolate the next PTS */
00617 #if LIBAVCODEC_BUILD >= 4754
00618             if( p_dec->fmt_in.video.i_frame_rate > 0 &&
00619                 p_dec->fmt_in.video.i_frame_rate_base > 0 )
00620             {
00621                 p_sys->i_pts += I64C(1000000) *
00622                     (2 + p_sys->p_ff_pic->repeat_pict) *
00623                     p_dec->fmt_in.video.i_frame_rate_base *
00624                     p_block->i_rate / INPUT_RATE_DEFAULT /
00625                     (2 * p_dec->fmt_in.video.i_frame_rate);
00626             }
00627             else if( p_sys->p_context->time_base.den > 0 )
00628             {
00629                 p_sys->i_pts += I64C(1000000) *
00630                     (2 + p_sys->p_ff_pic->repeat_pict) *
00631                     p_sys->p_context->time_base.num *
00632                     p_block->i_rate / INPUT_RATE_DEFAULT /
00633                     (2 * p_sys->p_context->time_base.den);
00634             }
00635 #else
00636             if( p_sys->p_context->frame_rate > 0 )
00637             {
00638                 p_sys->i_pts += I64C(1000000) *
00639                     (2 + p_sys->p_ff_pic->repeat_pict) *
00640                     p_sys->p_context->frame_rate_base *
00641                     p_block->i_rate / INPUT_RATE_DEFAULT /
00642                     (2 * p_sys->p_context->frame_rate);
00643             }
00644 #endif
00645 
00646             if( p_sys->b_first_frame )
00647             {
00648                 /* Hack to force display of still pictures */
00649                 p_sys->b_first_frame = VLC_FALSE;
00650                 p_pic->b_force = VLC_TRUE;
00651             }
00652 
00653             p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict;
00654 #if LIBAVCODEC_BUILD >= 4685
00655             p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame;
00656             p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first;
00657 #endif
00658 
00659             return p_pic;
00660         }
00661         else
00662         {
00663             p_dec->pf_vout_buffer_del( p_dec, p_pic );
00664         }
00665     }
00666 
00667     block_Release( p_block );
00668     return NULL;
00669 }
00670 
00671 /*****************************************************************************
00672  * EndVideo: decoder destruction
00673  *****************************************************************************
00674  * This function is called when the thread ends after a successful
00675  * initialization.
00676  *****************************************************************************/
00677 void E_(EndVideoDec)( decoder_t *p_dec )
00678 {
00679     decoder_sys_t *p_sys = p_dec->p_sys;
00680 
00681     if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
00682 
00683 #ifdef LIBAVCODEC_PP
00684     E_(ClosePostproc)( p_dec, p_sys->p_pp );
00685 #endif
00686 
00687     free( p_sys->p_buffer_orig );
00688 }
00689 
00690 /*****************************************************************************
00691  * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg
00692  *****************************************************************************/
00693 static void ffmpeg_InitCodec( decoder_t *p_dec )
00694 {
00695     decoder_sys_t *p_sys = p_dec->p_sys;
00696     int i_size = p_dec->fmt_in.i_extra;
00697 
00698     if( !i_size ) return;
00699 
00700     if( p_sys->i_codec_id == CODEC_ID_SVQ3 )
00701     {
00702         uint8_t *p;
00703 
00704         p_sys->p_context->extradata_size = i_size + 12;
00705         p = p_sys->p_context->extradata  =
00706             malloc( p_sys->p_context->extradata_size );
00707 
00708         memcpy( &p[0],  "SVQ3", 4 );
00709         memset( &p[4], 0, 8 );
00710         memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );
00711 
00712         /* Now remove all atoms before the SMI one */
00713         if( p_sys->p_context->extradata_size > 0x5a &&
00714             strncmp( &p[0x56], "SMI ", 4 ) )
00715         {
00716             uint8_t *psz = &p[0x52];
00717 
00718             while( psz < &p[p_sys->p_context->extradata_size - 8] )
00719             {
00720                 int i_size = GetDWBE( psz );
00721                 if( i_size <= 1 )
00722                 {
00723                     /* FIXME handle 1 as long size */
00724                     break;
00725                 }
00726                 if( !strncmp( &psz[4], "SMI ", 4 ) )
00727                 {
00728                     memmove( &p[0x52], psz,
00729                              &p[p_sys->p_context->extradata_size] - psz );
00730                     break;
00731                 }
00732 
00733                 psz += i_size;
00734             }
00735         }
00736     }
00737     else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '0' ) ||
00738              p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '3' ) ||
00739              p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '2', '0' ) )
00740     {
00741         if( p_dec->fmt_in.i_extra == 8 )
00742         {
00743             p_sys->p_context->extradata_size = 8;
00744             p_sys->p_context->extradata = malloc( 8 );
00745 
00746             memcpy( p_sys->p_context->extradata,
00747                     p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
00748             p_sys->p_context->sub_id= ((uint32_t*)p_dec->fmt_in.p_extra)[1];
00749 
00750             msg_Warn( p_dec, "using extra data for RV codec sub_id=%08x",
00751                       p_sys->p_context->sub_id );
00752         }
00753     }
00754     else
00755     {
00756         p_sys->p_context->extradata_size = i_size;
00757         p_sys->p_context->extradata =
00758             malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
00759         memcpy( p_sys->p_context->extradata,
00760                 p_dec->fmt_in.p_extra, i_size );
00761         memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
00762                 0, FF_INPUT_BUFFER_PADDING_SIZE );
00763     }
00764 }
00765 
00766 /*****************************************************************************
00767  * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
00768  *                     picture_t structure (when not in direct rendering mode).
00769  *****************************************************************************/
00770 static void ffmpeg_CopyPicture( decoder_t *p_dec,
00771                                 picture_t *p_pic, AVFrame *p_ff_pic )
00772 {
00773     decoder_sys_t *p_sys = p_dec->p_sys;
00774 
00775     if( ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) )
00776     {
00777         int i_plane, i_size, i_line;
00778         uint8_t *p_dst, *p_src;
00779         int i_src_stride, i_dst_stride;
00780 
00781 #ifdef LIBAVCODEC_PP
00782         if( p_sys->p_pp && p_sys->b_pp )
00783             E_(PostprocPict)( p_dec, p_sys->p_pp, p_pic, p_ff_pic );
00784         else
00785 #endif
00786         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
00787         {
00788             p_src  = p_ff_pic->data[i_plane];
00789             p_dst = p_pic->p[i_plane].p_pixels;
00790             i_src_stride = p_ff_pic->linesize[i_plane];
00791             i_dst_stride = p_pic->p[i_plane].i_pitch;
00792 
00793             i_size = __MIN( i_src_stride, i_dst_stride );
00794             for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;
00795                  i_line++ )
00796             {
00797                 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_size );
00798                 p_src += i_src_stride;
00799                 p_dst += i_dst_stride;
00800             }
00801         }
00802     }
00803     else
00804     {
00805         AVPicture dest_pic;
00806         int i;
00807 
00808         /* we need to convert to I420 */
00809         switch( p_sys->p_context->pix_fmt )
00810         {
00811         case PIX_FMT_YUV410P:
00812         case PIX_FMT_YUV411P:
00813         case PIX_FMT_BGR24:
00814         case PIX_FMT_PAL8:
00815             for( i = 0; i < p_pic->i_planes; i++ )
00816             {
00817                 dest_pic.data[i] = p_pic->p[i].p_pixels;
00818                 dest_pic.linesize[i] = p_pic->p[i].i_pitch;
00819             }
00820             img_convert( &dest_pic, PIX_FMT_YUV420P,
00821                          (AVPicture *)p_ff_pic,
00822                          p_sys->p_context->pix_fmt,
00823                          p_sys->p_context->width,
00824                          p_sys->p_context->height );
00825             break;
00826         default:
00827             msg_Err( p_dec, "don't know how to convert chroma %i",
00828                      p_sys->p_context->pix_fmt );
00829             p_dec->b_error = 1;
00830             break;
00831         }
00832     }
00833 }
00834 
00835 /*****************************************************************************
00836  * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
00837  *****************************************************************************
00838  * It is used for direct rendering as well as to get the right PTS for each
00839  * decoded picture (even in indirect rendering mode).
00840  *****************************************************************************/
00841 static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
00842                                AVFrame *p_ff_pic )
00843 {
00844     decoder_t *p_dec = (decoder_t *)p_context->opaque;
00845     decoder_sys_t *p_sys = p_dec->p_sys;
00846     picture_t *p_pic;
00847 
00848     /* Set picture PTS */
00849     if( p_sys->input_pts )
00850     {
00851         p_ff_pic->pts = p_sys->input_pts;
00852     }
00853     else if( p_sys->input_dts )
00854     {
00855         /* Some demuxers only set the dts so let's try to find a useful
00856          * timestamp from this */
00857         if( !p_context->has_b_frames || !p_sys->b_has_b_frames ||
00858             !p_ff_pic->reference || !p_sys->i_pts )
00859         {
00860             p_ff_pic->pts = p_sys->input_dts;
00861         }
00862         else p_ff_pic->pts = 0;
00863     }
00864     else p_ff_pic->pts = 0;
00865 
00866     if( p_sys->i_pts ) /* make sure 1st frame has a pts > 0 */
00867     {
00868         p_sys->input_pts = p_sys->input_dts = 0;
00869     }
00870 
00871     p_ff_pic->opaque = 0;
00872 
00873     /* Not much to do in indirect rendering mode */
00874     if( !p_sys->b_direct_rendering || p_sys->b_pp )
00875     {
00876         return avcodec_default_get_buffer( p_context, p_ff_pic );
00877     }
00878 
00879     /* Some codecs set pix_fmt only after the 1st frame has been decoded,
00880      * so this check is necessary. */
00881     if( !ffmpeg_PixFmtToChroma( p_context->pix_fmt ) ||
00882         p_sys->p_context->width % 16 || p_sys->p_context->height % 16 )
00883     {
00884         msg_Dbg( p_dec, "disabling direct rendering" );
00885         p_sys->b_direct_rendering = 0;
00886         return avcodec_default_get_buffer( p_context, p_ff_pic );
00887     }
00888 
00889     /* Get a new picture */
00890     //p_sys->p_vout->render.b_allow_modify_pics = 0;
00891     p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
00892     if( !p_pic )
00893     {
00894         p_sys->b_direct_rendering = 0;
00895         return avcodec_default_get_buffer( p_context, p_ff_pic );
00896     }
00897     p_sys->p_context->draw_horiz_band = NULL;
00898 
00899     p_ff_pic->opaque = (void*)p_pic;
00900     p_ff_pic->type = FF_BUFFER_TYPE_USER;
00901     p_ff_pic->data[0] = p_pic->p[0].p_pixels;
00902     p_ff_pic->data[1] = p_pic->p[1].p_pixels;
00903     p_ff_pic->data[2] = p_pic->p[2].p_pixels;
00904     p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */
00905 
00906     p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
00907     p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
00908     p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
00909     p_ff_pic->linesize[3] = 0;
00910 
00911     if( p_ff_pic->reference != 0 )
00912     {
00913         p_dec->pf_picture_link( p_dec, p_pic );
00914     }
00915 
00916     /* FIXME what is that, should give good value */
00917     p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
00918 
00919     return 0;
00920 }
00921 
00922 static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
00923                                     AVFrame *p_ff_pic )
00924 {
00925     decoder_t *p_dec = (decoder_t *)p_context->opaque;
00926     picture_t *p_pic;
00927 
00928     if( !p_ff_pic->opaque )
00929     {
00930         avcodec_default_release_buffer( p_context, p_ff_pic );
00931         return;
00932     }
00933 
00934     p_pic = (picture_t*)p_ff_pic->opaque;
00935 
00936     p_ff_pic->data[0] = NULL;
00937     p_ff_pic->data[1] = NULL;
00938     p_ff_pic->data[2] = NULL;
00939     p_ff_pic->data[3] = NULL;
00940 
00941     if( p_ff_pic->reference != 0 )
00942     {
00943         p_dec->pf_picture_unlink( p_dec, p_pic );
00944     }
00945 }

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