diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | dxr3.c | 25 | ||||
-rw-r--r-- | dxr3audio-oss.c | 81 | ||||
-rw-r--r-- | dxr3audio-oss.h | 40 | ||||
-rw-r--r-- | dxr3audio.h | 26 | ||||
-rw-r--r-- | dxr3device.c | 23 | ||||
-rw-r--r-- | dxr3interface.c | 224 | ||||
-rw-r--r-- | dxr3interface.h | 24 | ||||
-rw-r--r-- | dxr3output-audio.c | 9 |
9 files changed, 192 insertions, 263 deletions
@@ -71,7 +71,8 @@ OBJS = $(PLUGIN).o dxr3multichannelaudio.o dxr3sysclock.o dxr3colormanager.o \ dxr3syncbuffer.o dxr3audiodecoder.o dxr3blackframe.o dxr3audio.o \ dxr3pesframe.o dxr3demuxdevice.o dxr3configdata.o dxr3ffmpeg.o \ dxr3interface_spu_encoder.o dxr3interface.o dxr3device.o \ - dxr3output.o dxr3output-video.o dxr3output-audio.o dxr3osd.o dxr3spudecoder.o + dxr3output.o dxr3output-video.o dxr3output-audio.o dxr3osd.o dxr3spudecoder.o \ + dxr3audio-oss.o ### Default target: @@ -124,22 +124,13 @@ void cMenuSetupDxr3::Store(void) } // ================================== -class cPluginDxr3 : public cPlugin -{ -private: - // Add any member variables or functions you may need here. +class cPluginDxr3 : public cPlugin { public: cPluginDxr3(); ~cPluginDxr3(); - const char *Version() - { - return VERSION; - } - const char *Description() - { - return tr(DESCRIPTION); - } + const char *Version() { return VERSION; } + const char *Description() { return tr(DESCRIPTION); } bool Initialize(); @@ -152,6 +143,9 @@ public: cMenuSetupPage *SetupMenu(); bool SetupParse(const char *Name, const char *Value); + +private: + cDxr3Device *device; }; // ================================== @@ -171,8 +165,7 @@ cPluginDxr3::~cPluginDxr3() // ================================== bool cPluginDxr3::Initialize() { - new cDxr3Device(); - + device = new cDxr3Device(); return true; } @@ -306,7 +299,7 @@ cString cPluginDxr3::SVDRPCommand(const char *Command, const char *Option, return cString::sprintf("Saturation set to %d", cDxr3Interface::Instance().GetSaturation()); } - if (!strcasecmp(Command, "SDO")) +/* if (!strcasecmp(Command, "SDO")) { cDxr3Interface::Instance().SetAudioDigitalPCM(); return "Switched to digital PCM audio output"; @@ -321,7 +314,7 @@ cString cPluginDxr3::SVDRPCommand(const char *Command, const char *Option, cDxr3Interface::Instance().SetAudioDigitalAC3(); return "Switched to digital AC3 audio output"; } - +*/ return NULL; } diff --git a/dxr3audio-oss.c b/dxr3audio-oss.c new file mode 100644 index 0000000..13d4de7 --- /dev/null +++ b/dxr3audio-oss.c @@ -0,0 +1,81 @@ +#include <sys/soundcard.h> +#include <unistd.h> // for close + +#include "dxr3audio-oss.h" +#include "dxr3interface.h" + +static const char *DEV_DXR3_OSS = "_ma"; + +void cAudioOss::openDevice() +{ + fd = cDxr3Interface::Dxr3Open(DEV_DXR3_OSS, O_RDWR | O_NONBLOCK); + + if (!fd) { + esyslog("[dxr3-audio-oss] failed to open dxr3 audio subdevice"); + exit(1); + } + + if (cDxr3ConfigData::Instance().GetUseDigitalOut()) { + dsyslog("[dxr3-audio-oss] audio mode: digital"); + setAudioMode(DigitalPcm); + } else { + dsyslog("[dxr3-audio-oss] audio mode: analog"); + setAudioMode(Analog); + } +} + +void cAudioOss::releaseDevice() +{ + close(fd); +} + +void cAudioOss::setup(SampleContext ctx) +{ + // set sample rate + if (curContext.samplerate != ctx.samplerate) { + dsyslog("[dxr3-audio-oss] changing samplerate to %d (old %d) ", ctx.samplerate, curContext.samplerate); + curContext.samplerate = ctx.samplerate; + CHECK( ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &ctx.samplerate)); + } + + // set channels + if (curContext.channels != ctx.channels) { + dsyslog("[dxr3-audio-oss] changing num of channels to %d (old %d)", ctx.channels, curContext.channels); + curContext.channels = ctx.channels; + CHECK( ioctl(fd, SNDCTL_DSP_CHANNELS, &ctx.channels)); + } +} + +void cAudioOss::write(uchar* data, size_t size) +{ + size_t ret = WriteAllOrNothing(fd, data, size, 1000, 10); + + if (ret != size) { + dsyslog("[dxr3-audio-oss] writing audio failed"); + } +} + +void cAudioOss::setAudioMode(AudioMode mode) +{ + uint32_t ioval; + + switch (mode) { + case Analog: + ioval = EM8300_AUDIOMODE_ANALOG; + break; + + case DigitalPcm: + ioval = EM8300_AUDIOMODE_DIGITALPCM; + break; + + case Ac3: + ioval = EM8300_AUDIOMODE_DIGITALAC3; + break; + } + + // we need to do it this way, as we dont have access + // to the file handle for the conrtol sub device. + if (cDxr3Interface::Instance().OssSetPlayMode(ioval)) { + this->mode = mode; + } +} diff --git a/dxr3audio-oss.h b/dxr3audio-oss.h new file mode 100644 index 0000000..0aaef9d --- /dev/null +++ b/dxr3audio-oss.h @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2009 Christian Gmeiner + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, 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 Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef _AUDIO_OSS_H_ +#define _AUDIO_OSS_H_ + +#include "dxr3audio.h" + +class cAudioOss : public iAudio { +public: + cAudioOss() : iAudio(), fd(-1) {} + + virtual void openDevice(); + virtual void releaseDevice(); + virtual void setup(SampleContext ctx); + virtual void write(uchar* data, size_t size); + virtual void setAudioMode(AudioMode m); + +private: + int fd; +}; + +#endif /*_AUDIO_OSS_H_*/ diff --git a/dxr3audio.h b/dxr3audio.h index 8ac071f..384fff9 100644 --- a/dxr3audio.h +++ b/dxr3audio.h @@ -21,11 +21,29 @@ #ifndef _AUDIO_H_ #define _AUDIO_H_ +#include <vdr/tools.h> // for uchar + +struct SampleContext { + unsigned int channels; + unsigned int samplerate; +}; + class iAudio { public: + enum AudioMode { + Analog, + DigitalPcm, + Ac3, + }; + iAudio() : vol(0), audioChannel(0) {} virtual ~iAudio() {} + virtual void openDevice() = 0; + virtual void releaseDevice() = 0; + virtual void setup(SampleContext ctx) = 0; + virtual void write(uchar* data, size_t size) = 0; + void setVolume(int v) { vol = v; } void mute() { setVolume(0); } @@ -33,9 +51,17 @@ public: void setAudioChannel(int channel) { audioChannel = channel; } int getAudioChannel() { return audioChannel; } + virtual void setAudioMode(AudioMode m) = 0; + AudioMode getAudioMode() { return mode; } + + bool isAudioModeAC3() { return mode == Ac3; } + + protected: int vol; int audioChannel; + SampleContext curContext; + AudioMode mode; }; #endif /*_AUDIO_H_*/ diff --git a/dxr3device.c b/dxr3device.c index be84138..8b50cb2 100644 --- a/dxr3device.c +++ b/dxr3device.c @@ -27,7 +27,7 @@ #include "dxr3interface.h" #include "dxr3tools.h" #include "dxr3osd.h" -#include "dxr3audio.h" +#include "dxr3audio-oss.h" // ================================== //! constructor @@ -41,7 +41,8 @@ cDxr3Device::cDxr3Device() : m_DemuxDevice(cDxr3Interface::Instance()) // TODO: this will be later the place, // where we will decide what kind of // audio output system we will use. - audioOut = new iAudio(); + audioOut = new cAudioOss(); + audioOut->openDevice(); m_DemuxDevice.setAudio(audioOut); } @@ -49,6 +50,7 @@ cDxr3Device::cDxr3Device() : m_DemuxDevice(cDxr3Interface::Instance()) // ================================== cDxr3Device::~cDxr3Device() { + audioOut->releaseDevice(); delete audioOut; if (m_spuDecoder) @@ -81,14 +83,11 @@ bool cDxr3Device::CanReplay() const // ================================== bool cDxr3Device::SetPlayMode(ePlayMode PlayMode) { - if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED) - { - Tools::WriteInfoToOsd(tr("DXR3: releasing devices")); - cDxr3Interface::Instance().ExternalReleaseDevices(); - } - else - { - cDxr3Interface::Instance().ExternalReopenDevices(); + if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED) { + Tools::WriteInfoToOsd(tr("DXR3: releasing devices")); + cDxr3Interface::Instance().ExternalReleaseDevices(); + } else { + cDxr3Interface::Instance().ExternalReopenDevices(); } // should this really be here? @@ -273,8 +272,8 @@ int cDxr3Device::PlayAudio(const uchar *Data, int Length, uchar Id) bool isAc3 = ((Id & 0xF0) == 0x80) || Id == 0xbd; - if (isAc3 && !cDxr3Interface::Instance().IsAudioModeAC3()) - cDxr3Interface::Instance().SetAudioDigitalAC3(); + if (isAc3 && !audioOut->isAudioModeAC3()) + audioOut->setAudioMode(iAudio::Ac3); if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE && m_DemuxDevice.GetTrickState() == DXR3_FREEZE) || diff --git a/dxr3interface.c b/dxr3interface.c index df8518a..f0229e8 100644 --- a/dxr3interface.c +++ b/dxr3interface.c @@ -44,7 +44,7 @@ static const char *DEV_DXR3_CONT = ""; // ================================== //! constructor cDxr3Interface::cDxr3Interface() : - m_fdControl(-1), m_fdVideo(-1), m_fdAudio(-1), m_fdSpu(-1) + m_fdControl(-1), m_fdVideo(-1), m_fdSpu(-1) { ClaimDevices(); } @@ -57,8 +57,8 @@ cDxr3Interface::~cDxr3Interface() } // audio -bool cDxr3Interface::IsOssAudio() { - +bool cDxr3Interface::IsOssAudio() +{ // try to open oss audio interface int handle = Dxr3Open(DEV_DXR3_OSS, O_RDWR | O_NONBLOCK, false); @@ -70,157 +70,9 @@ bool cDxr3Interface::IsOssAudio() { return false; } - -// ================================== -//! set audio output to analog -void cDxr3Interface::SetAudioAnalog() -{ - uint32_t ioval = EM8300_AUDIOMODE_ANALOG; - - Lock(); - - if (!m_ExternalReleased && m_audioMode != ioval) - { - int prevMode = m_audioMode; - isyslog("dxr3: setting analog audio mode"); - if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) == -1) - { - esyslog("dxr3: unable to set analog audio mode: %m"); - } - else - { - m_audioMode = ioval; - } - - if (prevMode == EM8300_AUDIOMODE_DIGITALAC3) - { - ReOpenAudio(); - } - } - - Unlock(); -} - -// ================================== -//! set audio output to digital pcm -void cDxr3Interface::SetAudioDigitalPCM() -{ - uint32_t ioval = EM8300_AUDIOMODE_DIGITALPCM; - - Lock(); - - if (!m_ExternalReleased && m_audioMode != ioval) - { - int prevMode = m_audioMode; - isyslog("dxr3: setting digital PCM audio mode"); - if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) == -1) - { - esyslog("dxr3: unable to set digital PCM audio mode: %m"); - } - else - { - m_audioMode = ioval; - } - - if (prevMode == EM8300_AUDIOMODE_DIGITALAC3) - { - ReOpenAudio(); - } - } - - Unlock(); -} - -// ================================== -//! set audio output to digital ac3 -void cDxr3Interface::SetAudioDigitalAC3() -{ - uint32_t ioval = EM8300_AUDIOMODE_DIGITALAC3; - - Lock(); - - if (!m_ExternalReleased && m_audioMode != ioval) - { - isyslog("dxr3: setting digital AC3 audio mode"); - if (ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &ioval) == -1) - { - esyslog("dxr3: unable to set AC3 audio mode: %m"); - } - else - { - m_audioMode = ioval; - } - - ReOpenAudio(); - } - - Unlock(); -} - - -// ================================= -//! get current audio mode -int cDxr3Interface::GetAudioMode() +int cDxr3Interface::OssSetPlayMode(uint32_t mode) { - int audioMode = EM8300_AUDIOMODE_DEFAULT; - Lock(); - ioctl(m_fdControl, EM8300_IOCTL_GET_AUDIOMODE, &audioMode); - Unlock(); - return audioMode; -} - - -// ================================== -//! set audio speed -void cDxr3Interface::SetAudioSpeed(uint32_t speed) -{ - if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALAC3 && - m_audioDataRate != speed && speed != UNKNOWN_DATA_RATE) - { - if (ioctl(m_fdAudio, SNDCTL_DSP_SPEED, &speed) == -1) - { - esyslog("dxr3: unable to set DSP speed to %d: %m", speed); - } - else - { - m_audioDataRate = speed; - } - } -} - -// ================================== -//! set number of channels -void cDxr3Interface::SetChannelCount(uint32_t count) -{ - // 0 = mono, 1 = stereo - uint32_t ioval = count - 1; - - if (!m_ExternalReleased && m_audioMode != EM8300_AUDIOMODE_DIGITALAC3 && - m_audioChannelCount != count) { - if (ioctl(m_fdAudio, SNDCTL_DSP_STEREO, &ioval) == -1) { - esyslog("dxr3: unable to set channel count to %d: %m", count); - } else { - m_audioChannelCount = count; - } - } -} - -// ================================== -//! set audio sample size -void cDxr3Interface::SetAudioSampleSize(uint32_t sampleSize) -{ - if (!m_ExternalReleased) - { - if (ioctl(m_fdAudio, SNDCTL_DSP_SAMPLESIZE, sampleSize) == -1) - { - esyslog("dxr3: unable to set audio sample size to %d: %m", - sampleSize); - } - else - { - m_audioSampleSize = sampleSize; - } - } + return ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &mode); } // clock @@ -325,18 +177,8 @@ void cDxr3Interface::DisableSPU() //! disable audio output of dxr3 void cDxr3Interface::DisableAudio() { - m_AudioActive = false; - Lock(); - // we write zero buffers to dxr3 - if (!m_ExternalReleased) - { - for (int i = 0; i < 4; i++) - { - if (write(m_fdAudio, zerobuffer, ZEROBUFFER_SIZE) == -1) - Resuscitation(); - } - } + m_AudioActive = false; Unlock(); } @@ -557,30 +399,6 @@ void cDxr3Interface::PlayVideoFrame(const uint8_t* pBuf, int length, int times) } // ================================== -void cDxr3Interface::PlayAudioFrame(cFixedLengthFrame* pFrame) -{ - // TODO can this method get called, when external released? - - if (m_AudioActive && !m_ExternalReleased) { - Lock(); - - SetAudioSpeed(pFrame->GetSampleRate()); - SetChannelCount(pFrame->GetChannelCount()); - - int written = write(m_fdAudio, pFrame->GetData(), pFrame->GetCount()); - if (written == -1) { - esyslog("dxr3: unable to play audio frame: %m"); - // TODO: Resuscitation() ? - } else if (written != pFrame->GetCount()) { - esyslog("dxr3: unable to play whole audio frame, skipped" - " %d bytes", pFrame->GetCount() - written); - } - - Unlock(); - } -} - -// ================================== void cDxr3Interface::ClaimDevices() { // open control stream @@ -596,11 +414,10 @@ void cDxr3Interface::ClaimDevices() ///< open multimedia streams m_fdVideo = Dxr3Open(DEV_DXR3_VIDEO, O_WRONLY | O_SYNC); - m_fdAudio = Dxr3Open(DEV_DXR3_OSS, O_WRONLY | O_SYNC); m_fdSpu = Dxr3Open(DEV_DXR3_OSD, O_WRONLY | O_SYNC); // everything ok? - if (m_fdVideo == -1 || m_fdAudio == -1 || m_fdSpu == -1) + if (m_fdVideo == -1 || m_fdSpu == -1) { esyslog("dxr3: fatal: unable to open some em8300 devices"); exit(1); @@ -622,11 +439,6 @@ void cDxr3Interface::ClaimDevices() m_ExternalReleased = false; m_horizontal = 720; m_vertical = 576; - m_audioChannelCount = UNKNOWN_CHANNEL_COUNT; - m_audioDataRate = 0; - m_audioSampleSize = 0; - - m_audioMode = UNKNOWN_AUDIO_MODE; m_aspectRatio = UNKNOWN_ASPECT_RATIO; m_spuMode = EM8300_SPUMODE_OFF; @@ -645,7 +457,6 @@ void cDxr3Interface::ClaimDevices() } PlayBlackFrame(); - SetChannelCount(1); } // ================================== @@ -663,12 +474,7 @@ void cDxr3Interface::ReleaseDevices() close(m_fdSpu); m_fdSpu = -1; - if (m_fdAudio > -1) - close(m_fdAudio); - m_fdAudio = -1; - m_aspectRatio = UNKNOWN_ASPECT_RATIO; - m_audioMode = UNKNOWN_AUDIO_MODE; m_ExternalReleased = true; delete m_pClock; m_pClock = NULL; @@ -699,10 +505,9 @@ void cDxr3Interface::ExternalReopenDevices() // open 'multimedia' streams m_fdVideo = Dxr3Open(DEV_DXR3_VIDEO, O_WRONLY | O_SYNC); - m_fdAudio = Dxr3Open(DEV_DXR3_OSS, O_WRONLY | O_SYNC); m_fdSpu = Dxr3Open(DEV_DXR3_OSD, O_WRONLY | O_SYNC); - if (m_fdControl == -1 || m_fdVideo == -1 || m_fdAudio == -1 || + if (m_fdControl == -1 || m_fdVideo == -1 || m_fdSpu == -1) { ExternalReleaseDevices(); @@ -717,7 +522,6 @@ void cDxr3Interface::ExternalReopenDevices() exit(1); } - SetChannelCount(1); m_ExternalReleased = false; ConfigureDeviceAudio(); @@ -758,7 +562,7 @@ void cDxr3Interface::PlayBlackFrame() void cDxr3Interface::ReOpenAudio() { Lock(); - +/* if (!m_ExternalReleased) { if (m_fdAudio != -1) @@ -772,15 +576,10 @@ void cDxr3Interface::ReOpenAudio() m_fdAudio = Dxr3Open(DEV_DXR3_OSS, O_WRONLY | O_SYNC); - uint32_t tmpAudioDataRate = m_audioDataRate; - uint32_t tmpAudioChannelCount = m_audioChannelCount; - m_audioDataRate = m_audioChannelCount = 0; m_pClock = new cDxr3SysClock(m_fdControl, m_fdVideo, m_fdSpu); - SetAudioSpeed(tmpAudioDataRate); - SetChannelCount(tmpAudioChannelCount); } } - +*/ Unlock(); } @@ -888,6 +687,7 @@ void cDxr3Interface::ConfigureDevice() //! setup device audio based on config void cDxr3Interface::ConfigureDeviceAudio() { + /* // TODO: AC3? if (cDxr3ConfigData::Instance().GetUseDigitalOut()) { @@ -898,7 +698,7 @@ void cDxr3Interface::ConfigureDeviceAudio() { dsyslog("dxr3: configure: audio mode: analog"); SetAudioAnalog(); - } + }*/ } // ================================== diff --git a/dxr3interface.h b/dxr3interface.h index 3124264..dec2c8d 100644 --- a/dxr3interface.h +++ b/dxr3interface.h @@ -73,15 +73,9 @@ public: // audio bool IsOssAudio(); - void SetAudioAnalog(); - void SetAudioDigitalPCM(); - void SetAudioDigitalAC3(); - int GetAudioMode(); - int IsAudioModeAC3() { return GetAudioMode() == EM8300_AUDIOMODE_DIGITALAC3; } + int OssSetPlayMode(uint32_t mode); - void SetAudioSpeed(uint32_t speed); - void SetChannelCount(uint32_t count); - void SetAudioSampleSize(uint32_t sampleSize); + int IsAudioModeAC3() { return 0; } // clock void SetSysClock(uint32_t scr); @@ -133,15 +127,11 @@ public: void SingleStep(); void PlayVideoFrame(cFixedLengthFrame* pFrame, int times = 1); void PlayVideoFrame(const uint8_t* pBuf, int length, int times = 1); - void PlayAudioFrame(cFixedLengthFrame* pFrame); // external device access void ExternalReleaseDevices(); void ExternalReopenDevices(); - bool IsExternalReleased() const - { - return m_ExternalReleased; - } + bool IsExternalReleased() const { return m_ExternalReleased; } // tools void PlayBlackFrame(); @@ -171,21 +161,16 @@ private: // file handles int m_fdControl; ///< filehandle for contol fifo of dxr3 card int m_fdVideo; ///< filehandle for video fifo of dxr3 card - int m_fdAudio; ///< filehandle for audio fifo of dxr3 card int m_fdSpu; ///< filehandle for spu fifo of dxr3 card uint32_t m_lastSeenPts; // dxr3 clock cDxr3SysClock* m_pClock; ///< clock used for sync - uint32_t m_audioChannelCount; ///< how many channels in the current audiostream - uint32_t m_audioDataRate; ///< which rate is used for the current audiostream int m_aspectDelayCounter; uint32_t m_aspectRatio; ///< current used aspect ratio uint32_t m_horizontal; ///< horizontal size of current videostream uint32_t m_vertical; ///< vertical size of current videostream - uint32_t m_audioSampleSize; ///< how big is the sample size for the current audiostream - uint32_t m_audioMode; uint32_t m_spuMode; bool m_ExternalReleased; ///< is dxr3 used by e.g. mplayer? bool m_AudioActive; ///< is audio active? @@ -194,9 +179,6 @@ private: // bcs em8300_bcs_t m_bcs; ///< BrightnessContrastSaturation values - // spu - //cDxr3InterfaceSpu m_SpuInterface; - void UploadMicroCode(); void ConfigureDevice(); void ConfigureDeviceAudio(); diff --git a/dxr3output-audio.c b/dxr3output-audio.c index af1a879..34064cf 100644 --- a/dxr3output-audio.c +++ b/dxr3output-audio.c @@ -106,11 +106,18 @@ void cDxr3AudioOutThread::Action() void cDxr3AudioOutThread::PlayFrame(cFixedLengthFrame *frame) { + // update audio context + SampleContext ctx; + ctx.samplerate = frame->GetSampleRate(); + ctx.channels = frame->GetChannelCount(); + audioOutput->setup(ctx); + + // volume changes if (!cDxr3Interface::Instance().IsAudioModeAC3()) { audioOutput->changeVolume((short *)frame->GetData(), (size_t)frame->GetCount()); } - m_dxr3Device.PlayAudioFrame(frame); + audioOutput->write(frame->GetData(), frame->GetCount()); } #undef SCR |