📄 sdla_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) 2003-2006 Intel Corporation. All Rights Reserved.
//
*/
#if defined(SDL_ON) && (defined(LINUX32) || defined(WIN32))
#include <string.h>
#include <malloc.h>
#include "vm_time.h"
#include "sdla_render.h"
#include "ipps.h"
#include "vm_debug.h"
SDLAudioRender::SDLAudioRender(void)
{
if (!(SDL_WasInit(SDL_INIT_AUDIO)&SDL_INIT_AUDIO))
SDL_InitSubSystem(SDL_INIT_AUDIO);
memset(buffers, 0, sizeof(buffers));
m_bInitSemaphore = 0;
}
SDLAudioRender::~SDLAudioRender(void)
{
Close();
}
UMC_Status SDLAudioRender::Pause(bool pause)
{
SDL_PauseAudio(pause);
return UMC_OK;
}
void AudioCallBack(void *data,Uint8 *stream,Ipp32s nbytes)
{
SDLAudioRender* pthis = (SDLAudioRender*)data;
pthis->AudioThreadFunc(stream, nbytes);
}
void SDLAudioRender::AudioThreadFunc(Uint8 *stream, Ipp32s nbytes)
{
Ipp64f rpts= (Ipp64f)vm_time_get_tick() / (Ipp64f)vm_time_get_frequency();
if (!read_position)
vm_semaphore_wait(&sm_read_buffer);
Ipp64f pts=buffers[read_index].pts+
(Ipp64f)read_position/spec.channels/sizeof(Ipp16s)/spec.freq;
/* update offset for av synchronization */
offset=(rpts-prev_rpts)-(pts-prev_pts);
prev_rpts=rpts; prev_pts=pts;
for (Ipp32s nbytes_copied=0;nbytes>0;nbytes-=nbytes_copied) {
if (buffers[read_index].nbytes>0) {
nbytes_copied=buffers[read_index].nbytes-read_position;
if (nbytes<nbytes_copied) nbytes_copied=nbytes;
ippsCopy_8u(buffers[read_index].buffer+read_position,
stream,nbytes_copied);
stream+=nbytes_copied;
read_position+=nbytes_copied;
if (read_position>=buffers[read_index].nbytes) {
vm_semaphore_post(&sm_write_buffer);
if (++read_index>=NUM_SND_BUFFER) read_index=0;
if (nbytes>nbytes_copied) vm_semaphore_wait(&sm_read_buffer);
read_position=0;
}
} else {
nbytes_copied=nbytes;
ippsZero_8u(stream,nbytes_copied);
read_position+=nbytes_copied;
}
}
}
UMC_Status SDLAudioRender::Init(sAudioStreamInfo *info)
{
Ipp32s buffer_size = sizeof(Ipp16s) * info->channels * 1024;
for (Ipp32s i=0; i < NUM_SND_BUFFER ; i++) {
buffers[i].buffer = (Ipp8u *)malloc(buffer_size);
if (!buffers[i].buffer)
return UMC_ERR_ALLOC;
}
SDL_AudioSpec desired;
desired.freq=info->sample_frequency;
desired.channels=info->channels;
desired.format=AUDIO_S16LSB;
desired.samples=1024;
desired.userdata=this;
desired.callback=(void (*)(void*, Uint8*, Ipp32s))::AudioCallBack;
vm_semaphore_init(&sm_read_buffer, 0);
vm_semaphore_init(&sm_write_buffer, NUM_SND_BUFFER/2);
m_bInitSemaphore = true;
/* Try device specific audio first */
if (SDL_OpenAudio(&desired, &spec) < 0) {
vm_debug_trace(VM_DEBUG_ERROR, "Init: failed to open audio device\n");
return UMC_ERR_OPEN_FAILED;
}
/* If format changed, let SDL handle the format conversion */
if (desired.channels!=spec.channels || desired.format!=spec.format) {
vm_debug_trace(VM_DEBUG_WARNING, "Init: simulated audio\n");
memcpy(&spec, &desired, sizeof(spec));
SDL_CloseAudio();
if (SDL_OpenAudio(&spec, NULL) < 0) {
vm_debug_trace(VM_DEBUG_ERROR, "Init: failed to open audio device\n");
return UMC_ERR_OPEN_FAILED;
}
}
read_index=write_index=read_position=0;
return UMC_OK;
}
UMC_Status SDLAudioRender::Close(void)
{
SDL_CloseAudio();
if (m_bInitSemaphore) {
vm_semaphore_destroy(&sm_read_buffer);
vm_semaphore_destroy(&sm_write_buffer);
}
for (Ipp32s i=0;i<NUM_SND_BUFFER;i++) {
if (buffers[i].buffer) free(buffers[i].buffer);
buffers[i].buffer=NULL;
}
return UMC_OK;
}
Ipp64f SDLAudioRender::GetClockOffset(void) {
// add other compensations here
return offset;
}
UMC_Status SDLAudioRender::SendFrame(sMediaData* in)
{
vm_semaphore_wait(&sm_write_buffer);
ippsCopy_8u(in->pBuffer,buffers[write_index].buffer,in->cbBuffSize);
buffers[write_index].nbytes=in->cbBuffSize;
buffers[write_index].pts=in->frame_time;
if (++write_index>=NUM_SND_BUFFER) write_index=0;
vm_semaphore_post(&sm_read_buffer);
return UMC_OK;
}
void SDLAudioRender::SendEOF(void)
{
vm_semaphore_wait(&sm_write_buffer);
buffers[write_index].nbytes=0;
vm_semaphore_post(&sm_read_buffer);
}
Ipp64f SDLAudioRender::GetTime()
{
return 0.;
}
#endif // defined(SDL_ON) && (defined(LINUX32) || defined(WIN32))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -