From 0c051f71c3622e3e22ab8c2e59f154675c619f99 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 21 Jul 2011 10:19:14 +0000 Subject: [PATCH] Dynamic channel manager git-svn-id: file:///home/bas/coolstream_public_svn/THIRDPARTY/applications/neutrino-beta@1566 e54a6e83-5905-42d5-8d5c-058d10e6a962 Origin commit data ------------------ Commit: https://github.com/neutrino-images/ni-neutrino/commit/fa20172141c264abeb8d9d0d1686aa2a505949e1 Author: [CST] Focus Date: 2011-07-21 (Thu, 21 Jul 2011) --- src/zapit/include/zapit/cam.h | 35 +++++++++- src/zapit/src/cam.cpp | 122 ++++++++++++++++++++++++++++++++-- 2 files changed, 149 insertions(+), 8 deletions(-) diff --git a/src/zapit/include/zapit/cam.h b/src/zapit/include/zapit/cam.h index ba8d42ef0..3d8c8b735 100644 --- a/src/zapit/include/zapit/cam.h +++ b/src/zapit/include/zapit/cam.h @@ -25,6 +25,8 @@ #include "ci.h" #include +#include "types.h" +#include #define DEMUX_DECODE_0 1 #define DEMUX_DECODE_1 2 @@ -34,19 +36,48 @@ #define DEMUX_SOURCE_1 1 #define DEMUX_SOURCE_2 2 +#define LIVE_DEMUX 0 +#define STREAM_DEMUX 1 +#define RECORD_DEMUX 2 + class CCam : public CBasicClient { private: virtual unsigned char getVersion(void) const; virtual const char *getSocketName(void) const; - int camask, demux; + int camask, demuxes[3]; public: CCam(); bool sendMessage(const char * const data, const size_t length, bool update = false); bool setCaPmt(CCaPmt * const caPmt, int _demux = 0, int _camask = 1, bool update = false); int getCaMask(void) { return camask; }; - int getDemux(void) { return demux; }; + int makeMask(int demux, bool add); }; +typedef std::map cammap_t; +typedef cammap_t::iterator cammap_iterator_t; + +class CCamManager +{ + public: + enum runmode { + PLAY, + RECORD, + STREAM + }; + private: + cammap_t channel_map; + OpenThreads::Mutex mutex; + static CCamManager * manager; + bool SetMode(t_channel_id id, enum runmode mode, bool enable, bool force_update = false); + + public: + CCamManager(); + ~CCamManager(); + static CCamManager * getInstance(void); + bool Start(t_channel_id id, enum runmode mode, bool force_update = false) { return SetMode(id, mode, true, force_update); }; + bool Stop(t_channel_id id, enum runmode mode) { return SetMode(id, mode, false); }; + +}; #endif /* __cam_h__ */ diff --git a/src/zapit/src/cam.cpp b/src/zapit/src/cam.cpp index eda3fa4cf..463e5a666 100644 --- a/src/zapit/src/cam.cpp +++ b/src/zapit/src/cam.cpp @@ -25,11 +25,15 @@ #include #include /* CAMD_UDS_NAME */ #include /* get_length_field_size */ +#include +#include + +extern tallchans allchans; CCam::CCam() { - camask = 1; - demux = 0; + camask = 0; + demuxes[0] = demuxes[1] = demuxes[2] = 0; } unsigned char CCam::getVersion(void) const @@ -58,7 +62,6 @@ bool CCam::sendMessage(const char * const data, const size_t length, bool update if(!data || !length) { camask = 1; - demux = 0; return false; } if (!open_connection()) @@ -70,15 +73,122 @@ bool CCam::sendMessage(const char * const data, const size_t length, bool update bool CCam::setCaPmt(CCaPmt * const caPmt, int _demux, int _camask, bool update) { camask = _camask; - demux = _demux; + printf("CCam::setCaPmt cam %x source %d camask %d update %s\n", (int) this, _demux, camask, update ? "yes" : "no" ); + if(camask == 0) { + close_connection(); + return true; + } if (!caPmt) return true; - printf("CCam::setCaPmt cam %x source %d camask %d update %s\n", (int) this, demux, camask, update ? "yes" : "no" ); unsigned int size = caPmt->getLength(); unsigned char buffer[3 + get_length_field_size(size) + size]; - size_t pos = caPmt->writeToBuffer(buffer, demux, camask); + size_t pos = caPmt->writeToBuffer(buffer, _demux, camask); return sendMessage((char *)buffer, pos, update); } + +int CCam::makeMask(int demux, bool add) +{ + int mask = 0; + + if(add) + demuxes[demux]++; + else if(demuxes[demux] > 0) + demuxes[demux]--; + + for(int i = 0; i < 3; i++) { + if(demuxes[i] > 0) + mask |= 1 << i; + } + printf("CCam::MakeMask: demuxes %d:%d:%d old mask %d new mask %d\n", demuxes[0], demuxes[1], demuxes[2], camask, mask); + return mask; +} + +CCamManager * CCamManager::manager = NULL; + +CCamManager::CCamManager() +{ + channel_map.clear(); +} + +CCamManager::~CCamManager() +{ + for(cammap_iterator_t it = channel_map.begin(); it != channel_map.end(); it++) + delete it->second; + channel_map.clear(); +} + +CCamManager * CCamManager::getInstance(void) +{ + if(manager == NULL) + manager = new CCamManager(); + + return manager; +} + +bool CCamManager::SetMode(t_channel_id id, enum runmode mode, bool start, bool force_update) +{ + CCam * cam; + int oldmask, newmask; + int demux = DEMUX_SOURCE_0; + int source = DEMUX_SOURCE_0; + + tallchans_iterator cit = allchans.find(id); + if(cit == allchans.end()) { + printf("CCamManager: channel %llx not found\n", id); + return false; + } + + CZapitChannel * channel = &(cit->second); + + mutex.lock(); + if(channel->getCaPmt() == NULL) { + printf("CCamManager: channel %llx dont have caPmt\n", id); + mutex.unlock(); + return false; + } + + sat_iterator_t sit = satellitePositions.find(channel->getSatellitePosition()); + + cammap_iterator_t it = channel_map.find(id); + if(it == channel_map.end()) { + cam = new CCam(); + channel_map.insert(std::pair(id, cam)); + } else + cam = it->second; + + switch(mode) { + case PLAY: + source = DEMUX_SOURCE_0; + demux = LIVE_DEMUX; + break; + case RECORD: + source = DEMUX_SOURCE_0; + demux = RECORD_DEMUX;//FIXME + break; + case STREAM: + source = DEMUX_SOURCE_0; + demux = STREAM_DEMUX;//FIXME + break; + } + + oldmask = cam->getCaMask(); + newmask = cam->makeMask(demux, start); + + if((oldmask != newmask) || force_update) + cam->setCaPmt(channel->getCaPmt(), source, newmask, true); + + if(newmask == 0) { + /* FIXME: back to live channel from playback dont parse pmt and call setCaPmt + * (see CMD_SB_LOCK / UNLOCK PLAYBACK */ + //channel->setCaPmt(NULL); + channel->setRawPmt(NULL); + channel_map.erase(id); + delete cam; + } + mutex.unlock(); + + return true; +}