xvid.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:8k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * xvid.c: a decoder for libxvidcore, the Xvid video codec
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: xvid.c 6961 2004-03-05 17:34:23Z sam $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <vlc/vlc.h>
  27. #include <vlc/vout.h>
  28. #include <vlc/decoder.h>
  29. #include "codecs.h"
  30. #include <xvid.h>
  31. /*****************************************************************************
  32.  * Local prototypes
  33.  *****************************************************************************/
  34. static int RunDecoder  ( decoder_fifo_t * );
  35. static int OpenDecoder ( vlc_object_t * );
  36. /*****************************************************************************
  37.  * Module descriptor
  38.  *****************************************************************************/
  39. vlc_module_begin();
  40.     set_description( _("Xvid video decoder") );
  41.     set_capability( "decoder", 50 );
  42.     set_callbacks( OpenDecoder, NULL );
  43.     add_bool( "xvid-direct-render", 0, NULL, "direct rendering",
  44.               "Use libxvidcore's direct rendering feature.", VLC_TRUE );
  45. vlc_module_end();
  46. /*****************************************************************************
  47.  * OpenDecoder: probe the decoder and return score
  48.  *****************************************************************************
  49.  * FIXME: find fourcc formats supported by xvid
  50.  *****************************************************************************/
  51. static int OpenDecoder ( vlc_object_t *p_this )
  52. {
  53.     decoder_t *p_dec = (decoder_t*)p_this;
  54.     if( p_dec->fmt_in.i_codec != VLC_FOURCC('x','v','i','d')
  55.          && p_dec->fmt_in.i_codec != VLC_FOURCC('X','V','I','D')
  56.          && p_dec->fmt_in.i_codec != VLC_FOURCC('D','I','V','X') )
  57.     {
  58.         return VLC_EGENERIC;
  59.     }
  60.     p_dec->pf_run = RunDecoder;
  61.     return VLC_SUCCESS;
  62. }
  63. /*****************************************************************************
  64.  * RunDecoder: this function is called just after the thread is created
  65.  *****************************************************************************/
  66. static int RunDecoder ( decoder_fifo_t *p_fifo )
  67. {
  68.     XVID_INIT_PARAM    xinit;
  69.     XVID_DEC_PARAM     xparam;
  70.     BITMAPINFOHEADER * p_format;
  71.     void *             p_xvid;
  72.     pes_packet_t *     p_pes = NULL;
  73.     bit_stream_t       bit_stream;
  74.     vout_thread_t *    p_vout;
  75.     uint8_t *  p_buffer, * p_image;
  76.     int        i_ret;
  77.     int        i_width, i_height, i_chroma, i_aspect;
  78.     int        i_size, i_offset, i_image_size;
  79.     vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
  80.     if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
  81.     {
  82.         msg_Err( p_fifo, "cannot initialise bitstream" );
  83.         p_fifo->b_error = VLC_TRUE;
  84.         DecoderError( p_fifo );
  85.         return VLC_EGENERIC;
  86.     }
  87.     if( ( p_format = (BITMAPINFOHEADER *)p_fifo->p_bitmapinfoheader ) == NULL )
  88.     {
  89.         i_width  = 1;
  90.         i_height = 1;   // avoid segfault anyway it's wrong
  91.     }
  92.     else
  93.     {
  94.         /* Guess picture properties from the BIH */
  95.         i_width = p_format->biWidth;
  96.         i_height = p_format->biHeight;
  97.     }
  98.     i_chroma = VLC_FOURCC('Y','V','1','2');
  99.     i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
  100.     /* XXX: Completely arbitrary buffer size */
  101.     i_size = i_width * i_height / 4;
  102.     i_image_size = b_direct ? 0 : i_width * i_height * 4;
  103.     i_offset = 0;
  104.     p_buffer = malloc( i_size + i_image_size );
  105.     p_image = p_buffer + i_size;
  106.     if( !p_buffer )
  107.     {
  108.         msg_Err( p_fifo, "out of memory" );
  109.         p_fifo->b_error = VLC_TRUE;
  110.         CloseBitstream( &bit_stream );
  111.         DecoderError( p_fifo );
  112.         return VLC_EGENERIC;
  113.     }
  114.     xinit.cpu_flags = 0;
  115.     xvid_init( NULL, 0, &xinit, NULL );
  116.     xparam.width = i_width;
  117.     xparam.height = i_height;
  118.     i_ret = xvid_decore( NULL, XVID_DEC_CREATE, &xparam, NULL );
  119.     if( i_ret )
  120.     {
  121.         msg_Err( p_fifo, "cannot create xvid decoder" );
  122.         p_fifo->b_error = VLC_TRUE;
  123.         free( p_buffer );
  124.         CloseBitstream( &bit_stream );
  125.         DecoderError( p_fifo );
  126.         return VLC_EGENERIC;
  127.     }
  128.     p_xvid = xparam.handle;
  129.     /* Spawn a video output if there is none. First we look amongst our
  130.      * children, then we look for any other vout that might be available */
  131.     p_vout = vout_Request( p_fifo, NULL,
  132.                            i_width, i_height, i_chroma, i_aspect );
  133.     if( !p_vout )
  134.     {
  135.         msg_Err( p_fifo, "could not spawn vout" );
  136.         p_fifo->b_error = VLC_TRUE;
  137.         xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
  138.         free( p_buffer );
  139.         CloseBitstream( &bit_stream );
  140.         DecoderError( p_fifo );
  141.         return VLC_EGENERIC;
  142.     }
  143.     /* Main loop */
  144.     while( !p_fifo->b_die && !p_fifo->b_error )
  145.     {
  146.         XVID_DEC_FRAME xframe;
  147.         XVID_DEC_PICTURE xpic;
  148.         mtime_t i_pts = 0;
  149.         picture_t *p_pic;
  150.         GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
  151.         if( p_pes )
  152.         {
  153.             input_DeletePES( p_fifo->p_packets_mgt, p_pes );
  154.         }
  155.         input_ExtractPES( p_fifo, &p_pes );
  156.         if( p_pes )
  157.         {
  158.             /* Don't trust the sucker */
  159.             //i_pts = p_pes->i_pts + DEFAULT_PTS_DELAY;
  160.             i_pts = mdate() + DEFAULT_PTS_DELAY;
  161.         }
  162.         if( p_fifo->b_die || p_fifo->b_error )
  163.         {
  164.             break;
  165.         }
  166.         while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
  167.         {
  168.             if( p_fifo->b_die || p_fifo->b_error )
  169.             {
  170.                 break;
  171.             } 
  172.             msleep( VOUT_OUTMEM_SLEEP );
  173.         }
  174.         if( !p_pic )
  175.         {
  176.             break;
  177.         }
  178.         if( b_direct )
  179.         {
  180.             xpic.y = p_pic->p[0].p_pixels;
  181.             xpic.u = p_pic->p[1].p_pixels;
  182.             xpic.v = p_pic->p[2].p_pixels;
  183.             xpic.stride_y = p_pic->p[0].i_pitch;
  184.             xpic.stride_u = p_pic->p[1].i_pitch;
  185.             xpic.stride_v = p_pic->p[2].i_pitch;
  186.         }
  187.         /* Decode the stuff */
  188.         xframe.bitstream = p_buffer;
  189.         xframe.length = i_size;
  190.         xframe.image = b_direct ? (void*)&xpic : p_image;
  191.         xframe.stride = i_width;
  192.         xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
  193.         i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
  194.         /* FIXME: check i_ret */
  195.         if( !b_direct )
  196.         {
  197.             /* TODO: use pf_memcpy when this is stable. */
  198.             memcpy( p_pic->p[0].p_pixels,
  199.                     p_image,
  200.                     i_width * i_height );
  201.             memcpy( p_pic->p[2].p_pixels,
  202.                     p_image + i_width * i_height,
  203.                     i_width * i_height / 4 );
  204.             memcpy( p_pic->p[1].p_pixels,
  205.                     p_image + i_width * i_height + i_width * i_height / 4,
  206.                     i_width * i_height / 4 );
  207.         }
  208.         vout_DatePicture( p_vout, p_pic, i_pts );
  209.         vout_DisplayPicture( p_vout, p_pic );
  210.         /* Move the remaining data. TODO: only do this when necessary. */
  211.         memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
  212.         i_offset = i_size - xframe.length;
  213.     }
  214.     /* Clean up everything */
  215.     vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
  216.     xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
  217.     if( p_pes )
  218.     {
  219.         input_DeletePES( p_fifo->p_packets_mgt, p_pes );
  220.     }
  221.     free( p_buffer );
  222.     CloseBitstream( &bit_stream );
  223.     if( p_fifo->b_error )
  224.     {
  225.         DecoderError( p_fifo );
  226.         return VLC_EGENERIC;
  227.     }
  228.     return VLC_SUCCESS;
  229. }