diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | dxr3.c | 19 | ||||
-rw-r--r-- | dxr3.h | 1 | ||||
-rw-r--r-- | dxr3audio-oss.c | 7 | ||||
-rw-r--r-- | dxr3device.c | 332 | ||||
-rw-r--r-- | dxr3device.h | 46 | ||||
-rw-r--r-- | dxr3interface.c | 595 | ||||
-rw-r--r-- | dxr3interface.h | 161 | ||||
-rw-r--r-- | dxr3osd.c | 4 | ||||
-rw-r--r-- | dxr3spudecoder.c | 1 | ||||
-rw-r--r-- | spuencoder.c | 8 |
11 files changed, 332 insertions, 845 deletions
@@ -69,8 +69,7 @@ DEFINES += -DMICROCODE=\"/lib/firmware/em8300.bin\" OBJS = $(PLUGIN).o dxr3multichannelaudio.o \ dxr3audiodecoder.o dxr3blackframe.o dxr3audio.o \ dxr3pesframe.o settings.o \ - dxr3interface.o dxr3device.o \ - dxr3osd.o dxr3spudecoder.o \ + dxr3device.o dxr3osd.o dxr3spudecoder.o \ dxr3audio-oss.o dxr3audio-alsa.o spuencoder.o spuregion.o scaler.o ### Default target: @@ -29,7 +29,7 @@ eOSState cDxr3OsdItem::ProcessKey(eKeys Key) switch (m_item) { case DXR3_RESET_HARDWARE: - cDxr3Interface::instance()->ResetHardware(); + //cDxr3Interface::instance()->ResetHardware(); //cDxr3Device::Instance().Reset(); break; @@ -109,7 +109,7 @@ void cMenuSetupDxr3::Store(void) // Apply (some of the) settings - cDxr3Interface::instance()->updateBcsValues(); + //cDxr3Interface::instance()->updateBcsValues(); //cDxr3Device::instance()->Reset(); } @@ -136,9 +136,6 @@ public: cMenuSetupPage *SetupMenu(); bool SetupParse(const char *Name, const char *Value); - -private: - cDxr3Device *device; }; // ================================== @@ -158,7 +155,7 @@ cPluginDxr3::~cPluginDxr3() // ================================== bool cPluginDxr3::Initialize() { - device = new cDxr3Device(); + cDxr3Device::instance(); return true; } @@ -274,17 +271,17 @@ cString cPluginDxr3::SVDRPCommand(const char *Command, const char *Option, if (!strcasecmp(Command, "BRI")) { cSettings::instance()->brightness(value); - cDxr3Interface::instance()->updateBcsValues(); + //cDxr3Interface::instance()->updateBcsValues(); return cString::sprintf("Brightness set to %d", value); } if (!strcasecmp(Command, "CON")) { cSettings::instance()->contrast(value); - cDxr3Interface::instance()->updateBcsValues(); + //cDxr3Interface::instance()->updateBcsValues(); return cString::sprintf("Contrast set to %d", value); } if (!strcasecmp(Command, "SAT")) { cSettings::instance()->saturation(value); - cDxr3Interface::instance()->updateBcsValues(); + //cDxr3Interface::instance()->updateBcsValues(); return cString::sprintf("Saturation set to %d", value); } #if 0 @@ -302,11 +299,11 @@ cString cPluginDxr3::SVDRPCommand(const char *Command, const char *Option, } #endif if (!strcasecmp(Command, "DON")) { - device->turnPlugin(true); + cDxr3Device::instance()->turnPlugin(true); return "vdr-plugin-dxr3 turned on"; } if (!strcasecmp(Command, "DOF")) { - device->turnPlugin(false); + cDxr3Device::instance()->turnPlugin(false); return "vdr-plugin-dxr3 turned off"; } @@ -2,6 +2,7 @@ #define _DXR3_H_ #include <vdr/i18n.h> +#include "settings.h" static const char MAINMENUENTRY[] = trNOOP("DXR3 Functions"); diff --git a/dxr3audio-oss.c b/dxr3audio-oss.c index 4e70df4..d234307 100644 --- a/dxr3audio-oss.c +++ b/dxr3audio-oss.c @@ -20,9 +20,10 @@ #include <sys/soundcard.h> #include <unistd.h> // for close +#include <sys/ioctl.h> #include "dxr3audio-oss.h" -#include "dxr3interface.h" +#include "dxr3device.h" static const char *DEV_DXR3_OSS = "_ma"; @@ -31,7 +32,7 @@ void cAudioOss::openDevice() if (open) return; - fd = cDxr3Interface::Dxr3Open(DEV_DXR3_OSS, O_RDWR | O_NONBLOCK); + fd = cDxr3Device::Dxr3Open(DEV_DXR3_OSS, O_RDWR | O_NONBLOCK); if (!fd) { esyslog("[dxr3-audio-oss] failed to open dxr3 audio subdevice"); @@ -99,7 +100,7 @@ void cAudioOss::setDigitalAudio(bool on) // we need to do it this way, as we dont have access // to the file handle for the conrtol sub device. - cDxr3Interface::instance()->OssSetPlayMode(ioval); + cDxr3Device::instance()->ossSetPlayMode(ioval); digitalAudio = on; } diff --git a/dxr3device.c b/dxr3device.c index 72853d2..8177bec 100644 --- a/dxr3device.c +++ b/dxr3device.c @@ -20,20 +20,26 @@ * */ +#include <sys/ioctl.h> + #include "dxr3device.h" -#include "dxr3interface.h" #include "dxr3tools.h" #include "dxr3osd.h" #include "dxr3audio-oss.h" #include "dxr3audio-alsa.h" #include "dxr3pesframe.h" +#include "settings.h" + +static const char *DEV_DXR3_OSD = "_sp"; +static const char *DEV_DXR3_VIDEO = "_mv"; +static const char *DEV_DXR3_CONT = ""; -// ================================== -//! constructor -cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false) +cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false), playCount(0) { m_spuDecoder = NULL; + claimDevices(); + // TODO: this will be later the place, // where we will decide what kind of // audio output system we will use. @@ -44,18 +50,29 @@ cDxr3Device::cDxr3Device() : pluginOn(true), vPts(0), scrSet(false) aDecoder = new cDxr3AudioDecoder(); } -// ================================== cDxr3Device::~cDxr3Device() { audioOut->releaseDevice(); delete audioOut; delete aDecoder; + releaseDevices(); + if (m_spuDecoder) delete m_spuDecoder; } -// ================================== +int cDxr3Device::Dxr3Open(const char *name, int mode, bool report_error) +{ + const char *filename = *cDxr3Name(name, cSettings::instance()->card()); + int fd = open(filename, mode); + + if (report_error && (fd < 0)) { + LOG_ERROR_STR(filename); + } + return fd; +} + void cDxr3Device::MakePrimaryDevice(bool On) { #if VDRVERSNUM >= 10711 @@ -67,31 +84,30 @@ void cDxr3Device::MakePrimaryDevice(bool On) } } -// replaying -// ================================== -//! do we have an mpeg2 decoder? bool cDxr3Device::HasDecoder() const { - // sure we have one ;) return true; } -// ================================== -//! can we replay vdr recordings? bool cDxr3Device::CanReplay() const { - // also sure... return true; } -// ================================== bool cDxr3Device::SetPlayMode(ePlayMode PlayMode) { dsyslog("[dxr3-device] setting playmode %d", PlayMode); + uint32_t ioval = EM8300_PLAYMODE_PAUSED; + switch (PlayMode) { case pmNone: audioOut->setEnabled(false); + CHECK(ioctl(fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval)); + ioval = 0; + CHECK(ioctl(fdControl, EM8300_IOCTL_SCR_SET, &ioval)); + scrSet = false; + playCount = 0; break; case pmAudioVideo: @@ -106,49 +122,45 @@ bool cDxr3Device::SetPlayMode(ePlayMode PlayMode) return true; } -// ================================== int64_t cDxr3Device::GetSTC() { return (vPts << 1); } -// ================================== void cDxr3Device::TrickSpeed(int Speed) { dsyslog("dxr3: device: tricspeed: %d", Speed); } -// ================================== -//! clear our demux buffer void cDxr3Device::Clear() { dsyslog("[dxr3-device] clear"); + + uint32_t ioval = EM8300_SUBDEVICE_VIDEO; + CHECK(ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval)); + + ioval = EM8300_SUBDEVICE_AUDIO; + CHECK(ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval)); + cDevice::Clear(); } -// ================================== -//! play a recording void cDxr3Device::Play() { dsyslog("[dxr3-device] play"); } -// ================================== -//! puts the device into "freeze frame" mode void cDxr3Device::Freeze() { dsyslog("[dxr3-device] freeze"); } -// ================================== void cDxr3Device::Mute() { audioOut->mute(); cDevice::Mute(); } -// ================================== -//! displays the given I-frame as a still picture. void cDxr3Device::StillPicture(const uchar *Data, int Length) { dsyslog("[dxr3-device] stillpciture"); @@ -168,26 +180,13 @@ void cDxr3Device::StillPicture(const uchar *Data, int Length) } } -// ================================== bool cDxr3Device::Poll(cPoller &Poller, int TimeoutMs) { - /* - if ((m_DemuxDevice.GetDemuxMode() == DXR3_DEMUX_TRICK_MODE && - m_DemuxDevice.GetTrickState() == DXR3_FREEZE)) { - cCondWait::SleepMs(TimeoutMs); - return false; - } - return m_DemuxDevice.Poll(TimeoutMs); // Poller.Poll(TimeoutMs); - */ return true; } -// ================================== -//! actually plays the given data block as video int cDxr3Device::PlayVideo(const uchar *Data, int Length) { - static int i = 0; - cDxr3PesFrame frame; frame.parse(Data, Length); uint32_t pts = frame.GetPts(); @@ -199,24 +198,23 @@ int cDxr3Device::PlayVideo(const uchar *Data, int Length) } if (!scrSet && vPts != 0) { - cDxr3Interface::instance()->SetSysClock(vPts); + CHECK(ioctl(fdControl, EM8300_IOCTL_SCR_SET, &vPts)); scrSet = true; } - cDxr3Interface::instance()->PlayVideoFrame(&frame, vPts); + playVideoFrame(&frame, vPts); - if (i < 7) { - i++; + if (playCount < 7) { + playCount++; } - if (i == 7) { - cDxr3Interface::instance()->SetPlayMode(); - i = 8; + if (playCount == 7) { + //cDxr3Interface::instance()->SetPlayMode(); + setPlayMode(); + playCount = 8; } return Length; } -// ================================== -// plays additional audio streams, like Dolby Digital int cDxr3Device::PlayAudio(const uchar *Data, int Length, uchar Id) { cDxr3PesFrame frame; @@ -230,35 +228,61 @@ int cDxr3Device::PlayAudio(const uchar *Data, int Length, uchar Id) #if VDRVERSNUM >= 10710 void cDxr3Device::GetVideoSize(int &Width, int &Height, double &VideoAspect) { - cDxr3Interface::instance()->dimension((uint32_t&)Width, (uint32_t&)Height); - uint32_t aspect = cDxr3Interface::instance()->GetAspectRatio(); + uint32_t aspect; + CHECK(ioctl(fdControl, EM8300_IOCTL_GET_ASPECTRATIO, &aspect)); if (aspect == EM8300_ASPECTRATIO_4_3) { VideoAspect = 4.0 / 3.0; } else { VideoAspect = 16.0 / 9.0; } + + Width = horizontal; + Height = vertical; } #endif -// additional functions - -// ================================== void cDxr3Device::SetVideoFormat(bool VideoFormat16_9) { - cDxr3Interface::instance()->SetAspectRatio( - VideoFormat16_9 ? EM8300_ASPECTRATIO_16_9 : EM8300_ASPECTRATIO_4_3); + int ratio = EM8300_ASPECTRATIO_4_3; + if (VideoFormat16_9) { + ratio = EM8300_ASPECTRATIO_16_9; + } + + int aspect; + + if (cSettings::instance()->forceLetterBox()) { + ratio = EM8300_ASPECTRATIO_16_9; + } + + if (Setup.VideoFormat) { + aspect = EM8300_ASPECTRATIO_4_3; +#ifdef EM8300_IOCTL_SET_WSS + if (cSettings::Instance().GetUseWSS()) { + int wssmode; + if (ratio == EM8300_ASPECTRATIO_16_9) { + wssmode = EM8300_WSS_16_9; + } else { + wssmode = EM8300_WSS_OFF; + } + + CHECK(ioctl(fdControl, EM8300_IOCTL_SET_WSS, &wssmode); + } +#endif + } else { + aspect = ratio; + } + + CHECK(ioctl(fdControl, EM8300_IOCTL_SET_ASPECTRATIO, &aspect)); + + SetVideoDisplayFormat(eVideoDisplayFormat(Setup.VideoDisplayFormat)); } -// ================================== -//! sets volume for audio output void cDxr3Device::SetVolumeDevice(int Volume) { audioOut->setVolume(Volume); } -// ================================== -//! sets audio channel for audio output (stereo, mono left, mono right) void cDxr3Device::SetAudioChannelDevice(int AudioChannel) { audioOut->setAudioChannel(AudioChannel); @@ -274,8 +298,6 @@ void cDxr3Device::SetDigitalAudioDevice(bool on) audioOut->setDigitalAudio(on); } -// ================================== -// get spudecoder cSpuDecoder *cDxr3Device::GetSpuDecoder() { if (!m_spuDecoder && IsPrimaryDevice()) { @@ -302,7 +324,7 @@ void cDxr3Device::turnPlugin(bool on) } // get full control over device - cDxr3Interface::instance()->ClaimDevices(); + claimDevices(); audioOut->openDevice(); // enable pes packet processing @@ -319,7 +341,7 @@ void cDxr3Device::turnPlugin(bool on) // release device and give control to somebody else Tools::WriteInfoToOsd(tr("DXR3: releasing devices")); - cDxr3Interface::instance()->ReleaseDevices(); + releaseDevices(); audioOut->releaseDevice(); // disable pes packet processing @@ -327,6 +349,192 @@ void cDxr3Device::turnPlugin(bool on) } } +void cDxr3Device::dimension(uint32_t &hor, uint32_t &ver) +{ + hor = horizontal; + ver = vertical; +} + +void cDxr3Device::setPalette(uint8_t *pal) +{ + CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_SETPALETTE, pal)); +} + +void cDxr3Device::writeSpu(const uint8_t* data, int length) +{ + WriteAllOrNothing(fdSpu, data, length, 1000, 10); +} + +void cDxr3Device::setButton(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette) +{ + em8300_button_t button; + + button.color = palette >> 16; + button.contrast = palette & 0xFFFF; + button.top = sy; + button.bottom = ey; + button.left = sx; + button.right = ex; + + CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_BUTTON, &button)); +} + +void cDxr3Device::clearButton() +{ + em8300_button_t button; + + // todo: why are there 1s and 2s - memset 0 + button.color = 0; + button.contrast = 0; + button.top = 1; + button.bottom = 2; + button.left = 1; + button.right = 2; + + CHECK(ioctl(fdSpu, EM8300_IOCTL_SPU_BUTTON, &button)) +} + +int cDxr3Device::ossSetPlayMode(uint32_t mode) +{ + return ioctl(fdControl, EM8300_IOCTL_SET_AUDIOMODE, &mode); +} + +void cDxr3Device::claimDevices() +{ + // open control stream + fdControl = Dxr3Open(DEV_DXR3_CONT, O_WRONLY | O_SYNC); + if (fdControl < 0) { + esyslog("dxr3: please verify that the em8300 modules are loaded"); + exit(1); + } + + uploadFirmware(); + + ///< open multimedia streams + fdVideo = Dxr3Open(DEV_DXR3_VIDEO, O_WRONLY | O_SYNC); + fdSpu = Dxr3Open(DEV_DXR3_OSD, O_WRONLY | O_SYNC); + + // everything ok? + if (fdVideo < 0 || fdSpu < 0) { + esyslog("dxr3: fatal: unable to open some em8300 devices"); + exit(1); + } + + // configure device based on settings + //ConfigureDevice(); + + // get bcs values from driver + CHECK(ioctl(fdControl, EM8300_IOCTL_GETBCS, &bcs)); + + playBlackFrame(); +} + +void cDxr3Device::releaseDevices() +{ + close(fdControl); + close(fdVideo); + close(fdSpu); + + fdControl = fdVideo = fdSpu = -1; +} + +void cDxr3Device::uploadFirmware() +{ + if (!cSettings::instance()->loadFirmware()) { + return; + } + + dsyslog("[dxr3-interface] loading firmware"); + + // try to open it + // MICROCODE comes from makefile + int UCODE = open(MICROCODE, O_RDONLY); + + if (UCODE < 0) { + esyslog("dxr3: fatal: unable to open microcode file %s", MICROCODE); + exit(1); + } + + struct stat s; + if (fstat(UCODE, &s ) <0) { + esyslog("dxr3: fatal: unable to fstat microcode file %s", MICROCODE); + exit(1); + } + + // read microcode + em8300_microcode_t em8300_microcode; + em8300_microcode.ucode = new char[s.st_size]; + if (em8300_microcode.ucode == NULL) { + esyslog("dxr3: fatal: unable to malloc() space for microcode"); + exit(1); + } + + if (read(UCODE,em8300_microcode.ucode,s.st_size) < 1) { + esyslog("dxr3: fatal: unable to read microcode file %s", MICROCODE); + // free memory to avoid memory leak + delete[] (char*) em8300_microcode.ucode; + exit(1); + } + + close(UCODE); + em8300_microcode.ucode_size = s.st_size; + + // upload it + if( ioctl(fdControl, EM8300_IOCTL_INIT, &em8300_microcode) == -1) { + esyslog("dxr3: fatal: microcode upload failed: %m"); + // free memory to avoid memory leak + delete [] (char*) em8300_microcode.ucode; + exit(1); + } + + // free memory to avoid memory leak + delete [] (char*) em8300_microcode.ucode; +} + +void cDxr3Device::setPlayMode() +{ + em8300_register_t reg; + int ioval; + + ioval = EM8300_SUBDEVICE_AUDIO; + ioctl(fdControl, EM8300_IOCTL_FLUSH, &ioval); + fsync(fdVideo); + + ioval = EM8300_PLAYMODE_PLAY; + CHECK(ioctl(fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval)); + reg.microcode_register = 1; + reg.reg = 0; + reg.val = MVCOMMAND_SYNC; + + CHECK(ioctl(fdControl, EM8300_IOCTL_WRITEREG, ®)); +} + +void cDxr3Device::playVideoFrame(cDxr3PesFrame *frame, uint32_t pts) +{ + if (pts > 0) { + pts += 45000; + CHECK(ioctl(fdVideo, EM8300_IOCTL_VIDEO_SETPTS, &pts)); + } + + const uint8_t *data = frame->GetPayload(); + uint32_t len = frame->GetPayloadLength(); + + WriteAllOrNothing(fdVideo, data, len, 1000, 10); +} + +void cDxr3Device::playBlackFrame() +{ + extern char blackframe[]; + extern int blackframeLength; + + for (int i = 0; i < 3; i++) { + WriteAllOrNothing(fdVideo, (const uchar*)blackframe, blackframeLength, 1000, 10); + } + + horizontal = 720; + vertical = 576; +} + // Local variables: // mode: c++ // c-file-style: "stroustrup" diff --git a/dxr3device.h b/dxr3device.h index 34c210b..02cfae0 100644 --- a/dxr3device.h +++ b/dxr3device.h @@ -26,22 +26,33 @@ //#include <string> #include <vdr/device.h> +#include <linux/em8300.h> #include "dxr3audiodecoder.h" -#include "dxr3interface.h" #include "dxr3spudecoder.h" #include "dxr3audio.h" +#include "singleton.h" + +class cDxr3Name { +public: + cDxr3Name(const char *name, int n) { + snprintf(buffer, sizeof(buffer), "%s%s-%d", "/dev/em8300", name, n); + } + const char *operator*() { return buffer; } + +private: + char buffer[PATH_MAX]; +}; -// ================================== -// our device :) /*! cDxr3Device is the interface for VDR devices. Is is the part, which VDR "talks" with our plugin. */ -class cDxr3Device : public cDevice { +class cDxr3Device : public cDevice, public Singleton<cDxr3Device> { public: cDxr3Device(); ~cDxr3Device(); + static int Dxr3Open(const char *name, int mode, bool report_error = true); virtual void MakePrimaryDevice(bool On); // replaying @@ -76,14 +87,41 @@ public: void turnPlugin(bool on); + void dimension(uint32_t &horizontal, uint32_t &vertical); + + void setPalette(uint8_t *pal); + void writeSpu(const uint8_t* data, int length); + void setButton(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t palette); + void clearButton(); + + int ossSetPlayMode(uint32_t mode); + private: + + void claimDevices(); + void releaseDevices(); + void uploadFirmware(); + void setPlayMode(); + void playVideoFrame(cDxr3PesFrame *frame, uint32_t pts); + void playBlackFrame(); + cDxr3AudioDecoder *aDecoder; cDxr3SpuDecoder* m_spuDecoder; iAudio *audioOut; bool pluginOn; + em8300_bcs_t bcs; + + int fdControl; + int fdVideo; + int fdSpu; + uint32_t vPts; bool scrSet; + int playCount; + + uint32_t horizontal; + uint32_t vertical; }; #endif /*_DXR3_DEVICE_H_*/ diff --git a/dxr3interface.c b/dxr3interface.c deleted file mode 100644 index 4ecd40a..0000000 --- a/dxr3interface.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * dxr3interface.c - * - * Copyright (C) 2002-2004 Kai Möller - * Copyright (C) 2004-2009 Christian Gmeiner - * Copyright (C) 2005-2008 Ville Skyttä - * - * This library 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 library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "dxr3interface.h" -#include "dxr3osd.h" -#include "dxr3pesframe.h" - -static const char *DEV_DXR3_OSD = "_sp"; -static const char *DEV_DXR3_VIDEO = "_mv"; -static const char *DEV_DXR3_CONT = ""; - -static const int UNKNOWN_ASPECT_RATIO = 0xdeadbeef; - -// ================================== -//! constructor -cDxr3Interface::cDxr3Interface() : - m_fdControl(-1), m_fdVideo(-1), m_fdSpu(-1) -{ - ClaimDevices(); -} - -// ================================== -//! destructor -cDxr3Interface::~cDxr3Interface() -{ - ReleaseDevices(); -} - -// audio -int cDxr3Interface::OssSetPlayMode(uint32_t mode) -{ - return ioctl(m_fdControl, EM8300_IOCTL_SET_AUDIOMODE, &mode); -} - -// clock -// ================================== -void cDxr3Interface::SetSysClock(uint32_t scr) -{ - Lock(); - CHECK(ioctl(m_fdControl, EM8300_IOCTL_SCR_SET, &scr)); - Unlock(); -} - -// ================================== -uint32_t cDxr3Interface::GetSysClock() -{ - uint32_t retval; - - Lock(); - CHECK(ioctl(m_fdControl, EM8300_IOCTL_SCR_GET, &retval)); - Unlock(); - - return retval; -} - -// ================================== -void cDxr3Interface::SetPts(uint32_t pts) -{ - - Lock(); - CHECK(ioctl(m_fdVideo, EM8300_IOCTL_VIDEO_SETPTS, &pts)); - Unlock(); -} - -// ================================== -void cDxr3Interface::SetSpuPts(uint32_t pts) -{ - uint32_t newPts = 0; - - Lock(); - newPts = pts << 1; // fix for DVD subtitles - CHECK(ioctl(m_fdSpu, EM8300_IOCTL_SPU_SETPTS, &newPts)); - Unlock(); -} - -// set/get functions -// ================================== -//! get aspect ratio -uint32_t cDxr3Interface::GetAspectRatio() const -{ - int ioval = 0; - - Lock(); - - if (ioctl(m_fdControl, EM8300_IOCTL_GET_ASPECTRATIO, &ioval) == -1) - { - esyslog("dxr3: unable to get aspect ratio: %m"); - } - - Unlock(); - - return ioval; -} - -// ================================== -//! set aspect ratio -void cDxr3Interface::SetAspectRatio(uint32_t ratio) -{ - static int requestCounter = 0; - int aspect; - - Lock(); - - if (cSettings::instance()->forceLetterBox()) - ratio = EM8300_ASPECTRATIO_16_9; - - if (ratio != UNKNOWN_ASPECT_RATIO) - { - if (ratio != m_aspectRatio && requestCounter > 50) - { - if (Setup.VideoFormat) - { - aspect = EM8300_ASPECTRATIO_4_3; -#ifdef EM8300_IOCTL_SET_WSS - if (cSettings::Instance().GetUseWSS()) - { - int wssmode; - if (ratio == EM8300_ASPECTRATIO_16_9) - wssmode = EM8300_WSS_16_9; - else - wssmode = EM8300_WSS_OFF; - if (ioctl(m_fdControl, EM8300_IOCTL_SET_WSS, &wssmode) == -1) - { - esyslog("dxr3: unable to set WSS: %m"); - } - } -#endif - } - else - { - aspect = ratio; - } - - requestCounter = 0; - if (ioctl(m_fdControl, EM8300_IOCTL_SET_ASPECTRATIO, &aspect) == -1) - { - esyslog("dxr3: unable to set aspect ratio: %m"); - } - else - { - m_aspectRatio = ratio; - } - } - else - { - if (ratio != m_aspectRatio) - { - ++requestCounter; - } - else - { - requestCounter = 0; - } - } - } - - Unlock(); -} - - -void cDxr3Interface::setDimension(uint32_t horizontal, uint32_t vertical) -{ - if (horizontal > 0) { - m_horizontal = horizontal; - } - - if (vertical > 0) { - m_vertical = vertical; - } -} - -void cDxr3Interface::dimension(uint32_t &horizontal, uint32_t &vertical) -{ - horizontal = m_horizontal; - vertical = m_vertical; -} - -// play functions -// ================================== -//! set playing mode and start sync engine -void cDxr3Interface::SetPlayMode() -{ - // this is the case, when SVDRP command DOF was used and - // should be ignored. - if (m_fdControl == -1) { - return; - } - - em8300_register_t reg; - int ioval; - - Lock(); - - ioval = EM8300_SUBDEVICE_AUDIO; - ioctl(m_fdControl, EM8300_IOCTL_FLUSH, &ioval); - fsync(m_fdVideo); - - ioval = EM8300_PLAYMODE_PLAY; - if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) == -1) - { - esyslog("dxr3: unable to set play mode: %m"); - } - reg.microcode_register = 1; - reg.reg = 0; - reg.val = MVCOMMAND_SYNC; - - if (ioctl(m_fdControl, EM8300_IOCTL_WRITEREG, ®) == -1) - { - esyslog("dxr3: unable to start em8300 sync engine: %m"); - } - - Unlock(); -} - -// ================================== -void cDxr3Interface::Pause() -{ - int ioval = EM8300_PLAYMODE_PAUSED; - - Lock(); - - if (ioctl(m_fdControl, EM8300_IOCTL_SET_PLAYMODE, &ioval) == -1) - { - esyslog("dxr3: unable to set pause mode: %m"); - } - - Unlock(); -} - -// ================================== -void cDxr3Interface::PlayVideoFrame(cDxr3PesFrame *frame, uint32_t pts) -{ - //if (!m_VideoActive) { - // return; - //} - - if (pts > 0) { - pts += 45000; - this->SetPts(pts); - } - - Lock(); - - const uint8_t *data = frame->GetPayload(); - uint32_t len = frame->GetPayloadLength(); - - WriteAllOrNothing(m_fdVideo, data, len, 1000, 10); - - Unlock(); - - //SetAspectRatio(frame->GetAspectRatio()); -} - -// ================================== -void cDxr3Interface::ClaimDevices() -{ - // devices already open - if (m_fdControl > -1 && m_fdVideo > -1 && m_fdSpu > -1) { - return; - } - - // open control stream - m_fdControl = Dxr3Open(DEV_DXR3_CONT, O_WRONLY | O_SYNC); - if (m_fdControl == -1) - { - esyslog("dxr3: please verify that the em8300 modules are loaded"); - exit(1); - } - - // upload microcode to dxr3 - UploadMicroCode(); - - ///< open multimedia streams - m_fdVideo = Dxr3Open(DEV_DXR3_VIDEO, O_WRONLY | O_SYNC); - m_fdSpu = Dxr3Open(DEV_DXR3_OSD, O_WRONLY | O_SYNC); - - // everything ok? - if (m_fdVideo == -1 || m_fdSpu == -1) - { - esyslog("dxr3: fatal: unable to open some em8300 devices"); - exit(1); - } - - // set default values - m_VideoActive = false; - m_horizontal = 720; - m_vertical = 576; - m_aspectRatio = UNKNOWN_ASPECT_RATIO; - - // configure device based on settings - ConfigureDevice(); - - // get bcs values from driver - if (ioctl(m_fdControl, EM8300_IOCTL_GETBCS, &m_bcs) == -1) - { - esyslog("dxr3: failed to get brightness/contrast/saturation: %m"); - } - else - { - dsyslog("dxr3: intf: brightness=%d,contrast=%d,saturation=%d at init", - m_bcs.brightness, m_bcs.contrast, m_bcs.saturation); - } - - PlayBlackFrame(); -} - -// ================================== -void cDxr3Interface::ReleaseDevices() -{ - if (m_fdControl > -1) { - close(m_fdControl); - m_fdControl = -1; - } - - if (m_fdVideo > -1) { - close(m_fdVideo); - m_fdVideo = -1; - } - - if (m_fdSpu > -1) { - close(m_fdSpu); - m_fdSpu = -1; - } - - m_aspectRatio = UNKNOWN_ASPECT_RATIO; -} - -// tools -// ================================== -//! play black frame on tv -void cDxr3Interface::PlayBlackFrame() -{ - extern char blackframe[]; - extern int blackframeLength; - - Lock(); - - for (int i = 0; i < 3; i++) - { - if (write(m_fdVideo, blackframe, blackframeLength) == -1) - Resuscitation(); - } - - m_horizontal = 720; - m_vertical = 576; - - Unlock(); -} - -// ================================== -//! uploadroutine for microcode -void cDxr3Interface::UploadMicroCode() -{ - if (!cSettings::instance()->loadFirmware()) { - return; - } - - dsyslog("[dxr3-interface] loading firmware"); - em8300_microcode_t em8300_microcode; - struct stat s; - - // try to open it - // MICROCODE comes from makefile - int UCODE = open(MICROCODE, O_RDONLY); - - if (UCODE <0) - { - esyslog("dxr3: fatal: unable to open microcode file %s: %m", - MICROCODE); - exit(1); - } - - if (fstat(UCODE, &s ) <0) - { - esyslog("dxr3: fatal: unable to fstat microcode file %s: %m", - MICROCODE); - exit(1); - } - - // read microcode - em8300_microcode.ucode = new char[s.st_size]; - if (em8300_microcode.ucode == NULL) - { - esyslog("dxr3: fatal: unable to malloc() space for microcode"); - exit(1); - } - - if (read(UCODE,em8300_microcode.ucode,s.st_size) < 1) - { - esyslog("dxr3: fatal: unable to read microcode file %s: %m", - MICROCODE); - // free memory to avoid memory leak - delete [] (char*) em8300_microcode.ucode; - exit(1); - } - - close(UCODE); - - em8300_microcode.ucode_size = s.st_size; - - // upload it - if( ioctl(m_fdControl, EM8300_IOCTL_INIT, &em8300_microcode) == -1) - { - esyslog("dxr3: fatal: microcode upload failed: %m"); - // free memory to avoid memory leak - delete [] (char*) em8300_microcode.ucode; - exit(1); - } - - // free memory to avoid memory leak - delete [] (char*) em8300_microcode.ucode; -} - -// ================================== -//! config and setup device via ioctl calls -void cDxr3Interface::ConfigureDevice() -{ - uint32_t videomode = cSettings::instance()->videoMode(); - - switch (videomode) { - case PAL: - dsyslog("dxr3: configure: video mode: PAL"); - break; - - case PAL60: - dsyslog("dxr3: configure: video mode: PAL60"); - break; - - case NTSC: - dsyslog("dxr3: configure: video mode: NTSC"); - break; - } - - if (ioctl(m_fdControl, EM8300_IOCTL_SET_VIDEOMODE, &videomode) == -1) { - esyslog("dxr3: unable to set video mode: %m"); - } - - // set brightness/contrast/saturation - m_bcs.brightness = cSettings::instance()->brightness(); - m_bcs.contrast = cSettings::instance()->contrast(); - m_bcs.saturation = cSettings::instance()->saturation(); - dsyslog("dxr3: configure: brightness=%d,contrast=%d,saturation=%d", - m_bcs.brightness, m_bcs.contrast, m_bcs.saturation); - if (ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs) == -1) { - esyslog("dxr3: unable to set brightness/contrast/saturation: %m"); - } -} - -// ================================== -//! reset whole hardware -void cDxr3Interface::Resuscitation() -{ - time_t startt = time(&startt); - time_t endt = 0; - - dsyslog("dxr3: resuscitation: device failure or user initiated reset"); - - ReleaseDevices(); - Unlock(); - ClaimDevices(); - Lock(); - - endt = time(&endt); - if (endt - startt > 4) - { - esyslog("dxr3: fatal: reopening devices took too long"); - exit(1); - } - dsyslog("dxr3: resuscitation: reopening devices took %ld seconds", - endt - startt); -} - -// ================================== -void cDxr3Interface::WriteSpu(const uint8_t* pBuf, int length) -{ - Lock(); - - if (write(m_fdSpu, pBuf, length) == -1) - Resuscitation(); - - Unlock(); -} - -// ================================== -void cDxr3Interface::SetButton(uint16_t sx, uint16_t sy, uint16_t ex, - uint16_t ey, uint32_t palette) -{ - em8300_button_t button; - - button.color = palette >> 16; - button.contrast = palette & 0xFFFF; - button.top = sy; - button.bottom = ey; - button.left = sx; - button.right = ex; - - CHECK(ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button)); -} - -// ================================== -void cDxr3Interface::ClearButton() -{ - em8300_button_t button; - - button.color = 0; - button.contrast = 0; - button.top = 1; - button.bottom = 2; - button.left = 1; - button.right = 2; - - CHECK(ioctl(m_fdSpu, EM8300_IOCTL_SPU_BUTTON, &button)); -} - -// ================================== -void cDxr3Interface::SetPalette(unsigned int *pal) -{ - CHECK(ioctl(m_fdSpu, EM8300_IOCTL_SPU_SETPALETTE, (uint8_t*)pal)); -} - -// helper functions for dxr3 main osd screen -// ================================== -//! reset dxr3 card -void cDxr3Interface::ResetHardware() -{ - Lock(); - - isyslog("dxr3: hardware reset requested"); - Resuscitation(); - - Unlock(); -} - -void cDxr3Interface::updateBcsValues() -{ - // update m_bcs with values from settings - m_bcs.brightness = cSettings::instance()->brightness(); - m_bcs.contrast = cSettings::instance()->contrast(); - m_bcs.saturation = cSettings::instance()->saturation(); - - // update bcs values in hardware - CHECK(ioctl(m_fdControl, EM8300_IOCTL_SETBCS, &m_bcs)); -} - -// ================================== -//! get brightness -int cDxr3Interface::GetBrightness() -{ - return m_bcs.brightness; -} - -// ================================== -//! get contrast -int cDxr3Interface::GetContrast() -{ - return m_bcs.contrast; -} - -// ================================== -//! get saturation -int cDxr3Interface::GetSaturation() -{ - return m_bcs.saturation; -} - -// ================================== -cMutex* cDxr3Interface::m_pMutex = new cMutex; - -// Local variables: -// mode: c++ -// c-file-style: "stroustrup" -// c-file-offsets: ((inline-open . 0)) -// tab-width: 4; -// indent-tabs-mode: nil -// End: diff --git a/dxr3interface.h b/dxr3interface.h deleted file mode 100644 index 3b3191b..0000000 --- a/dxr3interface.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * dxr3interface.h - * - * Copyright (C) 2002-2004 Kai Möller - * Copyright (C) 2004-2009 Christian Gmeiner - * - * This library 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 library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef _DXR3_INTERFACE_H_ -#define _DXR3_INTERFACE_H_ - -#include <linux/em8300.h> -#include <sys/ioctl.h> -#include <linux/limits.h> - -#include <vdr/tools.h> -#include "settings.h" - -// ================================== -class cDxr3PesFrame; - -class cDxr3Name { -public: - cDxr3Name(const char *name, int n) { - snprintf(buffer, sizeof(buffer), "%s%s-%d", "/dev/em8300", name, n); - } - const char *operator*() { return buffer; } - -private: - char buffer[PATH_MAX]; -}; - -// ================================== -//! interafce to dxr3-card -/*! - cDxr3Interface is the interface to the dxr3 - driver and so to the card, - so this is the layer between plugin and driver. -*/ -class cDxr3Interface : public Singleton<cDxr3Interface> { -public: - cDxr3Interface(); - ~cDxr3Interface(); - - static int Dxr3Open(const char *name, int mode, bool report_error = true) { - const char *filename = *cDxr3Name(name, cSettings::instance()->card()); - int fd = open(filename, mode); - - if (report_error && (fd < 0)) { - LOG_ERROR_STR(filename); - } - return fd; - } - - // audio - int OssSetPlayMode(uint32_t mode); - - // clock - void SetSysClock(uint32_t scr); - uint32_t GetSysClock(); - void SetPts(uint32_t pts); - void SetSpuPts(uint32_t pts); - - // state changes - void EnableVideo() - { - m_VideoActive = true; - } - void DisableVideo() - { - m_VideoActive = false; - } - - // set/get functions - uint32_t GetAspectRatio() const; - void SetAspectRatio(uint32_t ratio); - - void setDimension(uint32_t horizontal, uint32_t vertical); - void dimension(uint32_t &horizontal, uint32_t &vertical); - - // play functions - void SetPlayMode(); - void Pause(); - void PlayVideoFrame(cDxr3PesFrame *frame, uint32_t pts); - - // device access - void ClaimDevices(); - void ReleaseDevices(); - - // tools - void PlayBlackFrame(); - - // osd/spu - void WriteSpu(const uint8_t* pBuf, int length); - void SetButton(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, - uint32_t palette); - void ClearButton(); - void SetPalette(unsigned int *pal); - - // helper functions for dxr3 main osd screen - void ResetHardware(); - - void updateBcsValues(); - // get brightness/contrast/saturation - int GetBrightness(); - int GetContrast(); - int GetSaturation(); - -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_fdSpu; ///< filehandle for spu fifo of dxr3 card - - 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 - bool m_VideoActive; ///< is video active? - - // bcs - em8300_bcs_t m_bcs; ///< BrightnessContrastSaturation values - - void UploadMicroCode(); - void ConfigureDevice(); - void Resuscitation(); - - static cMutex* m_pMutex; ///< mutex for dxr3interface - - static void Lock() - { - cDxr3Interface::m_pMutex->Lock(); - } - static void Unlock() - { - cDxr3Interface::m_pMutex->Unlock(); - } -}; - -#endif /*_DXR3_INTERFACE_H_*/ - -// Local variables: -// mode: c++ -// c-file-style: "stroustrup" -// c-file-offsets: ((inline-open . 0)) -// tab-width: 4; -// indent-tabs-mode: nil -// End: @@ -26,9 +26,9 @@ */ #include "dxr3osd.h" -#include "dxr3interface.h" #include "spuencoder.h" #include "scaler.h" +#include "dxr3device.h" // ================================== // ! create osd at (Left, Top, Level) @@ -201,7 +201,7 @@ void cDxr3Osd::Flush() bmap->Clean(); uint32_t horizontal, vertical; - cDxr3Interface::instance()->dimension(horizontal, vertical); + cDxr3Device::instance()->dimension(horizontal, vertical); int top = Top(); int left = Left(); diff --git a/dxr3spudecoder.c b/dxr3spudecoder.c index f01e718..32b5c55 100644 --- a/dxr3spudecoder.c +++ b/dxr3spudecoder.c @@ -26,7 +26,6 @@ #include <math.h> #include "dxr3spudecoder.h" -#include "dxr3interface.h" #include "dxr3tools.h" // ================================== diff --git a/spuencoder.c b/spuencoder.c index ed44b05..ec2d965 100644 --- a/spuencoder.c +++ b/spuencoder.c @@ -25,8 +25,8 @@ */ #include "spuencoder.h" -#include "dxr3interface.h" #include "dxr3tools.h" +#include "dxr3device.h" static const uint8_t CMD_FORCE_DISPLAYING = 0x00; static const uint8_t CMD_STOP_DISPLAYING = 0x02; @@ -64,7 +64,7 @@ void cSpuEncoder::clearOsd() // TODO: osd button handling - cDxr3Interface::instance()->WriteSpu((uchar *)&d, 10); + cDxr3Device::instance()->writeSpu((uchar *)&d, 10); } void cSpuEncoder::encode(cBitmap *bmap, int top, int left) @@ -133,7 +133,7 @@ void cSpuEncoder::encode(cBitmap *bmap, int top, int left) // we are ready to send generated spu data dsyslog("[dxr3-spuencoder] spu packet size %d (bytes). %d left", written, (MAX_SPU_DATA - written)); - cDxr3Interface::instance()->WriteSpu((uchar *)&spu, written); + cDxr3Device::instance()->writeSpu((uchar *)&spu, written); if (data) { delete data; @@ -251,7 +251,7 @@ void cSpuEncoder::generateColorPalette() } // upload color palette - cDxr3Interface::instance()->SetPalette(palcolors); + cDxr3Device::instance()->setPalette((uint8_t *)palcolors); } void cSpuEncoder::generateSpuData(bool topAndBottom) throw (char const* ) |