CCam: new code on using libdvbsi++

This commit is contained in:
[CST] Focus
2012-01-25 17:52:11 +04:00
parent 16f8d7d406
commit b122e5ff21
2 changed files with 330 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
/*
* $Id: cam.h,v 1.25 2003/02/09 19:22:08 thegoodguy Exp $
*
* (C) 2002-2003 Andreas Oberritter <obi@tuxbox.org>,
* thegoodguy <thegoodguy@berlios.de>
*
* 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 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#ifndef __capmt_h__
#define __capmt_h__
#include <basicclient.h>
#include "types.h"
#include <OpenThreads/Mutex>
#include <zapit/channel.h>
#define DEMUX_DECODE_0 1
#define DEMUX_DECODE_1 2
#define DEMUX_DECODE_2 4
#define DEMUX_SOURCE_0 0
#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, demuxes[3];
int source_demux;
public:
CCam();
bool sendMessage(const char * const data, const size_t length, bool update = false);
bool setCaPmt(CZapitChannel * channel, int _demux = 0, int _camask = 1, bool update = false);
int getCaMask(void) { return camask; };
int makeMask(int demux, bool add);
int getSource() { return source_demux; };
};
typedef std::map<t_channel_id, CCam*> 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 /* __capmt_h__ */

245
src/zapit/src/capmt.cpp Normal file
View File

@@ -0,0 +1,245 @@
/*
* $Id: cam.cpp,v 1.33 2004/04/04 20:20:45 obi Exp $
*
* (C) 2002 by Andreas Oberritter <obi@tuxbox.org>,
* thegoodguy <thegoodguy@berlios.de>
*
* 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 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
/* zapit */
#include <zapit/capmt.h>
#include <zapit/settings.h> /* CAMD_UDS_NAME */
#include <zapit/getservices.h>
#include <dvbsi++/program_map_section.h>
#include <dvbsi++/ca_program_map_section.h>
#define DEBUG_CAPMT
CCam::CCam()
{
camask = 0;
demuxes[0] = demuxes[1] = demuxes[2] = 0;
source_demux = -1;
}
unsigned char CCam::getVersion(void) const
{
return 0x9F;
}
const char *CCam::getSocketName(void) const
{
return CAMD_UDS_NAME;
}
bool CCam::sendMessage(const char * const data, const size_t length, bool update)
{
/* send_data return false without trying, if no opened connection */
if(update) {
if(!send_data(data, length)) {
if (!open_connection())
return false;
return send_data(data, length);
}
return true;
}
close_connection();
if(!data || !length) {
camask = 1;
return false;
}
if (!open_connection())
return false;
return send_data(data, length);
}
bool CCam::setCaPmt(CZapitChannel * channel, int _demux, int _camask, bool update)
{
int len;
unsigned char * buffer = channel->getRawPmt(len);
camask = _camask;
source_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(!buffer)
return false;
ProgramMapSection pmt(buffer);
CaProgramMapSection capmt(&pmt, 0x03, 0x01);
uint8_t tmp[10];
tmp[0] = 0x84;
tmp[1] = 0x02;
tmp[2] = channel->getPmtPid() >> 8;
tmp[3] = channel->getPmtPid() & 0xFF;
capmt.injectDescriptor(tmp, false);
tmp[0] = 0x82;
tmp[1] = 0x02;
tmp[2] = camask;
tmp[3] = source_demux;
capmt.injectDescriptor(tmp, false);
memset(tmp, 0, sizeof(tmp));
tmp[0] = 0x81;
tmp[1] = 0x08;
tmp[2] = channel->getSatellitePosition() >> 8;
tmp[3] = channel->getSatellitePosition() & 0xFF;
tmp[4] = channel->getFreqId() >> 8;
tmp[5] = channel->getFreqId() & 0xFF;
tmp[6] = channel->getTransportStreamId() >> 8;
tmp[7] = channel->getTransportStreamId() & 0xFF;
tmp[8] = channel->getOriginalNetworkId() >> 8;
tmp[9] = channel->getOriginalNetworkId() & 0xFF;
capmt.injectDescriptor(tmp, false);
unsigned char cabuf[2048];
int calen = capmt.writeToBuffer(cabuf);
#ifdef DEBUG_CAPMT
printf("CAPMT: ");
for(int i = 0; i < calen; i++)
printf("%02X ", cabuf[i]);
printf("\n");
#endif
return sendMessage((char *)cabuf, calen, 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 channel_id, enum runmode mode, bool start, bool force_update)
{
CCam * cam;
int oldmask, newmask;
int demux = DEMUX_SOURCE_0;
int source = DEMUX_SOURCE_0;
CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id);
if(channel == NULL) {
printf("CCamManager: channel %llx not found\n", channel_id);
return false;
}
printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update);
mutex.lock();
#if 0
if(channel->getCaPmt() == NULL) {
printf("CCamManager: channel %llx dont have caPmt\n", channel_id);
mutex.unlock();
return false;
}
#endif
cammap_iterator_t it = channel_map.find(channel_id);
if(it != channel_map.end()) {
cam = it->second;
} else if(start) {
cam = new CCam();
channel_map.insert(std::pair<t_channel_id, CCam*>(channel_id, cam));
} else {
mutex.unlock();
return false;
}
switch(mode) {
case PLAY:
source = DEMUX_SOURCE_0;
demux = LIVE_DEMUX;
break;
case RECORD:
source = channel->getRecordDemux(); //DEMUX_SOURCE_0;//FIXME
demux = channel->getRecordDemux(); //RECORD_DEMUX;//FIXME
break;
case STREAM:
source = DEMUX_SOURCE_0;
demux = STREAM_DEMUX;//FIXME
break;
}
oldmask = cam->getCaMask();
if(force_update)
newmask = oldmask;
else
newmask = cam->makeMask(demux, start);
if(cam->getSource() > 0)
source = cam->getSource();
printf("CCam::SetMode: source %d old mask %d new mask %d force update %s\n", source, oldmask, newmask, force_update ? "yes" : "no");
if((oldmask != newmask) || force_update) {
cam->setCaPmt(channel, 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);//FIXME
channel_map.erase(channel_id);
delete cam;
}
mutex.unlock();
return true;
}