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

dirac.c

00001 /*****************************************************************************
00002  * dirac.c: Dirac decoder/encoder module making use of libdirac.
00003  *          (http://www.bbc.co.uk/rd/projects/dirac/index.shtml)
00004  *****************************************************************************
00005  * Copyright (C) 1999-2001 the VideoLAN team
00006  * $Id: dirac.c 11664 2005-07-09 06:17:09Z courmisch $
00007  *
00008  * Authors: 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/sout.h>
00031 
00032 #include <libdirac_decoder/dirac_parser.h>
00033 #include <libdirac_encoder/dirac_encoder.h>
00034 
00035 /*****************************************************************************
00036  * decoder_sys_t : theora decoder descriptor
00037  *****************************************************************************/
00038 struct decoder_sys_t
00039 {
00040     /*
00041      * Dirac properties
00042      */
00043     dirac_decoder_t *p_dirac;
00044 };
00045 
00046 /*****************************************************************************
00047  * Local prototypes
00048  *****************************************************************************/
00049 static int        OpenDecoder  ( vlc_object_t * );
00050 static void       CloseDecoder ( vlc_object_t * );
00051 static picture_t *DecodeBlock  ( decoder_t *p_dec, block_t **pp_block );
00052 
00053 static int  OpenEncoder( vlc_object_t *p_this );
00054 static void CloseEncoder( vlc_object_t *p_this );
00055 static block_t *Encode( encoder_t *p_enc, picture_t *p_pict );
00056 
00057 #define ENC_CFG_PREFIX "sout-dirac-"
00058 
00059 static const char *ppsz_enc_options[] = {
00060     "quality", NULL
00061 };
00062 
00063 /*****************************************************************************
00064  * Module descriptor
00065  *****************************************************************************/
00066 #define ENC_QUALITY_TEXT N_("Encoding quality")
00067 #define ENC_QUALITY_LONGTEXT N_( \
00068   "Allows you to specify a quality between 1.0 (low) and 10.0 (high)." )
00069 
00070 vlc_module_begin();
00071     set_category( CAT_INPUT );
00072     set_subcategory( SUBCAT_INPUT_VCODEC );
00073     set_description( _("Dirac video decoder") );
00074     set_capability( "decoder", 100 );
00075     set_callbacks( OpenDecoder, CloseDecoder );
00076     add_shortcut( "dirac" );
00077 
00078     add_submodule();
00079     set_description( _("Dirac video encoder") );
00080     set_capability( "encoder", 100 );
00081     set_callbacks( OpenEncoder, CloseEncoder );
00082     add_shortcut( "dirac" );
00083     add_float( ENC_CFG_PREFIX "quality", 7.0, NULL, ENC_QUALITY_TEXT,
00084                ENC_QUALITY_LONGTEXT, VLC_FALSE );
00085 
00086 vlc_module_end();
00087 
00088 /*****************************************************************************
00089  * OpenDecoder: probe the decoder and return score
00090  *****************************************************************************/
00091 static int OpenDecoder( vlc_object_t *p_this )
00092 {
00093     decoder_t *p_dec = (decoder_t*)p_this;
00094     decoder_sys_t *p_sys;
00095     dirac_decoder_t *p_dirac;
00096 
00097     if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','r','a','c') )
00098     {
00099         return VLC_EGENERIC;
00100     }
00101 
00102     /* Initialise the dirac decoder */
00103     if( !(p_dirac = dirac_decoder_init(0)) ) return VLC_EGENERIC;
00104 
00105     /* Allocate the memory needed to store the decoder's structure */
00106     if( ( p_dec->p_sys = p_sys =
00107           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
00108     {
00109         msg_Err( p_dec, "out of memory" );
00110         return VLC_EGENERIC;
00111     }
00112 
00113     p_sys->p_dirac = p_dirac;
00114 
00115     /* Set output properties */
00116     p_dec->fmt_out.i_cat = VIDEO_ES;
00117     p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
00118 
00119     /* Set callbacks */
00120     p_dec->pf_decode_video = DecodeBlock;
00121 
00122     return VLC_SUCCESS;
00123 }
00124 
00125 static void FreeFrameBuffer( dirac_decoder_t *p_dirac )
00126 {
00127     if( p_dirac->fbuf )
00128     {
00129         int i;
00130         for( i = 0; i < 3; i++ )
00131         {
00132             if( p_dirac->fbuf->buf[i] ) free( p_dirac->fbuf->buf[i] );
00133             p_dirac->fbuf->buf[i] = 0;
00134         }
00135     }
00136 }
00137 
00138 /*****************************************************************************
00139  * GetNewPicture: Get a new picture from the vout and copy the decoder output
00140  *****************************************************************************/
00141 static picture_t *GetNewPicture( decoder_t *p_dec )
00142 {
00143     decoder_sys_t *p_sys = p_dec->p_sys;
00144     picture_t *p_pic;
00145     int i_plane;
00146 
00147     p_dec->fmt_out.i_codec =
00148         p_sys->p_dirac->seq_params.chroma == format411 ?
00149         VLC_FOURCC('I','4','1','1') :
00150         p_sys->p_dirac->seq_params.chroma == format420 ?
00151         VLC_FOURCC('I','4','2','0') :
00152         p_sys->p_dirac->seq_params.chroma == format422 ?
00153         VLC_FOURCC('I','4','2','2') : 0;
00154 
00155     p_dec->fmt_out.video.i_visible_width =
00156     p_dec->fmt_out.video.i_width = p_sys->p_dirac->seq_params.width;
00157     p_dec->fmt_out.video.i_visible_height =
00158     p_dec->fmt_out.video.i_height = p_sys->p_dirac->seq_params.height;
00159     p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * 4 / 3;
00160 
00161     p_dec->fmt_out.video.i_frame_rate =
00162         p_sys->p_dirac->seq_params.frame_rate.numerator;
00163     p_dec->fmt_out.video.i_frame_rate_base =
00164         p_sys->p_dirac->seq_params.frame_rate.denominator;
00165 
00166     /* Get a new picture */
00167     p_pic = p_dec->pf_vout_buffer_new( p_dec );
00168 
00169     if( p_pic == NULL ) return NULL;
00170 
00171     p_pic->b_progressive = !p_sys->p_dirac->seq_params.interlace;
00172     p_pic->b_top_field_first = p_sys->p_dirac->seq_params.topfieldfirst;
00173     p_pic->i_nb_fields = 2;
00174 
00175     /* Copy picture stride by stride */
00176     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
00177     {
00178         int i_line, i_width, i_dst_stride;
00179         uint8_t *p_src = p_sys->p_dirac->fbuf->buf[i_plane];
00180         uint8_t *p_dst = p_pic->p[i_plane].p_pixels;
00181 
00182         i_width = p_pic->p[i_plane].i_visible_pitch;
00183         i_dst_stride = p_pic->p[i_plane].i_pitch;
00184 
00185         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
00186         {
00187             p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
00188             p_src += i_width;
00189             p_dst += i_dst_stride;
00190         }
00191     }
00192 
00193     return p_pic;
00194 }
00195 
00196 /*****************************************************************************
00197  * CloseDecoder: decoder destruction
00198  *****************************************************************************/
00199 static void CloseDecoder( vlc_object_t *p_this )
00200 {
00201     decoder_t *p_dec = (decoder_t *)p_this;
00202     decoder_sys_t *p_sys = p_dec->p_sys;
00203 
00204     FreeFrameBuffer( p_sys->p_dirac );
00205     dirac_decoder_close( p_sys->p_dirac );
00206     free( p_sys );
00207 }
00208 
00209 /****************************************************************************
00210  * DecodeBlock: the whole thing
00211  ****************************************************************************
00212  * This function must be fed with complete frames.
00213  ****************************************************************************/
00214 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
00215 {
00216     decoder_sys_t *p_sys = p_dec->p_sys;
00217     dirac_decoder_state_t state;
00218     picture_t *p_pic;
00219     block_t *p_block;
00220 
00221     if( !pp_block || !*pp_block ) return NULL;
00222 
00223     p_block = *pp_block;
00224 
00225     while( 1 )
00226     {
00227         state = dirac_parse( p_sys->p_dirac );
00228 
00229         switch( state )
00230         {
00231         case STATE_BUFFER:
00232             if( !p_block->i_buffer )
00233             {
00234                 block_Release( p_block );
00235                 return NULL;
00236             }
00237 
00238             msg_Dbg( p_dec, "STATE_BUFFER" );
00239             dirac_buffer( p_sys->p_dirac, p_block->p_buffer,
00240                           p_block->p_buffer + p_block->i_buffer );
00241 
00242             p_block->i_buffer = 0;
00243             break;
00244 
00245         case STATE_SEQUENCE:
00246         {
00247             /* Initialize video output */
00248             uint8_t *buf[3];
00249 
00250             msg_Dbg( p_dec, "%dx%d, chroma %i, %f fps",
00251                      p_sys->p_dirac->seq_params.width,
00252                      p_sys->p_dirac->seq_params.height,
00253                      p_sys->p_dirac->seq_params.chroma,
00254                      (float)p_sys->p_dirac->seq_params.frame_rate.numerator/
00255                      p_sys->p_dirac->seq_params.frame_rate.denominator );
00256 
00257             FreeFrameBuffer( p_sys->p_dirac );
00258             buf[0] = malloc( p_sys->p_dirac->seq_params.width *
00259                              p_sys->p_dirac->seq_params.height );
00260             buf[1] = malloc( p_sys->p_dirac->seq_params.chroma_width *
00261                              p_sys->p_dirac->seq_params.chroma_height );
00262             buf[2] = malloc( p_sys->p_dirac->seq_params.chroma_width *
00263                              p_sys->p_dirac->seq_params.chroma_height );
00264 
00265             dirac_set_buf( p_sys->p_dirac, buf, NULL );
00266             break;
00267         }
00268 
00269         case STATE_SEQUENCE_END:
00270             msg_Dbg( p_dec, "SEQUENCE_END" );
00271             FreeFrameBuffer( p_sys->p_dirac );
00272             break;
00273 
00274         case STATE_PICTURE_START:
00275             msg_Dbg( p_dec, "PICTURE_START: frame_type=%i frame_num=%d",
00276                      p_sys->p_dirac->frame_params.ftype,
00277                      p_sys->p_dirac->frame_params.fnum );
00278             break;
00279 
00280         case STATE_PICTURE_AVAIL:
00281             msg_Dbg( p_dec, "PICTURE_AVAI : frame_type=%i frame_num=%d",
00282                      p_sys->p_dirac->frame_params.ftype,
00283                      p_sys->p_dirac->frame_params.fnum );
00284 
00285             /* Picture available for display */
00286             p_pic = GetNewPicture( p_dec );
00287             p_pic->date = p_block->i_pts > 0 ? p_block->i_pts : p_block->i_dts;
00288             p_pic->b_force = 1; // HACK
00289             return p_pic;
00290             break;
00291 
00292         case STATE_INVALID:
00293             msg_Dbg( p_dec, "STATE_INVALID" );
00294             break;
00295 
00296         default:
00297             break;
00298         }
00299     }
00300 
00301     /* Never reached */
00302     return NULL;
00303 }
00304 
00305 /*****************************************************************************
00306  * encoder_sys_t : dirac encoder descriptor
00307  *****************************************************************************/
00308 #define ENC_BUFSIZE 1024*1024
00309 struct encoder_sys_t
00310 {
00311     /*
00312      * Dirac properties
00313      */
00314     dirac_encoder_t *p_dirac;
00315     dirac_encoder_context_t ctx;
00316 
00317     uint8_t *p_buffer_in;
00318     int i_buffer_in;
00319 
00320     uint8_t p_buffer_out[ENC_BUFSIZE];
00321 };
00322 
00323 /*****************************************************************************
00324  * OpenEncoder: probe the encoder and return score
00325  *****************************************************************************/
00326 static int OpenEncoder( vlc_object_t *p_this )
00327 {
00328     encoder_t *p_enc = (encoder_t *)p_this;
00329     encoder_sys_t *p_sys = p_enc->p_sys;
00330     vlc_value_t val;
00331     float f_quality;
00332 
00333     if( p_enc->fmt_out.i_codec != VLC_FOURCC('d','r','a','c') &&
00334         !p_enc->b_force )
00335     {
00336         return VLC_EGENERIC;
00337     }
00338 
00339     /* Allocate the memory needed to store the decoder's structure */
00340     if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
00341     {
00342         msg_Err( p_enc, "out of memory" );
00343         return VLC_EGENERIC;
00344     }
00345     memset( p_sys, 0, sizeof(encoder_sys_t) );
00346     p_enc->p_sys = p_sys;
00347 
00348     p_enc->pf_encode_video = Encode;
00349     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
00350     p_enc->fmt_in.video.i_bits_per_pixel = 12;
00351     p_enc->fmt_out.i_codec = VLC_FOURCC('d','r','a','c');
00352 
00353     sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
00354 
00355     /* Initialse the encoder context with the presets for SD576 - Standard
00356      * Definition Digital (some parameters will be overwritten later on) */
00357     dirac_encoder_context_init( &p_sys->ctx, SD576 );
00358 
00359     /* Override parameters if required */
00360     p_sys->ctx.seq_params.width = p_enc->fmt_in.video.i_width;
00361     p_sys->ctx.seq_params.height = p_enc->fmt_in.video.i_height;
00362     p_sys->ctx.seq_params.chroma = format420;
00363     p_sys->ctx.seq_params.frame_rate.numerator =
00364         p_enc->fmt_in.video.i_frame_rate;
00365     p_sys->ctx.seq_params.frame_rate.denominator =
00366         p_enc->fmt_in.video.i_frame_rate_base;
00367     p_sys->ctx.seq_params.interlace = 0;
00368     p_sys->ctx.seq_params.topfieldfirst = 0;
00369 
00370     var_Get( p_enc, ENC_CFG_PREFIX "quality", &val );
00371     f_quality = val.f_float;
00372     if( f_quality > 10 ) f_quality = 10;
00373     if( f_quality < 1 ) f_quality = 1;
00374     p_sys->ctx.enc_params.qf = f_quality;
00375 
00376     /* Initialise the encoder with the encoder context */
00377     p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 );
00378 
00379     /* Set the buffer size for the encoded picture */
00380     p_sys->i_buffer_in = p_enc->fmt_in.video.i_width *
00381         p_enc->fmt_in.video.i_height * 3 / 2;
00382     p_sys->p_buffer_in = malloc( p_sys->i_buffer_in );
00383 
00384     return VLC_SUCCESS;
00385 }
00386 
00387 /****************************************************************************
00388  * Encode: the whole thing
00389  ****************************************************************************
00390  * This function spits out ogg packets.
00391  ****************************************************************************/
00392 static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
00393 {
00394     encoder_sys_t *p_sys = p_enc->p_sys;
00395     block_t *p_block, *p_chain = NULL;
00396     int i_plane, i_line, i_width, i_src_stride;
00397     uint8_t *p_dst;
00398 
00399     /* Copy input picture in encoder input buffer (stride by stride) */
00400     p_dst = p_sys->p_buffer_in;
00401     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
00402     {
00403         uint8_t *p_src = p_pic->p[i_plane].p_pixels;
00404         i_width = p_pic->p[i_plane].i_visible_pitch;
00405         i_src_stride = p_pic->p[i_plane].i_pitch;
00406 
00407         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
00408         {
00409             p_enc->p_vlc->pf_memcpy( p_dst, p_src, i_width );
00410             p_dst += i_width;
00411             p_src += i_src_stride;
00412         }
00413     }
00414 
00415     /* Load one frame of data into encoder */
00416     if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
00417                             p_sys->i_buffer_in ) >= 0 )
00418     {
00419         dirac_encoder_state_t state;
00420 
00421         msg_Dbg( p_enc, "dirac_encoder_load" );
00422 
00423         /* Retrieve encoded frames from encoder */
00424         do
00425         {
00426             p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
00427             p_sys->p_dirac->enc_buf.size = ENC_BUFSIZE;
00428             state = dirac_encoder_output( p_sys->p_dirac );
00429             msg_Dbg( p_enc, "dirac_encoder_output: %i", state );
00430             switch( state )
00431             {
00432             case ENC_STATE_AVAIL:
00433                  // Encoded frame available in encoder->enc_buf
00434                  // Encoded frame params available in enccoder->enc_fparams
00435                  // Encoded frame stats available in enccoder->enc_fstats
00436                  p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
00437                  memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
00438                          p_sys->p_dirac->enc_buf.size );
00439                  p_block->i_dts = p_block->i_pts = p_pic->date;
00440                  block_ChainAppend( &p_chain, p_block );
00441 
00442                  break;
00443             case ENC_STATE_BUFFER:
00444                 break;
00445             case ENC_STATE_INVALID:
00446             default:
00447                 break;
00448             }
00449             if( p_sys->p_dirac->decoded_frame_avail )
00450             {
00451                 //locally decoded frame is available in 
00452                 //encoder->dec_buf
00453                 //locally decoded frame parameters available
00454                 //in encoder->dec_fparams
00455             }
00456             if( p_sys->p_dirac->instr_data_avail )
00457             {
00458                 //Instrumentation data (motion vectors etc.)
00459                 //available in encoder->instr
00460             }
00461 
00462         } while( state == ENC_STATE_AVAIL );
00463     }
00464     else
00465     {
00466         msg_Dbg( p_enc, "dirac_encoder_load() error" );
00467     }
00468 
00469     return p_chain;
00470 }
00471 
00472 /*****************************************************************************
00473  * CloseEncoder: dirac encoder destruction
00474  *****************************************************************************/
00475 static void CloseEncoder( vlc_object_t *p_this )
00476 {
00477     encoder_t *p_enc = (encoder_t *)p_this;
00478     encoder_sys_t *p_sys = p_enc->p_sys;
00479 
00480     msg_Dbg( p_enc, "resulting bit-rate: %i bits/sec",
00481              p_sys->p_dirac->enc_seqstats.bit_rate );
00482 
00483     /* Free the encoder resources */
00484     dirac_encoder_close( p_sys->p_dirac );
00485  
00486     free( p_sys->p_buffer_in );
00487     free( p_sys );
00488 }

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