⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsa_audio_render.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
字号:
/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//       Copyright(c) 2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"

#ifdef UMC_ENABLE_ALSA_AUDIO_RENDER

#include "alsa_audio_render.h"

UMC::ALSAAudioRender::ALSAAudioRender():
  m_tickStartTime(0),
  m_tickPrePauseTime(0),
  m_dfStartPTS(-1.0),
  m_pPCMHandle(NULL),
  m_pHWParams(NULL)
{}

UMC::Status UMC::ALSAAudioRender::Init(MediaReceiverParams* pInit)
{
  Status umcRes = UMC_OK;
  snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
  int err = 0;

  AudioRenderParams* pParams =
    DynamicCast<AudioRenderParams, MediaReceiverParams>(pInit);
  if (NULL == pParams) {
    return UMC_ERR_NULL_PTR;
  }

//  m_pPCMDevice = "plughw:0,0";
  m_pPCMDevice = "default";

  err = snd_pcm_open(&m_pPCMHandle, m_pPCMDevice, SND_PCM_STREAM_PLAYBACK, 0);
  if (err < 0) {
    vm_debug_trace1(VM_DEBUG_ERROR, VM_STRING("Failed to open device %s\n"), m_pPCMDevice);
    return UMC_ERR_FAILED;
  }

  err = snd_pcm_hw_params_malloc(&m_pHWParams);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_malloc!!!\n"));
    return UMC_ERR_ALLOC;
  }

  err = snd_pcm_hw_params_any(m_pPCMHandle, m_pHWParams);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_any!!!\n"));
    return UMC_ERR_FAILED;
  }

  err = snd_pcm_hw_params_set_rate_resample(m_pPCMHandle, m_pHWParams, 0);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_rate_resample!!!\n"));
    return UMC_ERR_FAILED;
  }

  err = snd_pcm_hw_params_set_access(m_pPCMHandle, m_pHWParams, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_access!!!\n"));
    return UMC_ERR_FAILED;
  }

  switch(pParams->info.bitPerSample) {
    case 8:
      format = SND_PCM_FORMAT_S8;
      break;
    case 16:
      format = SND_PCM_FORMAT_S16_LE;
      break;
    case 24:
      format = SND_PCM_FORMAT_S24_LE;
      break;
    case 32:
      format = SND_PCM_FORMAT_S32_LE;
      break;
  }

  err = snd_pcm_hw_params_set_format(m_pPCMHandle, m_pHWParams, format);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_format!!!\n"));
    return UMC_ERR_FAILED;
  }

  Ipp32u need_rate = pParams->info.sample_frequency;
  err = snd_pcm_hw_params_set_rate_near(m_pPCMHandle, m_pHWParams, &need_rate, 0);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_rate_near!!!\n"));
    return UMC_ERR_FAILED;
  }

  err = snd_pcm_hw_params_set_channels(m_pPCMHandle, m_pHWParams, pParams->info.channels);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_channels!!!\n"));
    return UMC_ERR_FAILED;
  }

  Ipp32u buffer_time = ALSA_BUFFER_TIME;
  err = snd_pcm_hw_params_set_buffer_time_near(m_pPCMHandle, m_pHWParams, &buffer_time, 0);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_buffer_time_near!!!\n"));
    return UMC_ERR_FAILED;
  }

  Ipp32u period_time = ALSA_PERIOD_TIME;
  err = snd_pcm_hw_params_set_period_time_near(m_pPCMHandle, m_pHWParams, &period_time, 0);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_set_period_time_near!!!\n"));
    return UMC_ERR_FAILED;
  }

  err = snd_pcm_hw_params(m_pPCMHandle, m_pHWParams);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params!!!\n"));
    return UMC_ERR_FAILED;
  }

  umcRes = BasicAudioRender::Init(pInit);

  return umcRes;
}

