Ticket #2152: patch-freebox-unified-udp-v6.diff
File patch-freebox-unified-udp-v6.diff, 64.1 KB (added by , 19 years ago) |
---|
-
libs/libmythtv/freeboxsignalmonitor.cpp
2 2 3 3 // MythTV headers 4 4 #include "mpegstreamdata.h" 5 #include "freeboxchannel.h" 6 #include "freeboxfeederwrapper.h" 5 7 #include "freeboxsignalmonitor.h" 6 #include "rtspcomms.h"7 8 8 9 #undef DBG_SM 9 10 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ … … 34 35 dtvMonitorRunning(false) 35 36 { 36 37 bool isLocked = false; 37 if (GetChannel()->GetRTSP()->Init()) 38 FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo(); 39 if (chaninfo.isValid()) 38 40 { 39 FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo(); 40 isLocked = (chaninfo.isValid() && 41 GetChannel()->GetRTSP()->Open(chaninfo.m_url)); 41 isLocked = GetChannel()->GetFeeder()->Open(chaninfo.m_url); 42 42 } 43 43 44 44 QMutexLocker locker(&statusLock); … … 51 51 */ 52 52 FreeboxSignalMonitor::~FreeboxSignalMonitor() 53 53 { 54 GetChannel()->Get RTSP()->RemoveListener(this);54 GetChannel()->GetFeeder()->RemoveListener(this); 55 55 Stop(); 56 56 } 57 57 … … 63 63 void FreeboxSignalMonitor::deleteLater(void) 64 64 { 65 65 disconnect(); // disconnect signals we may be sending... 66 GetChannel()->Get RTSP()->RemoveListener(this);66 GetChannel()->GetFeeder()->RemoveListener(this); 67 67 Stop(); 68 68 DTVSignalMonitor::deleteLater(); 69 69 } … … 74 74 void FreeboxSignalMonitor::Stop(void) 75 75 { 76 76 DBG_SM("Stop", "begin"); 77 GetChannel()->Get RTSP()->RemoveListener(this);77 GetChannel()->GetFeeder()->RemoveListener(this); 78 78 SignalMonitor::Stop(); 79 79 if (dtvMonitorRunning) 80 80 { 81 GetChannel()->Get RTSP()->Stop();81 GetChannel()->GetFeeder()->Stop(); 82 82 dtvMonitorRunning = false; 83 83 pthread_join(table_monitor_thread, NULL); 84 84 } … … 101 101 102 102 GetStreamData()->AddListeningPID(0); 103 103 104 GetChannel()->Get RTSP()->AddListener(this);105 GetChannel()->Get RTSP()->Run();106 GetChannel()->Get RTSP()->RemoveListener(this);104 GetChannel()->GetFeeder()->AddListener(this); 105 GetChannel()->GetFeeder()->Run(); 106 GetChannel()->GetFeeder()->RemoveListener(this); 107 107 108 108 dtvMonitorRunning = false; 109 109 DBG_SM("Run", "end"); 110 110 } 111 111 112 112 void FreeboxSignalMonitor::AddData( 113 unsigned char *data, unsigned dataSize , struct timeval)113 unsigned char *data, unsigned dataSize) 114 114 { 115 115 GetStreamData()->ProcessData(data, dataSize); 116 116 } -
libs/libmythtv/freeboxfeederudp.cpp
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederUdp 3 * Copyright (c) 2006 by Mike Mironov & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #include "freeboxfeederudp.h" 8 9 // Qt headers 10 #include <qurl.h> 11 12 // Live555 headers 13 #include <BasicUsageEnvironment.hh> 14 #include <Groupsock.hh> 15 #include <GroupsockHelper.hh> 16 #include <BasicUDPSource.hh> 17 #include <TunnelEncaps.hh> 18 19 // MythTV headers 20 #include "freeboxmediasink.h" 21 #include "mythcontext.h" 22 #include "tspacket.h" 23 24 #define LOC QString("FbFeedUdp(%1):").arg(pthread_self()) 25 26 27 FreeboxFeederUdp::FreeboxFeederUdp(StreamDataListener &listener) : 28 FreeboxFeederLive(listener), 29 _source(NULL), 30 _sink(NULL) 31 { 32 VERBOSE(VB_RECORD, LOC + "ctor -- success"); 33 } 34 35 FreeboxFeederUdp::~FreeboxFeederUdp() 36 { 37 VERBOSE(VB_RECORD, LOC + "dtor -- begin"); 38 Close(); 39 VERBOSE(VB_RECORD, LOC + "dtor -- end"); 40 } 41 42 bool FreeboxFeederUdp::CanHandle(const QString &url) const 43 { 44 return url.startsWith("udp://", false); 45 } 46 47 bool FreeboxFeederUdp::Open(const QString &url) 48 { 49 VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin"); 50 51 QMutexLocker locker(&GetLock()); 52 53 if (_source) 54 { 55 VERBOSE(VB_RECORD, LOC + "Open() -- end 1"); 56 return true; 57 } 58 59 QUrl parse(url); 60 if (!parse.isValid() || !parse.hasHost() || !parse.hasPort()) 61 { 62 VERBOSE(VB_RECORD, LOC + "Open() -- end 2"); 63 return false; 64 } 65 66 struct in_addr addr; 67 addr.s_addr = our_inet_addr(parse.host().latin1()); 68 69 // Begin by setting up our usage environment: 70 if (!InitEnv()) 71 return false; 72 73 Groupsock *socket = new Groupsock(GetLiveEnv(), addr, parse.port(), 0); 74 if (!socket) 75 { 76 VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Socket."); 77 FreeEnv(); 78 return false; 79 } 80 _source = BasicUDPSource::createNew(GetLiveEnv(), socket); 81 if (!_source) 82 { 83 VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source."); 84 delete socket; 85 FreeEnv(); 86 return false; 87 } 88 89 _sink = FreeboxMediaSink::CreateNew( 90 GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024); 91 if (!_sink) 92 { 93 VERBOSE(VB_IMPORTANT, 94 QString("Freebox # Failed to create sink: %1") 95 .arg(GetLiveEnv().getResultMsg())); 96 Medium::close(_source); 97 _source = NULL; 98 delete socket; 99 FreeEnv(); 100 return false; 101 } 102 _sink->startPlaying(*_source, NULL, NULL); 103 104 VERBOSE(VB_RECORD, LOC + "Open() -- end"); 105 return true; 106 } 107 108 void FreeboxFeederUdp::Close(void) 109 { 110 VERBOSE(VB_RECORD, LOC + "Close() -- begin"); 111 Stop(); 112 113 QMutexLocker locker(&GetLock()); 114 115 if (_sink) 116 { 117 Medium::close(_sink); 118 _sink = NULL; 119 } 120 121 if (_source) 122 { 123 Groupsock *socket=_source->gs(); 124 Medium::close(_source); 125 _source=NULL; 126 delete socket; 127 } 128 129 FreeEnv(); 130 131 VERBOSE(VB_RECORD, LOC + "Close() -- end"); 132 } -
libs/libmythtv/streamdatalistener.h
1 /** -*- Mode: c++ -*- 2 * StreamDataListener 3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _STREAMDATALISTENER_H_ 8 #define _STREAMDATALISTENER_H_ 9 10 11 class StreamDataListener 12 { 13 public: 14 /// Callback function to add MPEG2 TS data 15 virtual void AddData(unsigned char *data, 16 unsigned int dataSize) = 0; 17 protected: 18 virtual ~StreamDataListener() {} 19 }; 20 21 #endif//_STREAMDATALISTENER_H_ -
libs/libmythtv/freeboxchannel.h
12 12 13 13 #include <qmutex.h> 14 14 15 class RTSPComms;15 class FreeboxFeederWrapper; 16 16 17 17 class FreeboxChannel : public ChannelBase 18 18 { … … 32 32 FreeboxChannelInfo GetCurrentChanInfo(void) const 33 33 { return GetChanInfo(curchannelname); } 34 34 35 RTSPComms *GetRTSP(void) { return m_rtsp; }36 const RTSPComms *GetRTSP(void) const { return m_rtsp; }35 FreeboxFeederWrapper *GetFeeder(void) { return m_feeder; } 36 const FreeboxFeederWrapper *GetFeeder(void) const { return m_feeder; } 37 37 38 38 private: 39 39 FreeboxChannelInfo GetChanInfo(const QString& channum, … … 41 41 42 42 QString m_videodev; 43 43 fbox_chan_map_t m_freeboxchannels; 44 RTSPComms *m_rtsp;44 FreeboxFeederWrapper *m_feeder; 45 45 mutable QMutex m_lock; 46 46 47 47 private: -
libs/libmythtv/freeboxchannelfetcher.h
7 7 // Qt headers 8 8 #include <qobject.h> 9 9 #include <qmutex.h> 10 #include <qurloperator.h> 10 11 11 12 // MythTV headers 12 13 #include "freeboxchannelinfo.h" 13 14 15 class FreeboxUrlFetch : public QObject 16 { 17 Q_OBJECT 18 19 private: 20 FreeboxUrlFetch(const QString& url); 21 ~FreeboxUrlFetch(); 22 23 QUrlOperator *op; 24 QNetworkProtocol::State state; 25 QString str; 26 27 private slots: 28 void finished(QNetworkOperation *op); 29 void data(const QByteArray &data,QNetworkOperation *op); 30 31 public: 32 static QString fetchData(const QString &url,bool inQtThread); 33 }; 34 14 35 class FreeboxChannelFetcher : public QObject 15 36 { 16 37 Q_OBJECT -
libs/libmythtv/libmythtv.pro
396 396 using_freebox { 397 397 HEADERS += freeboxrecorder.h freeboxmediasink.h 398 398 HEADERS += freeboxchannel.h freeboxchannelfetcher.h 399 HEADERS += freeboxsignalmonitor.h rtspcomms.h399 HEADERS += freeboxsignalmonitor.h 400 400 HEADERS += freeboxchannelinfo.h 401 HEADERS += freeboxfeeder.h 402 HEADERS += freeboxfeederlive.h 403 HEADERS += freeboxfeederrtsp.h 404 HEADERS += freeboxfeederudp.h 405 HEADERS += freeboxfeederwrapper.h 406 HEADERS += streamdatalistener.h 407 HEADERS += timeoutedtaskscheduler.h 401 408 402 409 SOURCES += freeboxrecorder.cpp freeboxmediasink.cpp 403 410 SOURCES += freeboxchannel.cpp freeboxchannelfetcher.cpp 404 SOURCES += freeboxsignalmonitor.cpp rtspcomms.cpp 411 SOURCES += freeboxsignalmonitor.cpp 412 SOURCES += freeboxfeederlive.cpp 413 SOURCES += freeboxfeederrtsp.cpp 414 SOURCES += freeboxfeederudp.cpp 415 SOURCES += freeboxfeederwrapper.cpp 416 SOURCES += timeoutedtaskscheduler.cpp 405 417 406 418 DEFINES += USING_FREEBOX 407 419 } -
libs/libmythtv/freeboxchannel.cpp
11 11 #include "libmyth/mythcontext.h" 12 12 #include "libmyth/mythdbcon.h" 13 13 #include "libmythtv/freeboxchannelfetcher.h" 14 #include "libmythtv/ rtspcomms.h"14 #include "libmythtv/freeboxfeederwrapper.h" 15 15 16 16 #define LOC QString("FBChan(%1): ").arg(GetCardID()) 17 17 #define LOC_ERR QString("FBChan(%1), Error: ").arg(GetCardID()) … … 20 20 const QString &videodev) 21 21 : ChannelBase(parent), 22 22 m_videodev(QDeepCopy<QString>(videodev)), 23 m_ rtsp(new RTSPComms()),23 m_feeder(new FreeboxFeederWrapper()), 24 24 m_lock(true) 25 25 { 26 26 VERBOSE(VB_CHANNEL, LOC + "ctor"); … … 29 29 FreeboxChannel::~FreeboxChannel() 30 30 { 31 31 VERBOSE(VB_CHANNEL, LOC + "dtor -- begin"); 32 if (m_ rtsp)32 if (m_feeder) 33 33 { 34 delete m_ rtsp;35 m_ rtsp= NULL;34 delete m_feeder; 35 m_feeder = NULL; 36 36 } 37 37 VERBOSE(VB_CHANNEL, LOC + "dtor -- end"); 38 38 } … … 193 193 } 194 194 195 195 // Try to map name to a channel in the map 196 const QString name = query.value(1).toString();196 const QString name = QString::fromUtf8(query.value(1).toString()); 197 197 for (it = m_freeboxchannels.begin(); 198 198 it != m_freeboxchannels.end(); ++it) 199 199 { -
libs/libmythtv/freeboxfeederlive.cpp
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederLive -- base class for livemedia based FreeboxFeeders 3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #include "freeboxfeederlive.h" 8 9 #include <cassert> 10 11 // MythTV headers 12 #include "mythcontext.h" 13 #include "timeoutedtaskscheduler.h" 14 15 #define LOC QString("FbFeedLive(%1):").arg(pthread_self()) 16 #define LOC_ERR QString("FbFeedLive(%1), Error:").arg(pthread_self()) 17 18 19 FreeboxFeederLive::FreeboxFeederLive(StreamDataListener &listener) : 20 _abort(0), 21 _running(false), 22 _live_env(NULL), 23 _lock(false), 24 _listener(listener) 25 { 26 } 27 28 FreeboxFeederLive::~FreeboxFeederLive() 29 { 30 } 31 32 bool FreeboxFeederLive::InitEnv(void) 33 { 34 TaskScheduler *scheduler = new TimeoutedTaskScheduler(500); 35 if (!scheduler) 36 { 37 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Scheduler."); 38 return false; 39 } 40 41 assert(_live_env==NULL); 42 _live_env = BasicUsageEnvironment::createNew(*scheduler); 43 if (!_live_env) 44 { 45 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Environment."); 46 delete scheduler; 47 return false; 48 } 49 50 return true; 51 } 52 53 void FreeboxFeederLive::FreeEnv(void) 54 { 55 if (_live_env) 56 { 57 TaskScheduler *scheduler = &_live_env->taskScheduler(); 58 _live_env->reclaim(); 59 _live_env = NULL; 60 delete scheduler; 61 } 62 } 63 64 void FreeboxFeederLive::Run(void) 65 { 66 VERBOSE(VB_RECORD, LOC + "Run() -- begin"); 67 _lock.lock(); 68 _running = true; 69 _abort = 0; 70 _lock.unlock(); 71 72 VERBOSE(VB_RECORD, LOC + "Run() -- loop begin"); 73 if (_live_env) 74 _live_env->taskScheduler().doEventLoop(&_abort); 75 VERBOSE(VB_RECORD, LOC + "Run() -- loop end"); 76 77 _lock.lock(); 78 _running = false; 79 _cond.wakeAll(); 80 _lock.unlock(); 81 VERBOSE(VB_RECORD, LOC + "Run() -- end"); 82 } 83 84 void FreeboxFeederLive::Stop(void) 85 { 86 VERBOSE(VB_RECORD, LOC + "Stop() -- begin"); 87 QMutexLocker locker(&_lock); 88 _abort = 0xFF; 89 90 while (_running) 91 _cond.wait(&_lock, 500); 92 VERBOSE(VB_RECORD, LOC + "Stop() -- end"); 93 } -
libs/libmythtv/freeboxmediasink.cpp
4 4 * Distributed as part of MythTV under GPL v2 and later. 5 5 */ 6 6 7 #include <algorithm>8 using namespace std;9 10 #include "mythcontext.h"11 7 #include "freeboxmediasink.h" 12 #include "rtspcomms.h" 8 #include "mythcontext.h" 9 #include "streamdatalistener.h" 13 10 14 #define LOC QString(" RTSPSink:")15 #define LOC_ERR QString(" RTSPSink, Error:")11 #define LOC QString("FbxSink:") 12 #define LOC_ERR QString("FbxSink, Error:") 16 13 17 FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv, 18 unsigned int bufferSize) : 19 MediaSink(pEnv), fBufferSize(bufferSize), 20 env(pEnv), lock(true) 14 FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv, 15 StreamDataListener &listener, 16 unsigned int bufferSize) : 17 MediaSink(pEnv), 18 fBufferSize(bufferSize), 19 env(pEnv), 20 _listener(listener), 21 lock(true) 21 22 { 22 23 fBuffer = new unsigned char[fBufferSize]; 23 24 } … … 31 32 } 32 33 } 33 34 34 FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment &env, 35 unsigned int bufferSize) 35 FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment &env, 36 StreamDataListener &listener, 37 unsigned int bufferSize) 36 38 { 37 return new FreeboxMediaSink(env, bufferSize);39 return new FreeboxMediaSink(env, listener, bufferSize); 38 40 } 39 41 40 42 Boolean FreeboxMediaSink::continuePlaying(void) … … 61 63 } 62 64 63 65 void FreeboxMediaSink::afterGettingFrame1(unsigned int frameSize, 64 struct timeval presentationTime)66 struct timeval) 65 67 { 66 lock.lock(); 67 vector<RTSPListener*>::iterator it = listeners.begin(); 68 for (; it != listeners.end(); ++it) 69 (*it)->AddData(fBuffer, frameSize, presentationTime); 70 lock.unlock(); 71 68 _listener.AddData(fBuffer, frameSize); 72 69 continuePlaying(); 73 70 } 74 71 75 void FreeboxMediaSink::AddListener(RTSPListener *item)76 {77 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");78 if (item)79 {80 RemoveListener(item);81 QMutexLocker locker(&lock);82 listeners.push_back(item);83 }84 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end");85 }86 87 void FreeboxMediaSink::RemoveListener(RTSPListener *item)88 {89 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin 1");90 QMutexLocker locker(&lock);91 vector<RTSPListener*>::iterator it =92 find(listeners.begin(), listeners.end(), item);93 if (it != listeners.end())94 {95 *it = *listeners.rbegin();96 listeners.resize(listeners.size() - 1);97 }98 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 6");99 }100 101 72 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/freeboxsignalmonitor.h
4 4 #define _FREEBOXSIGNALMONITOR_H_ 5 5 6 6 #include "dtvsignalmonitor.h" 7 #include " freeboxmediasink.h"7 #include "streamdatalistener.h" 8 8 9 class RTSPComms;10 9 class FreeboxChannel; 11 10 12 class FreeboxSignalMonitor : public DTVSignalMonitor, public RTSPListener 11 12 class FreeboxSignalMonitor : public DTVSignalMonitor, public StreamDataListener 13 13 { 14 14 Q_OBJECT 15 15 … … 21 21 22 22 void Stop(void); 23 23 24 // implements RTSPListener24 // implements StreamDataListener 25 25 void AddData(unsigned char *data, 26 unsigned dataSize, 27 struct timeval); 26 unsigned dataSize); 28 27 29 28 public slots: 30 29 void deleteLater(void); -
libs/libmythtv/freeboxfeederwrapper.cpp
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederWrapper 3 * Copyright (c) 2006 by Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #include "freeboxfeederwrapper.h" 8 9 #include "freeboxfeeder.h" 10 #include "freeboxfeederrtsp.h" 11 #include "freeboxfeederudp.h" 12 #include "mythcontext.h" 13 14 #define LOC QString("FBFeed: ") 15 #define LOC_ERR QString("FBFeed, Error: ") 16 17 18 FreeboxFeederWrapper::FreeboxFeederWrapper() : 19 _feeder(NULL) 20 { 21 } 22 23 FreeboxFeederWrapper::~FreeboxFeederWrapper() 24 { 25 if (_feeder) 26 { 27 _feeder->Stop(); 28 _feeder->Close(); 29 delete _feeder; 30 } 31 } 32 33 FreeboxFeeder* FreeboxFeederWrapper::NewFeeder(const QString &url, 34 StreamDataListener &listener) 35 { 36 if (url.startsWith("rtsp://", false)) 37 { 38 return new FreeboxFeederRtsp(listener); 39 } 40 else if (url.startsWith("udp://", false)) 41 { 42 return new FreeboxFeederUdp(listener); 43 } 44 45 VERBOSE(VB_RECORD, LOC_ERR + QString("InitFeeder() -- unhandled url (%1)") 46 .arg(url)); 47 return NULL; 48 } 49 50 bool FreeboxFeederWrapper::InitFeeder(const QString &url) 51 { 52 VERBOSE(VB_RECORD, LOC + "Init() -- begin"); 53 QMutexLocker locker(&_lock); 54 if (_feeder && _feeder->CanHandle(url)) 55 { 56 VERBOSE(VB_RECORD, LOC + "Init() -- end 0"); 57 return true; 58 } 59 60 delete _feeder; 61 _feeder = NewFeeder(url, *this); 62 63 VERBOSE(VB_RECORD, LOC + "Init() -- end 1"); 64 return _feeder != NULL; 65 } 66 67 bool FreeboxFeederWrapper::Open(const QString& url) 68 { 69 VERBOSE(VB_RECORD, LOC + "Open() -- begin"); 70 bool result = InitFeeder(url) && _feeder->Open(url); 71 VERBOSE(VB_RECORD, LOC + "Open() -- end"); 72 return result; 73 } 74 75 bool FreeboxFeederWrapper::IsOpen(void) const 76 { 77 VERBOSE(VB_RECORD, LOC + "IsOpen() -- begin"); 78 bool result = _feeder && _feeder->IsOpen(); 79 VERBOSE(VB_RECORD, LOC + "IsOpen() -- end"); 80 return result; 81 } 82 83 void FreeboxFeederWrapper::Close(void) 84 { 85 VERBOSE(VB_RECORD, LOC + "Close() -- begin"); 86 if (_feeder) _feeder->Close(); 87 VERBOSE(VB_RECORD, LOC + "Close() -- end"); 88 } 89 90 void FreeboxFeederWrapper::Run(void) 91 { 92 VERBOSE(VB_RECORD, LOC + "Run() -- begin"); 93 if (_feeder) _feeder->Run(); 94 VERBOSE(VB_RECORD, LOC + "Run() -- end"); 95 } 96 97 void FreeboxFeederWrapper::Stop(void) 98 { 99 VERBOSE(VB_RECORD, LOC + "Stop() -- begin"); 100 if (_feeder) _feeder->Stop(); 101 VERBOSE(VB_RECORD, LOC + "Stop() -- end"); 102 } 103 104 void FreeboxFeederWrapper::AddListener(StreamDataListener *item) 105 { 106 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin"); 107 if (!item) 108 { 109 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 0"); 110 return; 111 } 112 113 QMutexLocker locker(&_lock); 114 std::vector<StreamDataListener*>::iterator it = 115 find(_listeners.begin(), _listeners.end(), item); 116 if (it == _listeners.end()) // avoid duplicates 117 _listeners.push_back(item); 118 119 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 1"); 120 } 121 122 void FreeboxFeederWrapper::RemoveListener(StreamDataListener *item) 123 { 124 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin"); 125 QMutexLocker locker(&_lock); 126 std::vector<StreamDataListener*>::iterator it = 127 find(_listeners.begin(), _listeners.end(), item); 128 129 if (it == _listeners.end()) 130 { 131 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (not found)"); 132 return; 133 } 134 135 // remove from local list.. 136 *it = *_listeners.rbegin(); 137 _listeners.resize(_listeners.size() - 1); 138 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (ok, removed)"); 139 } 140 141 void FreeboxFeederWrapper::AddData(unsigned char *data, unsigned int dataSize) 142 { 143 QMutexLocker locker(&_lock); 144 std::vector<StreamDataListener*>::iterator it = _listeners.begin(); 145 std::vector<StreamDataListener*>::iterator end = _listeners.end(); 146 for( ; it!=end ; ++it ) 147 (*it)->AddData(data, dataSize); 148 } -
libs/libmythtv/freeboxchannelfetcher.cpp
4 4 #include <cmath> 5 5 #include <unistd.h> 6 6 7 // Qt headers 8 #include <qnetwork.h> 9 #include <qapplication.h> 10 7 11 // MythTV headers 8 12 #include "mythcontext.h" 9 13 #include "httpcomms.h" … … 21 25 static bool parse_extinf(const QString &data, 22 26 QString &channum, QString &name); 23 27 28 FreeboxUrlFetch::FreeboxUrlFetch(const QString& url) 29 : op(new QUrlOperator(url)), 30 state(QNetworkProtocol::StInProgress), 31 str("") 32 { 33 connect(op, SIGNAL( finished(QNetworkOperation *)), 34 this, SLOT( finished(QNetworkOperation *))); 35 connect(op, SIGNAL( data(const QByteArray &,QNetworkOperation *)), 36 this, SLOT( data(const QByteArray &,QNetworkOperation *))); 37 op->get(); 38 } 39 40 FreeboxUrlFetch::~FreeboxUrlFetch() 41 { 42 disconnect(); 43 delete op; 44 op=NULL; 45 } 46 47 void FreeboxUrlFetch::finished(QNetworkOperation *op) 48 { 49 state = op->state(); 50 } 51 52 void FreeboxUrlFetch::data(const QByteArray &data,QNetworkOperation *op) 53 { 54 if (!data.isNull()) 55 str += QString::fromUtf8(data.data(),data.size()); 56 state = op->state(); 57 } 58 59 QString FreeboxUrlFetch::fetchData(const QString &url,bool inQtThread) 60 { 61 FreeboxUrlFetch obj(url); 62 while(obj.state==QNetworkProtocol::StWaiting || 63 obj.state==QNetworkProtocol::StInProgress) 64 { 65 if (inQtThread) 66 qApp->processEvents(); 67 usleep(1000); 68 } 69 if (obj.state==QNetworkProtocol::StDone) 70 return obj.str; 71 else // QNetworkProtocol::StFailed || QNetworkProtocol::StStopped 72 return QString::null; 73 } 74 75 24 76 FreeboxChannelFetcher::FreeboxChannelFetcher(unsigned _sourceid, 25 77 unsigned _cardid) : 26 78 sourceid(_sourceid), cardid(_cardid), … … 177 229 QString FreeboxChannelFetcher::DownloadPlaylist(const QString &url, 178 230 bool inQtThread) 179 231 { 180 QString redirected_url = url; 232 if (url.startsWith("http:")) { 233 // Use Myth HttpComms for http URLs 234 QString redirected_url = url; 181 235 182 QString tmp = HttpComms::getHttp(183 redirected_url,184 10000 /* ms */, 3 /* retries */,185 3 /* redirects */, true /* allow gzip */,186 NULL /* login */, inQtThread);236 QString tmp = HttpComms::getHttp( 237 redirected_url, 238 10000 /* ms */, 3 /* retries */, 239 3 /* redirects */, true /* allow gzip */, 240 NULL /* login */, inQtThread); 187 241 188 if (redirected_url != url)189 {190 VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")191 .arg(redirected_url));192 }242 if (redirected_url != url) 243 { 244 VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1") 245 .arg(redirected_url)); 246 } 193 247 194 return QString::fromUtf8(tmp); 248 return QString::fromUtf8(tmp); 249 } else 250 return FreeboxUrlFetch::fetchData(url,inQtThread); 195 251 } 196 252 197 253 static uint estimate_number_of_channels(const QString &rawdata) -
libs/libmythtv/freeboxfeederrtsp.h
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederRtsp 3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef FREEBOXFEEDERRTSP_H 8 #define FREEBOXFEEDERRTSP_H 9 10 // MythTV headers 11 #include "freeboxfeederlive.h" 12 13 class RTSPClient; 14 class MediaSession; 15 16 17 class FreeboxFeederRtsp : public FreeboxFeederLive 18 { 19 public: 20 explicit FreeboxFeederRtsp(StreamDataListener &listener); 21 virtual ~FreeboxFeederRtsp(); 22 23 bool CanHandle(const QString &url) const; 24 bool Open(const QString &url); 25 bool IsOpen(void) const { return _session; } 26 void Close(void); 27 28 private: 29 RTSPClient *_rtsp_client; 30 MediaSession *_session; 31 32 private: 33 /// avoid default copy operator 34 FreeboxFeederRtsp& operator=(const FreeboxFeederRtsp&); 35 /// avoid default copy constructor 36 FreeboxFeederRtsp(const FreeboxFeederRtsp&); 37 /// avoid default constructor 38 FreeboxFeederRtsp(); 39 }; 40 41 #endif//FREEBOXFEEDERRTSP_H -
libs/libmythtv/freeboxrecorder.cpp
8 8 #include "mpegstreamdata.h" 9 9 #include "tspacket.h" 10 10 #include "freeboxchannel.h" 11 #include "freeboxfeederwrapper.h" 11 12 #include "freeboxrecorder.h" 12 #include "rtspcomms.h"13 13 14 14 #define LOC QString("FBRec: ") 15 15 #define LOC_ERR QString("FBRec, Error: ") … … 23 23 _channel(channel), 24 24 _stream_data(NULL) 25 25 { 26 _channel->Get RTSP()->AddListener(this);26 _channel->GetFeeder()->AddListener(this); 27 27 } 28 28 29 29 FreeboxRecorder::~FreeboxRecorder() 30 30 { 31 31 StopRecording(); 32 _channel->Get RTSP()->RemoveListener(this);32 _channel->GetFeeder()->RemoveListener(this); 33 33 } 34 34 35 35 bool FreeboxRecorder::Open(void) 36 36 { 37 37 VERBOSE(VB_RECORD, LOC + "Open() -- begin"); 38 38 39 if (_channel->Get RTSP()->IsOpen())40 _channel->Get RTSP()->Close();39 if (_channel->GetFeeder()->IsOpen()) 40 _channel->GetFeeder()->Close(); 41 41 42 42 FreeboxChannelInfo chaninfo = _channel->GetCurrentChanInfo(); 43 if (!chaninfo.isValid()) 44 { 45 _error = true; 46 } 47 else 48 { 49 _error = !(_channel->GetRTSP()->Init()); 50 if (!_error) 51 _error = !(_channel->GetRTSP()->Open(chaninfo.m_url)); 52 } 43 _error = !chaninfo.isValid() 44 || !_channel->GetFeeder()->Open(chaninfo.m_url); 53 45 54 46 VERBOSE(VB_RECORD, LOC + "Open() -- end err("<<_error<<")"); 55 47 return !_error; … … 58 50 void FreeboxRecorder::Close(void) 59 51 { 60 52 VERBOSE(VB_RECORD, LOC + "Close() -- begin"); 61 _channel->Get RTSP()->Stop();62 _channel->Get RTSP()->Close();53 _channel->GetFeeder()->Stop(); 54 _channel->GetFeeder()->Close(); 63 55 VERBOSE(VB_RECORD, LOC + "Close() -- end"); 64 56 } 65 57 … … 67 59 { 68 60 VERBOSE(VB_RECORD, LOC + "Pause() -- begin"); 69 61 DTVRecorder::Pause(clear); 70 _channel->Get RTSP()->Stop();71 _channel->Get RTSP()->Close();62 _channel->GetFeeder()->Stop(); 63 _channel->GetFeeder()->Close(); 72 64 VERBOSE(VB_RECORD, LOC + "Pause() -- end"); 73 65 } 74 66 75 67 void FreeboxRecorder::Unpause(void) 76 68 { 77 69 VERBOSE(VB_RECORD, LOC + "Unpause() -- begin"); 78 if (_recording && !_channel->Get RTSP()->IsOpen())70 if (_recording && !_channel->GetFeeder()->IsOpen()) 79 71 Open(); 72 if (_stream_data) 73 _stream_data->Reset(_stream_data->DesiredProgram()); 80 74 DTVRecorder::Unpause(); 81 75 VERBOSE(VB_RECORD, LOC + "Unpause() -- end"); 82 76 } … … 99 93 if (PauseAndWait()) 100 94 continue; 101 95 102 if (!_channel->Get RTSP()->IsOpen())96 if (!_channel->GetFeeder()->IsOpen()) 103 97 { 104 98 usleep(5000); 105 99 continue; 106 100 } 107 101 108 102 // Go into main RTSP loop, feeding data to AddData 109 _channel->Get RTSP()->Run();103 _channel->GetFeeder()->Run(); 110 104 } 111 105 112 106 // Finish up... … … 122 116 { 123 117 VERBOSE(VB_RECORD, LOC + "StopRecording() -- begin"); 124 118 Pause(); 125 _channel->Get RTSP()->Close();119 _channel->GetFeeder()->Close(); 126 120 127 121 _request_recording = false; 128 122 while (_recording) … … 153 147 // AddData : feed data from RTSP flow to mythtv 154 148 // =================================================== 155 149 void FreeboxRecorder::AddData(unsigned char *data, 156 unsigned dataSize, 157 struct timeval) 150 unsigned dataSize) 158 151 { 159 152 unsigned int readIndex = 0; 160 153 … … 166 159 return; 167 160 168 161 // Find the next TS Header in data 169 int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize );162 int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize - readIndex); 170 163 171 164 // if no TS, something bad happens 172 165 if (tsPos == -1) … … 184 177 185 178 // Check if the next packet in buffer is complete : 186 179 // packet size is 188 bytes long 187 if ((dataSize - tsPos ) < TSPacket::SIZE)180 if ((dataSize - tsPos - readIndex) < TSPacket::SIZE) 188 181 { 189 182 VERBOSE(VB_IMPORTANT, LOC_ERR + 190 183 "TS packet at stradles end of buffer."); … … 232 225 233 226 void FreeboxRecorder::SetStreamData(MPEGStreamData *data) 234 227 { 235 VERBOSE(VB_RECORD, LOC + "SetStreamData( )");228 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin"); 236 229 if (data == _stream_data) 230 { 231 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0"); 237 232 return; 233 } 238 234 239 235 MPEGStreamData *old_data = _stream_data; 240 236 _stream_data = data; … … 243 239 244 240 if (data) 245 241 data->AddMPEGSPListener(this); 242 VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1"); 246 243 } 247 244 248 245 void FreeboxRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat) -
libs/libmythtv/rtspcomms.cpp
1 /** -*- Mode: c++ -*-2 * RTSPComms3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 #include "rtspcomms.h"8 9 // Live555 headers10 #include <RTSPClient.hh>11 #include <BasicUsageEnvironment.hh>12 #include <MediaSession.hh>13 14 // MythTV headers15 #include "freeboxmediasink.h"16 #include "mythcontext.h"17 #include "tspacket.h"18 19 #define LOC QString("RTSPData:")20 #define LOC_ERR QString("RTSPData, Error:")21 22 // ============================================================================23 // RTSPData : Helper class use for static Callback handler24 // ============================================================================25 class RTSPData26 {27 public:28 RTSPData(MediaSubsession *pMediaSubSession) :29 mediaSubSession(pMediaSubSession)30 {31 }32 33 void SubsessionAfterPlayingCB(void);34 void SubsessionByeHandlerCB(void);35 36 private:37 MediaSubsession *mediaSubSession;38 };39 40 void RTSPData::SubsessionAfterPlayingCB(void)41 {42 MediaSubsession *subsession = mediaSubSession;43 Medium::close(subsession->sink);44 subsession->sink = NULL;45 46 MediaSession &session = subsession->parentSession();47 MediaSubsessionIterator iter(session);48 49 while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */50 {51 if (subsession->sink)52 return;53 }54 }55 56 static void sub_after_playing_cb(void *clientData)57 {58 ((RTSPData*)clientData)->SubsessionAfterPlayingCB();59 }60 61 void RTSPData::SubsessionByeHandlerCB(void)62 {63 SubsessionAfterPlayingCB();64 }65 66 static void sub_bye_handler_cb(void *clientData)67 {68 ((RTSPData*)clientData)->SubsessionByeHandlerCB();69 }70 71 RTSPComms::RTSPComms() :72 _abort(0), _running(false),73 _live_env(NULL), _rtsp_client(NULL),74 _session(NULL), _lock(false)75 {76 //Init();77 }78 79 RTSPComms::~RTSPComms()80 {81 VERBOSE(VB_RECORD, LOC + "dtor -- begin");82 //Stop();83 Close();84 //Deinit();85 VERBOSE(VB_RECORD, LOC + "dtor -- end");86 }87 88 bool RTSPComms::Init(void)89 {90 VERBOSE(VB_RECORD, LOC + "Init() -- begin");91 QMutexLocker locker(&_lock);92 93 if (_rtsp_client)94 return true;95 96 // Begin by setting up our usage environment:97 TaskScheduler *scheduler = BasicTaskScheduler::createNew();98 if (!scheduler)99 {100 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Scheduler.");101 return false;102 }103 104 _live_env = BasicUsageEnvironment::createNew(*scheduler);105 if (!_live_env)106 {107 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to create Live Environment.");108 delete scheduler;109 return false;110 }111 112 // Create our client object:113 _rtsp_client = RTSPClient::createNew(*_live_env, 0, "myRTSP", 0);114 115 if (!_rtsp_client)116 {117 VERBOSE(VB_IMPORTANT, LOC_ERR +118 QString("Failed to create RTSP client: %1")119 .arg(_live_env->getResultMsg()));120 121 _live_env->reclaim();122 _live_env = NULL;123 delete scheduler;124 }125 126 VERBOSE(VB_RECORD, LOC + "Init() -- end");127 return _rtsp_client;128 }129 130 void RTSPComms::Deinit(void)131 {132 VERBOSE(VB_RECORD, LOC + "Deinit() -- begin");133 134 if (_session)135 Close();136 137 if (_rtsp_client)138 {139 Medium::close(_rtsp_client);140 _rtsp_client = NULL;141 }142 143 if (_live_env)144 {145 TaskScheduler *scheduler = &_live_env->taskScheduler();146 _live_env->reclaim();147 _live_env = NULL;148 delete scheduler;149 }150 VERBOSE(VB_RECORD, LOC + "Deinit() -- end");151 }152 153 bool RTSPComms::Open(const QString &url)154 {155 VERBOSE(VB_RECORD, LOC + "Open() -- begin");156 157 if (!Init())158 return false;159 160 QMutexLocker locker(&_lock);161 162 // Setup URL for the current session163 char *sdpDescription = _rtsp_client->describeURL(url);164 _rtsp_client->describeStatus();165 166 if (!sdpDescription)167 {168 VERBOSE(VB_IMPORTANT, LOC + QString(169 "Failed to get a SDP "170 "description from URL: %1 %2")171 .arg(url).arg(_live_env->getResultMsg()));172 return false;173 }174 175 // Create a media session object from this SDP description:176 _session = MediaSession::createNew(*_live_env, sdpDescription);177 178 delete[] sdpDescription;179 180 if (!_session)181 {182 VERBOSE(VB_IMPORTANT, LOC +183 QString("Failed to create MediaSession: %1")184 .arg(_live_env->getResultMsg()));185 return false;186 }187 else if (!_session->hasSubsessions())188 {189 VERBOSE(VB_IMPORTANT, LOC +190 "This session has no media subsessions");191 Close();192 return false;193 }194 195 // Then, setup the "RTPSource"s for the session:196 MediaSubsessionIterator iter(*_session);197 MediaSubsession *subsession;198 bool madeProgress = false;199 200 while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */201 {202 if (!subsession->initiate(-1))203 {204 VERBOSE(VB_IMPORTANT, LOC +205 QString("Can't create receiver for: "206 "%1 / %2 subsession: %3")207 .arg(subsession->mediumName())208 .arg(subsession->codecName())209 .arg(_live_env->getResultMsg()));210 }211 else212 {213 madeProgress = true;214 215 if (subsession->rtpSource() != NULL)216 {217 unsigned const thresh = 1000000; // 1 second218 subsession->rtpSource()->219 setPacketReorderingThresholdTime(thresh);220 }221 }222 }223 224 if (!madeProgress)225 return false;226 227 // Perform additional 'setup' on each subsession, before playing them:228 madeProgress = false;229 iter.reset();230 while ((subsession = iter.next()) != NULL)231 {232 if (subsession->clientPortNum() == 0)233 continue; // port # was not set234 235 if (_rtsp_client->setupMediaSubsession(*subsession, false, false))236 {237 madeProgress = true;238 }239 else240 {241 VERBOSE(VB_IMPORTANT, LOC +242 QString("Failed to setup: %1 %2 : %3")243 .arg(subsession->mediumName())244 .arg(subsession->codecName())245 .arg(_live_env->getResultMsg()));246 }247 }248 249 if (!madeProgress)250 return false;251 252 // Create and start "FileSink"s for each subsession:253 // FileSink while receive Mpeg2 TS Data & will feed them to mythtv254 madeProgress = false;255 iter.reset();256 257 while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */258 {259 if (!subsession->readSource())260 continue; // was not initiated261 262 FreeboxMediaSink *freeboxMediaSink = FreeboxMediaSink::CreateNew(263 *_live_env, TSPacket::SIZE * 128*1024);264 265 subsession->sink = freeboxMediaSink;266 if (!subsession->sink)267 {268 VERBOSE(VB_IMPORTANT,269 QString("Freebox # Failed to create sink: %1")270 .arg(_live_env->getResultMsg()));271 }272 273 vector<RTSPListener*>::iterator it = _listeners.begin();274 for (; it != _listeners.end(); ++it)275 freeboxMediaSink->AddListener(*it);276 277 subsession->sink->startPlaying(*(subsession->readSource()),278 sub_after_playing_cb,279 new RTSPData(subsession));280 281 if (subsession->rtcpInstance())282 {283 subsession->rtcpInstance()->setByeHandler(284 sub_bye_handler_cb, new RTSPData(subsession));285 }286 287 madeProgress = true;288 }289 290 if (!madeProgress)291 return false;292 293 // Setup player294 if (!(_rtsp_client->playMediaSession(*_session)))295 {296 VERBOSE(VB_IMPORTANT, LOC +297 QString("Failed to start playing session: %1")298 .arg(_live_env->getResultMsg()));299 return false;300 }301 302 VERBOSE(VB_RECORD, LOC + "Open() -- end");303 return true;304 }305 306 void RTSPComms::Close(void)307 {308 VERBOSE(VB_RECORD, LOC + "Close() -- begin");309 Stop();310 311 VERBOSE(VB_RECORD, LOC + "Close() -- middle 1");312 313 _lock.lock();314 if (_session)315 {316 // Ensure RTSP cleanup, remove old RTSP session317 MediaSubsessionIterator iter(*_session);318 MediaSubsession *subsession;319 while ((subsession = iter.next())) /*<-extra braces for pedantic gcc*/320 {321 Medium::close(subsession->sink);322 subsession->sink = NULL;323 }324 325 _rtsp_client->teardownMediaSession(*_session);326 327 // Close all RTSP descriptor328 Medium::close(_session);329 _session = NULL;330 }331 _lock.unlock();332 333 VERBOSE(VB_RECORD, LOC + "Close() -- middle 2");334 335 Deinit();336 VERBOSE(VB_RECORD, LOC + "Close() -- end");337 }338 339 void RTSPComms::Run(void)340 {341 VERBOSE(VB_RECORD, LOC + "Run() -- begin");342 _lock.lock();343 _running = true;344 _abort = 0;345 _lock.unlock();346 347 VERBOSE(VB_RECORD, LOC + "Run() -- loop begin");348 if (_live_env)349 _live_env->taskScheduler().doEventLoop(&_abort);350 VERBOSE(VB_RECORD, LOC + "Run() -- loop end");351 352 _lock.lock();353 _running = false;354 _cond.wakeAll();355 _lock.unlock();356 VERBOSE(VB_RECORD, LOC + "Run() -- end");357 }358 359 void RTSPComms::Stop(void)360 {361 VERBOSE(VB_RECORD, LOC + "Stop() -- begin");362 QMutexLocker locker(&_lock);363 _abort = 0xFF;364 365 while (_running)366 _cond.wait(&_lock, 500);367 VERBOSE(VB_RECORD, LOC + "Stop() -- end");368 }369 370 void RTSPComms::AddListener(RTSPListener *item)371 {372 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");373 if (!item)374 {375 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 0");376 return;377 }378 379 // avoid duplicates380 RemoveListener(item);381 382 // add to local list383 QMutexLocker locker(&_lock);384 _listeners.push_back(item);385 386 // if there is a session, add to each subsession->sink387 if (!_session)388 {389 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 1");390 return;391 }392 393 MediaSubsessionIterator mit(*_session);394 MediaSubsession *subsession;395 while ((subsession = mit.next())) /* <- extra braces for pedantic gcc */396 {397 FreeboxMediaSink *sink = NULL;398 if ((sink = dynamic_cast<FreeboxMediaSink*>(subsession->sink)))399 sink->AddListener(item);400 }401 VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 2");402 }403 404 void RTSPComms::RemoveListener(RTSPListener *item)405 {406 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");407 QMutexLocker locker(&_lock);408 vector<RTSPListener*>::iterator it =409 find(_listeners.begin(), _listeners.end(), item);410 411 if (it == _listeners.end())412 {413 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 1");414 return;415 }416 417 // remove from local list..418 *it = *_listeners.rbegin();419 _listeners.resize(_listeners.size() - 1);420 421 // if there is a session, remove from each subsession->sink422 if (!_session)423 {424 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 2");425 return;426 }427 428 MediaSubsessionIterator mit(*_session);429 MediaSubsession *subsession;430 while ((subsession = mit.next())) /* <- extra braces for pedantic gcc */431 {432 FreeboxMediaSink *sink = NULL;433 if ((sink = dynamic_cast<FreeboxMediaSink*>(subsession->sink)))434 sink->RemoveListener(item);435 }436 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end 3");437 } -
libs/libmythtv/timeoutedtaskscheduler.cpp
1 /** -*- Mode: c++ -*- 2 * TimeoutedTaskScheduler 3 * Copyright (c) 2006 by Mike Mironov 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #include "timeoutedtaskscheduler.h" 8 9 10 TimeoutedTaskScheduler::TimeoutedTaskScheduler(unsigned maxDelayTimeMS) : 11 _maxDelayTimeUS(maxDelayTimeMS*1000) 12 { 13 } 14 15 void TimeoutedTaskScheduler::doEventLoop(char* watchVariable) 16 { 17 // Repeatedly loop, handling readble sockets and timed events: 18 while (1) 19 { 20 if (watchVariable != NULL && *watchVariable != 0) 21 break; 22 SingleStep(_maxDelayTimeUS); 23 } 24 } -
libs/libmythtv/freeboxfeederudp.h
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederUdp 3 * Copyright (c) 2006 by Mike Mironov & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef FREEBOXFEEDERUDP_H 8 #define FREEBOXFEEDERUDP_H 9 10 // MythTV headers 11 #include "freeboxfeederlive.h" 12 13 class BasicUDPSource; 14 class FreeboxMediaSink; 15 16 17 class FreeboxFeederUdp : public FreeboxFeederLive 18 { 19 public: 20 explicit FreeboxFeederUdp(StreamDataListener &listener); 21 virtual ~FreeboxFeederUdp(); 22 23 bool CanHandle(const QString &url) const; 24 bool Open(const QString &url); 25 bool IsOpen(void) const { return _source; } 26 void Close(void); 27 28 private: 29 BasicUDPSource *_source; 30 FreeboxMediaSink *_sink; 31 32 private: 33 /// avoid default copy operator 34 FreeboxFeederUdp& operator=(const FreeboxFeederUdp&); 35 /// avoid default copy constructor 36 FreeboxFeederUdp(const FreeboxFeederUdp&); 37 /// avoid default constructor 38 FreeboxFeederUdp(); 39 }; 40 41 #endif//FREEBOXFEEDERUDP_H -
libs/libmythtv/freeboxmediasink.h
7 7 #ifndef _FREEBOXMEDIASINK_H_ 8 8 #define _FREEBOXMEDIASINK_H_ 9 9 10 #include <vector>11 using namespace std;12 13 10 #include <qmutex.h> 14 11 15 12 #include <MediaSink.hh> 16 13 17 class RTSPListener 18 { 19 public: 20 /// Callback function to add MPEG2 TS data 21 virtual void AddData(unsigned char *data, 22 unsigned int dataSize, 23 struct timeval presentationTime) = 0; 24 protected: 25 virtual ~RTSPListener() {} 26 }; 14 class StreamDataListener; 27 15 16 28 17 // ============================================================================ 29 18 // FreeboxMediaSink : Helper class use to receive RTSP data from socket. 30 19 // ============================================================================ 31 20 class FreeboxMediaSink : public MediaSink 32 21 { 33 22 public: 34 static FreeboxMediaSink *CreateNew(UsageEnvironment &env, 35 unsigned bufferSize); 23 static FreeboxMediaSink *CreateNew(UsageEnvironment &env, 24 StreamDataListener &listener, 25 unsigned bufferSize); 36 26 37 void AddListener(RTSPListener*);38 void RemoveListener(RTSPListener*);39 40 27 protected: 41 FreeboxMediaSink(UsageEnvironment &env, 42 unsigned int bufferSize); 28 FreeboxMediaSink(UsageEnvironment &env, 29 StreamDataListener &listener, 30 unsigned int bufferSize); 43 31 virtual ~FreeboxMediaSink(); 44 32 45 33 virtual void afterGettingFrame1(unsigned frameSize, … … 58 46 unsigned char *fBuffer; 59 47 unsigned int fBufferSize; 60 48 UsageEnvironment &env; 61 vector<RTSPListener*> listeners;49 StreamDataListener &_listener; 62 50 mutable QMutex lock; 63 51 64 52 private: -
libs/libmythtv/freeboxrecorder.h
10 10 #include <qwaitcondition.h> 11 11 12 12 #include "dtvrecorder.h" 13 #include " freeboxmediasink.h"13 #include "streamdatalistener.h" 14 14 #include "streamlisteners.h" 15 15 16 16 class FreeboxChannel; 17 17 18 /** \brief Processes data from RTSPCommsand writes it to disk.18 /** \brief Processes data from StreamDataListener and writes it to disk. 19 19 */ 20 class FreeboxRecorder : public DTVRecorder, public RTSPListener, 20 class FreeboxRecorder : public DTVRecorder, 21 public StreamDataListener, 21 22 public MPEGSingleProgramStreamListener 22 23 { 23 24 friend class FreeboxMediaSink; 24 friend class RTSPComms;25 25 26 26 public: 27 27 FreeboxRecorder(TVRec *rec, FreeboxChannel *channel); … … 47 47 48 48 // implements RTSPListener 49 49 void AddData(unsigned char *data, 50 unsigned int dataSize, 51 struct timeval presentationTime); 50 unsigned int dataSize); 52 51 53 52 // implements MPEGSingleProgramStreamListener 54 53 void HandleSingleProgramPAT(ProgramAssociationTable *pat); … … 59 58 MPEGStreamData *_stream_data; 60 59 QWaitCondition _cond_recording; 61 60 62 63 61 private: 64 62 FreeboxRecorder& operator=(const FreeboxRecorder&); //< avoid default impl 65 63 FreeboxRecorder(const FreeboxRecorder&); //< avoid default impl -
libs/libmythtv/timeoutedtaskscheduler.h
1 /** -*- Mode: c++ -*- 2 * TimeoutedTaskScheduler 3 * Copyright (c) 2006 by Mike Mironov 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _TIMEOUTEDTASKSCHEDULER_H_ 8 #define _TIMEOUTEDTASKSCHEDULER_H_ 9 10 // Live555 headers 11 #include <BasicUsageEnvironment.hh> 12 13 14 class TimeoutedTaskScheduler : public BasicTaskScheduler 15 { 16 public: 17 TimeoutedTaskScheduler(unsigned maxDelayTimeMS); 18 19 public: 20 virtual void doEventLoop(char* watchVariable); 21 22 private: 23 unsigned _maxDelayTimeUS; 24 }; 25 26 #endif//_TIMEOUTEDTASKSCHEDULER_H_ -
libs/libmythtv/freeboxfeeder.h
1 /** -*- Mode: c++ -*- 2 * FreeboxFeeder 3 * Copyright (c) 2006 by Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef FREEBOXFEEDER_H 8 #define FREEBOXFEEDER_H 9 10 #include <qstring.h> 11 12 class StreamDataListener; 13 14 15 /** \interface FreeboxFeeder 16 ** \brief This is the interface that need to be implemented to support new 17 ** protocols in the FreeboxRecorder. 18 ** 19 ** To register a new implementation, it must be instanciated in 20 ** FreeboxFeederWrapper::NewFeeder(). 21 ** 22 ** \sa FreeboxFeederWrapper 23 */ 24 class FreeboxFeeder 25 { 26 public: 27 virtual ~FreeboxFeeder() {} 28 29 /// \brief Returns true if the feeder can handle url 30 virtual bool CanHandle(const QString &url) const = 0; 31 32 /// \brief Inits the feeder and opens the stream identified by url 33 virtual bool Open(const QString &url) = 0; 34 35 /// \brief Returns true if the feeder is currently open 36 virtual bool IsOpen(void) const = 0; 37 38 /// \brief Closes the stream and frees resources allocated in Open() 39 virtual void Close(void) = 0; 40 41 /** \brief Reads the stream and sends data to its StreamDataListener. This 42 ** is a blocking call : it should not exit until Stop() is called. 43 ** \sa Stop() 44 */ 45 virtual void Run(void) = 0; 46 47 /** \brief Signals to the Run() function that it should stop and exit 48 ** cleanly. 49 ** 50 ** This function should block until Run() has finished up. 51 ** \sa Run() 52 */ 53 virtual void Stop(void) = 0; 54 }; 55 56 #endif//FREEBOXFEEDER_H 57 -
libs/libmythtv/freeboxfeederrtsp.cpp
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederRtsp 3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #include "freeboxfeederrtsp.h" 8 9 // Live555 headers 10 #include <RTSPClient.hh> 11 #include <BasicUsageEnvironment.hh> 12 #include <MediaSession.hh> 13 14 // MythTV headers 15 #include "freeboxmediasink.h" 16 #include "mythcontext.h" 17 #include "tspacket.h" 18 19 #define LOC QString("FbFeedRtsp(%1):").arg(pthread_self()) 20 #define LOC_ERR QString("FbFeedRtsp(%1), Error:").arg(pthread_self()) 21 22 // ============================================================================ 23 // RTSPData : Helper class use for static Callback handler 24 // ============================================================================ 25 class RTSPData 26 { 27 public: 28 RTSPData(MediaSubsession *pMediaSubSession) : 29 mediaSubSession(pMediaSubSession) 30 { 31 } 32 33 void SubsessionAfterPlayingCB(void); 34 void SubsessionByeHandlerCB(void); 35 36 private: 37 MediaSubsession *mediaSubSession; 38 }; 39 40 void RTSPData::SubsessionAfterPlayingCB(void) 41 { 42 MediaSubsession *subsession = mediaSubSession; 43 Medium::close(subsession->sink); 44 subsession->sink = NULL; 45 } 46 47 static void sub_after_playing_cb(void *clientData) 48 { 49 ((RTSPData*)clientData)->SubsessionAfterPlayingCB(); 50 } 51 52 void RTSPData::SubsessionByeHandlerCB(void) 53 { 54 SubsessionAfterPlayingCB(); 55 } 56 57 static void sub_bye_handler_cb(void *clientData) 58 { 59 ((RTSPData*)clientData)->SubsessionByeHandlerCB(); 60 } 61 62 63 64 FreeboxFeederRtsp::FreeboxFeederRtsp(StreamDataListener &listener) : 65 FreeboxFeederLive(listener), 66 _rtsp_client(NULL), 67 _session(NULL) 68 { 69 VERBOSE(VB_RECORD, LOC + "ctor -- success"); 70 } 71 72 FreeboxFeederRtsp::~FreeboxFeederRtsp() 73 { 74 VERBOSE(VB_RECORD, LOC + "dtor -- begin"); 75 Close(); 76 VERBOSE(VB_RECORD, LOC + "dtor -- end"); 77 } 78 79 bool FreeboxFeederRtsp::CanHandle(const QString &url) const 80 { 81 return url.startsWith("rtsp://", false); 82 } 83 84 bool FreeboxFeederRtsp::Open(const QString &url) 85 { 86 VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin"); 87 88 QMutexLocker locker(&GetLock()); 89 90 if (_rtsp_client) 91 { 92 VERBOSE(VB_RECORD, LOC + "Open() -- end 1"); 93 return true; 94 } 95 96 // Begin by setting up our usage environment: 97 if (!InitEnv()) 98 return false; 99 100 // Create our client object: 101 _rtsp_client = RTSPClient::createNew(GetLiveEnv(), 0, "myRTSP", 0); 102 if (!_rtsp_client) 103 { 104 VERBOSE(VB_IMPORTANT, LOC_ERR + 105 QString("Failed to create RTSP client: %1") 106 .arg(GetLiveEnv().getResultMsg())); 107 FreeEnv(); 108 } 109 110 // Setup URL for the current session 111 char *sdpDescription = _rtsp_client->describeURL(url); 112 _rtsp_client->describeStatus(); 113 114 if (!sdpDescription) 115 { 116 VERBOSE(VB_IMPORTANT, LOC + QString( 117 "Failed to get a SDP " 118 "description from URL: %1 %2") 119 .arg(url).arg(GetLiveEnv().getResultMsg())); 120 return false; 121 } 122 123 // Create a media session object from this SDP description: 124 _session = MediaSession::createNew(GetLiveEnv(), sdpDescription); 125 126 delete[] sdpDescription; 127 128 if (!_session) 129 { 130 VERBOSE(VB_IMPORTANT, LOC + 131 QString("Failed to create MediaSession: %1") 132 .arg(GetLiveEnv().getResultMsg())); 133 return false; 134 } 135 else if (!_session->hasSubsessions()) 136 { 137 VERBOSE(VB_IMPORTANT, LOC + 138 "This session has no media subsessions"); 139 Close(); 140 return false; 141 } 142 143 // Then, setup the "RTPSource"s for the session: 144 MediaSubsessionIterator iter(*_session); 145 MediaSubsession *subsession; 146 bool madeProgress = false; 147 148 while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */ 149 { 150 if (!subsession->initiate(-1)) 151 { 152 VERBOSE(VB_IMPORTANT, LOC + 153 QString("Can't create receiver for: " 154 "%1 / %2 subsession: %3") 155 .arg(subsession->mediumName()) 156 .arg(subsession->codecName()) 157 .arg(GetLiveEnv().getResultMsg())); 158 } 159 else 160 { 161 madeProgress = true; 162 163 if (subsession->rtpSource() != NULL) 164 { 165 unsigned const thresh = 1000000; // 1 second 166 subsession->rtpSource()-> 167 setPacketReorderingThresholdTime(thresh); 168 } 169 } 170 } 171 172 if (!madeProgress) 173 return false; 174 175 // Perform additional 'setup' on each subsession, before playing them: 176 madeProgress = false; 177 iter.reset(); 178 while ((subsession = iter.next()) != NULL) 179 { 180 if (subsession->clientPortNum() == 0) 181 continue; // port # was not set 182 183 if (_rtsp_client->setupMediaSubsession(*subsession, false, false)) 184 { 185 madeProgress = true; 186 } 187 else 188 { 189 VERBOSE(VB_IMPORTANT, LOC + 190 QString("Failed to setup: %1 %2 : %3") 191 .arg(subsession->mediumName()) 192 .arg(subsession->codecName()) 193 .arg(GetLiveEnv().getResultMsg())); 194 } 195 } 196 197 if (!madeProgress) 198 return false; 199 200 // Create and start "FileSink"s for each subsession: 201 // FileSink while receive Mpeg2 TS Data & will feed them to mythtv 202 madeProgress = false; 203 iter.reset(); 204 205 while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */ 206 { 207 if (!subsession->readSource()) 208 continue; // was not initiated 209 210 FreeboxMediaSink *freeboxMediaSink = FreeboxMediaSink::CreateNew( 211 GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024); 212 213 subsession->sink = freeboxMediaSink; 214 if (!subsession->sink) 215 { 216 VERBOSE(VB_IMPORTANT, 217 QString("Freebox # Failed to create sink: %1") 218 .arg(GetLiveEnv().getResultMsg())); 219 } 220 221 subsession->sink->startPlaying(*(subsession->readSource()), 222 sub_after_playing_cb, 223 new RTSPData(subsession)); 224 225 if (subsession->rtcpInstance()) 226 { 227 subsession->rtcpInstance()->setByeHandler( 228 sub_bye_handler_cb, new RTSPData(subsession)); 229 } 230 231 madeProgress = true; 232 } 233 234 if (!madeProgress) 235 return false; 236 237 // Setup player 238 if (!(_rtsp_client->playMediaSession(*_session))) 239 { 240 VERBOSE(VB_IMPORTANT, LOC + 241 QString("Failed to start playing session: %1") 242 .arg(GetLiveEnv().getResultMsg())); 243 return false; 244 } 245 246 VERBOSE(VB_RECORD, LOC + "Open() -- end"); 247 return true; 248 } 249 250 void FreeboxFeederRtsp::Close(void) 251 { 252 VERBOSE(VB_RECORD, LOC + "Close() -- begin"); 253 Stop(); 254 255 QMutexLocker locker(&GetLock()); 256 257 if (_session) 258 { 259 // Ensure RTSP cleanup, remove old RTSP session 260 MediaSubsessionIterator iter(*_session); 261 MediaSubsession *subsession; 262 while ((subsession = iter.next())) /*<-extra braces for pedantic gcc*/ 263 { 264 Medium::close(subsession->sink); 265 subsession->sink = NULL; 266 } 267 268 _rtsp_client->teardownMediaSession(*_session); 269 270 // Close all RTSP descriptor 271 Medium::close(_session); 272 _session = NULL; 273 } 274 275 if (_rtsp_client) 276 { 277 Medium::close(_rtsp_client); 278 _rtsp_client = NULL; 279 } 280 281 FreeEnv(); 282 283 VERBOSE(VB_RECORD, LOC + "Close() -- end"); 284 } -
libs/libmythtv/freeboxfeederwrapper.h
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederWrapper 3 * Copyright (c) 2006 by Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef FREEBOXFEEDERWRAPPER_H 8 #define FREEBOXFEEDERWRAPPER_H 9 10 #include <qmutex.h> 11 #include <qstring.h> 12 #include <vector> 13 14 #include "streamdatalistener.h" 15 16 class FreeboxFeeder; 17 18 19 /** \class FreeboxFeederWrapper 20 ** \brief Handles the various implementations of FeederRecorder. 21 */ 22 class FreeboxFeederWrapper : private StreamDataListener 23 { 24 public: 25 FreeboxFeederWrapper(); 26 ~FreeboxFeederWrapper(); 27 28 public: 29 bool Open(const QString &url); 30 bool IsOpen(void) const; 31 void Close(void); 32 33 void Run(void); 34 void Stop(void); 35 36 void AddListener(StreamDataListener*); 37 void RemoveListener(StreamDataListener*); 38 39 private: 40 static FreeboxFeeder* NewFeeder(const QString &url, 41 StreamDataListener &listener); 42 bool InitFeeder(const QString &url); 43 44 private: // implements StreamDataListener 45 void AddData(unsigned char *data, unsigned int dataSize); 46 47 private: 48 FreeboxFeeder *_feeder; 49 mutable QMutex _lock; ///< Lock used to coordinate threads 50 std::vector<StreamDataListener*> _listeners; 51 52 private: 53 /// avoid default copy operator 54 FreeboxFeederWrapper& operator=(const FreeboxFeederWrapper&); 55 /// avoid default copy constructor 56 FreeboxFeederWrapper(const FreeboxFeederWrapper&); 57 }; 58 59 #endif//FREEBOXFEEDERWRAPPER_H -
libs/libmythtv/freeboxfeederlive.h
1 /** -*- Mode: c++ -*- 2 * FreeboxFeederLive -- base class for livemedia based FreeboxFeeders 3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars 4 * Distributed as part of MythTV under GPL v2 and later. 5 */ 6 7 #ifndef _FREEBOXFEEDERLIVE_H_ 8 #define _FREEBOXFEEDERLIVE_H_ 9 10 // C++ headers 11 #include <vector> 12 13 // Qt headers 14 #include <qwaitcondition.h> 15 #include <qmutex.h> 16 17 // Mythtv headers 18 #include "freeboxfeeder.h" 19 20 class QString; 21 class StreamDataListener; 22 class UsageEnvironment; 23 24 25 class FreeboxFeederLive : public FreeboxFeeder 26 { 27 public: 28 explicit FreeboxFeederLive(StreamDataListener &listener); 29 30 void Run(void); 31 void Stop(void); 32 33 protected: 34 virtual ~FreeboxFeederLive(); 35 bool InitEnv(void); 36 void FreeEnv(void); 37 38 UsageEnvironment& GetLiveEnv() { return *_live_env; } 39 QMutex& GetLock() { return _lock; } 40 StreamDataListener& GetListener() { return _listener; } 41 42 private: 43 char _abort; 44 bool _running; 45 UsageEnvironment *_live_env; 46 QWaitCondition _cond; ///< Condition used to coordinate threads 47 mutable QMutex _lock; ///< Lock used to coordinate threads 48 StreamDataListener &_listener; 49 50 private: 51 /// avoid default copy operator 52 FreeboxFeederLive& operator=(const FreeboxFeederLive&); 53 /// avoid default copy constructor 54 FreeboxFeederLive(const FreeboxFeederLive&); 55 /// avoid default constructor 56 FreeboxFeederLive(); 57 }; 58 59 #endif//_FREEBOXFEEDERLIVE_H_ -
libs/libmythtv/rtspcomms.h
1 /** -*- Mode: c++ -*-2 * RTSPComms3 * Copyright (c) 2006 by Laurent Arnal, Benjamin Lerman & Mickaël Remars4 * Distributed as part of MythTV under GPL v2 and later.5 */6 7 // C++ headers8 #include <vector>9 using namespace std;10 11 // Qt headers12 #include <qwaitcondition.h>13 #include <qmutex.h>14 15 // MythTV headers16 #include "freeboxchannel.h"17 18 class UsageEnvironment;19 class RTSPClient;20 class MediaSession;21 class RTSPListener;22 23 class RTSPComms24 {25 public:26 RTSPComms();27 virtual ~RTSPComms();28 29 bool Init(void);30 void Deinit(void);31 32 bool Open(const QString &url);33 bool IsOpen(void) const { return _session; }34 void Close(void);35 36 void Run(void);37 void Stop(void);38 39 void AddListener(RTSPListener*);40 void RemoveListener(RTSPListener*);41 42 private:43 44 char _abort;45 bool _running;46 UsageEnvironment *_live_env;47 RTSPClient *_rtsp_client;48 MediaSession *_session;49 vector<RTSPListener*> _listeners;50 QWaitCondition _cond; ///< Condition used to coordinate threads51 mutable QMutex _lock; ///< Lock used to coordinate threads52 };