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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * hd1000a.cpp : Roku HD1000 audio output
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: hd1000a.cpp 7107 2004-03-18 16:53:56Z jlj $
  6.  *
  7.  * Author: Jon Lech Johansen <jon-vl@nanocrew.net>
  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. extern "C"
  27. {
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <errno.h>
  31. #include <vlc/vlc.h>
  32. #include <vlc/aout.h>
  33. #include "aout_internal.h"
  34. }
  35. #include <deschutes/libraries/hdmachinex225/PCMAudioPlayer.h>
  36. #define FRAME_SIZE 4096
  37. /*****************************************************************************
  38.  * aout_sys_t: audio output method descriptor
  39.  *****************************************************************************
  40.  * This structure is part of the audio output thread descriptor.
  41.  * It describes the direct sound specific properties of an audio device.
  42.  *****************************************************************************/
  43. struct aout_sys_t
  44. {
  45.     u32 nAlignment;
  46.     u32 nSizeMultiple;
  47.     u32 nBuffers;
  48.     u32 nBufferSize;
  49.     void ** ppBuffers;
  50.     u32 nNextBufferIndex;
  51.     PCMAudioPlayer * pPlayer;
  52. };
  53. /*****************************************************************************
  54.  * Local prototypes.
  55.  *****************************************************************************/
  56. static int     Open        ( vlc_object_t * );
  57. static void    Close       ( vlc_object_t * );
  58. static void    Play        ( aout_instance_t * );
  59. static int     Thread      ( aout_instance_t * );
  60. static void    InterleaveS16( int16_t *, int16_t * );
  61. /*****************************************************************************
  62.  * Module descriptor
  63.  *****************************************************************************/
  64. vlc_module_begin();
  65.     set_description( N_("HD1000 audio output") );
  66.     set_capability( "audio output", 100 );
  67.     set_callbacks( Open, Close );
  68. vlc_module_end();
  69. /*****************************************************************************
  70.  * Open: open a dummy audio device
  71.  *****************************************************************************/
  72. static int Open( vlc_object_t * p_this )
  73. {
  74.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  75.     struct aout_sys_t * p_sys;
  76.     PCMAudioPlayer * pPlayer;
  77.     int i_volume;
  78.     /* Allocate structure */
  79.     p_aout->output.p_sys = p_sys =
  80.         (aout_sys_t *)malloc( sizeof( aout_sys_t ) );
  81.     if( p_aout->output.p_sys == NULL )
  82.     {
  83.         msg_Err( p_aout, "out of memory" );
  84.         return VLC_EGENERIC;
  85.     }
  86.     /* New PCMAudioPlayer */
  87.     p_sys->pPlayer = pPlayer = new PCMAudioPlayer();
  88.     if( p_sys->pPlayer == NULL )
  89.     {
  90.         msg_Err( p_aout, "out of memory" );
  91.         free( p_sys );
  92.         return VLC_EGENERIC;
  93.     }
  94.     /* Get Buffer Requirements */
  95.     if( !pPlayer->GetBufferRequirements( p_sys->nAlignment,
  96.                                          p_sys->nSizeMultiple,
  97.                                          p_sys->nBuffers ) )
  98.     {
  99.         msg_Err( p_aout, "GetBufferRequirements failed" );
  100.         delete pPlayer;
  101.         free( p_sys );
  102.         return VLC_EGENERIC;
  103.     } 
  104.     p_sys->nBuffers = __MIN( p_sys->nBuffers, 4 );
  105.     p_sys->ppBuffers = (void **)malloc( p_sys->nBuffers * sizeof( void * ) );
  106.     if( p_sys->ppBuffers == NULL )
  107.     {
  108.         msg_Err( p_aout, "out of memory" );
  109.         delete pPlayer;
  110.         free( p_sys );
  111.         return VLC_EGENERIC;
  112.     }
  113.     /* Open PCMAudioPlayer */
  114.     p_sys->nBufferSize = FRAME_SIZE * 4;
  115.     if( !pPlayer->Open( p_sys->nBuffers, p_sys->nBufferSize,
  116.                         p_sys->ppBuffers ) )
  117.     {
  118.         msg_Err( p_aout, "Open failed" );
  119.         delete pPlayer;
  120.         free( p_sys->ppBuffers );
  121.         free( p_sys );
  122.         return VLC_EGENERIC;
  123.     }
  124.     p_sys->nNextBufferIndex = 0;
  125.     if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
  126.     {
  127.         p_aout->output.output.i_rate = 44100;
  128.         if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
  129.         {
  130.             msg_Err( p_aout, "SetSampleRate failed" );
  131.             pPlayer->Close();
  132.             delete pPlayer;
  133.             free( p_sys->ppBuffers );
  134.             free( p_sys );
  135.             return VLC_EGENERIC;
  136.         }
  137.     }
  138.     p_aout->output.output.i_format = AOUT_FMT_S16_NE;
  139.     p_aout->output.i_nb_samples = FRAME_SIZE;
  140.     p_aout->output.output.i_physical_channels
  141.             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
  142.     p_aout->output.pf_play = Play;
  143.     aout_VolumeSoftInit( p_aout );
  144.     i_volume = config_GetInt( p_aout->p_vlc, "volume" );
  145.     pPlayer->SetVolume( (u32)__MIN( i_volume * 64, 0xFFFF ) );
  146.     /* Create thread and wait for its readiness. */
  147.     if( vlc_thread_create( p_aout, "aout", Thread,
  148.                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
  149.     {
  150.         msg_Err( p_aout, "cannot create OSS thread (%s)", strerror(errno) );
  151.         pPlayer->Close();
  152.         delete pPlayer;
  153.         free( p_sys->ppBuffers );
  154.         free( p_sys );
  155.         return VLC_ETHREAD;
  156.     }
  157.     return VLC_SUCCESS;
  158. }
  159. /*****************************************************************************
  160.  * Close: close our file
  161.  *****************************************************************************/
  162. static void Close( vlc_object_t * p_this )
  163. {
  164.     u32 i;
  165.     aout_instance_t * p_aout = (aout_instance_t *)p_this;
  166.     struct aout_sys_t * p_sys = p_aout->output.p_sys;
  167.     p_aout->b_die = VLC_TRUE;
  168.     vlc_thread_join( p_aout );
  169.     p_aout->b_die = VLC_FALSE;
  170.     do
  171.     {
  172.         i = p_sys->pPlayer->WaitForBuffer();
  173.     } while( i != 0 && i != p_sys->nBuffers );
  174.     p_sys->pPlayer->Close();
  175.     delete p_sys->pPlayer;
  176.     free( p_sys->ppBuffers );
  177.     free( p_sys );
  178. }
  179. /*****************************************************************************
  180.  * Play: do nothing
  181.  *****************************************************************************/
  182. static void Play( aout_instance_t * p_aout )
  183. {
  184. }
  185. /*****************************************************************************
  186.  * Thread: thread used to DMA the data to the device
  187.  *****************************************************************************/
  188. static int Thread( aout_instance_t * p_aout )
  189. {
  190.     aout_buffer_t * p_buffer;
  191.     struct aout_sys_t * p_sys = p_aout->output.p_sys;
  192.     PCMAudioPlayer * pPlayer = p_sys->pPlayer;
  193.     while( !p_aout->b_die )
  194.     {
  195.         pPlayer->WaitForBuffer();
  196.         vlc_mutex_lock( &p_aout->output_fifo_lock );
  197.         p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
  198.         vlc_mutex_unlock( &p_aout->output_fifo_lock );
  199. #define i p_sys->nNextBufferIndex
  200.         if( p_buffer == NULL )
  201.         {
  202.             p_aout->p_vlc->pf_memset( p_sys->ppBuffers[ i ], 0,
  203.                                       p_sys->nBufferSize ); 
  204.         }
  205.         else
  206.         {
  207.             InterleaveS16( (int16_t *)p_buffer->p_buffer,
  208.                            (int16_t *)p_sys->ppBuffers[ i ] );
  209.             aout_BufferFree( p_buffer );
  210.         }
  211.         if( !pPlayer->QueueBuffer( (s16 *)p_sys->ppBuffers[ i ],
  212.                                    p_sys->nBufferSize / 2 ) )
  213.         {
  214.             msg_Err( p_aout, "QueueBuffer failed" );
  215.         } 
  216.         i = (i + 1) % p_sys->nBuffers;
  217. #undef i
  218.     }
  219.     return VLC_SUCCESS;
  220. }
  221. /*****************************************************************************
  222.  * InterleaveS16: interleave samples
  223.  *****************************************************************************/
  224. static void InterleaveS16( int16_t * p_in, int16_t * p_out )
  225. {
  226.     for( int i = 0; i < FRAME_SIZE; i++ )
  227.     {
  228.         p_out[ i * 2 + 0 ] = p_in[ i * 2 + 1 ];
  229.         p_out[ i * 2 + 1 ] = p_in[ i * 2 + 0 ];
  230.     }
  231. }