UMC::Status UMC::ALSAAudioRender::SendFrame(MediaData* in)
{
  snd_pcm_state_t pcm_state;
  snd_pcm_format_t format = SND_PCM_FORMAT_UNKNOWN;
  snd_pcm_uframes_t size = 0;
  Ipp32s err = 0;
  Ipp32s format_len = 0;

  if (NULL == in->GetDataPointer()) {
    return UMC_ERR_NULL_PTR;
  }

  if (-1.0 == m_dfStartPTS) {
    m_dfStartPTS = in->GetTime();
  }

  if (!m_tickStartTime) {
   m_tickStartTime = vm_time_get_tick();
  }

  err = snd_pcm_hw_params_get_format(m_pHWParams, &format);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in snd_pcm_hw_params_get_format!!!\n"));
    return UMC_ERR_FAILED;
  }

  format_len = snd_pcm_format_width(format) >> 3;

  Ipp32s nframes = in->GetDataSize() / format_len;

  Ipp8u *pData = (Ipp8u *)in->GetDataPointer();

  nframes /= m_wInitedChannels;

  pcm_state = snd_pcm_state(m_pPCMHandle);
  if (pcm_state == SND_PCM_STATE_PREPARED) {
    snd_pcm_start(m_pPCMHandle);
  } else if (pcm_state != SND_PCM_STATE_RUNNING) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA render is not initialized!!!\n"));
    return UMC_ERR_NOT_INITIALIZED;
  }

  while (nframes > 0) {

    err = snd_pcm_writei(m_pPCMHandle, pData, nframes);
    if (err == -EAGAIN) { /* ring buffer is full */
      vm_time_sleep(5);
      continue;
    } else if (err == -EBADFD) {
      return UMC_ERR_FAILED;
    } else if (err == -EPIPE) {  /* underrun */
      err = snd_pcm_prepare(m_pPCMHandle);
      if (err < 0) {
        return UMC_ERR_FAILED;
      } else {
        vm_time_sleep(5);
        continue;
      }
    } else if (err < 0) {
      return UMC_ERR_FAILED;
    } else {
      nframes -= err;
      pData += (err * format_len * m_wInitedChannels);
    }
  }

  return UMC_OK;
}

UMC::Status UMC::ALSAAudioRender::Pause(bool pause)
{
  snd_pcm_state_t pcm_state;
  int err = 0;

  err = snd_pcm_hw_params_can_pause(m_pHWParams);
  if (err != 1) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: hardware does not support pause!!!\n"));
    return UMC_ERR_FAILED;
  }

  pcm_state = snd_pcm_state(m_pPCMHandle);
  if (pause) {
    if (pcm_state == SND_PCM_STATE_PAUSED)
      return UMC_OK;
    err = snd_pcm_pause(m_pPCMHandle, 1);
  } else {
    if (pcm_state != SND_PCM_STATE_PAUSED)
      return UMC_OK;
    err = snd_pcm_pause(m_pPCMHandle, 0);
  }
  if (err != 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in ALSAAudioRender::Pause!!!\n"));
    return UMC_ERR_FAILED;
  }

  m_tickPrePauseTime += vm_time_get_tick() - m_tickStartTime;
  m_tickStartTime = 0;

  return UMC_OK;
}

Ipp32f UMC::ALSAAudioRender::SetVolume(Ipp32f volume)
{
  return -1;
}

Ipp32f UMC::ALSAAudioRender::GetVolume()
{
  return -1;
}

UMC::Status UMC::ALSAAudioRender::DrainBuffer()
{
  int err = 0;
  snd_pcm_state_t pcm_state;

  err = snd_pcm_drain(m_pPCMHandle);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in DrainBuffer!!!"));
    return UMC_ERR_FAILED;
  }

  pcm_state = snd_pcm_state(m_pPCMHandle);
  while (pcm_state != SND_PCM_STATE_SETUP) {
    pcm_state = snd_pcm_state(m_pPCMHandle);
    vm_time_sleep(5);
  }

//   if (pcm_state == SND_PCM_STATE_PREPARED) {
//     printf("SND_PCM_STATE_PREPARED!!!\n");
//   } else if (pcm_state == SND_PCM_STATE_RUNNING) {
//     printf("SND_PCM_STATE_RUNNING!!!\n");
//   } else if (pcm_state == SND_PCM_STATE_DRAINING ) {
//     printf("SND_PCM_STATE_DRAINING !!!\n");
//   } else if (pcm_state == SND_PCM_STATE_SETUP ) {
//     printf("SND_PCM_STATE_SETUP !!!\n");
//   } else {
//     printf("ELSE state is %i!!!\n", pcm_state);
//   }

  return UMC_OK;
}

UMC::Status UMC::ALSAAudioRender::Close()
{
  Status umcRes = UMC_OK;
  snd_pcm_state_t pcm_state;

  umcRes = BasicAudioRender::Close();
  if (umcRes != UMC_OK) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in BasicAudioRender::Close()!!!"));
    return UMC_ERR_FAILED;
  }

  if (m_pHWParams) {
    snd_pcm_hw_params_free(m_pHWParams);
  }

  if (m_pPCMHandle) {
    snd_pcm_hw_free(m_pPCMHandle);
    snd_pcm_close(m_pPCMHandle);
  }

  return UMC_OK;
}

UMC::Status UMC::ALSAAudioRender::Reset()
{
  int err = 0;
  m_tickStartTime = 0;
  m_tickPrePauseTime = 0;
  m_dfStartPTS = -1.0;

  err = snd_pcm_reset (m_pPCMHandle);
  if (err < 0) {
    vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in ALSAAudioRender::Reset!!!"));
    return UMC_ERR_FAILED;
  }

  return BasicAudioRender::Reset();
}

Ipp64f UMC::ALSAAudioRender::GetTimeTick()
{
  Ipp64f dfRes = -1;
  Ipp32u uiBytesPlayed = 0;
  if (0 != m_tickStartTime) {
    dfRes = m_dfStartPTS + ((Ipp64f)(m_tickPrePauseTime +
            vm_time_get_tick() - m_tickStartTime)) / vm_time_get_frequency();
  } else {
    dfRes = m_dfStartPTS + ((Ipp64f)m_tickPrePauseTime) / vm_time_get_frequency();
  }

  Status umcRes = BasicAudioRender::GetTimeTick(dfRes);

  return dfRes;
}

UMC::Status UMC::ALSAAudioRender::SetParams(MediaReceiverParams *pMedia,
                                            Ipp32u  trickModes)
{
  int err = 0;
  AudioRenderParams* pParams =
    DynamicCast<AudioRenderParams, MediaReceiverParams>(pMedia);

  if (NULL == pParams) {
    return UMC_ERR_NULL_PTR;
  }

  sAudioStreamInfo* info = NULL;
  info = &pParams->info;

  if (info->channels != m_wInitedChannels) {

    err = snd_pcm_hw_params_set_channels(m_pPCMHandle, m_pHWParams, info->channels);
    if (err < 0) {
      vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in SetParams::snd_pcm_hw_params_set_channels!!!\n"));
      return UMC_ERR_FAILED;
    }

    m_wInitedChannels = info->channels;
  }
  if (info->sample_frequency != m_dwInitedFrequency) {

    Ipp32u need_rate = info->sample_frequency;
    err = snd_pcm_hw_params_set_rate_near(m_pPCMHandle, m_pHWParams, &need_rate, 0);
    if (err < 0) {
      vm_debug_trace(VM_DEBUG_ERROR, VM_STRING("ALSA: failed in SetParams::snd_pcm_hw_params_set_rate_near!!!\n"));
      return UMC_ERR_FAILED;
    }

    m_dwInitedFrequency = info->sample_frequency;
  }

  return UMC_OK;
}

#endif // UMC_ENABLE_ALSA_AUDIO_RENDER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -