diff options
author | Christian Gmeiner <christian.gmeiner@gmail.com> | 2010-02-03 11:34:01 +0100 |
---|---|---|
committer | Christian Gmeiner <christian.gmeiner@gmail.com> | 2010-02-03 11:34:01 +0100 |
commit | 1c564f1da32e294606bb815b23109e5a08d2e87b (patch) | |
tree | 69748b49cb3d4734beac87ab9b533695ffc48ce8 /dxr3device.c | |
parent | f69bf5ba73f56008514e4899cc9fef630ea9e044 (diff) | |
download | vdr-plugin-dxr3-1c564f1da32e294606bb815b23109e5a08d2e87b.tar.gz vdr-plugin-dxr3-1c564f1da32e294606bb815b23109e5a08d2e87b.tar.bz2 |
merge dxr3interface into dxr3device
Diffstat (limited to 'dxr3device.c')
-rw-r--r-- | dxr3device.c | 332 |
1 files changed, 270 insertions, 62 deletions
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" |