📄 alsa_audio_render.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 + -