dmo.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:54k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * dmo.c : DirectMedia Object decoder module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2002, 2003 the VideoLAN team
  5.  * $Id: 2e51be23f589e8159819e91cd22fe854a98615b5 $
  6.  *
  7.  * Author: Gildas Bazin <gbazin@videolan.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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_codec.h>
  32. #include <vlc_vout.h>
  33. #include <vlc_aout.h>
  34. #ifndef WIN32
  35. #    define LOADER
  36. #else
  37. #   include <objbase.h>
  38. #endif
  39. #ifdef LOADER
  40. /* Need the w32dll loader from mplayer */
  41. #   include <wine/winerror.h>
  42. #   include <ldt_keeper.h>
  43. #   include <wine/windef.h>
  44. #endif
  45. #include <vlc_codecs.h>
  46. #include "dmo.h"
  47. //#define DMO_DEBUG 1
  48. #ifdef LOADER
  49. /* Not Needed */
  50. long CoInitialize( void *pvReserved ) { VLC_UNUSED(pvReserved); return -1; }
  51. void CoUninitialize( void ) { }
  52. /* A few prototypes */
  53. HMODULE WINAPI LoadLibraryA(LPCSTR);
  54. #define LoadLibrary LoadLibraryA
  55. FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
  56. int     WINAPI FreeLibrary(HMODULE);
  57. #endif /* LOADER */
  58. typedef long (STDCALL *GETCLASS) ( const GUID*, const GUID*, void** );
  59. static const int pi_channels_maps[7] =
  60. {
  61.     0,
  62.     AOUT_CHAN_CENTER,
  63.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  64.     AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
  65.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
  66.      | AOUT_CHAN_REARRIGHT,
  67.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  68.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
  69.     AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
  70.      | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
  71. };
  72. /*****************************************************************************
  73.  * Module descriptor
  74.  *****************************************************************************/
  75. static int  DecoderOpen  ( vlc_object_t * );
  76. static void DecoderClose ( vlc_object_t * );
  77. static void *DecodeBlock ( decoder_t *, block_t ** );
  78. static void *DecoderThread( void * );
  79. static int  EncoderOpen  ( vlc_object_t * );
  80. static void EncoderClose ( vlc_object_t * );
  81. static block_t *EncodeBlock( encoder_t *, void * );
  82. static int  EncOpen  ( vlc_object_t * );
  83. static int LoadDMO( vlc_object_t *, HINSTANCE *, IMediaObject **,
  84.                     es_format_t *, bool );
  85. static void CopyPicture( picture_t *, uint8_t * );
  86. vlc_module_begin ()
  87.     set_description( N_("DirectMedia Object decoder") )
  88.     add_shortcut( "dmo" )
  89.     set_capability( "decoder", 1 )
  90.     set_callbacks( DecoderOpen, DecoderClose )
  91.     set_category( CAT_INPUT )
  92.     set_subcategory( SUBCAT_INPUT_SCODEC )
  93. #   define ENC_CFG_PREFIX "sout-dmo-"
  94.     add_submodule ()
  95.     set_description( N_("DirectMedia Object encoder") )
  96.     add_shortcut( "dmo" )
  97.     set_capability( "encoder", 10 )
  98.     set_callbacks( EncoderOpen, EncoderClose )
  99. vlc_module_end ()
  100. /*****************************************************************************
  101.  * Local prototypes
  102.  *****************************************************************************/
  103. /****************************************************************************
  104.  * Decoder descriptor declaration
  105.  ****************************************************************************/
  106. struct decoder_sys_t
  107. {
  108.     HINSTANCE hmsdmo_dll;
  109.     IMediaObject *p_dmo;
  110.     int i_min_output;
  111.     uint8_t *p_buffer;
  112.     date_t end_date;
  113. #ifdef LOADER
  114.     ldt_fs_t    *ldt_fs;
  115. #endif
  116.     vlc_thread_t thread;
  117.     vlc_mutex_t  lock;
  118.     vlc_cond_t   wait_input, wait_output;
  119.     bool         b_ready, b_works;
  120.     block_t    **pp_input;
  121.     int          i_output;
  122.     void       **pp_output;
  123. };
  124. const GUID IID_IWMCodecPrivateData = {0x73f0be8e, 0x57f7, 0x4f01, {0xaa, 0x66, 0x9f, 0x57, 0x34, 0xc, 0xfe, 0xe}};
  125. const GUID IID_IMediaObject = {0xd8ad0f58, 0x5494, 0x4102, {0x97, 0xc5, 0xec, 0x79, 0x8e, 0x59, 0xbc, 0xf4}};
  126. const GUID IID_IMediaBuffer = {0x59eff8b9, 0x938c, 0x4a26, {0x82, 0xf2, 0x95, 0xcb, 0x84, 0xcd, 0xc8, 0x37}};
  127. const GUID MEDIATYPE_Video = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
  128. const GUID MEDIATYPE_Audio = {0x73647561, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
  129. const GUID MEDIASUBTYPE_PCM = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
  130. const GUID FORMAT_VideoInfo = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
  131. const GUID FORMAT_WaveFormatEx = {0x05589f81, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
  132. const GUID GUID_NULL = {0x0000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
  133. const GUID MEDIASUBTYPE_I420 = {0x30323449, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
  134. const GUID MEDIASUBTYPE_YV12 = {0x32315659, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
  135. const GUID MEDIASUBTYPE_RGB24 = {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
  136. const GUID MEDIASUBTYPE_RGB565 = {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
  137. static const GUID guid_wvc1 = { 0xc9bfbccf, 0xe60e, 0x4588, { 0xa3, 0xdf, 0x5a, 0x03, 0xb1, 0xfd, 0x95, 0x85 } };
  138. static const GUID guid_wmv9 = { 0x724bb6a4, 0xe526, 0x450f, { 0xaf, 0xfa, 0xab, 0x9b, 0x45, 0x12, 0x91, 0x11 } };
  139. static const GUID guid_wmv = { 0x82d353df, 0x90bd, 0x4382, { 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34 } };
  140. static const GUID guid_wms = { 0x7bafb3b1, 0xd8f4, 0x4279, { 0x92, 0x53, 0x27, 0xda, 0x42, 0x31, 0x08, 0xde } };
  141. static const GUID guid_wmva ={ 0x03be3ac4, 0x84b7, 0x4e0e, { 0xa7, 0x8d, 0xd3, 0x52, 0x4e, 0x60, 0x39, 0x5a } };
  142. static const GUID guid_wma = { 0x874131cb, 0x4ecc, 0x443b, { 0x89, 0x48, 0x74, 0x6b, 0x89, 0x59, 0x5d, 0x20 } };
  143. static const GUID guid_wma9 = { 0x27ca0808, 0x01f5, 0x4e7a, { 0x8b, 0x05, 0x87, 0xf8, 0x07, 0xa2, 0x33, 0xd1 } };
  144. static const GUID guid_wmv_enc = { 0x3181343b, 0x94a2, 0x4feb, { 0xad, 0xef, 0x30, 0xa1, 0xdd, 0xe6, 0x17, 0xb4 } };
  145. static const GUID guid_wmv_enc2 = { 0x96b57cdd, 0x8966, 0x410c,{ 0xbb, 0x1f, 0xc9, 0x7e, 0xea, 0x76, 0x5c, 0x04 } };
  146. static const GUID guid_wma_enc = { 0x70f598e9, 0xf4ab, 0x495a, { 0x99, 0xe2, 0xa7, 0xc4, 0xd3, 0xd8, 0x9a, 0xbf } };
  147. typedef struct
  148. {
  149.     vlc_fourcc_t i_fourcc;
  150.     const char   *psz_dll;
  151.     const GUID   *p_guid;
  152. } codec_dll;
  153. static const codec_dll decoders_table[] =
  154. {
  155.     /* WVC1 */
  156.     { VLC_FOURCC('W','V','C','1'), "wvc1dmod.dll", &guid_wvc1 },
  157.     { VLC_FOURCC('w','v','c','1'), "wvc1dmod.dll", &guid_wvc1 },
  158.     /* WMV3 */
  159.     { VLC_FOURCC('W','M','V','3'), "wmv9dmod.dll", &guid_wmv9 },
  160.     { VLC_FOURCC('w','m','v','3'), "wmv9dmod.dll", &guid_wmv9 },
  161.     { VLC_FOURCC('W','M','V','P'), "wmv9dmod.dll", &guid_wmv9 },
  162.     { VLC_FOURCC('w','m','v','p'), "wmv9dmod.dll", &guid_wmv9 },
  163.     /* WMV2 */
  164.     { VLC_FOURCC('W','M','V','2'), "wmvdmod.dll", &guid_wmv },
  165.     { VLC_FOURCC('w','m','v','2'), "wmvdmod.dll", &guid_wmv },
  166.     /* WMV1 */
  167.     { VLC_FOURCC('W','M','V','1'), "wmvdmod.dll", &guid_wmv },
  168.     { VLC_FOURCC('w','m','v','1'), "wmvdmod.dll", &guid_wmv },
  169.     /* Screen codecs */
  170.     { VLC_FOURCC('M','S','S','2'), "wmsdmod.dll", &guid_wms },
  171.     { VLC_FOURCC('m','s','s','2'), "wmsdmod.dll", &guid_wms },
  172.     { VLC_FOURCC('M','S','S','1'), "wmsdmod.dll", &guid_wms },
  173.     { VLC_FOURCC('m','s','s','1'), "wmsdmod.dll", &guid_wms },
  174.     /* Windows Media Video Adv */
  175.     { VLC_FOURCC('W','M','V','A'), "wmvadvd.dll", &guid_wmva },
  176.     { VLC_FOURCC('w','m','v','a'), "wmvadvd.dll", &guid_wmva },
  177.     { VLC_FOURCC('W','V','P','2'), "wmvadvd.dll", &guid_wmva },
  178.     { VLC_FOURCC('w','v','p','2'), "wmvadvd.dll", &guid_wmva },
  179.     /* WMA 3 */
  180.     { VLC_FOURCC('W','M','A','3'), "wma9dmod.dll", &guid_wma9 },
  181.     { VLC_FOURCC('w','m','a','3'), "wma9dmod.dll", &guid_wma9 },
  182.     { VLC_FOURCC('W','M','A','P'), "wma9dmod.dll", &guid_wma9 },
  183.     { VLC_FOURCC('w','m','a','p'), "wma9dmod.dll", &guid_wma9 },
  184.     { VLC_FOURCC('W','M','A','L'), "wma9dmod.dll", &guid_wma9 },
  185.     { VLC_FOURCC('w','m','a','l'), "wma9dmod.dll", &guid_wma9 },
  186.     /* WMA 2 */
  187.     { VLC_FOURCC('W','M','A','2'), "wma9dmod.dll", &guid_wma9 },
  188.     { VLC_FOURCC('w','m','a','2'), "wma9dmod.dll", &guid_wma9 },
  189.     /* WMA Speech */
  190.     { VLC_FOURCC('W','M','A','S'), "wmspdmod.dll", &guid_wma },
  191.     { VLC_FOURCC('w','m','a','s'), "wmspdmod.dll", &guid_wma },
  192.     /* */
  193.     { 0, NULL, NULL }
  194. };
  195. static const codec_dll encoders_table[] =
  196. {
  197.     /* WMV3 */
  198.     { VLC_FOURCC('W','M','V','3'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  199.     { VLC_FOURCC('w','m','v','3'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  200.     /* WMV2 */
  201.     { VLC_FOURCC('W','M','V','2'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  202.     { VLC_FOURCC('w','m','v','2'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  203.     /* WMV1 */
  204.     { VLC_FOURCC('W','M','V','1'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  205.     { VLC_FOURCC('w','m','v','1'), "wmvdmoe2.dll", &guid_wmv_enc2 },
  206.     /* WMA 3 */
  207.     { VLC_FOURCC('W','M','A','3'), "wmadmoe.dll", &guid_wma_enc },
  208.     { VLC_FOURCC('w','m','a','3'), "wmadmoe.dll", &guid_wma_enc },
  209.     /* WMA 2 */
  210.     { VLC_FOURCC('W','M','A','2'), "wmadmoe.dll", &guid_wma_enc },
  211.     { VLC_FOURCC('w','m','a','2'), "wmadmoe.dll", &guid_wma_enc },
  212.     /* */
  213.     { 0, NULL, NULL }
  214. };
  215. static void WINAPI DMOFreeMediaType( DMO_MEDIA_TYPE *mt )
  216. {
  217.     if( mt->cbFormat != 0 ) CoTaskMemFree( (PVOID)mt->pbFormat );
  218.     if( mt->pUnk != NULL ) mt->pUnk->vt->Release( (IUnknown *)mt->pUnk );
  219.     mt->cbFormat = 0;
  220.     mt->pbFormat = NULL;
  221.     mt->pUnk = NULL;
  222. }
  223. /*****************************************************************************
  224.  * DecoderOpen: open dmo codec
  225.  *****************************************************************************/
  226. static int DecoderOpen( vlc_object_t *p_this )
  227. {
  228.     decoder_t *p_dec = (decoder_t*)p_this;
  229.     decoder_sys_t *p_sys;
  230.     /* We can't open it now, because of ldt_keeper or something
  231.      * Open/Decode/Close has to be done in the same thread */
  232.     /* Probe if we support it */
  233.     for( unsigned i = 0; decoders_table[i].i_fourcc != 0; i++ )
  234.     {
  235.         if( decoders_table[i].i_fourcc == p_dec->fmt_in.i_codec )
  236.         {
  237.             msg_Dbg( p_dec, "DMO codec for %4.4s may work with dll=%s",
  238.                      (char*)&p_dec->fmt_in.i_codec,
  239.                      decoders_table[i].psz_dll );
  240.             goto found;
  241.         }
  242.     }
  243.     return VLC_EGENERIC;
  244. found:
  245.     p_sys = p_dec->p_sys = malloc(sizeof(*p_sys));
  246.     if( !p_sys )
  247.         return VLC_ENOMEM;
  248.     /* Set callbacks */
  249.     p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
  250.         DecodeBlock;
  251.     p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
  252.         DecodeBlock;
  253.     vlc_mutex_init( &p_sys->lock );
  254.     vlc_cond_init( &p_sys->wait_input );
  255.     vlc_cond_init( &p_sys->wait_output );
  256.     p_sys->b_works =
  257.     p_sys->b_ready = false;
  258.     p_sys->pp_input = NULL;
  259.     TAB_INIT( p_sys->i_output, p_sys->pp_output );
  260.     if( vlc_clone( &p_sys->thread, DecoderThread, p_dec,
  261.                    VLC_THREAD_PRIORITY_INPUT ) )
  262.         goto error;
  263.     vlc_mutex_lock( &p_sys->lock );
  264.     while( !p_sys->b_ready )
  265.         vlc_cond_wait( &p_sys->wait_output, &p_sys->lock );
  266.     vlc_mutex_unlock( &p_sys->lock );
  267.     if( p_sys->b_works )
  268.         return VLC_SUCCESS;
  269.     vlc_join( p_sys->thread, NULL );
  270. error:
  271.     vlc_cond_destroy( &p_sys->wait_input );
  272.     vlc_cond_destroy( &p_sys->wait_output );
  273.     vlc_mutex_destroy( &p_sys->lock );
  274.     free( p_sys );
  275.     return VLC_ENOMEM;
  276. }
  277. /*****************************************************************************
  278.  * DecoderClose: close codec
  279.  *****************************************************************************/
  280. static void DecoderClose( vlc_object_t *p_this )
  281. {
  282.     decoder_t *p_dec = (decoder_t*)p_this;
  283.     decoder_sys_t *p_sys = p_dec->p_sys;
  284.     vlc_mutex_lock( &p_sys->lock );
  285.     p_sys->b_ready = false;
  286.     vlc_cond_signal( &p_sys->wait_input );
  287.     vlc_mutex_unlock( &p_sys->lock );
  288.     vlc_join( p_sys->thread, NULL );
  289.     TAB_CLEAN( p_sys->i_output, p_sys->pp_output );
  290.     vlc_cond_destroy( &p_sys->wait_input );
  291.     vlc_cond_destroy( &p_sys->wait_output );
  292.     vlc_mutex_destroy( &p_sys->lock );
  293.     free( p_sys );
  294. }
  295. static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
  296. {
  297.     decoder_sys_t *p_sys = p_dec->p_sys;
  298.     void *p_ret;
  299.     vlc_mutex_lock( &p_sys->lock );
  300.     if( p_sys->i_output <= 0 )
  301.     {
  302.         p_sys->pp_input = pp_block;
  303.         vlc_cond_signal( &p_sys->wait_input );
  304.         while( p_sys->pp_input )
  305.             vlc_cond_wait( &p_sys->wait_output, &p_sys->lock );
  306.     }
  307.     p_ret = NULL;
  308.     if( p_sys->i_output > 0 )
  309.     {
  310.         p_ret = p_sys->pp_output[0];
  311.         TAB_REMOVE( p_sys->i_output, p_sys->pp_output, p_ret );
  312.     }
  313.     vlc_mutex_unlock( &p_sys->lock );
  314.     return p_ret;
  315. }
  316. /*****************************************************************************
  317.  * DecOpen: open dmo codec
  318.  *****************************************************************************/
  319. static int DecOpen( decoder_t *p_dec )
  320. {
  321.     decoder_sys_t *p_sys = p_dec->p_sys;
  322.     DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;
  323.     IMediaObject *p_dmo = NULL;
  324.     HINSTANCE hmsdmo_dll = NULL;
  325.     VIDEOINFOHEADER *p_vih = NULL;
  326.     WAVEFORMATEX *p_wf = NULL;
  327. #ifdef LOADER
  328.     ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
  329. #else
  330.     /* Initialize OLE/COM */
  331.     CoInitialize( 0 );
  332. #endif /* LOADER */
  333.     if( LoadDMO( VLC_OBJECT(p_dec), &hmsdmo_dll, &p_dmo, &p_dec->fmt_in, false )
  334.         != VLC_SUCCESS )
  335.     {
  336.         hmsdmo_dll = 0;
  337.         p_dmo = 0;
  338.         goto error;
  339.     }
  340.     /* Setup input format */
  341.     memset( &dmo_input_type, 0, sizeof(dmo_input_type) );
  342.     dmo_input_type.pUnk = 0;
  343.     if( p_dec->fmt_in.i_cat == AUDIO_ES )
  344.     {
  345.         uint16_t i_tag;
  346.         int i_size = sizeof(WAVEFORMATEX) + p_dec->fmt_in.i_extra;
  347.         p_wf = malloc( i_size );
  348.         memset( p_wf, 0, sizeof(WAVEFORMATEX) );
  349.         if( p_dec->fmt_in.i_extra )
  350.             memcpy( &p_wf[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
  351.         dmo_input_type.majortype  = MEDIATYPE_Audio;
  352.         dmo_input_type.subtype    = dmo_input_type.majortype;
  353.         dmo_input_type.subtype.Data1 = p_dec->fmt_in.i_codec;
  354.         fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );
  355.         if( i_tag ) dmo_input_type.subtype.Data1 = i_tag;
  356.         p_wf->wFormatTag = dmo_input_type.subtype.Data1;
  357.         p_wf->nSamplesPerSec = p_dec->fmt_in.audio.i_rate;
  358.         p_wf->nChannels = p_dec->fmt_in.audio.i_channels;
  359.         p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;
  360.         p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;
  361.         p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;
  362.         p_wf->cbSize = p_dec->fmt_in.i_extra;
  363.         dmo_input_type.formattype = FORMAT_WaveFormatEx;
  364.         dmo_input_type.cbFormat   = i_size;
  365.         dmo_input_type.pbFormat   = (char *)p_wf;
  366.         dmo_input_type.bFixedSizeSamples = 1;
  367.         dmo_input_type.bTemporalCompression = 0;
  368.         dmo_input_type.lSampleSize = p_wf->nBlockAlign;
  369.     }
  370.     else
  371.     {
  372.         BITMAPINFOHEADER *p_bih;
  373.         int i_size = sizeof(VIDEOINFOHEADER) + p_dec->fmt_in.i_extra;
  374.         p_vih = malloc( i_size );
  375.         memset( p_vih, 0, sizeof(VIDEOINFOHEADER) );
  376.         if( p_dec->fmt_in.i_extra )
  377.             memcpy( &p_vih[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
  378.         p_bih = &p_vih->bmiHeader;
  379.         p_bih->biCompression = p_dec->fmt_in.i_codec;
  380.         p_bih->biWidth = p_dec->fmt_in.video.i_width;
  381.         p_bih->biHeight = p_dec->fmt_in.video.i_height;
  382.         p_bih->biBitCount = p_dec->fmt_in.video.i_bits_per_pixel;
  383.         p_bih->biPlanes = 1;
  384.         p_bih->biSize = i_size - sizeof(VIDEOINFOHEADER) +
  385.             sizeof(BITMAPINFOHEADER);
  386.         p_vih->rcSource.left = p_vih->rcSource.top = 0;
  387.         p_vih->rcSource.right = p_dec->fmt_in.video.i_width;
  388.         p_vih->rcSource.bottom = p_dec->fmt_in.video.i_height;
  389.         p_vih->rcTarget = p_vih->rcSource;
  390.         dmo_input_type.majortype  = MEDIATYPE_Video;
  391.         dmo_input_type.subtype    = dmo_input_type.majortype;
  392.         dmo_input_type.subtype.Data1 = p_dec->fmt_in.i_codec;
  393.         dmo_input_type.formattype = FORMAT_VideoInfo;
  394.         dmo_input_type.bFixedSizeSamples = 0;
  395.         dmo_input_type.bTemporalCompression = 1;
  396.         dmo_input_type.cbFormat = i_size;
  397.         dmo_input_type.pbFormat = (char *)p_vih;
  398.     }
  399.     if( p_dmo->vt->SetInputType( p_dmo, 0, &dmo_input_type, 0 ) )
  400.     {
  401.         msg_Err( p_dec, "can't set DMO input type" );
  402.         goto error;
  403.     }
  404.     msg_Dbg( p_dec, "DMO input type set" );
  405.     /* Setup output format */
  406.     memset( &dmo_output_type, 0, sizeof(dmo_output_type) );
  407.     dmo_output_type.pUnk = 0;
  408.     if( p_dec->fmt_in.i_cat == AUDIO_ES )
  409.     {
  410.         /* Setup the format */
  411.         p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
  412.         p_dec->fmt_out.audio.i_rate     = p_dec->fmt_in.audio.i_rate;
  413.         p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
  414.         p_dec->fmt_out.audio.i_bitspersample = 16;//p_dec->fmt_in.audio.i_bitspersample; We request 16
  415.         p_dec->fmt_out.audio.i_physical_channels =
  416.             p_dec->fmt_out.audio.i_original_channels =
  417.                 pi_channels_maps[p_dec->fmt_out.audio.i_channels];
  418.         p_wf->wFormatTag = WAVE_FORMAT_PCM;
  419.         p_wf->nSamplesPerSec = p_dec->fmt_out.audio.i_rate;
  420.         p_wf->nChannels = p_dec->fmt_out.audio.i_channels;
  421.         p_wf->wBitsPerSample = p_dec->fmt_out.audio.i_bitspersample;
  422.         p_wf->nBlockAlign =
  423.             p_wf->wBitsPerSample / 8 * p_wf->nChannels;
  424.         p_wf->nAvgBytesPerSec =
  425.             p_wf->nSamplesPerSec * p_wf->nBlockAlign;
  426.         p_wf->cbSize = 0;
  427.         dmo_output_type.majortype  = MEDIATYPE_Audio;
  428.         dmo_output_type.formattype = FORMAT_WaveFormatEx;
  429.         dmo_output_type.subtype    = MEDIASUBTYPE_PCM;
  430.         dmo_output_type.cbFormat   = sizeof(WAVEFORMATEX);
  431.         dmo_output_type.pbFormat   = (char *)p_wf;
  432.         dmo_output_type.bFixedSizeSamples = 1;
  433.         dmo_output_type.bTemporalCompression = 0;
  434.         dmo_output_type.lSampleSize = p_wf->nBlockAlign;
  435.     }
  436.     else
  437.     {
  438.         BITMAPINFOHEADER *p_bih;
  439.         DMO_MEDIA_TYPE mt;
  440.         unsigned i_chroma = VLC_FOURCC('Y','U','Y','2');
  441.         int i_planes = 1, i_bpp = 16;
  442.         int i = 0;
  443.         /* Find out which chroma to use */
  444.         while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
  445.         {
  446.             if( mt.subtype.Data1 == VLC_FOURCC('Y','V','1','2') )
  447.             {
  448.                 i_chroma = mt.subtype.Data1;
  449.                 i_planes = 3; i_bpp = 12;
  450.             }
  451.             DMOFreeMediaType( &mt );
  452.         }
  453.         p_dec->fmt_out.i_codec = i_chroma == VLC_FOURCC('Y','V','1','2') ?
  454.             VLC_FOURCC('I','4','2','0') : i_chroma;
  455.         p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
  456.         p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
  457.         p_dec->fmt_out.video.i_bits_per_pixel = i_bpp;
  458.         /* If an aspect-ratio was specified in the input format then force it */
  459.         if( p_dec->fmt_in.video.i_aspect )
  460.         {
  461.             p_dec->fmt_out.video.i_aspect = p_dec->fmt_in.video.i_aspect;
  462.         }
  463.         else
  464.         {
  465.             p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
  466.                 p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
  467.         }
  468.         p_bih = &p_vih->bmiHeader;
  469.         p_bih->biCompression = i_chroma;
  470.         p_bih->biHeight *= -1;
  471.         p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel;
  472.         p_bih->biSizeImage = p_dec->fmt_in.video.i_width *
  473.             p_dec->fmt_in.video.i_height *
  474.             (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8;
  475.         p_bih->biPlanes = i_planes;
  476.         p_bih->biSize = sizeof(BITMAPINFOHEADER);
  477.         dmo_output_type.majortype = MEDIATYPE_Video;
  478.         dmo_output_type.formattype = FORMAT_VideoInfo;
  479.         dmo_output_type.subtype = dmo_output_type.majortype;
  480.         dmo_output_type.subtype.Data1 = p_bih->biCompression;
  481.         dmo_output_type.bFixedSizeSamples = true;
  482.         dmo_output_type.bTemporalCompression = 0;
  483.         dmo_output_type.lSampleSize = p_bih->biSizeImage;
  484.         dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER);
  485.         dmo_output_type.pbFormat = (char *)p_vih;
  486.     }
  487. #ifdef DMO_DEBUG
  488.     /* Enumerate output types */
  489.     if( p_dec->fmt_in.i_cat == VIDEO_ES )
  490.     {
  491.         int i = 0;
  492.         DMO_MEDIA_TYPE mt;
  493.         while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
  494.         {
  495.             msg_Dbg( p_dec, "available output chroma: %4.4s",
  496.                      (char *)&mt.subtype.Data1 );
  497.             DMOFreeMediaType( &mt );
  498.         }
  499.     }
  500. #endif
  501.     if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) )
  502.     {
  503.         msg_Err( p_dec, "can't set DMO output type" );
  504.         goto error;
  505.     }
  506.     msg_Dbg( p_dec, "DMO output type set" );
  507.     /* Allocate the memory needed to store the decoder's structure */
  508.     p_sys->hmsdmo_dll = hmsdmo_dll;
  509.     p_sys->p_dmo = p_dmo;
  510. #ifdef LOADER
  511.     p_sys->ldt_fs = ldt_fs;
  512. #endif
  513.     /* Find out some properties of the output */
  514.     {
  515.         uint32_t i_size, i_align;
  516.         p_sys->i_min_output = 0;
  517.         if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
  518.         {
  519.             msg_Err( p_dec, "GetOutputSizeInfo() failed" );
  520.             goto error;
  521.         }
  522.         else
  523.         {
  524.             msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i",
  525.                      i_size, i_align );
  526.             p_sys->i_min_output = i_size;
  527.             p_sys->p_buffer = malloc( i_size );
  528.             if( !p_sys->p_buffer ) goto error;
  529.         }
  530.     }
  531.     /* Set output properties */
  532.     p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
  533.     if( p_dec->fmt_out.i_cat == AUDIO_ES )
  534.         date_Init( &p_sys->end_date, p_dec->fmt_in.audio.i_rate, 1 );
  535.     else
  536.         date_Init( &p_sys->end_date, 25 /* FIXME */, 1 );
  537.     free( p_vih );
  538.     free( p_wf );
  539.     vlc_mutex_lock( &p_sys->lock );
  540.     p_sys->b_ready =
  541.     p_sys->b_works = true;
  542.     vlc_cond_signal( &p_sys->wait_output );
  543.     vlc_mutex_unlock( &p_sys->lock );
  544.     return VLC_SUCCESS;
  545.  error:
  546.     if( p_dmo ) p_dmo->vt->Release( (IUnknown *)p_dmo );
  547.     if( hmsdmo_dll ) FreeLibrary( hmsdmo_dll );
  548. #ifdef LOADER
  549.     Restore_LDT_Keeper( ldt_fs );
  550. #else
  551.     /* Uninitialize OLE/COM */
  552.     CoUninitialize();
  553. #endif /* LOADER */
  554.     free( p_vih );
  555.     free( p_wf );
  556.     vlc_mutex_lock( &p_sys->lock );
  557.     p_sys->b_ready = true;
  558.     vlc_cond_signal( &p_sys->wait_output );
  559.     vlc_mutex_unlock( &p_sys->lock );
  560.     return VLC_EGENERIC;
  561. }
  562. /*****************************************************************************
  563.  * LoadDMO: Load the DMO object
  564.  *****************************************************************************/
  565. static int LoadDMO( vlc_object_t *p_this, HINSTANCE *p_hmsdmo_dll,
  566.                     IMediaObject **pp_dmo, es_format_t *p_fmt,
  567.                     bool b_out )
  568. {
  569.     DMO_PARTIAL_MEDIATYPE dmo_partial_type;
  570.     int i_err;
  571. #ifndef LOADER
  572.     long (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,
  573.                                const DMO_PARTIAL_MEDIATYPE *,
  574.                                uint32_t, const DMO_PARTIAL_MEDIATYPE *,
  575.                                IEnumDMO ** );
  576.     IEnumDMO *p_enum_dmo = NULL;
  577.     WCHAR *psz_dmo_name;
  578.     GUID clsid_dmo;
  579.     uint32_t i_dummy;
  580. #endif
  581.     GETCLASS GetClass;
  582.     IClassFactory *cFactory = NULL;
  583.     IUnknown *cObject = NULL;
  584.     const codec_dll *codecs_table = b_out ? encoders_table : decoders_table;
  585.     int i_codec;
  586.     /* Look for a DMO which can handle the requested codec */
  587.     if( p_fmt->i_cat == AUDIO_ES )
  588.     {
  589.         uint16_t i_tag;
  590.         dmo_partial_type.type = MEDIATYPE_Audio;
  591.         dmo_partial_type.subtype = dmo_partial_type.type;
  592.         dmo_partial_type.subtype.Data1 = p_fmt->i_codec;
  593.         fourcc_to_wf_tag( p_fmt->i_codec, &i_tag );
  594.         if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;
  595.     }
  596.     else
  597.     {
  598.         dmo_partial_type.type = MEDIATYPE_Video;
  599.         dmo_partial_type.subtype = dmo_partial_type.type;
  600.         dmo_partial_type.subtype.Data1 = p_fmt->i_codec;
  601.     }
  602. #ifndef LOADER
  603.     /* Load msdmo DLL */
  604.     *p_hmsdmo_dll = LoadLibrary( "msdmo.dll" );
  605.     if( *p_hmsdmo_dll == NULL )
  606.     {
  607.         msg_Dbg( p_this, "failed loading msdmo.dll" );
  608.         return VLC_EGENERIC;
  609.     }
  610.     OurDMOEnum = (void *)GetProcAddress( *p_hmsdmo_dll, "DMOEnum" );
  611.     if( OurDMOEnum == NULL )
  612.     {
  613.         msg_Dbg( p_this, "GetProcAddress failed to find DMOEnum()" );
  614.         FreeLibrary( *p_hmsdmo_dll );
  615.         return VLC_EGENERIC;
  616.     }
  617.     if( !b_out )
  618.     {
  619.         i_err = OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
  620.                             1, &dmo_partial_type, 0, NULL, &p_enum_dmo );
  621.     }
  622.     else
  623.     {
  624.         i_err = OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
  625.                             0, NULL, 1, &dmo_partial_type, &p_enum_dmo );
  626.     }
  627.     if( i_err )
  628.     {
  629.         FreeLibrary( *p_hmsdmo_dll );
  630.         /* return VLC_EGENERIC; */
  631.         /* Try loading the dll directly */
  632.         goto loader;
  633.     }
  634.     /* Pickup the first available codec */
  635.     *pp_dmo = 0;
  636.     while( ( S_OK == p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo,
  637.                      &psz_dmo_name, &i_dummy /* NULL doesn't work */ ) ) )
  638.     {
  639.         char psz_temp[MAX_PATH];
  640.         wcstombs( psz_temp, psz_dmo_name, MAX_PATH );
  641.         msg_Dbg( p_this, "found DMO: %s", psz_temp );
  642.         CoTaskMemFree( psz_dmo_name );
  643.         /* Create DMO */
  644.         if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC,
  645.                               &IID_IMediaObject, (void **)pp_dmo ) )
  646.         {
  647.             msg_Warn( p_this, "can't create DMO: %s", psz_temp );
  648.             *pp_dmo = 0;
  649.         }
  650.         else break;
  651.     }
  652.     p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo );
  653.     if( !*pp_dmo )
  654.     {
  655.         FreeLibrary( *p_hmsdmo_dll );
  656.         /* return VLC_EGENERIC; */
  657.         /* Try loading the dll directly */
  658.         goto loader;
  659.     }
  660.     return VLC_SUCCESS;
  661. loader:
  662. #endif   /* LOADER */
  663.     for( i_codec = 0; codecs_table[i_codec].i_fourcc != 0; i_codec++ )
  664.     {
  665.         if( codecs_table[i_codec].i_fourcc == p_fmt->i_codec )
  666.             break;
  667.     }
  668.     if( codecs_table[i_codec].i_fourcc == 0 )
  669.         return VLC_EGENERIC;    /* Can't happen */
  670.     *p_hmsdmo_dll = LoadLibrary( codecs_table[i_codec].psz_dll );
  671.     if( *p_hmsdmo_dll == NULL )
  672.     {
  673.         msg_Dbg( p_this, "failed loading '%s'",
  674.                  codecs_table[i_codec].psz_dll );
  675.         return VLC_EGENERIC;
  676.     }
  677.     GetClass = (GETCLASS)GetProcAddress( *p_hmsdmo_dll, "DllGetClassObject" );
  678.     if (!GetClass)
  679.     {
  680.         msg_Dbg( p_this, "GetProcAddress failed to find DllGetClassObject()" );
  681.         FreeLibrary( *p_hmsdmo_dll );
  682.         return VLC_EGENERIC;
  683.     }
  684.     i_err = GetClass( codecs_table[i_codec].p_guid, &IID_IClassFactory,
  685.                       (void**)&cFactory );
  686.     if( i_err || cFactory == NULL )
  687.     {
  688.         msg_Dbg( p_this, "no such class object" );
  689.         FreeLibrary( *p_hmsdmo_dll );
  690.         return VLC_EGENERIC;
  691.     }
  692.     i_err = cFactory->vt->CreateInstance( cFactory, 0, &IID_IUnknown,
  693.                                           (void**)&cObject );
  694.     cFactory->vt->Release( (IUnknown*)cFactory );
  695.     if( i_err || !cObject )
  696.     {
  697.         msg_Dbg( p_this, "class factory failure" );
  698.         FreeLibrary( *p_hmsdmo_dll );
  699.         return VLC_EGENERIC;
  700.     }
  701.     i_err = cObject->vt->QueryInterface( cObject, &IID_IMediaObject,
  702.                                         (void**)pp_dmo );
  703.     cObject->vt->Release( (IUnknown*)cObject );
  704.     if( i_err || !*pp_dmo )
  705.     {
  706.         msg_Dbg( p_this, "QueryInterface failure" );
  707.         FreeLibrary( *p_hmsdmo_dll );
  708.         return VLC_EGENERIC;
  709.     }
  710.     return VLC_SUCCESS;
  711. }
  712. static void DecClose( decoder_t *p_dec )
  713. {
  714.     decoder_sys_t *p_sys = p_dec->p_sys;
  715.     if( p_sys->p_dmo ) p_sys->p_dmo->vt->Release( (IUnknown *)p_sys->p_dmo );
  716.     FreeLibrary( p_sys->hmsdmo_dll );
  717. #ifdef LOADER
  718. #if 0
  719.     Restore_LDT_Keeper( p_sys->ldt_fs );
  720. #endif
  721. #else
  722.     /* Uninitialize OLE/COM */
  723.     CoUninitialize();
  724. #endif
  725.     free( p_sys->p_buffer );
  726. }
  727. /****************************************************************************
  728.  * DecodeBlock: the whole thing
  729.  ****************************************************************************
  730.  * This function must be fed with packets.
  731.  ****************************************************************************/
  732. static void *DecBlock( decoder_t *p_dec, block_t **pp_block )
  733. {
  734.     decoder_sys_t *p_sys = p_dec->p_sys;
  735.     block_t *p_block;
  736.     int i_result;
  737.     DMO_OUTPUT_DATA_BUFFER db;
  738.     CMediaBuffer *p_out;
  739.     block_t block_out;
  740.     uint32_t i_status;
  741.     if( !pp_block ) return NULL;
  742.     p_block = *pp_block;
  743.     /* Won't work with streams with B-frames, but do we have any ? */
  744.     if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts;
  745.     /* Date management */
  746.     if( p_block && p_block->i_pts > 0 &&
  747.         p_block->i_pts != date_Get( &p_sys->end_date ) )
  748.     {
  749.         date_Set( &p_sys->end_date, p_block->i_pts );
  750.     }
  751. #if 0 /* Breaks the video decoding */
  752.     if( !date_Get( &p_sys->end_date ) )
  753.     {
  754.         /* We've just started the stream, wait for the first PTS. */
  755.         if( p_block ) block_Release( p_block );
  756.         return NULL;
  757.     }
  758. #endif
  759.     /* Feed input to the DMO */
  760.     if( p_block && p_block->i_buffer )
  761.     {
  762.         CMediaBuffer *p_in;
  763.         p_in = CMediaBufferCreate( p_block, p_block->i_buffer, true );
  764.         i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
  765.                        (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFERF_SYNCPOINT,
  766.                        0, 0 );
  767.         p_in->vt->Release( (IUnknown *)p_in );
  768.         if( i_result == S_FALSE )
  769.         {
  770.             /* No output generated */
  771. #ifdef DMO_DEBUG
  772.             msg_Dbg( p_dec, "ProcessInput(): no output generated" );
  773. #endif
  774.             return NULL;
  775.         }
  776.         else if( i_result == (int)DMO_E_NOTACCEPTING )
  777.         {
  778.             /* Need to call ProcessOutput */
  779.             msg_Dbg( p_dec, "ProcessInput(): not accepting" );
  780.         }
  781.         else if( i_result != S_OK )
  782.         {
  783.             msg_Dbg( p_dec, "ProcessInput(): failed" );
  784.             return NULL;
  785.         }
  786.         else
  787.         {
  788. #ifdef DMO_DEBUG
  789.             msg_Dbg( p_dec, "ProcessInput(): successful" );
  790. #endif
  791.             *pp_block = NULL;
  792.         }
  793.     }
  794.     else if( p_block && !p_block->i_buffer )
  795.     {
  796.         block_Release( p_block );
  797.         *pp_block = NULL;
  798.     }
  799.     /* Get output from the DMO */
  800.     block_out.p_buffer = p_sys->p_buffer;
  801.     block_out.i_buffer = 0;
  802.     p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, false );
  803.     memset( &db, 0, sizeof(db) );
  804.     db.pBuffer = (IMediaBuffer *)p_out;
  805.     i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
  806.                    DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER,
  807.                    1, &db, &i_status );
  808.     if( i_result != S_OK )
  809.     {
  810.         if( i_result != S_FALSE )
  811.             msg_Dbg( p_dec, "ProcessOutput(): failed" );
  812. #ifdef DMO_DEBUG
  813.         else
  814.             msg_Dbg( p_dec, "ProcessOutput(): no output" );
  815. #endif
  816.         p_out->vt->Release( (IUnknown *)p_out );
  817.         return NULL;
  818.     }
  819. #ifdef DMO_DEBUG
  820.     msg_Dbg( p_dec, "ProcessOutput(): success" );
  821. #endif
  822.     if( !block_out.i_buffer )
  823.     {
  824. #ifdef DMO_DEBUG
  825.         msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );
  826. #endif
  827.         p_out->vt->Release( (IUnknown *)p_out );
  828.         return NULL;
  829.     }
  830.     if( p_dec->fmt_out.i_cat == VIDEO_ES )
  831.     {
  832.         /* Get a new picture */
  833.         picture_t *p_pic = decoder_NewPicture( p_dec );
  834.         if( !p_pic ) return NULL;
  835.         CopyPicture( p_pic, block_out.p_buffer );
  836.         /* Date management */
  837.         p_pic->date = date_Get( &p_sys->end_date );
  838.         date_Increment( &p_sys->end_date, 1 );
  839.         p_out->vt->Release( (IUnknown *)p_out );
  840.         return p_pic;
  841.     }
  842.     else
  843.     {
  844.         aout_buffer_t *p_aout_buffer;
  845.         int i_samples = block_out.i_buffer /
  846.             ( p_dec->fmt_out.audio.i_bitspersample *
  847.               p_dec->fmt_out.audio.i_channels / 8 );
  848.         p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_samples );
  849.         if( p_aout_buffer )
  850.         {
  851.             memcpy( p_aout_buffer->p_buffer,
  852.                     block_out.p_buffer, block_out.i_buffer );
  853.             /* Date management */
  854.             p_aout_buffer->start_date = date_Get( &p_sys->end_date );
  855.             p_aout_buffer->end_date =
  856.                 date_Increment( &p_sys->end_date, i_samples );
  857.         }
  858.         p_out->vt->Release( (IUnknown *)p_out );
  859.         return p_aout_buffer;
  860.     }
  861.     return NULL;
  862. }
  863. static void CopyPicture( picture_t *p_pic, uint8_t *p_in )
  864. {
  865.     int i_plane, i_line, i_width, i_dst_stride;
  866.     uint8_t *p_dst, *p_src = p_in;
  867.     p_dst = p_pic->p[1].p_pixels;
  868.     p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
  869.     p_pic->p[2].p_pixels = p_dst;
  870.     for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
  871.     {
  872.         p_dst = p_pic->p[i_plane].p_pixels;
  873.         i_width = p_pic->p[i_plane].i_visible_pitch;
  874.         i_dst_stride  = p_pic->p[i_plane].i_pitch;
  875.         for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
  876.         {
  877.             vlc_memcpy( p_dst, p_src, i_width );
  878.             p_src += i_width;
  879.             p_dst += i_dst_stride;
  880.         }
  881.     }
  882.     p_dst = p_pic->p[1].p_pixels;
  883.     p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
  884.     p_pic->p[2].p_pixels = p_dst;
  885. }
  886. static void *DecoderThread( void *data )
  887. {
  888.     decoder_t *p_dec = data;
  889.     decoder_sys_t *p_sys = p_dec->p_sys;
  890.     if( DecOpen( p_dec ) )
  891.         return NULL; /* failed */
  892.     vlc_mutex_lock( &p_sys->lock );
  893.     for( ;; )
  894.     {
  895.         while( p_sys->b_ready && !p_sys->pp_input )
  896.             vlc_cond_wait( &p_sys->wait_input, &p_sys->lock );
  897.         if( !p_sys->b_ready )
  898.             break;
  899.         for( ;; )
  900.         {
  901.             void *p_output = DecBlock( p_dec, p_sys->pp_input );
  902.             if( !p_output )
  903.                 break;
  904.             TAB_APPEND( p_sys->i_output, p_sys->pp_output, p_output );
  905.         }
  906.         p_sys->pp_input = NULL;
  907.         vlc_cond_signal( &p_sys->wait_output );
  908.     }
  909.     vlc_mutex_unlock( &p_sys->lock );
  910.     DecClose( p_dec );
  911.     return NULL;
  912. }
  913. /****************************************************************************
  914.  * Encoder descriptor declaration
  915.  ****************************************************************************/
  916. struct encoder_sys_t
  917. {
  918.     HINSTANCE hmsdmo_dll;
  919.     IMediaObject *p_dmo;
  920.     int i_min_output;
  921.     date_t end_date;
  922. #ifdef LOADER
  923.     ldt_fs_t    *ldt_fs;
  924. #endif
  925. };
  926. /*****************************************************************************
  927.  * EncoderOpen: open dmo codec
  928.  *****************************************************************************/
  929. static int EncoderOpen( vlc_object_t *p_this )
  930. {
  931.     encoder_t *p_enc = (encoder_t*)p_this;
  932.     int i_ret = EncOpen( p_this );
  933.     if( i_ret != VLC_SUCCESS ) return i_ret;
  934.     /* Set callbacks */
  935.     p_enc->pf_encode_video = (block_t *(*)(encoder_t *, picture_t *))
  936.         EncodeBlock;
  937.     p_enc->pf_encode_audio = (block_t *(*)(encoder_t *, aout_buffer_t *))
  938.         EncodeBlock;
  939.     return VLC_SUCCESS;
  940. }
  941. /*****************************************************************************
  942.  * EncoderSetVideoType: configures the input and output types of the dmo
  943.  *****************************************************************************/
  944. static int EncoderSetVideoType( encoder_t *p_enc, IMediaObject *p_dmo )
  945. {
  946.     int i, i_selected, i_err;
  947.     DMO_MEDIA_TYPE dmo_type;
  948.     VIDEOINFOHEADER vih, *p_vih;
  949.     BITMAPINFOHEADER *p_bih;
  950.     /* FIXME */
  951.     p_enc->fmt_in.video.i_bits_per_pixel =
  952.         p_enc->fmt_out.video.i_bits_per_pixel = 12;
  953.     /* Enumerate input format (for debug output) */
  954.     i = 0;
  955.     while( !p_dmo->vt->GetInputType( p_dmo, 0, i++, &dmo_type ) )
  956.     {
  957.         p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
  958.         msg_Dbg( p_enc, "available input chroma: %4.4s",
  959.                  (char *)&dmo_type.subtype.Data1 );
  960.         if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB565, 16 ) )
  961.             msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB565" );
  962.         if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB24, 16 ) )
  963.             msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB24" );
  964.         DMOFreeMediaType( &dmo_type );
  965.     }
  966.     /* Setup input format */
  967.     memset( &dmo_type, 0, sizeof(dmo_type) );
  968.     memset( &vih, 0, sizeof(VIDEOINFOHEADER) );
  969.     p_bih = &vih.bmiHeader;
  970.     p_bih->biCompression = VLC_FOURCC('I','4','2','0');
  971.     p_bih->biWidth = p_enc->fmt_in.video.i_width;
  972.     p_bih->biHeight = p_enc->fmt_in.video.i_height;
  973.     p_bih->biBitCount = p_enc->fmt_in.video.i_bits_per_pixel;
  974.     p_bih->biSizeImage = p_enc->fmt_in.video.i_width *
  975.         p_enc->fmt_in.video.i_height * p_enc->fmt_in.video.i_bits_per_pixel /8;
  976.     p_bih->biPlanes = 3;
  977.     p_bih->biSize = sizeof(BITMAPINFOHEADER);
  978.     vih.rcSource.left = vih.rcSource.top = 0;
  979.     vih.rcSource.right = p_enc->fmt_in.video.i_width;
  980.     vih.rcSource.bottom = p_enc->fmt_in.video.i_height;
  981.     vih.rcTarget = vih.rcSource;
  982.     vih.AvgTimePerFrame = INT64_C(10000000) / 25; //FIXME
  983.     dmo_type.majortype = MEDIATYPE_Video;
  984.     //dmo_type.subtype = MEDIASUBTYPE_RGB24;
  985.     dmo_type.subtype = MEDIASUBTYPE_I420;
  986.     //dmo_type.subtype.Data1 = p_bih->biCompression;
  987.     dmo_type.formattype = FORMAT_VideoInfo;
  988.     dmo_type.bFixedSizeSamples = TRUE;
  989.     dmo_type.bTemporalCompression = FALSE;
  990.     dmo_type.lSampleSize = p_bih->biSizeImage;
  991.     dmo_type.cbFormat = sizeof(VIDEOINFOHEADER);
  992.     dmo_type.pbFormat = (char *)&vih;
  993.     if( ( i_err = p_dmo->vt->SetInputType( p_dmo, 0, &dmo_type, 0 ) ) )
  994.     {
  995.         msg_Err( p_enc, "can't set DMO input type: %x", i_err );
  996.         return VLC_EGENERIC;
  997.     }
  998.     msg_Dbg( p_enc, "successfully set input type" );
  999.     /* Setup output format */
  1000.     memset( &dmo_type, 0, sizeof(dmo_type) );
  1001.     dmo_type.pUnk = 0;
  1002.     /* Enumerate output types */
  1003.     i = 0, i_selected = -1;
  1004.     while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) )
  1005.     {
  1006.         p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
  1007.         msg_Dbg( p_enc, "available output codec: %4.4s",
  1008.                  (char *)&dmo_type.subtype.Data1 );
  1009.         if( p_vih->bmiHeader.biCompression == p_enc->fmt_out.i_codec )
  1010.             i_selected = i - 1;
  1011.         DMOFreeMediaType( &dmo_type );
  1012.     }
  1013.     if( i_selected < 0 )
  1014.     {
  1015.         msg_Err( p_enc, "couldn't find codec: %4.4s",
  1016.                  (char *)&p_enc->fmt_out.i_codec );
  1017.         return VLC_EGENERIC;
  1018.     }
  1019.     p_dmo->vt->GetOutputType( p_dmo, 0, i_selected, &dmo_type );
  1020.     ((VIDEOINFOHEADER *)dmo_type.pbFormat)->dwBitRate =
  1021.         p_enc->fmt_out.i_bitrate;
  1022.     /* Get the private data for the codec */
  1023.     while( 1 )
  1024.     {
  1025.         IWMCodecPrivateData *p_privdata;
  1026.         VIDEOINFOHEADER *p_vih;
  1027.         uint8_t *p_data = 0;
  1028.         uint32_t i_data = 0, i_vih;
  1029.         i_err = p_dmo->vt->QueryInterface( (IUnknown *)p_dmo,
  1030.                                            &IID_IWMCodecPrivateData,
  1031.                                            (void **)&p_privdata );
  1032.         if( i_err ) break;
  1033.         i_err = p_privdata->vt->SetPartialOutputType( p_privdata, &dmo_type );
  1034.         if( i_err )
  1035.         {
  1036.             msg_Err( p_enc, "SetPartialOutputType() failed" );
  1037.             p_privdata->vt->Release( (IUnknown *)p_privdata );
  1038.             break;
  1039.         }
  1040.         i_err = p_privdata->vt->GetPrivateData( p_privdata, NULL, &i_data );
  1041.         if( i_err )
  1042.         {
  1043.             msg_Err( p_enc, "GetPrivateData() failed" );
  1044.             p_privdata->vt->Release( (IUnknown *)p_privdata );
  1045.             break;
  1046.         }
  1047.         p_data = malloc( i_data );
  1048.         i_err = p_privdata->vt->GetPrivateData( p_privdata, p_data, &i_data );
  1049.         /* Update the media type with the private data */
  1050.         i_vih = dmo_type.cbFormat + i_data;
  1051.         p_vih = CoTaskMemAlloc( i_vih );
  1052.         memcpy( p_vih, dmo_type.pbFormat, dmo_type.cbFormat );
  1053.         memcpy( ((uint8_t *)p_vih) + dmo_type.cbFormat, p_data, i_data );
  1054.         DMOFreeMediaType( &dmo_type );
  1055.         dmo_type.pbFormat = (char*)p_vih;
  1056.         dmo_type.cbFormat = i_vih;
  1057.         msg_Dbg( p_enc, "found extra data: %i", i_data );
  1058.         p_enc->fmt_out.i_extra = i_data;
  1059.         p_enc->fmt_out.p_extra = p_data;
  1060.         break;
  1061.     }
  1062.     i_err = p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_type, 0 );
  1063.     p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat;
  1064.     p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
  1065.     DMOFreeMediaType( &dmo_type );
  1066.     if( i_err )
  1067.     {
  1068.         msg_Err( p_enc, "can't set DMO output type: %i", i_err );
  1069.         return VLC_EGENERIC;
  1070.     }
  1071.     msg_Dbg( p_enc, "successfully set output type" );
  1072.     return VLC_SUCCESS;
  1073. }
  1074. /*****************************************************************************
  1075.  * EncoderSetAudioType: configures the input and output types of the dmo
  1076.  *****************************************************************************/
  1077. static int EncoderSetAudioType( encoder_t *p_enc, IMediaObject *p_dmo )
  1078. {
  1079.     int i, i_selected, i_err;
  1080.     unsigned int i_last_byterate;
  1081.     uint16_t i_tag;
  1082.     DMO_MEDIA_TYPE dmo_type;
  1083.     WAVEFORMATEX *p_wf;
  1084.     /* Setup the format structure */
  1085.     fourcc_to_wf_tag( p_enc->fmt_out.i_codec, &i_tag );
  1086.     if( i_tag == 0 ) return VLC_EGENERIC;
  1087.     p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE;
  1088.     p_enc->fmt_in.audio.i_bitspersample = 16;
  1089.     /* We first need to choose an output type from the predefined
  1090.      * list of choices (we cycle through the list to select the best match) */
  1091.     i = 0; i_selected = -1; i_last_byterate = 0;
  1092.     while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) )
  1093.     {
  1094.         p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
  1095.         msg_Dbg( p_enc, "available format :%i, sample rate: %i, channels: %i, "
  1096.                  "bits per sample: %i, bitrate: %i, blockalign: %i",
  1097.                  (int) p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
  1098.                  (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
  1099.                  (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
  1100.         if( p_wf->wFormatTag == i_tag &&
  1101.             p_wf->nSamplesPerSec == p_enc->fmt_in.audio.i_rate &&
  1102.             p_wf->nChannels == p_enc->fmt_in.audio.i_channels &&
  1103.             p_wf->wBitsPerSample == p_enc->fmt_in.audio.i_bitspersample )
  1104.         {
  1105.             if( p_wf->nAvgBytesPerSec <
  1106.                 p_enc->fmt_out.i_bitrate * 110 / 800 /* + 10% */ &&
  1107.                 p_wf->nAvgBytesPerSec > i_last_byterate )
  1108.             {
  1109.                 i_selected = i - 1;
  1110.                 i_last_byterate = p_wf->nAvgBytesPerSec;
  1111.                 msg_Dbg( p_enc, "selected entry %i (bitrate: %i)",
  1112.                          i_selected, p_wf->nAvgBytesPerSec * 8 );
  1113.             }
  1114.         }
  1115.         DMOFreeMediaType( &dmo_type );
  1116.     }
  1117.     if( i_selected < 0 )
  1118.     {
  1119.         msg_Err( p_enc, "couldn't find a matching output" );
  1120.         return VLC_EGENERIC;
  1121.     }
  1122.     p_dmo->vt->GetOutputType( p_dmo, 0, i_selected, &dmo_type );
  1123.     p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
  1124.     msg_Dbg( p_enc, "selected format: %i, sample rate:%i, "
  1125.              "channels: %i, bits per sample: %i, bitrate: %i, blockalign: %i",
  1126.              (int)p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
  1127.              (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
  1128.              (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
  1129.     p_enc->fmt_out.audio.i_rate = p_wf->nSamplesPerSec;
  1130.     p_enc->fmt_out.audio.i_channels = p_wf->nChannels;
  1131.     p_enc->fmt_out.audio.i_bitspersample = p_wf->wBitsPerSample;
  1132.     p_enc->fmt_out.audio.i_blockalign = p_wf->nBlockAlign;
  1133.     p_enc->fmt_out.i_bitrate = p_wf->nAvgBytesPerSec * 8;
  1134.     if( p_wf->cbSize )
  1135.     {
  1136.         msg_Dbg( p_enc, "found cbSize: %i", p_wf->cbSize );
  1137.         p_enc->fmt_out.i_extra = p_wf->cbSize;
  1138.         p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra );
  1139.         memcpy( p_enc->fmt_out.p_extra, &p_wf[1], p_enc->fmt_out.i_extra );
  1140.     }
  1141.     i_err = p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_type, 0 );
  1142.     DMOFreeMediaType( &dmo_type );
  1143.     if( i_err )
  1144.     {
  1145.         msg_Err( p_enc, "can't set DMO output type: %i", i_err );
  1146.         return VLC_EGENERIC;
  1147.     }
  1148.     msg_Dbg( p_enc, "successfully set output type" );
  1149.     /* Setup the input type */
  1150.     i = 0; i_selected = -1;
  1151.     while( !p_dmo->vt->GetInputType( p_dmo, 0, i++, &dmo_type ) )
  1152.     {
  1153.         p_wf = (WAVEFORMATEX *)dmo_type.pbFormat;
  1154.         msg_Dbg( p_enc, "available format :%i, sample rate: %i, channels: %i, "
  1155.                  "bits per sample: %i, bitrate: %i, blockalign: %i",
  1156.                  (int) p_wf->wFormatTag, (int)p_wf->nSamplesPerSec,
  1157.                  (int)p_wf->nChannels, (int)p_wf->wBitsPerSample,
  1158.                  (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign );
  1159.         if( p_wf->wFormatTag == WAVE_FORMAT_PCM &&
  1160.             p_wf->nSamplesPerSec == p_enc->fmt_in.audio.i_rate &&
  1161.             p_wf->nChannels == p_enc->fmt_in.audio.i_channels &&
  1162.             p_wf->wBitsPerSample == p_enc->fmt_in.audio.i_bitspersample )
  1163.         {
  1164.             i_selected = i - 1;
  1165.         }
  1166.         DMOFreeMediaType( &dmo_type );
  1167.     }
  1168.     if( i_selected < 0 )
  1169.     {
  1170.         msg_Err( p_enc, "couldn't find a matching input" );
  1171.         return VLC_EGENERIC;
  1172.     }
  1173.     p_dmo->vt->GetInputType( p_dmo, 0, i_selected, &dmo_type );
  1174.     i_err = p_dmo->vt->SetInputType( p_dmo, 0, &dmo_type, 0 );
  1175.     DMOFreeMediaType( &dmo_type );
  1176.     if( i_err )
  1177.     {
  1178.         msg_Err( p_enc, "can't set DMO input type: %x", i_err );
  1179.         return VLC_EGENERIC;
  1180.     }
  1181.     msg_Dbg( p_enc, "successfully set input type" );
  1182.     return VLC_SUCCESS;
  1183. }
  1184. /*****************************************************************************
  1185.  * EncOpen: open dmo codec
  1186.  *****************************************************************************/
  1187. static int EncOpen( vlc_object_t *p_this )
  1188. {
  1189.     encoder_t *p_enc = (encoder_t*)p_this;
  1190.     encoder_sys_t *p_sys = NULL;
  1191.     IMediaObject *p_dmo = NULL;
  1192.     HINSTANCE hmsdmo_dll = NULL;
  1193. #ifdef LOADER
  1194.     ldt_fs_t *ldt_fs = Setup_LDT_Keeper();
  1195. #else
  1196.     /* Initialize OLE/COM */
  1197.     CoInitialize( 0 );
  1198. #endif /* LOADER */
  1199.     if( LoadDMO( p_this, &hmsdmo_dll, &p_dmo, &p_enc->fmt_out, true )
  1200.         != VLC_SUCCESS )
  1201.     {
  1202.         hmsdmo_dll = 0;
  1203.         p_dmo = 0;
  1204.         goto error;
  1205.     }
  1206.     if( p_enc->fmt_in.i_cat == VIDEO_ES )
  1207.     {
  1208.         if( EncoderSetVideoType( p_enc, p_dmo ) != VLC_SUCCESS ) goto error;
  1209.     }
  1210.     else
  1211.     {
  1212.         if( EncoderSetAudioType( p_enc, p_dmo ) != VLC_SUCCESS ) goto error;
  1213.     }
  1214.     /* Allocate the memory needed to store the decoder's structure */
  1215.     if( ( p_enc->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
  1216.     {
  1217.         goto error;
  1218.     }
  1219.     p_sys->hmsdmo_dll = hmsdmo_dll;
  1220.     p_sys->p_dmo = p_dmo;
  1221. #ifdef LOADER
  1222.     p_sys->ldt_fs = ldt_fs;
  1223. #endif
  1224.     /* Find out some properties of the inputput */
  1225.     {
  1226.         uint32_t i_size, i_align, dum;
  1227.         if( p_dmo->vt->GetInputSizeInfo( p_dmo, 0, &i_size, &i_align, &dum ) )
  1228.             msg_Err( p_enc, "GetInputSizeInfo() failed" );
  1229.         else
  1230.             msg_Dbg( p_enc, "GetInputSizeInfo(): bytes %i, align %i, %i",
  1231.                      i_size, i_align, dum );
  1232.     }
  1233.     /* Find out some properties of the output */
  1234.     {
  1235.         uint32_t i_size, i_align;
  1236.         p_sys->i_min_output = 0;
  1237.         if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
  1238.         {
  1239.             msg_Err( p_enc, "GetOutputSizeInfo() failed" );
  1240.             goto error;
  1241.         }
  1242.         else
  1243.         {
  1244.             msg_Dbg( p_enc, "GetOutputSizeInfo(): bytes %i, align %i",
  1245.                      i_size, i_align );
  1246.             p_sys->i_min_output = i_size;
  1247.         }
  1248.     }
  1249.     /* Set output properties */
  1250.     p_enc->fmt_out.i_cat = p_enc->fmt_out.i_cat;
  1251.     if( p_enc->fmt_out.i_cat == AUDIO_ES )
  1252.         date_Init( &p_sys->end_date, p_enc->fmt_out.audio.i_rate, 1 );
  1253.     else
  1254.         date_Init( &p_sys->end_date, 25 /* FIXME */, 1 );
  1255.     return VLC_SUCCESS;
  1256.  error:
  1257.     if( p_dmo ) p_dmo->vt->Release( (IUnknown *)p_dmo );
  1258.     if( hmsdmo_dll ) FreeLibrary( hmsdmo_dll );
  1259. #ifdef LOADER
  1260.     Restore_LDT_Keeper( ldt_fs );
  1261. #else
  1262.     /* Uninitialize OLE/COM */
  1263.     CoUninitialize();
  1264. #endif /* LOADER */
  1265.     free( p_sys );
  1266.     return VLC_EGENERIC;
  1267. }
  1268. /****************************************************************************
  1269.  * Encode: the whole thing
  1270.  ****************************************************************************/
  1271. static block_t *EncodeBlock( encoder_t *p_enc, void *p_data )
  1272. {
  1273.     encoder_sys_t *p_sys = p_enc->p_sys;
  1274.     CMediaBuffer *p_in;
  1275.     block_t *p_chain = NULL;
  1276.     block_t *p_block_in;
  1277.     uint32_t i_status;
  1278.     int i_result;
  1279.     mtime_t i_pts;
  1280.     if( !p_data ) return NULL;
  1281.     if( p_enc->fmt_out.i_cat == VIDEO_ES )
  1282.     {
  1283.         /* Get picture data */
  1284.         int i_plane, i_line, i_width, i_src_stride;
  1285.         picture_t *p_pic = (picture_t *)p_data;
  1286.         uint8_t *p_dst;
  1287.         int i_buffer = p_enc->fmt_in.video.i_width *
  1288.             p_enc->fmt_in.video.i_height *
  1289.             p_enc->fmt_in.video.i_bits_per_pixel / 8;
  1290.         p_block_in = block_New( p_enc, i_buffer );
  1291.         /* Copy picture stride by stride */
  1292.         p_dst = p_block_in->p_buffer;
  1293.         for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
  1294.         {
  1295.             uint8_t *p_src = p_pic->p[i_plane].p_pixels;
  1296.             i_width = p_pic->p[i_plane].i_visible_pitch;
  1297.             i_src_stride = p_pic->p[i_plane].i_pitch;
  1298.             for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;
  1299.                  i_line++ )
  1300.             {
  1301.                 vlc_memcpy( p_dst, p_src, i_width );
  1302.                 p_dst += i_width;
  1303.                 p_src += i_src_stride;
  1304.             }
  1305.         }
  1306.         i_pts = p_pic->date;
  1307.     }
  1308.     else
  1309.     {
  1310.         aout_buffer_t *p_aout_buffer = (aout_buffer_t *)p_data;
  1311.         p_block_in = block_New( p_enc, p_aout_buffer->i_nb_bytes );
  1312.         memcpy( p_block_in->p_buffer, p_aout_buffer->p_buffer,
  1313.                 p_block_in->i_buffer );
  1314.         i_pts = p_aout_buffer->start_date;
  1315.     }
  1316.     /* Feed input to the DMO */
  1317.     p_in = CMediaBufferCreate( p_block_in, p_block_in->i_buffer, true );
  1318.     i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
  1319.        (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFERF_TIME, i_pts * 10, 0 );
  1320.     p_in->vt->Release( (IUnknown *)p_in );
  1321.     if( i_result == S_FALSE )
  1322.     {
  1323.         /* No output generated */
  1324. #ifdef DMO_DEBUG
  1325.         msg_Dbg( p_enc, "ProcessInput(): no output generated %"PRId64, i_pts );
  1326. #endif
  1327.         return NULL;
  1328.     }
  1329.     else if( i_result == (int)DMO_E_NOTACCEPTING )
  1330.     {
  1331.         /* Need to call ProcessOutput */
  1332.         msg_Dbg( p_enc, "ProcessInput(): not accepting" );
  1333.     }
  1334.     else if( i_result != S_OK )
  1335.     {
  1336.         msg_Dbg( p_enc, "ProcessInput(): failed: %x", i_result );
  1337.         return NULL;
  1338.     }
  1339. #ifdef DMO_DEBUG
  1340.     msg_Dbg( p_enc, "ProcessInput(): success" );
  1341. #endif
  1342.     /* Get output from the DMO */
  1343.     while( 1 )
  1344.     {
  1345.         DMO_OUTPUT_DATA_BUFFER db;
  1346.         block_t *p_block_out;
  1347.         CMediaBuffer *p_out;
  1348.         p_block_out = block_New( p_enc, p_sys->i_min_output );
  1349.         p_block_out->i_buffer = 0;
  1350.         p_out = CMediaBufferCreate(p_block_out, p_sys->i_min_output, false);
  1351.         memset( &db, 0, sizeof(db) );
  1352.         db.pBuffer = (IMediaBuffer *)p_out;
  1353.         i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
  1354.                                                     0, 1, &db, &i_status );
  1355.         if( i_result != S_OK )
  1356.         {
  1357.             if( i_result != S_FALSE )
  1358.                 msg_Dbg( p_enc, "ProcessOutput(): failed: %x", i_result );
  1359. #ifdef DMO_DEBUG
  1360.             else
  1361.                 msg_Dbg( p_enc, "ProcessOutput(): no output" );
  1362. #endif
  1363.             p_out->vt->Release( (IUnknown *)p_out );
  1364.             block_Release( p_block_out );
  1365.             return p_chain;
  1366.         }
  1367.         if( !p_block_out->i_buffer )
  1368.         {
  1369. #ifdef DMO_DEBUG
  1370.             msg_Dbg( p_enc, "ProcessOutput(): no output (i_buffer_out == 0)" );
  1371. #endif
  1372.             p_out->vt->Release( (IUnknown *)p_out );
  1373.             block_Release( p_block_out );
  1374.             return p_chain;
  1375.         }
  1376.         if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME )
  1377.         {
  1378. #ifdef DMO_DEBUG
  1379.             msg_Dbg( p_enc, "ProcessOutput(): pts: %"PRId64", %"PRId64,
  1380.                      i_pts, db.rtTimestamp / 10 );
  1381. #endif
  1382.             i_pts = db.rtTimestamp / 10;
  1383.         }
  1384.         if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH )
  1385.         {
  1386.             p_block_out->i_length = db.rtTimelength / 10;
  1387. #ifdef DMO_DEBUG
  1388.             msg_Dbg( p_enc, "ProcessOutput(): length: %"PRId64,
  1389.                      p_block_out->i_length );
  1390. #endif
  1391.         }
  1392.         if( p_enc->fmt_out.i_cat == VIDEO_ES )
  1393.         {
  1394.             if( db.dwStatus & DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT )
  1395.                 p_block_out->i_flags |= BLOCK_FLAG_TYPE_I;
  1396.             else
  1397.                 p_block_out->i_flags |= BLOCK_FLAG_TYPE_P;
  1398.         }
  1399.         p_block_out->i_dts = p_block_out->i_pts = i_pts;
  1400.         block_ChainAppend( &p_chain, p_block_out );
  1401.     }
  1402. }
  1403. /*****************************************************************************
  1404.  * EncoderClose: close codec
  1405.  *****************************************************************************/
  1406. void EncoderClose( vlc_object_t *p_this )
  1407. {
  1408.     encoder_t *p_enc = (encoder_t*)p_this;
  1409.     encoder_sys_t *p_sys = p_enc->p_sys;
  1410.     if( !p_sys ) return;
  1411.     if( p_sys->p_dmo ) p_sys->p_dmo->vt->Release( (IUnknown *)p_sys->p_dmo );
  1412.     FreeLibrary( p_sys->hmsdmo_dll );
  1413. #ifdef LOADER
  1414. #if 0
  1415.     Restore_LDT_Keeper( p_sys->ldt_fs );
  1416. #endif
  1417. #else
  1418.     /* Uninitialize OLE/COM */
  1419.     CoUninitialize();
  1420. #endif
  1421.     free( p_sys );
  1422. }