Ticket #2152: patch-freebox-unified-udp-v15.diff

File patch-freebox-unified-udp-v15.diff, 86.0 KB (added by mikemiron@…, 18 years ago)

new version of patch

  • libs/libmythtv/freeboxsignalmonitor.cpp

     
    22
    33// MythTV headers
    44#include "mpegstreamdata.h"
     5#include "freeboxchannel.h"
     6#include "freeboxfeederwrapper.h"
    57#include "freeboxsignalmonitor.h"
    6 #include "rtspcomms.h"
    78
    89#undef DBG_SM
    910#define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
     
    3435      dtvMonitorRunning(false)
    3536{
    3637    bool isLocked = false;
    37     if (GetChannel()->GetRTSP()->Init())
     38    FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
     39    if (chaninfo.isValid())
    3840    {
    39         FreeboxChannelInfo chaninfo = GetChannel()->GetCurrentChanInfo();
    40         isLocked = (chaninfo.isValid() &&
    41                     GetChannel()->GetRTSP()->Open(chaninfo.m_url));
     41        isLocked = GetChannel()->GetFeeder()->Open(chaninfo.m_url);
    4242    }
    4343
    4444    QMutexLocker locker(&statusLock);
     
    5151 */
    5252FreeboxSignalMonitor::~FreeboxSignalMonitor()
    5353{
    54     GetChannel()->GetRTSP()->RemoveListener(this);
     54    GetChannel()->GetFeeder()->RemoveListener(this);
    5555    Stop();
    5656}
    5757
     
    6363void FreeboxSignalMonitor::deleteLater(void)
    6464{
    6565    disconnect(); // disconnect signals we may be sending...
    66     GetChannel()->GetRTSP()->RemoveListener(this);
     66    GetChannel()->GetFeeder()->RemoveListener(this);
    6767    Stop();
    6868    DTVSignalMonitor::deleteLater();
    6969}
     
    7474void FreeboxSignalMonitor::Stop(void)
    7575{
    7676    DBG_SM("Stop", "begin");
    77     GetChannel()->GetRTSP()->RemoveListener(this);
     77    GetChannel()->GetFeeder()->RemoveListener(this);
    7878    SignalMonitor::Stop();
    7979    if (dtvMonitorRunning)
    8080    {
    81         GetChannel()->GetRTSP()->Stop();
     81        GetChannel()->GetFeeder()->Stop();
    8282        dtvMonitorRunning = false;
    8383        pthread_join(table_monitor_thread, NULL);
    8484    }
     
    101101
    102102    GetStreamData()->AddListeningPID(0);
    103103
    104     GetChannel()->GetRTSP()->AddListener(this);
    105     GetChannel()->GetRTSP()->Run();
    106     GetChannel()->GetRTSP()->RemoveListener(this);
     104    GetChannel()->GetFeeder()->AddListener(this);
     105    GetChannel()->GetFeeder()->Run();
     106    GetChannel()->GetFeeder()->RemoveListener(this);
    107107
    108108    dtvMonitorRunning = false;
    109109    DBG_SM("Run", "end");
    110110}
    111111
    112 void FreeboxSignalMonitor::AddData(
    113     unsigned char *data, unsigned dataSize, struct timeval)
     112void FreeboxSignalMonitor::ProcessTSPacket(const TSPacket &packet)
    114113{
    115     GetStreamData()->ProcessData(data, dataSize);
     114    GetStreamData()->ProcessTSPacket(packet);
    116115}
    117116
    118117/** \fn FreeboxSignalMonitor::UpdateValues(void)
  • 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
     27FEEDERREG_IMPL(FreeboxFeederUdp,"udp://");
     28   
     29
     30FreeboxFeederUdp::FreeboxFeederUdp(StreamDataListener &listener) :
     31    FreeboxFeederLive(listener),
     32    _source(NULL),
     33    _sink(NULL)
     34{
     35    VERBOSE(VB_RECORD, LOC + "ctor -- success");
     36}
     37
     38FreeboxFeederUdp::~FreeboxFeederUdp()
     39{
     40    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
     41    Close();
     42    VERBOSE(VB_RECORD, LOC + "dtor -- end");
     43}
     44
     45bool FreeboxFeederUdp::Open(const QString &url)
     46{
     47    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
     48
     49    QMutexLocker locker(&GetLock());
     50
     51    if (_source)
     52    {
     53        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
     54        return true;
     55    }
     56       
     57    QUrl parse(url);
     58    if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
     59    {
     60        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
     61        return false;
     62    }
     63       
     64    struct in_addr addr;
     65    addr.s_addr = our_inet_addr(parse.host().latin1());
     66
     67    // Begin by setting up our usage environment:
     68    if (!InitEnv())
     69        return false;
     70   
     71    Groupsock *socket = new Groupsock(GetLiveEnv(), addr, parse.port(), 0);
     72    if (!socket)
     73    {
     74        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Socket.");
     75        FreeEnv();
     76        return false;
     77    }
     78    _source = BasicUDPSource::createNew(GetLiveEnv(), socket);
     79    if (!_source)
     80    {
     81        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live UDP Source.");
     82        delete socket;
     83        FreeEnv();
     84        return false;
     85    }
     86
     87    _sink = FreeboxMediaSink::CreateNew(
     88        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
     89    if (!_sink)
     90    {
     91        VERBOSE(VB_IMPORTANT,
     92                QString("Freebox # Failed to create sink: %1")
     93                .arg(GetLiveEnv().getResultMsg()));
     94        Medium::close(_source);
     95        _source = NULL;
     96        delete socket;
     97        FreeEnv();
     98        return false;
     99    }
     100    _sink->startPlaying(*_source, NULL, NULL);
     101       
     102    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     103    return true;
     104}
     105
     106void FreeboxFeederUdp::Close(void)
     107{
     108    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     109    Stop();
     110
     111    QMutexLocker locker(&GetLock());
     112
     113    if (_sink)
     114    {
     115        Medium::close(_sink);
     116        _sink = NULL;
     117    }
     118
     119    if (_source)
     120    {
     121        Groupsock *socket=_source->gs();
     122        Medium::close(_source);
     123        _source=NULL;
     124        delete socket;
     125    }
     126
     127    FreeEnv();
     128
     129    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     130}
  • libs/libmythtv/tspacketsplitter.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 _TSPACKETSPLITTER_H_
     8#define _TSPACKETSPLITTER_H_
     9
     10#include "streamdatalistener.h"
     11
     12class TSPacketListener;
     13
     14
     15class TSPacketSplitter : public StreamDataListener
     16{
     17  public:
     18    explicit TSPacketSplitter(TSPacketListener &listener);
     19    ~TSPacketSplitter();
     20
     21    void Reset(void);
     22   
     23  public: // implements StreamDataListener
     24    void AddData(unsigned char *data, unsigned int dataSize);
     25
     26  private:
     27    TSPacketListener &_listener;
     28    unsigned char    *_buffer;
     29    int               _bufferIndex;
     30
     31  private:
     32    /// avoid default copy operator
     33    TSPacketSplitter& operator=(const TSPacketSplitter&);
     34    /// avoid default copy constructor
     35    TSPacketSplitter(const TSPacketSplitter&);
     36    /// avoid default constructor
     37    TSPacketSplitter();
     38};
     39
     40#endif//_TSPACKETSPLITTER_H_
  • 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
     11class 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/freeboxfeederfile.h

     
     1/** -*- Mode: c++ -*
     2 *  FreeboxFeederFile
     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 FREEBOXFEEDERFILE_H
     8#define FREEBOXFEEDERFILE_H
     9
     10// MythTV headers
     11#include "freeboxfeederlive.h"
     12#include "freeboxfeederwrapper.h"
     13
     14class ByteStreamFileSource;
     15class FreeboxMediaSink;
     16
     17
     18class FreeboxFeederFile : public FreeboxFeederLive
     19{
     20  public:
     21    FreeboxFeederFile(StreamDataListener &listener);
     22    virtual ~FreeboxFeederFile();
     23
     24    bool Open(const QString &url);
     25    bool IsOpen(void) const { return _source; }
     26    void Close(void);
     27
     28  private:
     29    ByteStreamFileSource    *_source;
     30    FreeboxMediaSink        *_sink;
     31
     32  private:
     33    /// avoid default copy operator
     34    FreeboxFeederFile& operator=(const FreeboxFeederFile&);
     35    /// avoid default copy constructor
     36    FreeboxFeederFile(const FreeboxFeederFile&);
     37    /// avoid default constructor
     38    FreeboxFeederFile();
     39   
     40  FEEDERREG_DECL
     41};
     42
     43#endif//FREEBOXFEEDERFILE_H
  • libs/libmythtv/freeboxchannel.h

     
    1212
    1313#include <qmutex.h>
    1414
    15 class RTSPComms;
     15class FreeboxFeederWrapper;
    1616
    1717class FreeboxChannel : public ChannelBase
    1818{
     
    3232    FreeboxChannelInfo GetCurrentChanInfo(void) const
    3333        { return GetChanInfo(curchannelname); }
    3434
    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; }
    3737   
    3838  private:
    3939    FreeboxChannelInfo GetChanInfo(const QString& channum,
     
    4141
    4242    QString               m_videodev;
    4343    fbox_chan_map_t       m_freeboxchannels;
    44     RTSPComms            *m_rtsp;
     44    FreeboxFeederWrapper *m_feeder;
    4545    mutable QMutex        m_lock;
    4646
    4747  private:
  • libs/libmythtv/freeboxchannelfetcher.h

     
    77// Qt headers
    88#include <qobject.h>
    99#include <qmutex.h>
     10#include <qurloperator.h>
    1011
    1112// MythTV headers
    1213#include "freeboxchannelinfo.h"
    1314
     15class 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
    1435class FreeboxChannelFetcher : public QObject
    1536{
    1637    Q_OBJECT
  • libs/libmythtv/libmythtv.pro

     
    396396    using_freebox {
    397397        HEADERS += freeboxrecorder.h           freeboxmediasink.h
    398398        HEADERS += freeboxchannel.h            freeboxchannelfetcher.h
    399         HEADERS += freeboxsignalmonitor.h      rtspcomms.h
    400         HEADERS += freeboxchannelinfo.h
     399        HEADERS += freeboxsignalmonitor.h      freeboxchannelinfo.h
     400        HEADERS += freeboxfeeder.h             freeboxfeederlive.h
     401        HEADERS += freeboxfeederrtsp.h         freeboxfeederudp.h
     402        HEADERS += freeboxfeederfile.h         freeboxfeederwrapper.h
     403        HEADERS += streamdatalistener.h        timeoutedtaskscheduler.h
     404        HEADERS += tspacketlistener.h          tspacketsplitter.h
     405        HEADERS += freeboxfeederrtp.h
    401406
    402407        SOURCES += freeboxrecorder.cpp         freeboxmediasink.cpp
    403408        SOURCES += freeboxchannel.cpp          freeboxchannelfetcher.cpp
    404         SOURCES += freeboxsignalmonitor.cpp    rtspcomms.cpp
     409        SOURCES += freeboxsignalmonitor.cpp    freeboxfeederwrapper.cpp
     410        SOURCES += freeboxfeederlive.cpp       freeboxfeederrtsp.cpp
     411        SOURCES += freeboxfeederudp.cpp        freeboxfeederfile.cpp
     412        SOURCES += timeoutedtaskscheduler.cpp  tspacketsplitter.cpp
     413        SOURCES += freeboxfeederrtp.cpp
    405414
    406415        DEFINES += USING_FREEBOX
    407416    }
  • libs/libmythtv/freeboxchannel.cpp

     
    1111#include "libmyth/mythcontext.h"
    1212#include "libmyth/mythdbcon.h"
    1313#include "libmythtv/freeboxchannelfetcher.h"
    14 #include "libmythtv/rtspcomms.h"
     14#include "libmythtv/freeboxfeederwrapper.h"
    1515
    1616#define LOC QString("FBChan(%1): ").arg(GetCardID())
    1717#define LOC_ERR QString("FBChan(%1), Error: ").arg(GetCardID())
     
    2020                               const QString &videodev)
    2121    : ChannelBase(parent),
    2222      m_videodev(QDeepCopy<QString>(videodev)),
    23       m_rtsp(new RTSPComms()),
     23      m_feeder(new FreeboxFeederWrapper()),
    2424      m_lock(true)
    2525{
    2626    VERBOSE(VB_CHANNEL, LOC + "ctor");
     
    2929FreeboxChannel::~FreeboxChannel()
    3030{
    3131    VERBOSE(VB_CHANNEL, LOC + "dtor -- begin");
    32     if (m_rtsp)
     32    if (m_feeder)
    3333    {
    34         delete m_rtsp;
    35         m_rtsp = NULL;
     34        delete m_feeder;
     35        m_feeder = NULL;
    3636    }
    3737    VERBOSE(VB_CHANNEL, LOC + "dtor -- end");
    3838}
     
    193193        }
    194194
    195195        // 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());
    197197        for (it = m_freeboxchannels.begin();
    198198             it != m_freeboxchannels.end(); ++it)
    199199        {
  • 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
     19FreeboxFeederLive::FreeboxFeederLive(StreamDataListener &listener) :
     20    _abort(0),
     21    _running(false),
     22    _live_env(NULL),
     23    _lock(false),
     24    _listener(listener)
     25{
     26}
     27
     28FreeboxFeederLive::~FreeboxFeederLive()
     29{
     30}
     31
     32bool 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
     53void 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
     64void 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
     84void 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

     
    44 *  Distributed as part of MythTV under GPL v2 and later.
    55 */
    66
    7 #include <algorithm>
    8 using namespace std;
    9 
    10 #include "mythcontext.h"
    117#include "freeboxmediasink.h"
    12 #include "rtspcomms.h"
     8#include "mythcontext.h"
     9#include "streamdatalistener.h"
    1310
    14 #define LOC QString("RTSPSink:")
    15 #define LOC_ERR QString("RTSPSink, Error:")
     11#define LOC QString("FbxSink:")
     12#define LOC_ERR QString("FbxSink, Error:")
    1613
    17 FreeboxMediaSink::FreeboxMediaSink(UsageEnvironment &pEnv,
    18                                    unsigned int      bufferSize) :
    19     MediaSink(pEnv),    fBufferSize(bufferSize),
    20     env(pEnv),          lock(true)
     14FreeboxMediaSink::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)
    2122{
    2223    fBuffer = new unsigned char[fBufferSize];
    2324}
     
    3132    }
    3233}
    3334
    34 FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment &env,
    35                                               unsigned int      bufferSize)
     35FreeboxMediaSink *FreeboxMediaSink::CreateNew(UsageEnvironment   &env,
     36                                              StreamDataListener &listener,
     37                                              unsigned int        bufferSize)
    3638{
    37     return new FreeboxMediaSink(env, bufferSize);
     39    return new FreeboxMediaSink(env, listener, bufferSize);
    3840}
    3941
    4042Boolean FreeboxMediaSink::continuePlaying(void)
     
    6163}
    6264
    6365void FreeboxMediaSink::afterGettingFrame1(unsigned int   frameSize,
    64                                           struct timeval presentationTime)
     66                                          struct timeval)
    6567{
    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);
    7269    continuePlaying();
    7370}
    7471
    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 
    10172/* vim: set expandtab tabstop=4 shiftwidth=4: */
  • libs/libmythtv/freeboxsignalmonitor.h

     
    44#define _FREEBOXSIGNALMONITOR_H_
    55
    66#include "dtvsignalmonitor.h"
    7 #include "freeboxmediasink.h"
     7#include "tspacketlistener.h"
    88
    9 class RTSPComms;
    109class FreeboxChannel;
    1110
    12 class FreeboxSignalMonitor : public DTVSignalMonitor, public RTSPListener
     11
     12class FreeboxSignalMonitor : public DTVSignalMonitor, public TSPacketListener
    1313{
    1414    Q_OBJECT
    1515
     
    2121
    2222    void Stop(void);
    2323
    24     // implements RTSPListener
    25     void AddData(unsigned char *data,
    26                  unsigned       dataSize,
    27                  struct timeval);
     24    // implements TSPacketListener
     25    void ProcessTSPacket(const TSPacket &packet);
    2826
    2927  public slots:
    3028    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 <qstring.h>
     8#include <vector>
     9
     10#include "freeboxfeederwrapper.h"
     11
     12#include "freeboxfeeder.h"
     13#include "mythcontext.h"
     14
     15#define LOC QString("FBFeed: ")
     16#define LOC_ERR QString("FBFeed, Error: ")
     17
     18// Registration of feeders
     19class FreeboxRegistratorSinglton
     20{
     21  public:
     22    static FreeboxRegistratorSinglton &getInstance(void);
     23
     24    void Register(FreeboxFeederWrapper::CanHandleFn,
     25                  FreeboxFeederWrapper::FeederConstructorFn);
     26    FreeboxFeeder *CreateNew(const QString &url, StreamDataListener &listener);
     27    bool HaveHandler(const QString &url);
     28
     29  private:
     30    // default construct is private to force use of getInstance()
     31    FreeboxRegistratorSinglton() {}
     32    FreeboxFeederWrapper::FeederConstructorFn GetConstructor(const QString &);
     33
     34  private:
     35    typedef std::pair<FreeboxFeederWrapper::CanHandleFn,
     36            FreeboxFeederWrapper::FeederConstructorFn> FuncPair;
     37    std::vector<FuncPair> _regdata;
     38
     39  private:
     40    // avoid default copy operator
     41    FreeboxRegistratorSinglton &operator=(const FreeboxRegistratorSinglton&);
     42    // avoid default copy constructor
     43    FreeboxRegistratorSinglton(const FreeboxRegistratorSinglton&);
     44};
     45
     46FreeboxRegistratorSinglton &FreeboxRegistratorSinglton::getInstance()
     47{
     48    static FreeboxRegistratorSinglton instance = FreeboxRegistratorSinglton();
     49    return instance;
     50}
     51
     52void FreeboxRegistratorSinglton::Register(
     53        FreeboxFeederWrapper::CanHandleFn f1,
     54        FreeboxFeederWrapper::FeederConstructorFn f2)
     55{
     56    _regdata.push_back(FuncPair(f1,f2));
     57}
     58
     59FreeboxFeederWrapper::FeederConstructorFn
     60    FreeboxRegistratorSinglton::GetConstructor(const QString &url)
     61{
     62    std::vector<FuncPair>::const_iterator it = _regdata.begin();
     63    std::vector<FuncPair>::const_iterator end = _regdata.end();
     64    for( ; it!=end ; ++it )
     65        if (it->first(url))
     66            return it->second;
     67    return NULL;
     68}
     69
     70FreeboxFeeder *FreeboxRegistratorSinglton::CreateNew(
     71        const QString      &url,
     72        StreamDataListener &listener)
     73{
     74    FreeboxFeederWrapper::FeederConstructorFn func = GetConstructor(url);
     75    return func ? func(listener) : NULL;
     76}
     77
     78bool FreeboxRegistratorSinglton::HaveHandler(const QString &url)
     79{
     80    return GetConstructor(url);
     81}
     82
     83
     84
     85void FreeboxFeederWrapper::RegisterHandler(
     86        CanHandleFn         f1,
     87        FeederConstructorFn f2)
     88{
     89    FreeboxRegistratorSinglton::getInstance().Register(f1,f2);
     90}
     91
     92bool FreeboxFeederWrapper::HaveHandler(const QString &url)
     93{
     94    return FreeboxRegistratorSinglton::getInstance().HaveHandler(url);
     95}
     96
     97FreeboxFeederWrapper::FreeboxFeederWrapper() :
     98    _splitter(*this),
     99    _feeder(NULL)
     100{
     101}
     102
     103FreeboxFeederWrapper::~FreeboxFeederWrapper()
     104{
     105    if (_feeder)
     106    {
     107        _feeder->Stop();
     108        _feeder->Close();
     109        delete _feeder;
     110    }
     111}
     112
     113FreeboxFeeder* FreeboxFeederWrapper::NewFeeder(const QString      &url,
     114                                               StreamDataListener &listener)
     115{
     116    FreeboxFeeder *result = FreeboxRegistratorSinglton::getInstance()
     117        .CreateNew(url,listener);
     118    if (!result)
     119    {
     120        VERBOSE(VB_RECORD, LOC_ERR +
     121            QString("NewFeeder() -- unhandled url (%1)").arg(url));
     122    }
     123    return result;
     124}
     125
     126bool FreeboxFeederWrapper::InitFeeder(const QString &url)
     127{
     128    VERBOSE(VB_RECORD, LOC + "Init() -- begin");
     129    QMutexLocker locker(&_lock);
     130    if (_feeder && _feeder->CanHandle(url))
     131    {
     132        VERBOSE(VB_RECORD, LOC + "Init() -- end 0");
     133        return true;
     134    }
     135
     136    delete _feeder;
     137    _feeder = NewFeeder(url, _splitter);
     138
     139    VERBOSE(VB_RECORD, LOC + "Init() -- end 1");
     140    return _feeder != NULL;
     141}
     142
     143bool FreeboxFeederWrapper::Open(const QString& url)
     144{
     145    VERBOSE(VB_RECORD, LOC + "Open() -- begin");
     146    _splitter.Reset();
     147    bool result = InitFeeder(url) && _feeder->Open(url);
     148    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     149    return result;
     150}
     151
     152bool FreeboxFeederWrapper::IsOpen(void) const
     153{
     154    VERBOSE(VB_RECORD, LOC + "IsOpen() -- begin");
     155    bool result = _feeder && _feeder->IsOpen();
     156    VERBOSE(VB_RECORD, LOC + "IsOpen() -- end");
     157    return result;
     158}
     159
     160void FreeboxFeederWrapper::Close(void)
     161{
     162    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     163    _splitter.Reset();
     164    if (_feeder) _feeder->Close();
     165    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     166}
     167
     168void FreeboxFeederWrapper::Run(void)
     169{
     170    VERBOSE(VB_RECORD, LOC + "Run() -- begin");
     171    _splitter.Reset();
     172    if (_feeder) _feeder->Run();
     173    VERBOSE(VB_RECORD, LOC + "Run() -- end");
     174}
     175
     176void FreeboxFeederWrapper::Stop(void)
     177{
     178    VERBOSE(VB_RECORD, LOC + "Stop() -- begin");
     179    _splitter.Reset();
     180    if (_feeder) _feeder->Stop();
     181    VERBOSE(VB_RECORD, LOC + "Stop() -- end");
     182}
     183
     184void FreeboxFeederWrapper::AddListener(TSPacketListener *item)
     185{
     186    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- begin");
     187    if (!item)
     188    {
     189        VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 0");
     190        return;
     191    }
     192
     193    QMutexLocker locker(&_lock);
     194    std::vector<TSPacketListener*>::iterator it =
     195        find(_listeners.begin(), _listeners.end(), item);
     196    if (it == _listeners.end()) // avoid duplicates
     197        _listeners.push_back(item);
     198
     199    VERBOSE(VB_RECORD, LOC + "AddListener("<<item<<") -- end 1");
     200}
     201
     202void FreeboxFeederWrapper::RemoveListener(TSPacketListener *item)
     203{
     204    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- begin");
     205    QMutexLocker locker(&_lock);
     206    std::vector<TSPacketListener*>::iterator it =
     207        find(_listeners.begin(), _listeners.end(), item);
     208
     209    if (it == _listeners.end())
     210    {
     211        VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (not found)");
     212        return;
     213    }
     214
     215    // remove from local list..
     216    *it = *_listeners.rbegin();
     217    _listeners.resize(_listeners.size() - 1);
     218    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<item<<") -- end (ok, removed)");
     219}
     220
     221void FreeboxFeederWrapper::ProcessTSPacket(const TSPacket &packet)
     222{
     223    QMutexLocker locker(&_lock);
     224    std::vector<TSPacketListener*>::iterator it = _listeners.begin();
     225    std::vector<TSPacketListener*>::iterator end = _listeners.end();
     226    for( ; it!=end ; ++it )
     227        (*it)->ProcessTSPacket(packet);
     228}
  • libs/libmythtv/freeboxchannelfetcher.cpp

     
    44#include <cmath>
    55#include <unistd.h>
    66
     7// Qt headers
     8#include <qnetwork.h>
     9#include <qapplication.h>
     10
    711// MythTV headers
    812#include "mythcontext.h"
    913#include "httpcomms.h"
    1014#include "cardutil.h"
    1115#include "channelutil.h"
    1216#include "freeboxchannelfetcher.h"
     17#include "freeboxfeederwrapper.h"
    1318
    1419#define LOC QString("FBChanFetch: ")
    1520#define LOC_ERR QString("FBChanFetch, Error: ")
     
    2126static bool parse_extinf(const QString &data,
    2227                         QString &channum, QString &name);
    2328
     29FreeboxUrlFetch::FreeboxUrlFetch(const QString& url)
     30    :   op(new QUrlOperator(url)),
     31    state(QNetworkProtocol::StInProgress),
     32    str("")
     33{
     34    connect(op,   SIGNAL( finished(QNetworkOperation *)),
     35            this, SLOT(   finished(QNetworkOperation *)));
     36    connect(op,   SIGNAL( data(const QByteArray &,QNetworkOperation *)),
     37            this, SLOT(   data(const QByteArray &,QNetworkOperation *)));
     38    op->get();
     39}
     40
     41FreeboxUrlFetch::~FreeboxUrlFetch()
     42{
     43    disconnect();
     44    delete op;
     45    op=NULL;
     46}
     47
     48void FreeboxUrlFetch::finished(QNetworkOperation *op)
     49{
     50    state = op->state();
     51}
     52
     53void FreeboxUrlFetch::data(const QByteArray &data,QNetworkOperation *op)
     54{
     55    if (!data.isNull())
     56        str += QString::fromUtf8(data.data(),data.size());
     57    state = op->state();
     58}
     59
     60QString FreeboxUrlFetch::fetchData(const QString &url,bool inQtThread)
     61{
     62    FreeboxUrlFetch obj(url);
     63    while(obj.state==QNetworkProtocol::StWaiting ||
     64            obj.state==QNetworkProtocol::StInProgress)
     65    {
     66        if (inQtThread)
     67            qApp->processEvents();
     68        usleep(1000);
     69    }
     70    if (obj.state==QNetworkProtocol::StDone)
     71        return obj.str;
     72    else // QNetworkProtocol::StFailed || QNetworkProtocol::StStopped
     73        return QString::null;
     74}
     75
     76
    2477FreeboxChannelFetcher::FreeboxChannelFetcher(unsigned _sourceid,
    2578                                             unsigned _cardid) :
    2679    sourceid(_sourceid),    cardid(_cardid),
     
    177230QString FreeboxChannelFetcher::DownloadPlaylist(const QString &url,
    178231                                                bool inQtThread)
    179232{
    180     QString redirected_url = url;
     233    if (url.startsWith("http:")) {
     234        // Use Myth HttpComms for http URLs
     235        QString redirected_url = url;
    181236
    182     QString tmp = HttpComms::getHttp(
    183         redirected_url,
    184         10000 /* ms        */, 3     /* retries      */,
    185         3     /* redirects */, true  /* allow gzip   */,
    186         NULL  /* login     */, inQtThread);
     237        QString tmp = HttpComms::getHttp(
     238            redirected_url,
     239            10000 /* ms        */, 3     /* retries      */,
     240            3     /* redirects */, true  /* allow gzip   */,
     241            NULL  /* login     */, inQtThread);
    187242
    188     if (redirected_url != url)
    189     {
    190         VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
    191                 .arg(redirected_url));
    192     }
     243        if (redirected_url != url)
     244        {
     245            VERBOSE(VB_CHANNEL, QString("Channel URL redirected to %1")
     246                    .arg(redirected_url));
     247        }
    193248
    194     return QString::fromUtf8(tmp);
     249        return QString::fromUtf8(tmp);
     250    } else
     251        return FreeboxUrlFetch::fetchData(url,inQtThread);
    195252}
    196253
    197254static uint estimate_number_of_channels(const QString &rawdata)
     
    251308        QString msg = tr("Encountered malformed channel");
    252309        if (!channum.isEmpty())
    253310        {
    254             chanmap[channum] = info;
    255 
    256             msg = tr("Parsing Channel #%1 : %2 : %3")
    257                 .arg(channum).arg(info.m_name).arg(info.m_url);
    258             VERBOSE(VB_CHANNEL, msg);
    259 
    260             msg = QString::null; // don't tell fetcher
     311            if (FreeboxFeederWrapper::HaveHandler(info.m_url))
     312            {
     313                chanmap[channum] = info;
     314   
     315                msg = tr("Parsing Channel #%1 : %2 : %3")
     316                    .arg(channum).arg(info.m_name).arg(info.m_url);
     317                VERBOSE(VB_CHANNEL, msg);
     318   
     319                msg = QString::null; // don't tell fetcher
     320            }
     321            else
     322            {
     323                msg = tr("Unhandled url %1").arg(info.m_url);
     324                VERBOSE(VB_CHANNEL, msg);
     325            }
    261326        }
    262327
    263328        if (fetcher)
  • libs/libmythtv/tspacketsplitter.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 <cassert>
     8
     9#include "tspacketsplitter.h"
     10
     11#include "mythcontext.h"
     12#include "tspacket.h"
     13#include "tspacketlistener.h"
     14
     15#define LOC_ERR QString("TSSplit, Error: ")
     16#define LOC_WARN QString("TSSplit, Warning: ")
     17
     18
     19TSPacketSplitter::TSPacketSplitter(TSPacketListener &listener) :
     20    _listener(listener),
     21    _buffer(new unsigned char[TSPacket::SIZE]),
     22    _bufferIndex(0)
     23{
     24}
     25
     26TSPacketSplitter::~TSPacketSplitter()
     27{
     28    delete[] _buffer;
     29}
     30
     31void TSPacketSplitter::Reset(void)
     32{
     33    _bufferIndex = 0;
     34}
     35
     36// ===================================================
     37// findTSHeader : find a TS Header in flow
     38// ===================================================
     39static int TSPacketSplitter_findTSHeader(const unsigned char *data,
     40                                             uint dataSize)
     41{
     42    //TODO improve this with code from MPEGStreamData::ResyncStream()
     43    for(unsigned pos = 0; pos < dataSize; ++pos)
     44        if (data[pos] == 0x47)
     45            return pos;
     46
     47    return -1;
     48}
     49
     50// ===================================================
     51// AddData : feed data from flow to listeners
     52// ===================================================
     53void TSPacketSplitter::AddData(unsigned char *data,
     54                               unsigned       dataSize)
     55{
     56    if (_bufferIndex)
     57    {
     58        // Have old data in buffer
     59        unsigned reminder = TSPacket::SIZE - _bufferIndex;
     60        memcpy(_buffer + _bufferIndex, data, min(reminder, dataSize));
     61        if (dataSize < reminder)
     62        {
     63            _bufferIndex += dataSize;
     64            return;
     65        }
     66        else
     67        {
     68            // We got full packet
     69            data += reminder;
     70            dataSize -= reminder;
     71            // Cast current found TS Packet to TSPacket structure
     72            const TSPacket &packet = *reinterpret_cast<const TSPacket*>(_buffer);
     73            _listener.ProcessTSPacket(packet);
     74        }
     75    }
     76
     77    unsigned int readIndex = 0;
     78   
     79    // data may be compose from more than one packet, loop to consume all data
     80    while (readIndex < dataSize)
     81    {
     82        // Find the next TS Header in data
     83        int tsPos = TSPacketSplitter_findTSHeader(
     84                        data + readIndex, dataSize - readIndex);
     85
     86        // if no TS, something bad happens
     87        if (-1 == tsPos)
     88        {
     89            readIndex = dataSize;
     90            VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
     91            break;
     92        }
     93
     94        // if TS Header not at start of data, we receive out of sync data
     95        if (tsPos > 0)
     96        {
     97            VERBOSE(VB_IMPORTANT, LOC_ERR +
     98                    QString("TS packet at %1, not in sync.").arg(tsPos));
     99        }
     100
     101        // Check if the next packet in buffer is complete :
     102        // packet size is 188 bytes long
     103        if ((dataSize - tsPos - readIndex) < TSPacket::SIZE)
     104        {
     105            readIndex += tsPos;
     106            VERBOSE(VB_IMPORTANT, LOC_ERR +
     107                    "TS packet at stradles end of buffer.");
     108            break;
     109        }
     110
     111        // Cast current found TS Packet to TSPacket structure
     112        const void *p = data + tsPos + readIndex;
     113        const TSPacket &packet = *reinterpret_cast<const TSPacket*>(p);
     114        _listener.ProcessTSPacket(packet);
     115
     116        // follow to next packet
     117        readIndex += tsPos + TSPacket::SIZE;
     118    }
     119
     120    // write in buffer synced data
     121    if (readIndex < dataSize)
     122    {
     123        assert(dataSize - readIndex < TSPacket::SIZE);
     124        memcpy(_buffer, data + readIndex, dataSize - readIndex);
     125        _bufferIndex = dataSize - readIndex;
     126    }
     127    else
     128        _bufferIndex = 0;
     129}
  • 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 "freeboxfeederwrapper.h"
     12#include "freeboxfeederlive.h"
     13
     14class RTSPClient;
     15class MediaSession;
     16
     17
     18class FreeboxFeederRtsp : public FreeboxFeederLive
     19{
     20  public:
     21    FreeboxFeederRtsp(StreamDataListener &listener);
     22    virtual ~FreeboxFeederRtsp();
     23
     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  FEEDERREG_DECL
     41};
     42
     43#endif//FREEBOXFEEDERRTSP_H
  • libs/libmythtv/freeboxfeederfile.cpp

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxFeederFile
     3 *
     4 *  Please, don't submit bug reports if it
     5 *  can't read your file. Just use MythVideo!
     6 *
     7 *  Copyright (c) 2006 by Mike Mironov & Mickaël Remars
     8 *  Distributed as part of MythTV under GPL v2 and later.
     9 */
     10
     11#include "freeboxfeederfile.h"
     12
     13// Qt headers
     14#include <qurl.h>
     15
     16// Live555 headers
     17#include <BasicUsageEnvironment.hh>
     18#include <Groupsock.hh>
     19#include <GroupsockHelper.hh>
     20#include <ByteStreamFileSource.hh>
     21#include <TunnelEncaps.hh>
     22
     23// MythTV headers
     24#include "freeboxmediasink.h"
     25#include "mythcontext.h"
     26#include "tspacket.h"
     27
     28#define LOC QString("FbFeedFile:")
     29
     30
     31FEEDERREG_IMPL(FreeboxFeederFile,"file:");
     32
     33
     34FreeboxFeederFile::FreeboxFeederFile(StreamDataListener &listener) :
     35    FreeboxFeederLive(listener),
     36    _source(NULL),
     37    _sink(NULL)
     38{
     39}
     40
     41FreeboxFeederFile::~FreeboxFeederFile()
     42{
     43    Close();
     44}
     45
     46bool FreeboxFeederFile::Open(const QString &url)
     47{
     48    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
     49
     50    QMutexLocker locker(&GetLock());
     51
     52    if (_source)
     53    {
     54        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
     55        return true;
     56    }
     57       
     58    QUrl parse(url);
     59    if (!parse.hasPath() || !parse.isLocalFile())
     60    {
     61        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
     62        return false;
     63    }
     64       
     65    // Begin by setting up our usage environment:
     66    if (!InitEnv())
     67        return false;
     68   
     69    _source = ByteStreamFileSource::createNew(GetLiveEnv(), parse.path().local8Bit());
     70    if (!_source)
     71    {
     72        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live File Source.");
     73        FreeEnv();
     74        return false;
     75    }
     76
     77    _sink = FreeboxMediaSink::CreateNew(
     78        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
     79    if (!_sink)
     80    {
     81        VERBOSE(VB_IMPORTANT,
     82                QString("Freebox # Failed to create sink: %1")
     83                .arg(GetLiveEnv().getResultMsg()));
     84        Medium::close(_source);
     85        _source = NULL;
     86        FreeEnv();
     87        return false;
     88    }
     89    _sink->startPlaying(*_source, NULL, NULL);
     90       
     91    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     92    return true;
     93}
     94
     95void FreeboxFeederFile::Close(void)
     96{
     97    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     98    Stop();
     99
     100    QMutexLocker locker(&GetLock());
     101
     102    if (_sink)
     103    {
     104        Medium::close(_sink);
     105        _sink = NULL;
     106    }
     107
     108    if (_source)
     109    {
     110        Medium::close(_source);
     111        _source=NULL;
     112    }
     113
     114    FreeEnv();
     115
     116    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     117}
  • libs/libmythtv/freeboxrecorder.cpp

     
    88#include "mpegstreamdata.h"
    99#include "tspacket.h"
    1010#include "freeboxchannel.h"
     11#include "freeboxfeederwrapper.h"
    1112#include "freeboxrecorder.h"
    12 #include "rtspcomms.h"
    1313
    1414#define LOC QString("FBRec: ")
    1515#define LOC_ERR QString("FBRec, Error: ")
     
    2323    _channel(channel),
    2424    _stream_data(NULL)
    2525{
    26     _channel->GetRTSP()->AddListener(this);
     26    _channel->GetFeeder()->AddListener(this);
    2727}
    2828
    2929FreeboxRecorder::~FreeboxRecorder()
    3030{
    3131    StopRecording();
    32     _channel->GetRTSP()->RemoveListener(this);
     32    _channel->GetFeeder()->RemoveListener(this);
    3333}
    3434
    3535bool FreeboxRecorder::Open(void)
    3636{
    3737    VERBOSE(VB_RECORD, LOC + "Open() -- begin");
    3838
    39     if (_channel->GetRTSP()->IsOpen())
    40         _channel->GetRTSP()->Close();
     39    if (_channel->GetFeeder()->IsOpen())
     40        _channel->GetFeeder()->Close();
    4141
    4242    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);
    5345
    5446    VERBOSE(VB_RECORD, LOC + "Open() -- end err("<<_error<<")");
    5547    return !_error;
     
    5850void FreeboxRecorder::Close(void)
    5951{
    6052    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
    61     _channel->GetRTSP()->Stop();
    62     _channel->GetRTSP()->Close();
     53    _channel->GetFeeder()->Stop();
     54    _channel->GetFeeder()->Close();
    6355    VERBOSE(VB_RECORD, LOC + "Close() -- end");
    6456}
    6557
     
    6759{
    6860    VERBOSE(VB_RECORD, LOC + "Pause() -- begin");
    6961    DTVRecorder::Pause(clear);
    70     _channel->GetRTSP()->Stop();
    71     _channel->GetRTSP()->Close();
     62    _channel->GetFeeder()->Stop();
     63    _channel->GetFeeder()->Close();
    7264    VERBOSE(VB_RECORD, LOC + "Pause() -- end");
    7365}
    7466
    7567void FreeboxRecorder::Unpause(void)
    7668{
    7769    VERBOSE(VB_RECORD, LOC + "Unpause() -- begin");
    78     if (_recording && !_channel->GetRTSP()->IsOpen())
     70    if (_recording && !_channel->GetFeeder()->IsOpen())
    7971        Open();
     72    if (_stream_data)
     73        _stream_data->Reset(_stream_data->DesiredProgram());
    8074    DTVRecorder::Unpause();
    8175    VERBOSE(VB_RECORD, LOC + "Unpause() -- end");
    8276}
     
    9993        if (PauseAndWait())
    10094            continue;
    10195
    102         if (!_channel->GetRTSP()->IsOpen())
     96        if (!_channel->GetFeeder()->IsOpen())
    10397        {
    10498            usleep(5000);
    10599            continue;
    106100        }
    107101
    108102        // Go into main RTSP loop, feeding data to AddData
    109         _channel->GetRTSP()->Run();
     103        _channel->GetFeeder()->Run();
    110104    }
    111105
    112106    // Finish up...
     
    122116{
    123117    VERBOSE(VB_RECORD, LOC + "StopRecording() -- begin");
    124118    Pause();
    125     _channel->GetRTSP()->Close();
     119    _channel->GetFeeder()->Close();
    126120
    127121    _request_recording = false;
    128122    while (_recording)
     
    131125    VERBOSE(VB_RECORD, LOC + "StopRecording() -- end");
    132126}
    133127
    134 // ===================================================
    135 // findTSHeader : find a TS Header in flow
    136 // ===================================================
    137 static int FreeboxRecorder_findTSHeader(const unsigned char *data,
    138                                         uint dataSize)
    139 {
    140     unsigned int pos = 0;
    141 
    142     while (pos < dataSize)
    143     {
    144         if (data[pos] == 0x47)
    145             return pos;
    146         pos++;
    147     }
    148 
    149     return -1;
    150 }
    151 
    152 // ===================================================
    153 // AddData : feed data from RTSP flow to mythtv
    154 // ===================================================
    155 void FreeboxRecorder::AddData(unsigned char *data,
    156                               unsigned       dataSize,
    157                               struct timeval)
    158 {
    159     unsigned int readIndex = 0;
    160 
    161     // data may be compose from more than one packet, loop to consume all data
    162     while (readIndex < dataSize)
    163     {
    164         // If recorder is paused, stop there
    165         if (IsPaused())
    166             return;
    167 
    168         // Find the next TS Header in data
    169         int tsPos = FreeboxRecorder_findTSHeader(data + readIndex, dataSize);
    170 
    171         // if no TS, something bad happens
    172         if (tsPos == -1)
    173         {
    174             VERBOSE(VB_IMPORTANT, LOC_ERR + "No TS header.");
    175             break;
    176         }
    177 
    178         // if TS Header not at start of data, we receive out of sync data
    179         if (tsPos > 0)
    180         {
    181             VERBOSE(VB_IMPORTANT, LOC_ERR +
    182                     QString("TS packet at %1, not in sync.").arg(tsPos));
    183         }
    184 
    185         // Check if the next packet in buffer is complete :
    186         // packet size is 188 bytes long
    187         if ((dataSize - tsPos) < TSPacket::SIZE)
    188         {
    189             VERBOSE(VB_IMPORTANT, LOC_ERR +
    190                     "TS packet at stradles end of buffer.");
    191             break;
    192         }
    193 
    194         // Cast current found TS Packet to TSPacket structure
    195         const void *newData = data + tsPos + readIndex;
    196         ProcessTSPacket(*reinterpret_cast<const TSPacket*>(newData));
    197 
    198         // follow to next packet
    199         readIndex += tsPos + TSPacket::SIZE;
    200     }
    201 }
    202 
    203128void FreeboxRecorder::ProcessTSPacket(const TSPacket& tspacket)
    204129{
     130    // If recorder is paused, stop there
     131    if (IsPaused())
     132        return;
     133
    205134    if (!_stream_data)
    206135        return;
    207136
     
    232161
    233162void FreeboxRecorder::SetStreamData(MPEGStreamData *data)
    234163{
    235     VERBOSE(VB_RECORD, LOC + "SetStreamData()");
     164    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
    236165    if (data == _stream_data)
     166    {
     167        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
    237168        return;
     169    }
    238170
    239171    MPEGStreamData *old_data = _stream_data;
    240172    _stream_data = data;
     
    243175
    244176    if (data)
    245177        data->AddMPEGSPListener(this);
     178    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
    246179}
    247180
    248181void FreeboxRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
  • libs/libmythtv/rtspcomms.cpp

     
    1 /** -*- Mode: c++ -*-
    2  *  RTSPComms
    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 "rtspcomms.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("RTSPData:")
    20 #define LOC_ERR QString("RTSPData, Error:")
    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     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 session
    163     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         else
    212         {
    213             madeProgress = true;
    214 
    215             if (subsession->rtpSource() != NULL)
    216             {
    217                 unsigned const thresh = 1000000; // 1 second
    218                 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 set
    234 
    235         if (_rtsp_client->setupMediaSubsession(*subsession, false, false))
    236         {
    237             madeProgress = true;
    238         }
    239         else
    240         {
    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 mythtv
    254     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 initiated
    261 
    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 player
    294     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 session
    317         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 descriptor
    328         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 duplicates
    380     RemoveListener(item);
    381 
    382     // add to local list
    383     QMutexLocker locker(&_lock);
    384     _listeners.push_back(item);
    385 
    386     // if there is a session, add to each subsession->sink
    387     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->sink
    422     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
     10TimeoutedTaskScheduler::TimeoutedTaskScheduler(unsigned maxDelayTimeMS) :
     11    _maxDelayTimeUS(maxDelayTimeMS*1000)
     12{
     13}
     14
     15void 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 "freeboxfeederwrapper.h"
     12#include "freeboxfeederlive.h"
     13
     14class BasicUDPSource;
     15class FreeboxMediaSink;
     16
     17
     18class FreeboxFeederUdp : public FreeboxFeederLive
     19{
     20  public:
     21    FreeboxFeederUdp(StreamDataListener &listener);
     22    virtual ~FreeboxFeederUdp();
     23
     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  FEEDERREG_DECL 
     41};
     42
     43#endif//FREEBOXFEEDERUDP_H
  • libs/libmythtv/tspacketlistener.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 _TSPACKETLISTENER_H_
     8#define _TSPACKETLISTENER_H_
     9
     10class TSPacket;
     11
     12class TSPacketListener
     13{
     14  public:
     15    /// Callback function to process MPEG2 TS packet
     16    virtual void ProcessTSPacket(const TSPacket &packet) = 0;
     17  protected:
     18    virtual ~TSPacketListener() {}
     19};
     20
     21#endif//_TSPACKETLISTENER_H_
  • libs/libmythtv/freeboxmediasink.h

     
    77#ifndef _FREEBOXMEDIASINK_H_
    88#define _FREEBOXMEDIASINK_H_
    99
    10 #include <vector>
    11 using namespace std;
    12 
    1310#include <qmutex.h>
    1411
    1512#include <MediaSink.hh>
    1613
    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 };
     14class StreamDataListener;
    2715
     16
    2817// ============================================================================
    2918// FreeboxMediaSink : Helper class use to receive RTSP data from socket.
    3019// ============================================================================
    3120class FreeboxMediaSink : public MediaSink
    3221{
    3322  public:
    34     static FreeboxMediaSink *CreateNew(UsageEnvironment &env,
    35                                        unsigned          bufferSize);
     23    static FreeboxMediaSink *CreateNew(UsageEnvironment   &env,
     24                                       StreamDataListener &listener,
     25                                       unsigned            bufferSize);
    3626
    37     void AddListener(RTSPListener*);
    38     void RemoveListener(RTSPListener*);
    39 
    4027  protected:
    41     FreeboxMediaSink(UsageEnvironment &env,
    42                      unsigned int      bufferSize);
     28    FreeboxMediaSink(UsageEnvironment   &env,
     29                     StreamDataListener &listener,
     30                     unsigned int        bufferSize);
    4331    virtual ~FreeboxMediaSink();
    4432
    4533    virtual void afterGettingFrame1(unsigned       frameSize,
     
    5846    unsigned char         *fBuffer;
    5947    unsigned int           fBufferSize;
    6048    UsageEnvironment      &env;
    61     vector<RTSPListener*>  listeners;
     49    StreamDataListener    &_listener;
    6250    mutable QMutex         lock;
    6351
    6452  private:
  • libs/libmythtv/freeboxrecorder.h

     
    1010#include <qwaitcondition.h>
    1111
    1212#include "dtvrecorder.h"
    13 #include "freeboxmediasink.h"
     13#include "tspacketlistener.h"
    1414#include "streamlisteners.h"
    1515
    1616class FreeboxChannel;
    1717
    18 /** \brief Processes data from RTSPComms and writes it to disk.
     18/** \brief Processes data from StreamDataListener and writes it to disk.
    1919 */
    20 class FreeboxRecorder : public DTVRecorder, public RTSPListener,
     20class FreeboxRecorder : public DTVRecorder,
     21                        public TSPacketListener,
    2122                        public MPEGSingleProgramStreamListener
    2223{
    2324    friend class FreeboxMediaSink;
    24     friend class RTSPComms;
    2525
    2626  public:
    2727    FreeboxRecorder(TVRec *rec, FreeboxChannel *channel);
     
    4343    virtual MPEGStreamData *GetStreamData(void) { return _stream_data; }
    4444
    4545  private:
     46    // implements TSPacketListener
    4647    void ProcessTSPacket(const TSPacket& tspacket);
    4748
    48     // implements RTSPListener
    49     void AddData(unsigned char *data,
    50                  unsigned int   dataSize,
    51                  struct timeval presentationTime);
    52 
    5349    // implements MPEGSingleProgramStreamListener
    5450    void HandleSingleProgramPAT(ProgramAssociationTable *pat);
    5551    void HandleSingleProgramPMT(ProgramMapTable *pmt);
     
    5955    MPEGStreamData *_stream_data;
    6056    QWaitCondition  _cond_recording;
    6157
    62 
    6358  private:
    6459    FreeboxRecorder& operator=(const FreeboxRecorder&); //< avoid default impl
    6560    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
     14class 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
     10class QString;
     11
     12
     13/** \interface FreeboxFeeder
     14**  \brief This is the interface that need to be implemented to support new
     15**         protocols in the FreeboxRecorder.
     16**
     17**  To add a new implementation, sub-class FreeboxFeederFactory and register
     18**  it using FreeboxFeederFactory::Register()
     19**
     20**  \sa FreeboxFeederFactory
     21**  \sa FreeboxFeederFactory::Register()
     22*/
     23class FreeboxFeeder
     24{
     25  public:
     26    virtual ~FreeboxFeeder() {}
     27
     28    /** \brief Returns true if the feeder can handle url
     29    **  \sa FreeboxFeederFactory::CanHandle(const QString&)
     30    */
     31    virtual bool CanHandle(const QString &url) const = 0;
     32
     33    /// \brief Inits the feeder and opens the stream identified by url
     34    virtual bool Open(const QString &url) = 0;
     35
     36    /// \brief Returns true if the feeder is currently open
     37    virtual bool IsOpen(void) const = 0;
     38
     39    /// \brief Closes the stream and frees resources allocated in Open()
     40    virtual void Close(void) = 0;
     41
     42    /** \brief Reads the stream and sends data to its StreamDataListener. This
     43    **         is a blocking call : it should not exit until Stop() is called.
     44    **  \sa Stop()
     45    */
     46    virtual void Run(void) = 0;
     47
     48    /** \brief Signals to the Run() function that it should stop and exit
     49    **         cleanly.
     50    **
     51    **  This function should block until Run() has finished up.
     52    **  \sa Run()
     53    */
     54    virtual void Stop(void) = 0;
     55};
     56
     57#endif//FREEBOXFEEDER_H
  • 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// ============================================================================
     25class 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
     40void RTSPData::SubsessionAfterPlayingCB(void)
     41{
     42    MediaSubsession *subsession = mediaSubSession;
     43    Medium::close(subsession->sink);
     44    subsession->sink = NULL;
     45}
     46
     47static void sub_after_playing_cb(void *clientData)
     48{
     49    ((RTSPData*)clientData)->SubsessionAfterPlayingCB();
     50}
     51
     52void RTSPData::SubsessionByeHandlerCB(void)
     53{
     54    SubsessionAfterPlayingCB();
     55}
     56
     57static void sub_bye_handler_cb(void *clientData)
     58{
     59    ((RTSPData*)clientData)->SubsessionByeHandlerCB();
     60}
     61
     62
     63FEEDERREG_IMPL(FreeboxFeederRtsp,"rtsp://");
     64
     65
     66FreeboxFeederRtsp::FreeboxFeederRtsp(StreamDataListener &listener) :
     67    FreeboxFeederLive(listener),
     68    _rtsp_client(NULL),
     69    _session(NULL)
     70{
     71    VERBOSE(VB_RECORD, LOC + "ctor -- success");
     72}
     73
     74FreeboxFeederRtsp::~FreeboxFeederRtsp()
     75{
     76    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
     77    Close();
     78    VERBOSE(VB_RECORD, LOC + "dtor -- end");
     79}
     80
     81bool FreeboxFeederRtsp::Open(const QString &url)
     82{
     83    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
     84
     85    QMutexLocker locker(&GetLock());
     86
     87    if (_rtsp_client)
     88    {
     89        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
     90        return true;
     91    }
     92
     93    // Begin by setting up our usage environment:
     94    if (!InitEnv())
     95        return false;
     96
     97    // Create our client object:
     98    _rtsp_client = RTSPClient::createNew(GetLiveEnv(), 0, "myRTSP", 0);
     99    if (!_rtsp_client)
     100    {
     101        VERBOSE(VB_IMPORTANT, LOC_ERR +
     102                QString("Failed to create RTSP client: %1")
     103                .arg(GetLiveEnv().getResultMsg()));
     104        FreeEnv();
     105    }
     106
     107    // Setup URL for the current session
     108    char *sdpDescription = _rtsp_client->describeURL(url);
     109    _rtsp_client->describeStatus();
     110
     111    if (!sdpDescription)
     112    {
     113        VERBOSE(VB_IMPORTANT, LOC + QString(
     114                    "Failed to get a SDP "
     115                    "description from URL: %1 %2")
     116                .arg(url).arg(GetLiveEnv().getResultMsg()));
     117        return false;
     118    }
     119
     120    // Create a media session object from this SDP description:
     121    _session = MediaSession::createNew(GetLiveEnv(), sdpDescription);
     122
     123    delete[] sdpDescription;
     124
     125    if (!_session)
     126    {
     127        VERBOSE(VB_IMPORTANT, LOC +
     128                QString("Failed to create MediaSession: %1")
     129                .arg(GetLiveEnv().getResultMsg()));
     130        return false;
     131    }
     132    else if (!_session->hasSubsessions())
     133    {
     134        VERBOSE(VB_IMPORTANT, LOC +
     135                "This session has no media subsessions");
     136        Close();
     137        return false;
     138    }
     139
     140    // Then, setup the "RTPSource"s for the session:
     141    MediaSubsessionIterator iter(*_session);
     142    MediaSubsession *subsession;
     143    bool madeProgress = false;
     144
     145    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
     146    {
     147        if (!subsession->initiate(-1))
     148        {
     149            VERBOSE(VB_IMPORTANT, LOC +
     150                    QString("Can't create receiver for: "
     151                            "%1 / %2 subsession: %3")
     152                    .arg(subsession->mediumName())
     153                    .arg(subsession->codecName())
     154                    .arg(GetLiveEnv().getResultMsg()));
     155        }
     156        else
     157        {
     158            madeProgress = true;
     159
     160            if (subsession->rtpSource() != NULL)
     161            {
     162                unsigned const thresh = 1000000; // 1 second
     163                subsession->rtpSource()->
     164                    setPacketReorderingThresholdTime(thresh);
     165            }
     166        }
     167    }
     168
     169    if (!madeProgress)
     170        return false;
     171
     172    // Perform additional 'setup' on each subsession, before playing them:
     173    madeProgress = false;
     174    iter.reset();
     175    while ((subsession = iter.next()) != NULL)
     176    {
     177        if (subsession->clientPortNum() == 0)
     178            continue; // port # was not set
     179
     180        if (_rtsp_client->setupMediaSubsession(*subsession, false, false))
     181        {
     182            madeProgress = true;
     183        }
     184        else
     185        {
     186            VERBOSE(VB_IMPORTANT, LOC +
     187                    QString("Failed to setup: %1 %2 : %3")
     188                    .arg(subsession->mediumName())
     189                    .arg(subsession->codecName())
     190                    .arg(GetLiveEnv().getResultMsg()));
     191        }
     192    }
     193
     194    if (!madeProgress)
     195        return false;
     196
     197    // Create and start "FileSink"s for each subsession:
     198    // FileSink while receive Mpeg2 TS Data & will feed them to mythtv
     199    madeProgress = false;
     200    iter.reset();
     201
     202    while ((subsession = iter.next())) /* <- extra braces for pedantic gcc */
     203    {
     204        if (!subsession->readSource())
     205            continue; // was not initiated
     206
     207        FreeboxMediaSink *freeboxMediaSink = FreeboxMediaSink::CreateNew(
     208            GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
     209
     210        subsession->sink = freeboxMediaSink;
     211        if (!subsession->sink)
     212        {
     213            VERBOSE(VB_IMPORTANT,
     214                    QString("Freebox # Failed to create sink: %1")
     215                    .arg(GetLiveEnv().getResultMsg()));
     216        }
     217
     218        subsession->sink->startPlaying(*(subsession->readSource()),
     219                                       sub_after_playing_cb,
     220                                       new RTSPData(subsession));
     221
     222        if (subsession->rtcpInstance())
     223        {
     224            subsession->rtcpInstance()->setByeHandler(
     225                sub_bye_handler_cb, new RTSPData(subsession));
     226        }
     227
     228        madeProgress = true;
     229    }
     230
     231    if (!madeProgress)
     232        return false;
     233
     234    // Setup player
     235    if (!(_rtsp_client->playMediaSession(*_session)))
     236    {
     237        VERBOSE(VB_IMPORTANT, LOC +
     238                QString("Failed to start playing session: %1")
     239                .arg(GetLiveEnv().getResultMsg()));
     240        return false;
     241    }
     242
     243    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     244    return true;
     245}
     246
     247void FreeboxFeederRtsp::Close(void)
     248{
     249    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     250    Stop();
     251
     252    QMutexLocker locker(&GetLock());
     253
     254    if (_session)
     255    {
     256        // Ensure RTSP cleanup, remove old RTSP session
     257        MediaSubsessionIterator iter(*_session);
     258        MediaSubsession *subsession;
     259        while ((subsession = iter.next())) /*<-extra braces for pedantic gcc*/
     260        {
     261            Medium::close(subsession->sink);
     262            subsession->sink = NULL;
     263        }
     264
     265        _rtsp_client->teardownMediaSession(*_session);
     266
     267        // Close all RTSP descriptor
     268        Medium::close(_session);
     269        _session = NULL;
     270    }
     271
     272    if (_rtsp_client)
     273    {
     274        Medium::close(_rtsp_client);
     275        _rtsp_client = NULL;
     276    }
     277
     278    FreeEnv();
     279
     280    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     281}
  • libs/libmythtv/freeboxfeederrtp.h

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxFeederRtp
     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 FREEBOXFEEDERRTP_H
     8#define FREEBOXFEEDERRTP_H
     9
     10// MythTV headers
     11#include "freeboxfeederwrapper.h"
     12#include "freeboxfeederlive.h"
     13
     14class SimpleRTPSource;
     15class FreeboxMediaSink;
     16
     17
     18class FreeboxFeederRtp : public FreeboxFeederLive
     19{
     20  public:
     21    FreeboxFeederRtp(StreamDataListener &listener);
     22    virtual ~FreeboxFeederRtp();
     23
     24    bool Open(const QString &url);
     25    bool IsOpen(void) const { return _source; }
     26    void Close(void);
     27
     28  private:
     29    SimpleRTPSource    *_source;
     30    FreeboxMediaSink   *_sink;
     31
     32  private:
     33    /// avoid default copy operator
     34    FreeboxFeederRtp& operator=(const FreeboxFeederRtp&);
     35    /// avoid default copy constructor
     36    FreeboxFeederRtp(const FreeboxFeederRtp&);
     37    /// avoid default constructor
     38    FreeboxFeederRtp();
     39   
     40  FEEDERREG_DECL 
     41};
     42
     43#endif//FREEBOXFEEDERRTP_H
  • 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 <vector>
     12
     13#include "tspacketlistener.h"
     14#include "tspacketsplitter.h"
     15
     16class FreeboxFeeder;
     17class FreeboxFeederFactory;
     18class QString;
     19class StreamDataListener;
     20
     21
     22// Helper macros for registration of new feeder
     23#define FEEDERREG_DECL                                             \
     24  public:                                                          \
     25    static bool CanHandleStatic(const QString &url);               \
     26    bool CanHandle(const QString &url) const                       \
     27    {                                                              \
     28        return CanHandleStatic(url);                               \
     29    }                                                              \
     30    static FreeboxFeeder *createNew(StreamDataListener &listener);
     31
     32#define FEEDERREG_IMPL(TYPE,PREFIX)                          \
     33class TYPE##Reg                                              \
     34{                                                            \
     35  public:                                                    \
     36    TYPE##Reg()                                              \
     37    {                                                        \
     38        FreeboxFeederWrapper::RegisterHandler(               \
     39            TYPE::CanHandleStatic,                           \
     40            TYPE::createNew);                                \
     41    }                                                        \
     42};                                                           \
     43static TYPE##Reg TYPE##RegInstance=TYPE##Reg();              \
     44bool TYPE::CanHandleStatic(const QString &url)               \
     45{                                                            \
     46    return url.startsWith(PREFIX,false);                     \
     47}                                                            \
     48FreeboxFeeder *TYPE::createNew(StreamDataListener &listener) \
     49{                                                            \
     50    return new TYPE(listener);                               \
     51}
     52
     53   
     54/** \class FreeboxFeederWrapper
     55**  \brief Handles the various implementations of FeederRecorder.
     56*/
     57class FreeboxFeederWrapper : private TSPacketListener
     58{
     59  public:
     60    FreeboxFeederWrapper();
     61    ~FreeboxFeederWrapper();
     62
     63  public:
     64    bool Open(const QString &url);
     65    bool IsOpen(void) const;
     66    void Close(void);
     67
     68    void Run(void);
     69    void Stop(void);
     70
     71    void AddListener(TSPacketListener*);
     72    void RemoveListener(TSPacketListener*);
     73   
     74    // Feeder registration
     75    typedef FreeboxFeeder *(*FeederConstructorFn)(StreamDataListener &listener);
     76    typedef bool (*CanHandleFn)(const QString &url);
     77    static void RegisterHandler(CanHandleFn, FeederConstructorFn);
     78    static bool HaveHandler(const QString &url);
     79   
     80  private:
     81    static FreeboxFeeder* NewFeeder(const QString      &url,
     82                                    StreamDataListener &listener);
     83    bool InitFeeder(const QString &url);
     84
     85  private: // implements TSPacketListener
     86    void ProcessTSPacket(const TSPacket &packet);
     87
     88  private:
     89    TSPacketSplitter _splitter;
     90    FreeboxFeeder   *_feeder;
     91    mutable QMutex   _lock; ///< Lock  used to coordinate threads
     92    std::vector<TSPacketListener*> _listeners;
     93
     94  private:
     95    /// avoid default copy operator
     96    FreeboxFeederWrapper& operator=(const FreeboxFeederWrapper&);
     97    /// avoid default copy constructor
     98    FreeboxFeederWrapper(const FreeboxFeederWrapper&);
     99};
     100
     101#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
     20class QString;
     21class StreamDataListener;
     22class UsageEnvironment;
     23
     24
     25class FreeboxFeederLive : public FreeboxFeeder
     26{
     27  public:
     28    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/freeboxfeederrtp.cpp

     
     1/** -*- Mode: c++ -*-
     2 *  FreeboxFeederRtp
     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 "freeboxfeederrtp.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 <SimpleRTPSource.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("FbFeedRtp(%1):").arg(pthread_self())
     25
     26
     27FEEDERREG_IMPL(FreeboxFeederRtp,"rtp://");
     28   
     29
     30FreeboxFeederRtp::FreeboxFeederRtp(StreamDataListener &listener) :
     31    FreeboxFeederLive(listener),
     32    _source(NULL),
     33    _sink(NULL)
     34{
     35    VERBOSE(VB_RECORD, LOC + "ctor -- success");
     36}
     37
     38FreeboxFeederRtp::~FreeboxFeederRtp()
     39{
     40    VERBOSE(VB_RECORD, LOC + "dtor -- begin");
     41    Close();
     42    VERBOSE(VB_RECORD, LOC + "dtor -- end");
     43}
     44
     45bool FreeboxFeederRtp::Open(const QString &url)
     46{
     47    VERBOSE(VB_RECORD, LOC + "Open(\""<<url<<"\") -- begin");
     48
     49    QMutexLocker locker(&GetLock());
     50
     51    if (_source)
     52    {
     53        VERBOSE(VB_RECORD, LOC + "Open() -- end 1");
     54        return true;
     55    }
     56       
     57    QUrl parse(url);
     58    if (!parse.isValid() || !parse.hasHost() || !parse.hasPort())
     59    {
     60        VERBOSE(VB_RECORD, LOC + "Open() -- end 2");
     61        return false;
     62    }
     63       
     64    struct in_addr addr;
     65    addr.s_addr = our_inet_addr(parse.host().latin1());
     66
     67    // Begin by setting up our usage environment:
     68    if (!InitEnv())
     69        return false;
     70   
     71    Groupsock *socket = new Groupsock(GetLiveEnv(), addr, parse.port(), 0);
     72    if (!socket)
     73    {
     74        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live RTP Socket.");
     75        FreeEnv();
     76        return false;
     77    }
     78   
     79    _source = SimpleRTPSource::createNew(GetLiveEnv(), socket, 33, 90000, "video/MP2T", 0, False);
     80    if (!_source)
     81    {
     82        VERBOSE(VB_IMPORTANT, LOC + "Failed to create Live RTP Source.");
     83        delete socket;
     84        FreeEnv();
     85        return false;
     86    }
     87
     88    _sink = FreeboxMediaSink::CreateNew(
     89        GetLiveEnv(), GetListener(), TSPacket::SIZE * 128*1024);
     90    if (!_sink)
     91    {
     92        VERBOSE(VB_IMPORTANT,
     93                QString("Freebox # Failed to create sink: %1")
     94                .arg(GetLiveEnv().getResultMsg()));
     95        Medium::close(_source);
     96        _source = NULL;
     97        delete socket;
     98        FreeEnv();
     99        return false;
     100    }
     101    _sink->startPlaying(*_source, NULL, NULL);
     102       
     103    VERBOSE(VB_RECORD, LOC + "Open() -- end");
     104    return true;
     105}
     106
     107void FreeboxFeederRtp::Close(void)
     108{
     109    VERBOSE(VB_RECORD, LOC + "Close() -- begin");
     110    Stop();
     111
     112    QMutexLocker locker(&GetLock());
     113
     114    if (_sink)
     115    {
     116        Medium::close(_sink);
     117        _sink = NULL;
     118    }
     119
     120    if (_source)
     121    {
     122        Groupsock *socket=_source->RTPgs();
     123        Medium::close(_source);
     124        _source=NULL;
     125        delete socket;
     126    }
     127
     128    FreeEnv();
     129
     130    VERBOSE(VB_RECORD, LOC + "Close() -- end");
     131}
  • libs/libmythtv/rtspcomms.h

     
    1 /** -*- Mode: c++ -*-
    2  *  RTSPComms
    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 // C++ headers
    8 #include <vector>
    9 using namespace std;
    10 
    11 // Qt headers
    12 #include <qwaitcondition.h>
    13 #include <qmutex.h>
    14 
    15 // MythTV headers
    16 #include "freeboxchannel.h"
    17 
    18 class UsageEnvironment;
    19 class RTSPClient;
    20 class MediaSession;
    21 class RTSPListener;
    22 
    23 class RTSPComms
    24 {
    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 threads
    51     mutable QMutex      _lock;       ///< Lock  used to coordinate threads
    52 };