Skip to content
This repository has been archived by the owner on Sep 30, 2018. It is now read-only.

Commit

Permalink
[droid] add AESinkAUDIOTRACK but leave disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
davilla authored and Cory Fields committed Jul 2, 2012
1 parent 72b21e8 commit bc73239
Show file tree
Hide file tree
Showing 5 changed files with 603 additions and 0 deletions.
15 changes: 15 additions & 0 deletions xbmc/cores/AudioEngine/AESinkFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
#if defined(HAS_ALSA)
#include "Sinks/AESinkALSA.h"
#endif
#if defined(TARGET_ANDROID)
#include "Sinks/AESinkAUDIOTRACK.h"
#endif
#include "Sinks/AESinkOSS.h"
#else
#pragma message("NOTICE: No audio sink for target platform. Audio output will not be available.")
Expand All @@ -51,6 +54,9 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver)
#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
#if defined(HAS_ALSA)
driver == "ALSA" ||
#endif
#if defined(TARGET_ANDROID)
//driver == "AUDIOTRACK" ||
#endif
driver == "OSS" ||
#elif defined(TARGET_WINDOWS)
Expand Down Expand Up @@ -111,6 +117,11 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma
if (driver.empty() || driver == "ALSA")
TRY_SINK(ALSA)
#endif
#if defined(TARGET_ANDROID)
//if (driver.empty() || driver == "AUDIOTRACK")
// TRY_SINK(AUDIOTRACK)
#endif

if (driver.empty() || driver == "OSS")
TRY_SINK(OSS)

Expand Down Expand Up @@ -153,6 +164,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list)
ENUMERATE_SINK(ALSA);
#endif

#if defined(TARGET_ANDROID)
//ENUMERATE_SINK(AUDIOTRACK);
#endif

#if defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
ENUMERATE_SINK(OSS);
#endif
Expand Down
3 changes: 3 additions & 0 deletions xbmc/cores/AudioEngine/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ SRCS += Sinks/AESinkALSA.cpp
SRCS += Sinks/AESinkOSS.cpp
SRCS += Sinks/AESinkProfiler.cpp
SRCS += Sinks/AESinkNULL.cpp
ifeq (@USE_ANDROID@,1)
SRCS += Sinks/AESinkAUDIOTRACK.cpp
endif

SRCS += Utils/AEChannelInfo.cpp
SRCS += Utils/AEBuffer.cpp
Expand Down
266 changes: 266 additions & 0 deletions xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/*
* Copyright (C) 2010-2012 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#include "system.h"

#include "AESinkAUDIOTRACK.h"
#include "DynamicDll.h"
#include "Utils/AEUtil.h"
#include "Utils/AERingBuffer.h"
#include "utils/log.h"

#include <stdint.h>
#include <limits.h>

#include <libaudiotrack_wrapper.h>

////////////////////////////////////////////////////////////////////////////////////////////
class DllLibAudioTrackInterface
{
public:
virtual ~DllLibAudioTrackInterface() {}

virtual ATW_ctx ATW_create()=0;
virtual void ATW_release(ATW_ctx ctx)=0;
virtual int ATW_get_min_framecount(ATW_ctx ctx, int* frameCount, int sampleRate)=0;
virtual int ATW_set( ATW_ctx ctx, int channelCount, int sampleRate, int frameCount,
ATWCallback cbf, void* cbf_ctx)=0;
virtual void ATW_start(ATW_ctx ctx)=0;
virtual void ATW_stop( ATW_ctx ctx)=0;
virtual int ATW_write(ATW_ctx ctx, const void* buffer, size_t size)=0;
virtual void ATW_flush(ATW_ctx ctx)=0;
virtual void ATW_pause(ATW_ctx ctx)=0;
virtual void ATW_mute( ATW_ctx ctx, int mute)=0;
virtual int ATW_muted(ATW_ctx ctx)=0;
virtual void ATW_set_volume(ATW_ctx ctx, float left, float right)=0;
virtual int ATW_latency(ATW_ctx ctx)=0;
};

class DllLibAudioTrack : public DllDynamic, DllLibAudioTrackInterface
{
DECLARE_DLL_WRAPPER(DllLibAudioTrack, "libaudiotrack_wrapper.so")

DEFINE_METHOD0(ATW_ctx, ATW_create)
DEFINE_METHOD1(void, ATW_release, (ATW_ctx p1))
DEFINE_METHOD3(int, ATW_get_min_framecount,(ATW_ctx p1, int *p2, int p3))
DEFINE_METHOD6(int, ATW_set, (ATW_ctx p1, int p2, int p3, int p4,
ATWCallback p5, void *p6))
DEFINE_METHOD1(void, ATW_start, (ATW_ctx p1))
DEFINE_METHOD1(void, ATW_stop, (ATW_ctx p1))
DEFINE_METHOD3(int, ATW_write, (ATW_ctx p1, const void* p2, size_t p3))
DEFINE_METHOD1(void, ATW_flush, (ATW_ctx p1))
DEFINE_METHOD1(void, ATW_pause, (ATW_ctx p1))
DEFINE_METHOD2(void, ATW_mute, (ATW_ctx p1, int p2))
DEFINE_METHOD1(int, ATW_muted, (ATW_ctx p1))
DEFINE_METHOD3(void, ATW_set_volume, (ATW_ctx p1, float p2, float p3))
DEFINE_METHOD1(int, ATW_latency, (ATW_ctx p1))

BEGIN_METHOD_RESOLVE()
RESOLVE_METHOD(ATW_create)
RESOLVE_METHOD(ATW_release)
RESOLVE_METHOD(ATW_get_min_framecount)
RESOLVE_METHOD(ATW_set)
RESOLVE_METHOD(ATW_start)
RESOLVE_METHOD(ATW_stop)
RESOLVE_METHOD(ATW_write)
RESOLVE_METHOD(ATW_flush)
RESOLVE_METHOD(ATW_pause)
RESOLVE_METHOD(ATW_mute)
RESOLVE_METHOD(ATW_muted)
RESOLVE_METHOD(ATW_set_volume)
RESOLVE_METHOD(ATW_latency)
END_METHOD_RESOLVE()
};

DllLibAudioTrack *CAESinkAUDIOTRACK::m_dll = NULL;

CAESinkAUDIOTRACK::CAESinkAUDIOTRACK()
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::CAESinkAUDIOTRACK");
if (!m_dll)
{
m_dll = new DllLibAudioTrack;
m_dll->Load();
}
m_buffer = NULL;
m_ATWrapper = m_dll->ATW_create();
}

CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK()
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::~CAESinkAUDIOTRACK");
//delete m_dll, m_dll = NULL;
}

bool CAESinkAUDIOTRACK::Initialize(AEAudioFormat &format, std::string &device)
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Initialize");
if (!m_ATWrapper)
return false;

//format.m_sampleRate = (format.m_sampleRate = 44100) ? 44100 : 48000;
format.m_sampleRate = 48000;
format.m_dataFormat = AE_FMT_S16LE;

CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Initialize2");
int min_frames;
m_dll->ATW_get_min_framecount(m_ATWrapper, &min_frames, format.m_sampleRate);

CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Initialize3, min_frames(%d)", min_frames);
format.m_frames = min_frames;
format.m_frameSamples = format.m_channelLayout.Count();
format.m_frameSize = format.m_frameSamples * (CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3);
m_dll->ATW_set(m_ATWrapper, format.m_frameSamples, format.m_sampleRate, format.m_frames,
AudioTrackCallback, this);

m_format = format;
m_started = false;
m_draining = false;
m_buffer = new AERingBuffer(m_format.m_frameSize * m_format.m_sampleRate);

m_dll->ATW_start(m_ATWrapper), m_started = true;

return true;
}

void CAESinkAUDIOTRACK::Deinitialize()
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Deinitialize");
m_dll->ATW_stop(m_ATWrapper);
m_dll->ATW_release(m_ATWrapper), m_ATWrapper = NULL;
m_draining = false;
delete m_buffer, m_buffer = NULL;
}

bool CAESinkAUDIOTRACK::IsCompatible(const AEAudioFormat format, const std::string device)
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::IsCompatible");
return ((m_format.m_sampleRate == format.m_sampleRate) &&
(m_format.m_dataFormat == format.m_dataFormat) &&
(m_format.m_channelLayout == format.m_channelLayout));
}

double CAESinkAUDIOTRACK::GetDelay()
{
// DVDAudio.cpp says, returns the time it takes to play a packet if we add one at this time
// return the delay in seconds
float seconds_to_empty = (double)m_buffer->GetReadSize() / (double)m_format.m_sampleRate;
float latency_sec = (double)m_dll->ATW_latency(m_ATWrapper) / 1000.0;
//CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::GetDelay, latency_sec(%f), buffer_sec(%f)",
// latency_sec, buffer_sec);
return seconds_to_empty + latency_sec;
}

double CAESinkAUDIOTRACK::GetCacheTime()
{
// DVDAudio.cpp says, returns total amount of data cached in audio output at this time
float seconds_to_full = (double)m_buffer->GetWriteSize() / (double)m_format.m_sampleRate;
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::GetCacheTime, seconds_to_full(%f)", seconds_to_full);
return seconds_to_full;
}

double CAESinkAUDIOTRACK::GetCacheTotal()
{
float buffer_totalsec = (double)m_buffer->GetMaxSize() / (double)m_format.m_sampleRate;
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::GetCacheTotal, buffer_sec(%f)", buffer_totalsec);
return buffer_totalsec;
}

unsigned int CAESinkAUDIOTRACK::AddPackets(uint8_t *data, unsigned int frames)
{
//CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::AddPackets, frames(%d)", frames);
unsigned int room = m_buffer->GetWriteSize();
unsigned int addbytes = frames * m_format.m_frameSize;
unsigned int bytes_per_second = m_format.m_frameSize * m_format.m_sampleRate;

if (m_draining)
return frames;

if (!m_started)
m_dll->ATW_start(m_ATWrapper), m_started = true;

unsigned int total_ms_sleep = 0;
while (!m_draining && addbytes > room && total_ms_sleep < 200)
{
// we got deleted
if (!m_buffer || m_draining )
return 0;

unsigned int ms_sleep_time = (1000 * room) / bytes_per_second;
if (ms_sleep_time == 0)
ms_sleep_time++;

// sleep until we have space (estimated) or 1ms min
Sleep(ms_sleep_time);
total_ms_sleep += ms_sleep_time;

room = m_buffer->GetWriteSize();
}

if (addbytes > room)
frames = 0;
else
m_buffer->Write(data, addbytes);

Sleep(frames/m_format.m_sampleRate);
return frames;
}

void CAESinkAUDIOTRACK::Drain()
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::Drain");
m_started = false;
m_draining = true;
m_dll->ATW_stop( m_ATWrapper);
m_dll->ATW_flush(m_ATWrapper);
//m_dll->ATW_start(m_ATWrapper);
}

void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list)
{
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::EnumerateDevicesEx, entry");
CAEDeviceInfo info;

info.m_channels.Reset();
info.m_dataFormats.clear();
info.m_sampleRates.clear();

info.m_deviceType = AE_DEVTYPE_PCM;
info.m_deviceName = "AudioTrack";
info.m_displayName = "android";
info.m_displayNameExtra = "default display";
info.m_channels += AE_CH_FL;
info.m_channels += AE_CH_FR;
//info.m_sampleRates.push_back(44100);
info.m_sampleRates.push_back(48000);
info.m_dataFormats.push_back(AE_FMT_S16LE);

list.push_back(info);
CLog::Log(LOGDEBUG, "CAESinkAUDIOTRACK::EnumerateDevicesEx, exit");
}

int CAESinkAUDIOTRACK::AudioTrackCallback(void *ctx, void *buffer, size_t size)
{
CAESinkAUDIOTRACK *at_ctx = (CAESinkAUDIOTRACK*)ctx;
unsigned int readsize = std::min(at_ctx->m_buffer->GetReadSize(), size);
at_ctx->m_buffer->Read((unsigned char*)buffer, readsize);
return readsize;
}
65 changes: 65 additions & 0 deletions xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once
/*
* Copyright (C) 2010-2012 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/

#include "system.h"
#ifdef TARGET_ANDROID

#include "Interfaces/AESink.h"
#include "Utils/AEDeviceInfo.h"
#include <stdint.h>

typedef void* ATW_ctx;
class AERingBuffer;
class DllLibAudioTrack;

class CAESinkAUDIOTRACK : public IAESink
{
public:
virtual const char *GetName() { return "AUDIOTRACK"; }

CAESinkAUDIOTRACK();
virtual ~CAESinkAUDIOTRACK();

virtual bool Initialize(AEAudioFormat &format, std::string &device);
virtual void Deinitialize();
virtual bool IsCompatible(const AEAudioFormat format, const std::string device);

virtual double GetDelay ();
virtual double GetCacheTime ();
virtual double GetCacheTotal ();
virtual unsigned int AddPackets (uint8_t *data, unsigned int frames);
virtual void Drain ();

static void EnumerateDevicesEx(AEDeviceInfoList &list);

static int AudioTrackCallback(void *ctx, void *buffer, size_t size);
private:
static DllLibAudioTrack *m_dll;
AEAudioFormat m_format;
ATW_ctx m_ATWrapper;
AERingBuffer *m_buffer;
bool m_started;
bool m_draining;

};

#endif
Loading

0 comments on commit bc73239

Please sign in to comment.