Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 259009 | Differences between
and this patch

Collapse All | Expand All

(-)mythtv/configure (+7 lines)
Lines 157-162 Link Here
157
  echo "  --disable-hdhomerun      disable support for HDHomeRun boxes"
157
  echo "  --disable-hdhomerun      disable support for HDHomeRun boxes"
158
  echo "  --disable-v4l            disable Video4Linux support"
158
  echo "  --disable-v4l            disable Video4Linux support"
159
  echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l support"
159
  echo "  --disable-ivtv           disable ivtv support (PVR-x50) req. v4l support"
160
  echo "  --disable-hdpvr          disable HD-PVR support"
160
  echo "  --disable-dvb            disable DVB support"
161
  echo "  --disable-dvb            disable DVB support"
161
  echo "  --dvb-path=HDRLOC        location of directory containing"
162
  echo "  --dvb-path=HDRLOC        location of directory containing"
162
  echo "                           'linux/dvb/frontend.h', not the"
163
  echo "                           'linux/dvb/frontend.h', not the"
Lines 891-896 Link Here
891
    hdhomerun
892
    hdhomerun
892
    iptv
893
    iptv
893
    ivtv
894
    ivtv
895
    hdpvr
894
    joystick_menu
896
    joystick_menu
895
    libfftw3
897
    libfftw3
896
    lirc
898
    lirc
Lines 1048-1053 Link Here
1048
firewire_deps="backend"
1050
firewire_deps="backend"
1049
iptv_deps="backend"
1051
iptv_deps="backend"
1050
ivtv_deps="backend v4l"
1052
ivtv_deps="backend v4l"
1053
hdpvr_deps="backend v4l"
1051
hdhomerun_deps="backend"
1054
hdhomerun_deps="backend"
1052
opengl_deps="GL_gl_h"
1055
opengl_deps="GL_gl_h"
1053
opengl_deps_any="windows x11"
1056
opengl_deps_any="windows x11"
Lines 1179-1184 Link Here
1179
hdhomerun="yes"
1182
hdhomerun="yes"
1180
iptv="yes"
1183
iptv="yes"
1181
ivtv="yes"
1184
ivtv="yes"
1185
hdpvr="yes"
1182
joystick_menu="default"
1186
joystick_menu="default"
1183
lamemp3="yes"
1187
lamemp3="yes"
1184
lirc="yes"
1188
lirc="yes"
Lines 1628-1633 Link Here
1628
    SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME),-current_version,$(SPPVERSION),-compatibility_version,$(SPPVERSION) -Wl,-read_only_relocs,suppress'
1632
    SHFLAGS='-dynamiclib -Wl,-single_module -Wl,-install_name,$(SHLIBDIR)/$(SLIBNAME),-current_version,$(SPPVERSION),-compatibility_version,$(SPPVERSION) -Wl,-read_only_relocs,suppress'
1629
    VHOOKSHFLAGS='-dynamiclib -Wl,-single_module -flat_namespace -undefined suppress -Wl,-install_name,$(SHLIBDIR)/vhook/$@'
1633
    VHOOKSHFLAGS='-dynamiclib -Wl,-single_module -flat_namespace -undefined suppress -Wl,-install_name,$(SHLIBDIR)/vhook/$@'
1630
    strip="strip -x"
1634
    strip="strip -x"
1635
    disable hdpvr
1631
    FFLDFLAGS="-Wl,-dynamic,-search_paths_first"
1636
    FFLDFLAGS="-Wl,-dynamic,-search_paths_first"
1632
    SLIBSUF=".dylib"
1637
    SLIBSUF=".dylib"
1633
    SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME).$(LIBVERSION)$(SLIBSUF)'
1638
    SLIBNAME_WITH_VERSION='$(SLIBPREF)$(FULLNAME).$(LIBVERSION)$(SLIBSUF)'
Lines 1662-1667 Link Here
1662
    disable ffserver
1667
    disable ffserver
1663
    SLIBPREF="lib"
1668
    SLIBPREF="lib"
1664
    SLIBSUF=".dll"
1669
    SLIBSUF=".dll"
1670
    disable hdpvr
1665
    EXESUF=".exe"
1671
    EXESUF=".exe"
1666
    SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)'
1672
    SLIBNAME_WITH_VERSION='$(SLIBPREF)$(NAME)-$(LIBVERSION)$(SLIBSUF)'
1667
    SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)'
1673
    SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(NAME)-$(LIBMAJOR)$(SLIBSUF)'
Lines 2999-3004 Link Here
2999
if enabled backend; then
3005
if enabled backend; then
3000
  echo "Video4Linux sup.          ${v4l-no}"
3006
  echo "Video4Linux sup.          ${v4l-no}"
3001
  echo "ivtv support              ${ivtv-no}"
3007
  echo "ivtv support              ${ivtv-no}"
3008
  echo "HR-PVR support            ${hdpvr-no}"
3002
  echo "FireWire support          ${firewire-no}"
3009
  echo "FireWire support          ${firewire-no}"
3003
  echo "DVB support               ${dvb-no} [$dvb_path]"
3010
  echo "DVB support               ${dvb-no} [$dvb_path]"
3004
  echo "DBox2 support             ${dbox2-no}"
3011
  echo "DBox2 support             ${dbox2-no}"
(-)mythtv/libs/libmythtv/cardutil.h (-7 / +21 lines)
Lines 53-58 Link Here
53
        FIREWIRE,
53
        FIREWIRE,
54
        HDHOMERUN,
54
        HDHOMERUN,
55
        FREEBOX,
55
        FREEBOX,
56
        HDPVR     = 12,
56
    };
57
    };
57
58
58
    static enum CARD_TYPES toCardType(const QString &name)
59
    static enum CARD_TYPES toCardType(const QString &name)
Lines 81-86 Link Here
81
            return HDHOMERUN;
82
            return HDHOMERUN;
82
        if ("FREEBOX" == name)
83
        if ("FREEBOX" == name)
83
            return FREEBOX;
84
            return FREEBOX;
85
        if ("HDPVR" == name)
86
            return HDPVR;
84
        return ERROR_UNKNOWN;
87
        return ERROR_UNKNOWN;
85
    }
88
    }
86
89
Lines 95-101 Link Here
95
    static bool         IsUnscanable(const QString &rawtype)
98
    static bool         IsUnscanable(const QString &rawtype)
96
    {
99
    {
97
        return
100
        return
98
            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2");
101
            (rawtype == "FIREWIRE")  || (rawtype == "DBOX2") ||
102
            (rawtype == "HDPVR");
99
    }
103
    }
100
104
101
    static bool         IsEITCapable(const QString &rawtype)
105
    static bool         IsEITCapable(const QString &rawtype)
Lines 119-125 Link Here
119
123
120
    static bool         IsTuningAnalog(const QString &rawtype)
124
    static bool         IsTuningAnalog(const QString &rawtype)
121
    {
125
    {
122
        return (rawtype == "V4L");
126
        return
127
            (rawtype == "V4L")    || (rawtype == "MPEG") ||
128
            (rawtype == "HDPVR");
123
    }
129
    }
124
130
125
    /// Convenience function for GetCardIDs(const QString&, QString, QString)
131
    /// Convenience function for GetCardIDs(const QString&, QString, QString)
Lines 137-142 Link Here
137
143
138
    static bool         IsCardTypePresent(const QString &rawtype,
144
    static bool         IsCardTypePresent(const QString &rawtype,
139
                                          QString hostname = QString::null);
145
                                          QString hostname = QString::null);
146
    static QStringList  GetCardTypes(void); // card types on ALL hosts
147
140
    static QStringVec   GetVideoDevices(const QString &rawtype,
148
    static QStringVec   GetVideoDevices(const QString &rawtype,
141
                                        QString hostname = QString::null);
149
                                        QString hostname = QString::null);
142
150
Lines 144-149 Link Here
144
        { return get_on_cardid("cardtype", cardid).upper(); }
152
        { return get_on_cardid("cardtype", cardid).upper(); }
145
    static QString      GetVideoDevice(uint cardid)
153
    static QString      GetVideoDevice(uint cardid)
146
        { return get_on_cardid("videodevice", cardid); }
154
        { return get_on_cardid("videodevice", cardid); }
155
    static QString      GetAudioDevice(uint cardid)
156
        { return get_on_cardid("audiodevice", cardid); }
147
    static QString      GetVBIDevice(uint cardid)
157
    static QString      GetVBIDevice(uint cardid)
148
        { return get_on_cardid("vbidevice", cardid); }
158
        { return get_on_cardid("vbidevice", cardid); }
149
    static uint         GetHDHRTuner(uint cardid)
159
    static uint         GetHDHRTuner(uint cardid)
Lines 188-195 Link Here
188
198
189
    static QString      ProbeSubTypeName(uint cardid);
199
    static QString      ProbeSubTypeName(uint cardid);
190
200
191
    static QStringList  probeInputs(QString device,
201
    static QStringList  ProbeVideoInputs(QString device,
192
                                    QString cardtype = QString::null);
202
                                         QString cardtype = QString::null);
203
    static QStringList  ProbeAudioInputs(QString device,
204
                                         QString cardtype = QString::null);
193
    static void         GetCardInputs(uint                cardid,
205
    static void         GetCardInputs(uint                cardid,
194
                                      const QString      &device,
206
                                      const QString      &device,
195
                                      const QString      &cardtype,
207
                                      const QString      &cardtype,
Lines 234-244 Link Here
234
                                   uint32_t &version);
246
                                   uint32_t &version);
235
    static bool         GetV4LInfo(int videofd, QString &card, QString &driver)
247
    static bool         GetV4LInfo(int videofd, QString &card, QString &driver)
236
        { uint32_t dummy; return GetV4LInfo(videofd, card, driver, dummy); }
248
        { uint32_t dummy; return GetV4LInfo(videofd, card, driver, dummy); }
237
    static InputNames   probeV4LInputs(int videofd, bool &ok);
249
    static InputNames   ProbeV4LVideoInputs(int videofd, bool &ok);
250
    static InputNames   ProbeV4LAudioInputs(int videofd, bool &ok);
238
251
239
  private:
252
  private:
240
    static QStringList  probeV4LInputs(QString device);
253
    static QStringList  ProbeV4LVideoInputs(QString device);
241
    static QStringList  probeDVBInputs(QString device);
254
    static QStringList  ProbeV4LAudioInputs(QString device);
255
    static QStringList  ProbeDVBInputs(QString device);
242
};
256
};
243
257
244
#endif //_CARDUTIL_H_
258
#endif //_CARDUTIL_H_
(-)mythtv/libs/libmythtv/videosource.h (+33 lines)
Lines 299-304 Link Here
299
    }
299
    }
300
};
300
};
301
301
302
class TunerCardAudioInput : public ComboBoxSetting, public CaptureCardDBStorage
303
{
304
    Q_OBJECT
305
  public:
306
    TunerCardAudioInput(const CaptureCard &parent,
307
                        QString dev  = QString::null,
308
                        QString type = QString::null);
309
310
  public slots:
311
    void fillSelections(const QString &device);
312
313
  private:
314
    QString last_device;
315
    QString last_cardtype;
316
};
317
302
class DVBAudioDevice : public LineEditSetting, public CaptureCardDBStorage
318
class DVBAudioDevice : public LineEditSetting, public CaptureCardDBStorage
303
{
319
{
304
    Q_OBJECT
320
    Q_OBJECT
Lines 385-390 Link Here
385
    TunerCardInput    *input;
401
    TunerCardInput    *input;
386
};
402
};
387
403
404
class HDPVRConfigurationGroup: public VerticalConfigurationGroup
405
{
406
   Q_OBJECT
407
408
  public:
409
    HDPVRConfigurationGroup(CaptureCard &parent);
410
411
  public slots:
412
    void probeCard(const QString &device);
413
414
  private:
415
    CaptureCard         &parent;
416
    TransLabelSetting   *cardinfo;
417
    TunerCardInput      *videoinput;
418
    TunerCardAudioInput *audioinput;
419
};
420
388
class DVBCardNum;
421
class DVBCardNum;
389
class DVBInput;
422
class DVBInput;
390
class DVBCardName;
423
class DVBCardName;
(-)mythtv/libs/libmythtv/libmythtv.pro (-2 / +7 lines)
Lines 386-393 Link Here
386
386
387
    # Support for Video4Linux devices
387
    # Support for Video4Linux devices
388
    using_v4l {
388
    using_v4l {
389
        HEADERS += channel.h                   analogsignalmonitor.h
389
        HEADERS += v4lchannel.h                analogsignalmonitor.h
390
        SOURCES += channel.cpp                 analogsignalmonitor.h
390
        SOURCES += v4lchannel.cpp              analogsignalmonitor.h
391
391
392
        DEFINES += USING_V4L
392
        DEFINES += USING_V4L
393
    }
393
    }
Lines 472-477 Link Here
472
    using_ivtv:SOURCES += mpegrecorder.cpp
472
    using_ivtv:SOURCES += mpegrecorder.cpp
473
    using_ivtv:DEFINES += USING_IVTV
473
    using_ivtv:DEFINES += USING_IVTV
474
474
475
    # Support for HD-PVR on Linux
476
    using_hdpvr:HEADERS *= mpegrecorder.h
477
    using_hdpvr:SOURCES *= mpegrecorder.cpp
478
    using_hdpvr:DEFINES += USING_HDPVR
479
475
    # Support for Linux DVB drivers
480
    # Support for Linux DVB drivers
476
    using_dvb {
481
    using_dvb {
477
        # Basic DVB types
482
        # Basic DVB types
(-)mythtv/libs/libmythtv/v4lchannel.h (+108 lines)
Line 0 Link Here
1
// -*- Mode: c++ -*-
2
3
#ifndef V4LCHANNEL_H
4
#define V4LCHANNEL_H
5
6
#include "dtvchannel.h"
7
#include "videodev_myth.h" // needed for v4l2_std_id type
8
9
using namespace std;
10
11
#define FAKE_VIDEO 0
12
13
class TVRec;
14
15
typedef QMap<int,int>         VidModV4L1;
16
typedef QMap<int,v4l2_std_id> VidModV4L2;
17
18
/** \class V4LChannel
19
 *  \brief Implements tuning for TV cards using the V4L driver API,
20
 *         both versions 1 and 2.
21
 *
22
 *   This class supports a wide range of tuning hardware including
23
 *   frame grabbers (whose output requires encoding), hardware encoders,
24
 *   digital cameras, and non-encoding hardware which simply records
25
 *   pre-encoded broadcast streams.
26
 *
27
 */
28
class V4LChannel : public DTVChannel
29
{
30
 public:
31
    V4LChannel(TVRec *parent, const QString &videodevice);
32
    virtual ~V4LChannel(void);
33
34
    bool Init(QString &inputname, QString &startchannel, bool setchan);
35
36
    bool Open(void);
37
    void Close(void);
38
39
    // Sets
40
    void SetFd(int fd); 
41
    void SetFormat(const QString &format);
42
    int  SetDefaultFreqTable(const QString &name);
43
    bool SetChannelByString(const QString &chan); 
44
45
    // Gets
46
    bool IsOpen(void)       const { return GetFd() >= 0; }
47
    int  GetFd(void)        const { return videofd; }
48
    QString GetDevice(void) const { return device; }
49
    QString GetSIStandard(void) const { return "atsc"; }
50
51
    // Commands
52
    bool SwitchToInput(int newcapchannel, bool setstarting);
53
    bool Retune(void);
54
55
    // Picture attributes.
56
    bool InitPictureAttributes(void);
57
    int  GetPictureAttribute(PictureAttribute) const;
58
    int  ChangePictureAttribute(PictureAdjustType, PictureAttribute, bool up);
59
60
    // PID caching
61
    void SaveCachedPids(const pid_cache_t&) const;
62
    void GetCachedPids(pid_cache_t&) const;
63
64
    // Digital scanning stuff
65
    bool TuneMultiplex(uint mplexid, QString inputname);
66
    bool Tune(const DTVMultiplex &tuning, QString inputname);
67
68
    // Analog scanning stuff
69
    bool Tune(uint frequency, QString inputname,
70
              QString modulation, QString si_std);
71
72
  private:
73
    // Helper Sets
74
    void SetFreqTable(const int index);
75
    int  SetFreqTable(const QString &name);
76
    bool SetInputAndFormat(int newcapchannel, QString newFmt);
77
78
    // Helper Gets
79
    int  GetCurrentChannelNum(const QString &channame);
80
    QString GetFormatForChannel(QString channum,
81
                                QString inputname);
82
83
    // Helper Commands
84
    bool InitPictureAttribute(const QString db_col_name);
85
    bool TuneTo(const QString &chan, int finetune);
86
    bool InitializeInputs(void);
87
88
  private:
89
    // Data
90
    QString     device;
91
    int         videofd;
92
    QString     device_name;
93
    QString     driver_name;
94
    QMap<QString,int> pict_attr_default;
95
96
    struct CHANLIST *curList;  
97
    int         totalChannels;
98
99
    QString     currentFormat;
100
    bool        is_dtv;         ///< Set if 'currentFormat' is a DTV format
101
    bool        usingv4l2;      ///< Set to true if tuner accepts v4l2 commands
102
    VidModV4L1  videomode_v4l1; ///< Current video mode if 'usingv4l2' is false
103
    VidModV4L2  videomode_v4l2; ///< Current video mode if 'usingv4l2' is true
104
105
    int         defaultFreqTable;
106
};
107
108
#endif
(-)mythtv/libs/libmythtv/channel.h (-108 lines)
Lines 1-108 Link Here
1
// -*- Mode: c++ -*-
2
3
#ifndef CHANNEL_H
4
#define CHANNEL_H
5
6
#include "dtvchannel.h"
7
#include "videodev_myth.h" // needed for v4l2_std_id type
8
9
using namespace std;
10
11
#define FAKE_VIDEO 0
12
13
class TVRec;
14
15
typedef QMap<int,int>         VidModV4L1;
16
typedef QMap<int,v4l2_std_id> VidModV4L2;
17
18
/** \class Channel
19
 *  \brief Implements tuning for TV cards using the V4L driver API,
20
 *         both versions 1 and 2.
21
 *
22
 *   This class supports a wide range of tuning hardware including
23
 *   frame grabbers (whose output requires encoding), hardware encoders,
24
 *   digital cameras, and non-encoding hardware which simply records
25
 *   pre-encoded broadcast streams.
26
 *
27
 */
28
class Channel : public DTVChannel
29
{
30
 public:
31
    Channel(TVRec *parent, const QString &videodevice);
32
    virtual ~Channel(void);
33
34
    bool Init(QString &inputname, QString &startchannel, bool setchan);
35
36
    bool Open(void);
37
    void Close(void);
38
39
    // Sets
40
    void SetFd(int fd); 
41
    void SetFormat(const QString &format);
42
    int  SetDefaultFreqTable(const QString &name);
43
    bool SetChannelByString(const QString &chan); 
44
45
    // Gets
46
    bool IsOpen(void)       const { return GetFd() >= 0; }
47
    int  GetFd(void)        const { return videofd; }
48
    QString GetDevice(void) const { return device; }
49
    QString GetSIStandard(void) const { return "atsc"; }
50
51
    // Commands
52
    bool SwitchToInput(int newcapchannel, bool setstarting);
53
    bool Retune(void);
54
55
    // Picture attributes.
56
    bool InitPictureAttributes(void);
57
    int  GetPictureAttribute(PictureAttribute) const;
58
    int  ChangePictureAttribute(PictureAdjustType, PictureAttribute, bool up);
59
60
    // PID caching
61
    void SaveCachedPids(const pid_cache_t&) const;
62
    void GetCachedPids(pid_cache_t&) const;
63
64
    // Digital scanning stuff
65
    bool TuneMultiplex(uint mplexid, QString inputname);
66
    bool Tune(const DTVMultiplex &tuning, QString inputname);
67
68
    // Analog scanning stuff
69
    bool Tune(uint frequency, QString inputname,
70
              QString modulation, QString si_std);
71
72
  private:
73
    // Helper Sets
74
    void SetFreqTable(const int index);
75
    int  SetFreqTable(const QString &name);
76
    bool SetInputAndFormat(int newcapchannel, QString newFmt);
77
78
    // Helper Gets
79
    int  GetCurrentChannelNum(const QString &channame);
80
    QString GetFormatForChannel(QString channum,
81
                                QString inputname);
82
83
    // Helper Commands
84
    bool InitPictureAttribute(const QString db_col_name);
85
    bool TuneTo(const QString &chan, int finetune);
86
    bool InitializeInputs(void);
87
88
  private:
89
    // Data
90
    QString     device;
91
    int         videofd;
92
    QString     device_name;
93
    QString     driver_name;
94
    QMap<QString,int> pict_attr_default;
95
96
    struct CHANLIST *curList;  
97
    int         totalChannels;
98
99
    QString     currentFormat;
100
    bool        is_dtv;         ///< Set if 'currentFormat' is a DTV format
101
    bool        usingv4l2;      ///< Set to true if tuner accepts v4l2 commands
102
    VidModV4L1  videomode_v4l1; ///< Current video mode if 'usingv4l2' is false
103
    VidModV4L2  videomode_v4l2; ///< Current video mode if 'usingv4l2' is true
104
105
    int         defaultFreqTable;
106
};
107
108
#endif
(-)mythtv/libs/libmythtv/dbcheck.cpp (-2 lines)
Lines 3640-3647 Link Here
3640
    return true;
3640
    return true;
3641
}
3641
}
3642
3642
3643
3644
3645
bool InitializeDatabase(void)
3643
bool InitializeDatabase(void)
3646
{
3644
{
3647
    MSqlQuery query(MSqlQuery::InitCon());
3645
    MSqlQuery query(MSqlQuery::InitCon());
(-)mythtv/libs/libmythtv/scanwizardscanner.cpp (-3 / +6 lines)
Lines 46-52 Link Here
46
#include "dvbconfparser.h"
46
#include "dvbconfparser.h"
47
47
48
#ifdef USING_V4L
48
#ifdef USING_V4L
49
#include "channel.h"
49
#include "v4lchannel.h"
50
#include "analogsignalmonitor.h"
50
#include "analogsignalmonitor.h"
51
#endif
51
#endif
52
52
Lines 511-518 Link Here
511
#endif
511
#endif
512
512
513
#ifdef USING_V4L
513
#ifdef USING_V4L
514
    if (("V4L" == card_type) || ("MPEG" == card_type))
514
    if (("V4L" == card_type) || ("MPEG" == card_type) ||
515
        channel = new Channel(NULL, device);
515
        ("HDPVR" == card_type))
516
    {
517
        channel = new V4LChannel(NULL, device);
518
    }
516
#endif
519
#endif
517
520
518
#ifdef USING_HDHOMERUN
521
#ifdef USING_HDHOMERUN
(-)mythtv/libs/libmythtv/dtvrecorder.h (-3 / +10 lines)
Lines 55-70 Link Here
55
55
56
    void BufferedWrite(const TSPacket &tspacket);
56
    void BufferedWrite(const TSPacket &tspacket);
57
57
58
    // MPEG "audio only" support
58
    // MPEG TS "audio only" support
59
    bool FindAudioKeyframes(const TSPacket *tspacket);
59
    bool FindAudioKeyframes(const TSPacket *tspacket);
60
60
61
    // MPEG2 support
61
    // MPEG2 TS support
62
    bool FindMPEG2Keyframes(const TSPacket* tspacket);
62
    bool FindMPEG2Keyframes(const TSPacket* tspacket);
63
63
64
    // MPEG4 AVC / H.264 support
64
    // MPEG4 AVC / H.264 TS support
65
    bool FindH264Keyframes(const TSPacket* tspacket);
65
    bool FindH264Keyframes(const TSPacket* tspacket);
66
    void HandleH264Keyframe(void);
66
    void HandleH264Keyframe(void);
67
67
68
    // MPEG2 PS support (Hauppauge PVR-x50/PVR-500)
69
    void HandlePSKeyframe(void);
70
    bool FindPSKeyFrames(unsigned char *buffer, int len);
71
68
    // For handling other (non audio/video) packets
72
    // For handling other (non audio/video) packets
69
    bool FindOtherKeyframes(const TSPacket *tspacket);
73
    bool FindOtherKeyframes(const TSPacket *tspacket);
70
74
Lines 93-98 Link Here
93
97
94
    bool _has_written_other_keyframe;
98
    bool _has_written_other_keyframe;
95
99
100
    /// Used for PVR-150/250/500 which have a fixed keyframe distance of 12 or 15
101
    int _keyframedist;
102
96
    // state tracking variables
103
    // state tracking variables
97
    /// True iff recording is actually being performed
104
    /// True iff recording is actually being performed
98
    bool _recording;
105
    bool _recording;
(-)mythtv/libs/libmythtv/analogsignalmonitor.cpp (-2 / +2 lines)
Lines 8-19 Link Here
8
#include "videodev_myth.h"
8
#include "videodev_myth.h"
9
#include "mythcontext.h"
9
#include "mythcontext.h"
10
#include "analogsignalmonitor.h"
10
#include "analogsignalmonitor.h"
11
#include "channel.h"
11
#include "v4lchannel.h"
12
12
13
#define LOC QString("AnalogSM: ").arg(channel->GetDevice())
13
#define LOC QString("AnalogSM: ").arg(channel->GetDevice())
14
#define LOC_ERR QString("AnalogSM, Error: ").arg(channel->GetDevice())
14
#define LOC_ERR QString("AnalogSM, Error: ").arg(channel->GetDevice())
15
15
16
AnalogSignalMonitor::AnalogSignalMonitor(int db_cardnum, Channel *_channel,
16
AnalogSignalMonitor::AnalogSignalMonitor(int db_cardnum, V4LChannel *_channel,
17
                                         uint64_t _flags, const char *_name) :
17
                                         uint64_t _flags, const char *_name) :
18
    SignalMonitor(db_cardnum, _channel, _flags, _name),
18
    SignalMonitor(db_cardnum, _channel, _flags, _name),
19
    usingv4l2(false)
19
    usingv4l2(false)
(-)mythtv/libs/libmythtv/siscan.cpp (-4 / +4 lines)
Lines 29-35 Link Here
29
29
30
#include "dvbchannel.h"
30
#include "dvbchannel.h"
31
#include "hdhrchannel.h"
31
#include "hdhrchannel.h"
32
#include "channel.h"
32
#include "v4lchannel.h"
33
#include "compat.h"
33
#include "compat.h"
34
34
35
QString SIScan::loc(const SIScan *siscan)
35
QString SIScan::loc(const SIScan *siscan)
Lines 555-564 Link Here
555
#endif
555
#endif
556
}
556
}
557
557
558
Channel *SIScan::GetChannel(void)
558
V4LChannel *SIScan::GetV4LChannel(void)
559
{
559
{
560
#ifdef USING_V4L
560
#ifdef USING_V4L
561
    return dynamic_cast<Channel*>(channel);
561
    return dynamic_cast<V4LChannel*>(channel);
562
#else
562
#else
563
    return NULL;
563
    return NULL;
564
#endif
564
#endif
Lines 1619-1625 Link Here
1619
#endif // USING_DVB
1619
#endif // USING_DVB
1620
1620
1621
#ifdef USING_V4L
1621
#ifdef USING_V4L
1622
    if (GetChannel())
1622
    if (GetV4LChannel())
1623
    {
1623
    {
1624
        // convert to visual carrier
1624
        // convert to visual carrier
1625
        tuning.frequency = tuning.frequency - 1750000;
1625
        tuning.frequency = tuning.frequency - 1750000;
(-)mythtv/libs/libmythtv/dtvrecorder.cpp (-1 / +110 lines)
Lines 46-51 Link Here
46
    _request_recording(false),
46
    _request_recording(false),
47
    _wait_for_keyframe_option(true),
47
    _wait_for_keyframe_option(true),
48
    _has_written_other_keyframe(false),
48
    _has_written_other_keyframe(false),
49
    _keyframedist(15),
49
    // state
50
    // state
50
    _recording(false),
51
    _recording(false),
51
    _error(false),
52
    _error(false),
Lines 57-62 Link Here
57
    _frames_seen_count(0),          _frames_written_count(0)
58
    _frames_seen_count(0),          _frames_written_count(0)
58
{
59
{
59
    SetPositionMapType(MARK_GOP_BYFRAME);
60
    SetPositionMapType(MARK_GOP_BYFRAME);
61
    _payload_buffer.reserve(TSPacket::SIZE * (50 + 1));
60
}
62
}
61
63
62
DTVRecorder::~DTVRecorder()
64
DTVRecorder::~DTVRecorder()
Lines 431-437 Link Here
431
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
433
bool DTVRecorder::FindH264Keyframes(const TSPacket *tspacket)
432
{
434
{
433
    if (!ringBuffer)
435
    if (!ringBuffer)
436
    {
437
        VERBOSE(VB_IMPORTANT, LOC_ERR + "FindH264Keyframes: No ringbuffer");
434
        return false;
438
        return false;
439
    }
435
440
436
    bool haveBufferedData = !_payload_buffer.empty();
441
    bool haveBufferedData = !_payload_buffer.empty();
437
    if (!tspacket->HasPayload()) // no payload to scan
442
    if (!tspacket->HasPayload()) // no payload to scan
Lines 528-534 Link Here
528
                hasFrame = true;
533
                hasFrame = true;
529
            }
534
            }
530
535
531
            if (_h264_kf_seq.IsOnFrame())
536
            else if (_h264_kf_seq.IsOnFrame())
532
                hasFrame = true;
537
                hasFrame = true;
533
        }
538
        }
534
    } // for (; i < TSPacket::SIZE; i++)
539
    } // for (; i < TSPacket::SIZE; i++)
Lines 572-575 Link Here
572
    CheckForRingBufferSwitch();
577
    CheckForRingBufferSwitch();
573
}
578
}
574
579
580
/** \fn DTVRecorder::HandlePSKeyframe(void)
581
 *  \brief This save the current frame to the position maps
582
 *         and handles ringbuffer switching.
583
 */
584
void DTVRecorder::HandlePSKeyframe(void)
585
{
586
    if (!ringBuffer)
587
        return;
588
589
    unsigned long long frameNum = _last_gop_seen;
590
591
    _first_keyframe = (_first_keyframe < 0) ? frameNum : _first_keyframe;
592
593
    // Add key frame to position map
594
    positionMapLock.lock();
595
    if (!positionMap.contains(frameNum))
596
    {
597
        long long startpos = ringBuffer->GetWritePosition();
598
        // FIXME: handle keyframes with start code spanning over two ts packets
599
        startpos += _payload_buffer.size();
600
        positionMapDelta[frameNum] = startpos;
601
        positionMap[frameNum]      = startpos;
602
    }
603
    positionMapLock.unlock();
604
605
    // Perform ringbuffer switch if needed.
606
    CheckForRingBufferSwitch();
607
}
608
609
610
bool DTVRecorder::FindPSKeyFrames(unsigned char *buffer, int len)
611
{
612
    unsigned char *bufptr = buffer, *bufstart = buffer;
613
    uint v = 0;
614
    int leftlen = len;
615
    bool hasKeyFrame = false;
616
617
    while (bufptr < buffer + len)
618
    {
619
        v = *bufptr++;
620
        if (_start_code == 0x000001)
621
        {
622
            _start_code = ((_start_code << 8) | v) & 0xFFFFFF;
623
            const int stream_id = _start_code & 0x000000ff;
624
625
            if (stream_id == PESStreamID::PackHeader)
626
            {
627
                _last_keyframe_seen = ringBuffer->GetWritePosition() +
628
                                      _payload_buffer.size();
629
630
                int curpos = bufptr - bufstart - 4;
631
                if (curpos < 0)
632
                {
633
                    // header was split
634
                    if (_payload_buffer.size() + curpos > 0)
635
                        ringBuffer->Write(&_payload_buffer[0],
636
                                          _payload_buffer.size() + curpos);
637
638
                    _payload_buffer.resize(4);
639
                    memcpy(&_payload_buffer[0], &_start_code, 4);
640
641
                    leftlen = leftlen - curpos + 4;
642
                    bufstart = bufptr;
643
                }
644
                else
645
                {
646
                    // header was entirely in this packet
647
                    int idx = _payload_buffer.size();
648
                    _payload_buffer.resize(idx + curpos);
649
                    memcpy(&_payload_buffer[idx], bufstart, curpos);
650
651
                    bufstart += curpos;
652
                    leftlen -= curpos;
653
654
                    if (_payload_buffer.size() > 0)
655
                        ringBuffer->Write(&_payload_buffer[0],
656
                                          _payload_buffer.size());
657
                    _payload_buffer.clear();
658
                }
659
                _frames_seen_count++;
660
            }
661
            else if (stream_id == PESStreamID::SequenceStartCode)
662
            {
663
                _last_seq_seen = _last_keyframe_seen;
664
            }
665
            else if (stream_id == PESStreamID::GOPStartCode &&
666
                     _last_seq_seen == _last_keyframe_seen)
667
            {
668
                _frames_written_count = _last_gop_seen * _keyframedist;
669
                _last_gop_seen++;
670
                HandlePSKeyframe();
671
            }
672
        }
673
        else
674
            _start_code = ((_start_code << 8) | v) & 0xFFFFFF;
675
    }
676
677
    int idx = _payload_buffer.size();
678
    _payload_buffer.resize(idx + leftlen);
679
    memcpy(&_payload_buffer[idx], bufstart, leftlen);
680
681
    return hasKeyFrame;
682
}
683
575
/* vim: set expandtab tabstop=4 shiftwidth=4: */
684
/* vim: set expandtab tabstop=4 shiftwidth=4: */
(-)mythtv/libs/libmythtv/mpegrecorder.h (-28 / +74 lines)
Lines 3-14 Link Here
3
#ifndef MPEGRECORDER_H_
3
#ifndef MPEGRECORDER_H_
4
#define MPEGRECORDER_H_
4
#define MPEGRECORDER_H_
5
5
6
#include "recorderbase.h"
6
#include "dtvrecorder.h"
7
#include "tspacket.h"
8
#include "mpegstreamdata.h"
9
#include "DeviceReadBuffer.h"
7
10
8
struct AVFormatContext;
11
struct AVFormatContext;
9
struct AVPacket;
12
struct AVPacket;
10
13
11
class MpegRecorder : public RecorderBase
14
class MpegRecorder : public DTVRecorder,
15
                     public MPEGSingleProgramStreamListener,
16
                     public TSPacketListener,
17
                     public TSPacketListenerAV,
18
                     public ReaderPausedCB
12
{
19
{
13
  public:
20
  public:
14
    MpegRecorder(TVRec*);
21
    MpegRecorder(TVRec*);
Lines 33-68 Link Here
33
    bool PauseAndWait(int timeout = 100);
40
    bool PauseAndWait(int timeout = 100);
34
41
35
    bool IsRecording(void) { return recording; }
42
    bool IsRecording(void) { return recording; }
36
    bool IsErrored(void) { return errored; }
37
43
38
    long long GetFramesWritten(void) { return framesWritten; }
39
40
    bool Open(void);
44
    bool Open(void);
41
    int GetVideoFd(void) { return chanfd; }
45
    int GetVideoFd(void) { return chanfd; }
42
46
43
    long long GetKeyframePosition(long long desired);
47
    // TS
48
    virtual void SetStreamData(MPEGStreamData*);
49
    virtual MPEGStreamData *GetStreamData(void) { return _stream_data; }
44
50
45
    void SetNextRecording(const ProgramInfo*, RingBuffer*);
51
    // TSPacketListener
52
    bool ProcessTSPacket(const TSPacket &tspacket);
46
53
54
    // TSPacketListenerAV
55
    bool ProcessVideoTSPacket(const TSPacket &tspacket);
56
    bool ProcessAudioTSPacket(const TSPacket &tspacket);
57
    bool ProcessAVTSPacket(const TSPacket &tspacket);
58
59
    // Implements MPEGSingleProgramStreamListener
60
    void HandleSingleProgramPAT(ProgramAssociationTable *pat);
61
    void HandleSingleProgramPMT(ProgramMapTable *pmt);
62
63
    // ReaderPausedCB
64
    virtual void ReaderPaused(int fd) { paused = true; pauseWait.wakeAll(); }
65
47
  private:
66
  private:
48
    bool SetupRecording(void);
67
    void SetIntOption(RecordingProfile *profile, const QString &name);
49
    void FinishRecording(void);
68
    void SetStrOption(RecordingProfile *profile, const QString &name);
50
    void HandleKeyframe(void);
51
69
52
    void ProcessData(unsigned char *buffer, int len);
53
54
    bool OpenMpegFileAsInput(void);
70
    bool OpenMpegFileAsInput(void);
55
    bool OpenV4L2DeviceAsInput(void);
71
    bool OpenV4L2DeviceAsInput(void);
56
    bool SetIVTVDeviceOptions(int chanfd);
72
    bool SetIVTVDeviceOptions(int chanfd);
57
    bool SetV4L2DeviceOptions(int chanfd);
73
    bool SetV4L2DeviceOptions(int chanfd);
74
    bool SetFormat(int chanfd);
75
    bool SetLanguageMode(int chanfd);
76
    bool SetRecordingVolume(int chanfd);
58
    bool SetVBIOptions(int chanfd);
77
    bool SetVBIOptions(int chanfd);
59
    uint GetFilteredStreamType(void) const;
78
    uint GetFilteredStreamType(void) const;
60
    uint GetFilteredAudioSampleRate(void) const;
79
    uint GetFilteredAudioSampleRate(void) const;
61
    uint GetFilteredAudioLayer(void) const;
80
    uint GetFilteredAudioLayer(void) const;
62
    uint GetFilteredAudioBitRate(uint audio_layer) const;
81
    uint GetFilteredAudioBitRate(uint audio_layer) const;
63
82
83
    bool StartEncoding(int fd);
84
    bool StopEncoding(int fd);
85
64
    void ResetForNewFile(void);
86
    void ResetForNewFile(void);
65
87
88
    void HandleResolutionChanges(void);
89
90
    inline bool CheckCC(uint pid, uint cc);
91
66
    bool deviceIsMpegFile;
92
    bool deviceIsMpegFile;
67
    int bufferSize;
93
    int bufferSize;
68
94
Lines 78-119 Link Here
78
    // State
104
    // State
79
    bool recording;
105
    bool recording;
80
    bool encoding;
106
    bool encoding;
81
    bool errored;
107
    bool needs_resolution;
108
    mutable QMutex start_stop_encoding_lock;
109
    QMutex recording_wait_lock;
110
    QWaitCondition recording_wait;
82
111
83
    // Pausing state
112
    // Pausing state
84
    bool cleartimeonpause;
113
    bool cleartimeonpause;
85
114
86
    // Number of frames written
87
    long long framesWritten;
88
89
    // Encoding info
115
    // Encoding info
90
    int width, height;
116
    int width, height;
91
    int bitrate, maxbitrate, streamtype, aspectratio;
117
    int bitrate, maxbitrate, streamtype, aspectratio;
92
    int audtype, audsamplerate, audbitratel1, audbitratel2, audbitratel3;
118
    int audtype, audsamplerate, audbitratel1, audbitratel2, audbitratel3;
93
    int audvolume;
119
    int audvolume;
94
    unsigned int language; ///< 0 is Main Lang; 1 is SAP Lang; 2 is Dual
120
    unsigned int language; ///< 0 is Main Lang; 1 is SAP Lang; 2 is Dual
121
    unsigned int low_mpeg4avgbitrate;
122
    unsigned int low_mpeg4peakbitrate;
123
    unsigned int medium_mpeg4avgbitrate;
124
    unsigned int medium_mpeg4peakbitrate;
125
    unsigned int high_mpeg4avgbitrate;
126
    unsigned int high_mpeg4peakbitrate;
95
127
96
    // Input file descriptors
128
    // Input file descriptors
97
    int chanfd;
129
    int chanfd;
98
    int readfd;
130
    int readfd;
99
131
100
    // Keyframe tracking inforamtion
101
    int keyframedist;
102
    bool gopset;
103
    unsigned int leftovers;
104
    long long lastpackheaderpos;
105
    long long lastseqstart;
106
    long long numgops;
107
108
    // buffer used for ...
109
    unsigned char *buildbuffer;
110
    unsigned int buildbuffersize;
111
112
    static const int   audRateL1[];
132
    static const int   audRateL1[];
113
    static const int   audRateL2[];
133
    static const int   audRateL2[];
114
    static const int   audRateL3[];
134
    static const int   audRateL3[];
115
    static const char *streamType[];
135
    static const char *streamType[];
116
    static const char *aspectRatio[];
136
    static const char *aspectRatio[];
117
    static const unsigned int kBuildBufferMaxSize;
137
    static const unsigned int kBuildBufferMaxSize;
138
139
    // Buffer device reads
140
    DeviceReadBuffer *_device_read_buffer;
141
142
    // TS
143
    MPEGStreamData *_stream_data;
144
    unsigned char   _stream_id[0x1fff];
145
    unsigned char   _pid_status[0x1fff];
146
    unsigned char   _continuity_counter[0x1fff];
147
    static const unsigned char kPayloadStartSeen = 0x2;
148
149
    // Statistics
150
    mutable uint        _continuity_error_count;
151
    mutable uint        _stream_overflow_count;
152
    mutable uint        _bad_packet_count;
118
};
153
};
154
155
inline bool MpegRecorder::CheckCC(uint pid, uint new_cnt)
156
{
157
    bool ok = ((((_continuity_counter[pid] + 1) & 0xf) == new_cnt) ||
158
               (_continuity_counter[pid] == 0xFF));
159
160
    _continuity_counter[pid] = new_cnt & 0xf;
161
162
    return ok;
163
}
164
119
#endif
165
#endif
(-)mythtv/libs/libmythtv/channelbase.cpp (-1 / +1 lines)
Lines 17-23 Link Here
17
17
18
// MythTV headers
18
// MythTV headers
19
#include "videodev_myth.h"
19
#include "videodev_myth.h"
20
#include "channel.h"
20
#include "channelbase.h"
21
#include "frequencies.h"
21
#include "frequencies.h"
22
#include "tv_rec.h"
22
#include "tv_rec.h"
23
#include "mythcontext.h"
23
#include "mythcontext.h"
(-)mythtv/libs/libmythtv/mpeg/h264utils.h (+20 lines)
Lines 35-40 Link Here
35
35
36
#include <stdint.h>
36
#include <stdint.h>
37
37
38
extern "C" {
39
#include <limits.h> // golomb.h should include this...
40
#include "golomb.h"
41
}
42
38
namespace H264
43
namespace H264
39
{
44
{
40
45
Lines 174-179 Link Here
174
179
175
  private:
180
  private:
176
    void KeyframePredicate(const uint8_t new_first_NAL_byte); /* throw() */
181
    void KeyframePredicate(const uint8_t new_first_NAL_byte); /* throw() */
182
    void decode_Header(GetBitContext *gb);
183
    void decode_SPS(GetBitContext *gb);
177
184
178
    bool    errored;
185
    bool    errored;
179
    bool    state_changed;
186
    bool    state_changed;
Lines 182-195 Link Here
182
    int64_t  sync_stream_offset;
189
    int64_t  sync_stream_offset;
183
190
184
    uint8_t first_NAL_byte;
191
    uint8_t first_NAL_byte;
192
    int     log2_max_frame_num;
193
    int     frame_num;
194
    int     prev_frame_num;
185
195
186
    bool    saw_AU_delimiter;
196
    bool    saw_AU_delimiter;
187
    bool    saw_first_VCL_NAL_unit;
197
    bool    saw_first_VCL_NAL_unit;
188
    bool    saw_sps;
198
    bool    saw_sps;
199
    bool    new_VLC_NAL;
189
200
201
    bool    separate_colour_plane_flag;
202
    bool    frame_mbs_only_flag;
203
    bool    prev_field_pic_flag;
204
    bool    prev_bottom_field_flag;
205
    uint    prev_pic_parameter_set_id;
206
207
190
    bool    did_evaluate_once;
208
    bool    did_evaluate_once;
191
    bool    keyframe;
209
    bool    keyframe;
192
    int64_t keyframe_sync_stream_offset;
210
    int64_t keyframe_sync_stream_offset;
211
212
    GetBitContext gb;
193
};
213
};
194
214
195
} // namespace H264
215
} // namespace H264
(-)mythtv/libs/libmythtv/mpeg/mpegdescriptors.cpp (-9 / +82 lines)
Lines 3-11 Link Here
3
3
4
#include <limits.h>
4
#include <limits.h>
5
5
6
#include <qdeepcopy.h>
7
6
#include "atscdescriptors.h"
8
#include "atscdescriptors.h"
7
#include "dvbdescriptors.h"
9
#include "dvbdescriptors.h"
8
10
11
QMutex                RegistrationDescriptor::description_map_lock;
12
bool                  RegistrationDescriptor::description_map_initialized = false;
13
QMap<QString,QString> RegistrationDescriptor::description_map;
14
9
desc_list_t MPEGDescriptor::Parse(
15
desc_list_t MPEGDescriptor::Parse(
10
    const unsigned char* data, uint len)
16
    const unsigned char* data, uint len)
11
{
17
{
Lines 448-466 Link Here
448
    return str;
454
    return str;
449
}
455
}
450
456
457
void RegistrationDescriptor::InitializeDescriptionMap(void)
458
{
459
    QMutexLocker locker(&description_map_lock);
460
    if (description_map_initialized)
461
        return;
462
463
    description_map["AC-3"] = "ATSC audio stream A/52";
464
    description_map["AVSV"] = "China A/V Working Group";
465
    description_map["BDC0"] = "Broadcast Data Corporation Software Data Service";
466
    description_map["BSSD"] = "SMPTE 302M-1998 Audio data as specified in (AES3)";
467
    description_map["CAPO"] = "SMPTE 315M-1999 Camera Positioning Information";
468
    description_map["CUEI"] = "SCTE 35 2003, Cable Digital Program Insertion Cueing Message";
469
    description_map["DDED"] = "LGEUS Digital Delivery with encryption and decryption";
470
    description_map["DISH"] = "EchoStar MPEG streams";
471
    description_map["DRA1"] = "Chinese EIS SJ/T11368-2006 DRA digital audio";
472
    description_map["DTS1"] = "DTS Frame size of 512 bytes";
473
    description_map["DTS2"] = "DTS Frame size of 1024 bytes";
474
    description_map["DTS3"] = "DTS Frame size of 2048";
475
    description_map["DVDF"] = "DVD compatible MPEG2-TS";
476
    description_map["ETV1"] = "CableLabs ETV info is present";
477
    description_map["GA94"] = "ATSC program ID A/53";
478
    description_map["GWKS"] = "GuideWorks EPG info";
479
    description_map["HDMV"] = "Blu-Ray A/V for read-only media (H.264 TS)";
480
    description_map["HDMX"] = "Matsushita-TS";
481
    description_map["KLVA"] = "SMPTE RP 217-2001 MXF KLV packets present";
482
    description_map["LU-A"] = "SMPTE RDD-11 HDSDI HD serial/video data";
483
    description_map["MTRM"] = "D-VHS compatible MPEG2-TS";
484
    description_map["NMR1"] = "Nielsen content identifier";
485
    description_map["PAUX"] = "Philips ES containing low-speed data";
486
    description_map["PMSF"] = "MPEG-TS stream modified by STB";
487
    description_map["PRMC"] = "Philips ES containing remote control data";
488
    description_map["SCTE"] = "SCTE 54 2003 Digital Video Service Multiplex and TS for Cable";
489
    description_map["SEN1"] = "ATSC Private Information identifies source of stream";
490
    description_map["SESF"] = "Blu-Ray A/V for ReWritable media (H.264 TS)";
491
    description_map["SPLC"] = "SMPTE Proposed 312M Splice Point compatible TS";
492
    description_map["SVMD"] = "SMPTE Proposed Video Metatdata Dictionary for MPEG2-TS";
493
    description_map["SZMI"] = "ATSC Private Info from Building B";
494
    description_map["TRIV"] = "ATSC Private Info from Triveni Digital";
495
    description_map["TSBV"] = "Toshiba self-encoded H.264 TS";
496
    description_map["TSHV"] = "Sony self-encoded MPEG-TS and private data";
497
    description_map["TSMV"] = "Sony self-encoded MPEG-TS and private data";
498
    description_map["TVG1"] = "TV Guide EPG Data";
499
    description_map["TVG2"] = "TV Guide EPG Data";
500
    description_map["TVG3"] = "TV Guide EPG Data";
501
    description_map["ULE1"] = "IETF RFC4326 compatible MPEG2-TS";
502
    description_map["VC-1"] = "SMPTE Draft RP 227 VC-1 Bitstream Transport Encodings";
503
504
    for (uint i = 0; i <= 99; i++)
505
    {
506
        description_map[QString("US%1").arg(i, 2, 0)] =
507
            "NIMA, Unspecified military application";
508
    }
509
510
    description_map_initialized = true;
511
}
512
513
QString RegistrationDescriptor::GetDescription(const QString &fmt)
514
{
515
    InitializeDescriptionMap();
516
517
    QString ret = QString::null;
518
    {
519
        QMutexLocker locker(&description_map_lock);
520
        QMap<QString,QString>::const_iterator it = description_map.find(fmt);
521
        if (it != description_map.end())
522
            ret = QDeepCopy<QString>(*it);
523
    }
524
525
    return ret;
526
}
527
451
QString RegistrationDescriptor::toString() const
528
QString RegistrationDescriptor::toString() const
452
{
529
{
453
    QString fmt = FormatIdentifierString();
530
    QString fmt = FormatIdentifierString();
454
    QString msg = QString("Registration Descriptor: '%1' ").arg(fmt);
531
    QString msg = QString("Registration Descriptor: '%1' ").arg(fmt);
455
    QString msg2 = "Unknown";
532
456
    if (fmt == "CUEI")
533
    QString msg2 = GetDescription(fmt);
457
        msg2 = "SCTE 35 2003, Cable Digital Program Insertion Cueing Message";
534
    if (msg2.isEmpty())
458
    else if (fmt == "AC-3")
535
        msg2 = "Unknown, see http://www.smpte-ra.org/mpegreg/mpegreg.html";
459
        msg2 = "ATSC audio stream A/52";
536
460
    else if (fmt == "GA94")
461
        msg2 = "ATSC program ID A/53";
462
    else
463
        msg2 = "Unknown, see http://www.smpte-ra.org/mpegreg.html";
464
    return msg + msg2;
537
    return msg + msg2;
465
}
538
}
466
539
(-)mythtv/libs/libmythtv/mpeg/h264utils.cpp (-4 / +173 lines)
Lines 33-47 Link Here
33
// C headers
33
// C headers
34
#include <cstring>
34
#include <cstring>
35
35
36
// C++ headers
37
#include <iostream>
38
39
// MythTV headers
36
// MythTV headers
37
#include "mythverbose.h"
40
#include "h264utils.h"
38
#include "h264utils.h"
41
39
42
extern "C" {
40
extern "C" {
43
// from libavcodec
41
// from libavcodec
44
extern const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state);
42
extern const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state);
43
#include "avcodec.h"
45
}
44
}
46
45
47
namespace H264
46
namespace H264
Lines 62-70 Link Here
62
61
63
    first_NAL_byte = H264::NALUnitType::UNKNOWN;
62
    first_NAL_byte = H264::NALUnitType::UNKNOWN;
64
63
64
    log2_max_frame_num = -1;
65
    frame_num = 0;
66
    prev_frame_num = -1;
67
65
    saw_AU_delimiter = false;
68
    saw_AU_delimiter = false;
66
    saw_first_VCL_NAL_unit = false;
69
    saw_first_VCL_NAL_unit = false;
67
    saw_sps = false;
70
    saw_sps = false;
71
    separate_colour_plane_flag = false;
72
    frame_mbs_only_flag = true;
73
    new_VLC_NAL = false;
68
74
69
    did_evaluate_once = false;
75
    did_evaluate_once = false;
70
    keyframe = false;
76
    keyframe = false;
Lines 127-133 Link Here
127
    // stage 3: did we see the AU's first VCL NAL unit yet?
133
    // stage 3: did we see the AU's first VCL NAL unit yet?
128
    if (!saw_first_VCL_NAL_unit && NALUnitType::IsVCLType(new_NAL_type))
134
    if (!saw_first_VCL_NAL_unit && NALUnitType::IsVCLType(new_NAL_type))
129
    {
135
    {
130
        saw_first_VCL_NAL_unit = true;
136
        saw_first_VCL_NAL_unit = new_VLC_NAL;
131
        saw_AU_delimiter = false;
137
        saw_AU_delimiter = false;
132
        state_changed = true;
138
        state_changed = true;
133
        if (saw_sps)
139
        if (saw_sps)
Lines 154-162 Link Here
154
        if ((sync_accumulator & 0xffffff00) == 0x00000100)
160
        if ((sync_accumulator & 0xffffff00) == 0x00000100)
155
        {
161
        {
156
            uint8_t k = *(local_bytes-1);
162
            uint8_t k = *(local_bytes-1);
163
            uint8_t NAL_type = k & 0x1f;
157
            sync_stream_offset = stream_offset;
164
            sync_stream_offset = stream_offset;
158
            keyframe = false;
165
            keyframe = false;
159
166
167
            if (NAL_type == NALUnitType::SPS ||
168
                NAL_type == NALUnitType::SLICE ||
169
                NAL_type == NALUnitType::SLICE_DPA)
170
            {
171
                /*
172
                  bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE
173
                  bytes larger then the actual read bits
174
                */
175
                if (local_bytes + 20 + FF_INPUT_BUFFER_PADDING_SIZE <
176
                    local_bytes_end)
177
                {
178
                    init_get_bits(&gb, local_bytes,
179
                                  8 * (local_bytes_end - local_bytes));
180
181
                    if (NAL_type == NALUnitType::SPS)
182
                        decode_SPS(&gb);
183
                    else
184
                        decode_Header(&gb);
185
                }
186
            }
187
            else if (NAL_type == NALUnitType::SLICE_IDR)
188
            {
189
                frame_num = 0;
190
            }
191
160
            KeyframePredicate(k);
192
            KeyframePredicate(k);
161
            first_NAL_byte = k;
193
            first_NAL_byte = k;
162
194
Lines 175-178 Link Here
175
    return saw_first_VCL_NAL_unit;
207
    return saw_first_VCL_NAL_unit;
176
}
208
}
177
209
210
void KeyframeSequencer::decode_Header(GetBitContext *gb)
211
{
212
    uint first_mb_in_slice;
213
    uint slice_type;
214
    uint pic_parameter_set_id;
215
    bool field_pic_flag;
216
    bool bottom_field_flag;
217
218
    if (log2_max_frame_num < 1)
219
    {
220
        VERBOSE(VB_IMPORTANT, "KeyframeSequencer::decode_Header: "
221
                "SPS has not been parsed!");
222
        return;
223
    }
224
225
    new_VLC_NAL = false;
226
227
    prev_frame_num = frame_num;
228
229
    first_mb_in_slice = get_ue_golomb(gb);
230
    slice_type = get_ue_golomb(gb);
231
232
    pic_parameter_set_id = get_ue_golomb(gb);
233
    if (pic_parameter_set_id != prev_pic_parameter_set_id)
234
    {
235
        new_VLC_NAL = true;
236
        prev_pic_parameter_set_id = pic_parameter_set_id;
237
    }
238
    
239
    if (separate_colour_plane_flag)
240
        get_bits(gb, 2);  // colour_plane_id
241
    
242
    frame_num = get_bits(gb, log2_max_frame_num);
243
244
    if (frame_mbs_only_flag)
245
    {
246
        new_VLC_NAL = true;
247
    }
248
    else
249
    {
250
        /* From section 7.3.3 Slice header syntax
251
           if (!frame_mbs_only_flag)
252
           {
253
               field_pic_flag = get_bits1(gb);
254
               if (field_pic_flag)
255
                   bottom_field_flag = get_bits1(gb);
256
           }
257
        */
258
259
        field_pic_flag = get_bits1(gb);
260
        if (field_pic_flag != prev_field_pic_flag)
261
        {
262
            new_VLC_NAL = true;
263
            prev_field_pic_flag = field_pic_flag;
264
        }
265
266
        if (field_pic_flag)
267
        {
268
            bottom_field_flag = get_bits1(gb);
269
            if (bottom_field_flag != prev_bottom_field_flag)
270
            {
271
                new_VLC_NAL = !bottom_field_flag;
272
                prev_bottom_field_flag = bottom_field_flag;
273
            }
274
        }
275
    }
276
}
277
278
/*
279
 * libavcodec used for example
280
 */
281
void KeyframeSequencer::decode_SPS(GetBitContext * gb)
282
{
283
    int profile_idc, chroma_format_idc;
284
285
    profile_idc = get_bits(gb, 8); // profile_idc
286
    get_bits1(gb);   // constraint_set0_flag
287
    get_bits1(gb);   // constraint_set1_flag
288
    get_bits1(gb);   // constraint_set2_flag
289
    get_bits1(gb);   // constraint_set3_flag
290
    get_bits(gb, 4); // reserved
291
    get_bits(gb, 8); // level_idc
292
    get_ue_golomb(gb);  // sps_id
293
294
    if (profile_idc >= 100)
295
    { // high profile
296
        if ((chroma_format_idc = get_ue_golomb(gb)) == 3) // chroma_format_idc
297
            separate_colour_plane_flag = (get_bits1(gb) == 1);
298
299
        get_ue_golomb(gb);  // bit_depth_luma_minus8
300
        get_ue_golomb(gb);  // bit_depth_chroma_minus8
301
        get_bits1(gb);      // qpprime_y_zero_transform_bypass_flag
302
303
        if (get_bits1(gb))      // seq_scaling_matrix_present_flag
304
        {
305
            for (int idx = 0; idx < ((chroma_format_idc != 3) ? 8 : 12); ++idx)
306
            {
307
                get_bits1(gb);  // scaling_list
308
            }
309
        }
310
    }
311
312
    log2_max_frame_num = get_ue_golomb(gb) + 4;
313
314
    uint pic_order_cnt_type;
315
    uint log2_max_pic_order_cnt_lsb;
316
    bool delta_pic_order_always_zero_flag;
317
    int  offset_for_non_ref_pic;
318
    int  offset_for_top_to_bottom_field;
319
    uint tmp;
320
    uint num_ref_frames;
321
    bool gaps_in_frame_num_allowed_flag;
322
    uint pic_width_in_mbs;
323
    uint pic_height_in_map_units;
324
325
    pic_order_cnt_type = get_ue_golomb(gb);
326
    if (pic_order_cnt_type == 0)
327
    {
328
        log2_max_pic_order_cnt_lsb = get_ue_golomb(gb) + 4;
329
    }
330
    else if (pic_order_cnt_type == 1)
331
    {
332
        delta_pic_order_always_zero_flag = get_bits1(gb);
333
        offset_for_non_ref_pic = get_se_golomb(gb);
334
        offset_for_top_to_bottom_field = get_se_golomb(gb);
335
        tmp = get_ue_golomb(gb);
336
        for (uint idx = 0; idx < tmp; ++idx)
337
            get_se_golomb(gb);  // offset_for_ref_frame[i]
338
    }
339
340
    num_ref_frames = get_ue_golomb(gb);
341
    gaps_in_frame_num_allowed_flag = get_bits1(gb);
342
    pic_width_in_mbs = get_ue_golomb(gb) + 1;
343
    pic_height_in_map_units = get_ue_golomb(gb) + 1;
344
    frame_mbs_only_flag = get_bits1(gb);
345
}
346
178
} // namespace H264
347
} // namespace H264
(-)mythtv/libs/libmythtv/mpeg/mpegdescriptors.h (+20 lines)
Lines 3-9 Link Here
3
#ifndef _MPEG_DESCRIPTORS_H_
3
#ifndef _MPEG_DESCRIPTORS_H_
4
#define _MPEG_DESCRIPTORS_H_
4
#define _MPEG_DESCRIPTORS_H_
5
5
6
// ANSI C headers
6
#include <cassert>
7
#include <cassert>
8
9
// C++ headers
10
#include <vector>
11
using namespace std;
12
13
// Qt headers
14
#include <qmutex.h>
15
#include <qstring.h>
16
17
// MythTV
7
#include "iso639.h"
18
#include "iso639.h"
8
19
9
typedef vector<const unsigned char*> desc_list_t;
20
typedef vector<const unsigned char*> desc_list_t;
Lines 188-193 Link Here
188
            QChar(_data[4]) + QChar(_data[5]);
199
            QChar(_data[4]) + QChar(_data[5]);
189
    }
200
    }
190
    QString toString() const;
201
    QString toString() const;
202
203
  private:
204
    static void InitializeDescriptionMap(void);
205
    static QString GetDescription(const QString &fmt);
206
207
  private:
208
    static QMutex                description_map_lock;
209
    static bool                  description_map_initialized;
210
    static QMap<QString,QString> description_map;
191
};
211
};
192
212
193
class ConditionalAccessDescriptor : public MPEGDescriptor
213
class ConditionalAccessDescriptor : public MPEGDescriptor
(-)mythtv/libs/libmythtv/signalmonitor.cpp (-3 / +4 lines)
Lines 23-29 Link Here
23
23
24
#ifdef USING_V4L
24
#ifdef USING_V4L
25
#   include "analogsignalmonitor.h"
25
#   include "analogsignalmonitor.h"
26
#   include "channel.h"
26
#   include "v4lchannel.h"
27
#endif
27
#endif
28
28
29
#ifdef USING_HDHOMERUN
29
#ifdef USING_HDHOMERUN
Lines 93-101 Link Here
93
93
94
#ifdef USING_V4L
94
#ifdef USING_V4L
95
    if ((cardtype.upper() == "V4L") ||
95
    if ((cardtype.upper() == "V4L") ||
96
        (cardtype.upper() == "MPEG"))
96
        (cardtype.upper() == "MPEG") ||
97
        (cardtype.upper() == "HDPVR"))
97
    {
98
    {
98
        Channel *chan = dynamic_cast<Channel*>(channel);
99
        V4LChannel *chan = dynamic_cast<V4LChannel*>(channel);
99
        if (chan)
100
        if (chan)
100
            signalMonitor = new AnalogSignalMonitor(db_cardnum, chan);
101
            signalMonitor = new AnalogSignalMonitor(db_cardnum, chan);
101
    }
102
    }
(-)mythtv/libs/libmythtv/v4lchannel.cpp (+1320 lines)
Line 0 Link Here
1
// Std C headers
2
#include <cstdio>
3
#include <cstdlib>
4
#include <cerrno>
5
6
// POSIX headers
7
#include <unistd.h>
8
#include <fcntl.h>
9
#include <sys/ioctl.h>
10
#include <sys/types.h>
11
#include <sys/stat.h>
12
#include <sys/wait.h>
13
14
// C++ headers
15
#include <algorithm>
16
#include <iostream>
17
using namespace std;
18
19
// Qt headers
20
#include <qsqldatabase.h>
21
22
// MythTV headers
23
#include "videodev_myth.h"
24
#include "v4lchannel.h"
25
#include "frequencies.h"
26
#include "tv_rec.h"
27
#include "mythcontext.h"
28
#include "mythdbcon.h"
29
#include "channelutil.h"
30
#include "cardutil.h"
31
32
#define DEBUG_ATTRIB 1
33
34
#define LOC QString("Channel(%1): ").arg(device)
35
#define LOC_WARN QString("Channel(%1) Warning: ").arg(device)
36
#define LOC_ERR QString("Channel(%1) Error: ").arg(device)
37
38
static int format_to_mode(const QString& fmt, int v4l_version);
39
static QString mode_to_format(int mode, int v4l_version);
40
41
/** \class Channel
42
 *  \brief Class implementing ChannelBase interface to tuning hardware
43
 *         when using Video4Linux based drivers.
44
 */
45
46
V4LChannel::V4LChannel(TVRec *parent, const QString &videodevice)
47
    : DTVChannel(parent),
48
      device(videodevice),          videofd(-1),
49
      device_name(QString::null),   driver_name(QString::null),
50
      curList(NULL),                totalChannels(0),
51
      currentFormat(""),            is_dtv(false),
52
      usingv4l2(false),             defaultFreqTable(1)
53
{
54
}
55
56
V4LChannel::~V4LChannel(void)
57
{
58
    Close();
59
}
60
61
bool V4LChannel::Init(QString &inputname, QString &startchannel, bool setchan)
62
{
63
    if (setchan)
64
    {
65
        SetFormat(gContext->GetSetting("TVFormat"));
66
        SetDefaultFreqTable(gContext->GetSetting("FreqTable"));
67
    }
68
    return ChannelBase::Init(inputname, startchannel, setchan);
69
}
70
71
bool V4LChannel::Open(void)
72
{
73
#if FAKE_VIDEO
74
    return true;
75
#endif
76
    if (videofd >= 0)
77
        return true;
78
79
    videofd = open(device.ascii(), O_RDWR);
80
    if (videofd < 0)
81
    {
82
         VERBOSE(VB_IMPORTANT,
83
                 QString("Channel(%1)::Open(): Can't open video device, "
84
                         "error \"%2\"").arg(device).arg(strerror(errno)));
85
         return false;
86
    }
87
88
    usingv4l2 = CardUtil::hasV4L2(videofd);
89
    CardUtil::GetV4LInfo(videofd, device_name, driver_name);
90
    VERBOSE(VB_CHANNEL, LOC + QString("Device name '%1' driver '%2'.")
91
            .arg(device_name).arg(driver_name));
92
93
    if (!InitializeInputs())
94
    {
95
        Close();
96
        return false;
97
    }
98
99
    SetFormat("Default");
100
101
    return true;
102
}
103
104
void V4LChannel::Close(void)
105
{
106
    if (videofd >= 0)
107
        close(videofd);
108
    videofd = -1;
109
}
110
111
void V4LChannel::SetFd(int fd)
112
{
113
    if (fd != videofd)
114
        Close();
115
    videofd = (fd >= 0) ? fd : -1;
116
}
117
118
static int format_to_mode(const QString &fmt, int v4l_version)
119
{
120
    if (2 == v4l_version)
121
    {
122
        if (fmt == "PAL-BG")
123
            return V4L2_STD_PAL_BG;
124
        else if (fmt == "PAL-D")
125
            return V4L2_STD_PAL_D;
126
        else if (fmt == "PAL-DK")
127
            return V4L2_STD_PAL_DK;
128
        else if (fmt == "PAL-I")
129
            return V4L2_STD_PAL_I;
130
        else if (fmt == "PAL-60")
131
            return V4L2_STD_PAL_60;
132
        else if (fmt == "SECAM")
133
            return V4L2_STD_SECAM;
134
        else if (fmt == "SECAM-D")
135
            return V4L2_STD_SECAM_D;
136
        else if (fmt == "PAL-NC")
137
            return V4L2_STD_PAL_Nc;
138
        else if (fmt == "PAL-M")
139
            return V4L2_STD_PAL_M;
140
        else if (fmt == "PAL-N")
141
            return V4L2_STD_PAL_N;
142
        else if (fmt == "NTSC-JP")
143
            return V4L2_STD_NTSC_M_JP;
144
        // generics...
145
        else if (fmt.left(4) == "NTSC")
146
            return V4L2_STD_NTSC;
147
        else if (fmt.left(4) == "ATSC")
148
            return V4L2_STD_NTSC; // We've dropped V4L ATSC support...
149
        else if (fmt.left(3) == "PAL")
150
            return V4L2_STD_PAL;
151
        return V4L2_STD_NTSC;
152
    }
153
    else if (1 == v4l_version)
154
    {
155
        if (fmt == "NTSC-JP")
156
            return 6;
157
        else if (fmt.left(5) == "SECAM")
158
            return VIDEO_MODE_SECAM;
159
        else if (fmt == "PAL-NC")
160
            return 3;
161
        else if (fmt == "PAL-M")
162
            return 4;
163
        else if (fmt == "PAL-N")
164
            return 5;
165
        // generics...
166
        else if (fmt.left(3) == "PAL")
167
            return VIDEO_MODE_PAL;
168
        else if (fmt.left(4) == "NTSC")
169
            return VIDEO_MODE_NTSC;
170
        else if (fmt.left(4) == "ATSC")
171
            return VIDEO_MODE_NTSC; // We've dropped V4L ATSC support...
172
        return VIDEO_MODE_NTSC;
173
    }
174
175
    VERBOSE(VB_IMPORTANT,
176
            "format_to_mode() does not recognize V4L" << v4l_version);
177
178
    return V4L2_STD_NTSC; // assume V4L version 2
179
}
180
181
static QString mode_to_format(int mode, int v4l_version)
182
{
183
    if (2 == v4l_version)
184
    {
185
        if (mode == V4L2_STD_NTSC)
186
            return "NTSC";
187
        else if (mode == V4L2_STD_NTSC_M_JP)
188
            return "NTSC-JP";
189
        else if (mode == V4L2_STD_PAL)
190
            return "PAL";
191
        else if (mode == V4L2_STD_PAL_60)
192
            return "PAL-60";
193
        else if (mode == V4L2_STD_PAL_BG)
194
            return "PAL-BG";
195
        else if (mode == V4L2_STD_PAL_D)
196
            return "PAL-D";
197
        else if (mode == V4L2_STD_PAL_DK)
198
            return "PAL-DK";
199
        else if (mode == V4L2_STD_PAL_I)
200
            return "PAL-I";
201
        else if (mode == V4L2_STD_PAL_M)
202
            return "PAL-M";
203
        else if (mode == V4L2_STD_PAL_N)
204
            return "PAL-N";
205
        else if (mode == V4L2_STD_PAL_Nc)
206
            return "PAL-NC";
207
        else if (mode == V4L2_STD_SECAM)
208
            return "SECAM";
209
        else if (mode == V4L2_STD_SECAM_D)
210
            return "SECAM-D";
211
        // generic..
212
        else if ((V4L2_STD_NTSC_M      == mode) ||
213
                 (V4L2_STD_NTSC_443    == mode) ||
214
                 (V4L2_STD_NTSC_M_KR   == mode))
215
            return "NTSC";
216
        else if ((V4L2_STD_PAL_B       == mode) ||
217
                 (V4L2_STD_PAL_B1      == mode) ||
218
                 (V4L2_STD_PAL_G       == mode) ||
219
                 (V4L2_STD_PAL_H       == mode) ||
220
                 (V4L2_STD_PAL_D1      == mode) ||
221
                 (V4L2_STD_PAL_K       == mode))
222
            return "PAL";
223
        else if ((V4L2_STD_SECAM_B     == mode) ||
224
                 (V4L2_STD_SECAM_DK    == mode) ||
225
                 (V4L2_STD_SECAM_G     == mode) ||
226
                 (V4L2_STD_SECAM_H     == mode) ||
227
                 (V4L2_STD_SECAM_K     == mode) ||
228
                 (V4L2_STD_SECAM_K1    == mode) ||
229
                 (V4L2_STD_SECAM_L     == mode) ||
230
                 (V4L2_STD_SECAM_LC    == mode))
231
            return "SECAM";
232
        else if ((V4L2_STD_ATSC        == mode) ||
233
                 (V4L2_STD_ATSC_8_VSB  == mode) ||
234
                 (V4L2_STD_ATSC_16_VSB == mode))
235
        {
236
            // We've dropped V4L ATSC support, but this still needs to be
237
            // returned here so we will change the mode if the device is
238
            // in ATSC mode already.
239
            return "ATSC";
240
        }
241
    }
242
    else if (1 == v4l_version)
243
    {
244
        if (mode == VIDEO_MODE_NTSC)
245
            return "NTSC";
246
        else if (mode == VIDEO_MODE_ATSC)
247
            return "ATSC";
248
        else if (mode == VIDEO_MODE_PAL)
249
            return "PAL";
250
        else if (mode == VIDEO_MODE_SECAM)
251
            return "SECAM";
252
        else if (mode == 3)
253
            return "PAL-NC";
254
        else if (mode == 4)
255
            return "PAL-M";
256
        else if (mode == 5)
257
            return "PAL-N";
258
        else if (mode == 6)
259
            return "NTSC-JP";
260
    }
261
    else
262
    {
263
        VERBOSE(VB_IMPORTANT,
264
                "mode_to_format() does not recognize V4L" << v4l_version);
265
    }
266
267
    return "Unknown";
268
}
269
270
/** \fn V4LChannel::InitializeInputs(void)
271
 *  This enumerates the inputs, converts the format
272
 *  string to something the hardware understands, and
273
 *  if the parent pointer is valid retrieves the
274
 *  channels from the database.
275
 */
276
bool V4LChannel::InitializeInputs(void)
277
{
278
    // Get Inputs from DB
279
    if (!ChannelBase::InitializeInputs())
280
        return false;
281
282
    // Get global TVFormat setting
283
    QString fmt = gContext->GetSetting("TVFormat");
284
    VERBOSE(VB_CHANNEL, QString("Global TVFormat Setting '%1'").arg(fmt));
285
    int videomode_v4l1 = format_to_mode(fmt.upper(), 1);
286
    int videomode_v4l2 = format_to_mode(fmt.upper(), 2);
287
288
    bool ok = false;
289
    InputNames v4l_inputs = CardUtil::ProbeV4LVideoInputs(videofd, ok);
290
291
    // Insert info from hardware
292
    uint valid_cnt = 0;
293
    InputMap::const_iterator it;
294
    for (it = inputs.begin(); it != inputs.end(); ++it)
295
    {
296
        InputNames::const_iterator v4l_it = v4l_inputs.begin();
297
        for (; v4l_it != v4l_inputs.end(); ++v4l_it)
298
        {
299
            if (*v4l_it == (*it)->name)
300
            {
301
                (*it)->inputNumV4L   = v4l_it.key();
302
                (*it)->videoModeV4L1 = videomode_v4l1;
303
                (*it)->videoModeV4L2 = videomode_v4l2;
304
                valid_cnt++;
305
            }
306
        }
307
    }
308
309
    // print em
310
    for (it = inputs.begin(); it != inputs.end(); ++it)
311
    {
312
        VERBOSE(VB_CHANNEL, LOC + QString("Input #%1: '%2' schan(%3) "
313
                                          "tun(%4) v4l1(%5) v4l2(%6)")
314
                .arg(it.key()).arg((*it)->name).arg((*it)->startChanNum)
315
                .arg((*it)->tuneToChannel)
316
                .arg(mode_to_format((*it)->videoModeV4L1,1))
317
                .arg(mode_to_format((*it)->videoModeV4L2,2)));
318
    }
319
320
    return valid_cnt;
321
}
322
323
/** \fn V4LChannel::SetFormat(const QString &format)
324
 *  \brief Initializes tuner and modulator variables
325
 *
326
 *  \param format One of twelve formats:
327
 *                "NTSC",   "NTSC-JP", "ATSC",
328
 *                "SECAM",
329
 *                "PAL",    "PAL-BG",  "PAL-DK",   "PAL-I",
330
 *                "PAL-60", "PAL-NC",  "PAL-M", or "PAL-N"
331
 */
332
void V4LChannel::SetFormat(const QString &format)
333
{
334
    if (!Open())
335
        return;
336
337
    int inputNum = currentInputID;
338
    if (currentInputID < 0)
339
        inputNum = GetNextInputNum();
340
341
    QString fmt = format;
342
    if ((fmt == "Default") || format.isEmpty())
343
    {
344
        InputMap::const_iterator it = inputs.find(inputNum);
345
        if (it != inputs.end())
346
            fmt = mode_to_format((*it)->videoModeV4L2, 2);
347
    }
348
349
    VERBOSE(VB_CHANNEL, LOC + QString("SetFormat(%1) fmt(%2) input(%3)")
350
            .arg(format).arg(fmt).arg(inputNum));
351
352
    if ((fmt == currentFormat) || SetInputAndFormat(inputNum, fmt))
353
    {
354
        currentFormat = fmt;
355
        is_dtv        = (fmt == "ATSC");
356
    }
357
}
358
359
int V4LChannel::SetDefaultFreqTable(const QString &name)
360
{
361
    defaultFreqTable = SetFreqTable(name);
362
    return defaultFreqTable;
363
}
364
365
void V4LChannel::SetFreqTable(const int index)
366
{
367
    curList = chanlists[index].list;
368
    totalChannels = chanlists[index].count;
369
}
370
371
int V4LChannel::SetFreqTable(const QString &name)
372
{
373
    int i = 0;
374
    char *listname = (char *)chanlists[i].name;
375
376
    curList = NULL;
377
    while (listname != NULL)
378
    {
379
        if (name == listname)
380
        {
381
            SetFreqTable(i);
382
            return i;
383
        }
384
        i++;
385
        listname = (char *)chanlists[i].name;
386
    }
387
388
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::SetFreqTable(): Invalid "
389
                                "frequency table name %2, using %3.").
390
            arg(device).arg(name).arg((char *)chanlists[1].name));
391
    SetFreqTable(1);
392
    return 1;
393
}
394
395
int V4LChannel::GetCurrentChannelNum(const QString &channame)
396
{
397
    for (int i = 0; i < totalChannels; i++)
398
    {
399
        if (channame == curList[i].name)
400
            return i;
401
    }
402
403
    VERBOSE(VB_IMPORTANT, LOC_ERR +
404
            QString("GetCurrentChannelNum(%1): "
405
                    "Failed to find Channel").arg(channame));
406
407
    return -1;
408
}
409
410
void V4LChannel::SaveCachedPids(const pid_cache_t &pid_cache) const
411
{
412
    int chanid = GetChanID();
413
    if (chanid > 0)
414
        DTVChannel::SaveCachedPids(chanid, pid_cache);
415
}
416
417
void V4LChannel::GetCachedPids(pid_cache_t &pid_cache) const
418
{
419
    int chanid = GetChanID();
420
    if (chanid > 0)
421
        DTVChannel::GetCachedPids(chanid, pid_cache);
422
}
423
424
bool V4LChannel::SetChannelByString(const QString &channum)
425
{
426
    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum);
427
    QString loc_err = loc + ", Error: ";
428
    VERBOSE(VB_CHANNEL, loc);
429
    
430
    if (!Open())
431
    {
432
        VERBOSE(VB_IMPORTANT, loc_err + "Channel object "
433
                "will not open, can not change channels.");
434
435
        return false;
436
    }
437
438
    QString inputName;
439
    if (!CheckChannel(channum, inputName))
440
    {
441
        VERBOSE(VB_IMPORTANT, loc_err +
442
                "CheckChannel failed.\n\t\t\tPlease verify the channel "
443
                "in the 'mythtv-setup' Channel Editor.");
444
445
        return false;
446
    }
447
448
    // If CheckChannel filled in the inputName then we need to
449
    // change inputs and return, since the act of changing
450
    // inputs will change the channel as well.
451
    if (!inputName.isEmpty())
452
        return ChannelBase::SwitchToInput(inputName, channum);
453
454
    ClearDTVInfo();
455
456
    InputMap::const_iterator it = inputs.find(currentInputID);
457
    if (it == inputs.end())
458
        return false;
459
460
    uint mplexid_restriction;
461
    if (!IsInputAvailable(currentInputID, mplexid_restriction))
462
        return false;
463
464
    // Fetch tuning data from the database.
465
    QString tvformat, modulation, freqtable, freqid, dtv_si_std;
466
    int finetune;
467
    uint64_t frequency;
468
    int mpeg_prog_num;
469
    uint atsc_major, atsc_minor, mplexid, tsid, netid;
470
471
    if (!ChannelUtil::GetChannelData(
472
        (*it)->sourceid, channum,
473
        tvformat, modulation, freqtable, freqid,
474
        finetune, frequency,
475
        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
476
        mplexid, commfree))
477
    {
478
        return false;
479
    }
480
481
    if (mplexid_restriction && (mplexid != mplexid_restriction))
482
        return false;
483
484
    // If the frequency is zeroed out, don't use it directly.
485
    bool ok = (frequency > 0);
486
487
    if (!ok)
488
    {
489
        frequency = (freqid.toInt(&ok) + finetune) * 1000;
490
        mplexid = 0;
491
    }
492
    bool isFrequency = ok && (frequency > 10000000);
493
494
    // If we are tuning to a freqid, rather than an actual frequency,
495
    // we need to set the frequency table to use.
496
    if (!isFrequency)
497
    {
498
        if (freqtable == "default" || freqtable.isEmpty())
499
            SetFreqTable(defaultFreqTable);
500
        else
501
            SetFreqTable(freqtable);
502
    }
503
504
    // Set NTSC, PAL, ATSC, etc.
505
    SetFormat(tvformat);
506
507
    // If a tuneToChannel is set make sure we're still on it
508
    if (!(*it)->tuneToChannel.isEmpty() && (*it)->tuneToChannel != "Undefined")
509
        TuneTo((*it)->tuneToChannel, 0);
510
511
    // Tune to proper frequency
512
    if ((*it)->externalChanger.isEmpty())
513
    {
514
        if ((*it)->name.contains("composite", false) ||
515
            (*it)->name.contains("s-video", false))
516
        {
517
            VERBOSE(VB_GENERAL, LOC_WARN + "You have not set "
518
                    "an external channel changing"
519
                    "\n\t\t\tscript for a composite or s-video "
520
                    "input. Channel changing will do nothing.");
521
        }
522
        else if (isFrequency)
523
        {
524
            if (!Tune(frequency, "", (is_dtv) ? "8vsb" : "analog", dtv_si_std))
525
            {
526
                return false;
527
            }
528
        }
529
        else
530
        {
531
            if (!TuneTo(freqid, finetune))
532
                return false;
533
        }
534
    }
535
    else if (!ChangeExternalChannel(freqid))
536
        return false;
537
538
    // Set the current channum to the new channel's channum
539
    curchannelname = QDeepCopy<QString>(channum);
540
541
    // Setup filters & recording picture attributes for framegrabing recorders
542
    // now that the new curchannelname has been established.
543
    if (pParent)
544
        pParent->SetVideoFiltersForChannel(GetCurrentSourceID(), channum);
545
    InitPictureAttributes();
546
547
    // Set the major and minor channel for any additional multiplex tuning
548
    SetDTVInfo(atsc_major, atsc_minor, netid, tsid, mpeg_prog_num);
549
550
    // Set this as the future start channel for this source
551
    inputs[currentInputID]->startChanNum = QDeepCopy<QString>(curchannelname);
552
553
    return true;
554
}
555
556
bool V4LChannel::TuneTo(const QString &channum, int finetune)
557
{
558
    int i = GetCurrentChannelNum(channum);
559
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::TuneTo(%2): "
560
                                "curList[%3].freq(%4)")
561
            .arg(device).arg(channum).arg(i)
562
            .arg((i != -1) ? curList[i].freq : -1));
563
564
    if (i == -1)
565
    {
566
        VERBOSE(VB_IMPORTANT, QString("Channel(%1)::TuneTo(%2): Error, "
567
                                      "failed to find channel.")
568
                .arg(device).arg(channum));
569
        return false;
570
    }
571
572
    int frequency = (curList[i].freq + finetune) * 1000;
573
574
    return Tune(frequency, "", "analog", "analog");
575
}
576
577
bool V4LChannel::Tune(const DTVMultiplex &tuning, QString inputname)
578
{
579
    return Tune(tuning.frequency - 1750000, // to visual carrier
580
                inputname, tuning.modulation.toString(), tuning.sistandard);
581
}
582
583
/** \fn V4LChannel::Tune(uint,QString,QString,QString)
584
 *  \brief Tunes to a specific frequency (Hz) on a particular input, using
585
 *         the specified modulation.
586
 *
587
 *  Note: This function always uses modulator zero.
588
 *
589
 *  \param frequency Frequency in Hz, this is divided by 62.5 kHz or 62.5 Hz
590
 *                   depending on the modulator and sent to the hardware.
591
 *  \param inputname Name of the input (Television, Antenna 1, etc.)
592
 *  \param modulation "radio", "analog", or "digital"
593
 */
594
bool V4LChannel::Tune(uint frequency, QString inputname,
595
                   QString modulation, QString si_std)
596
{
597
    VERBOSE(VB_CHANNEL, LOC + QString("Tune(%1, %2, %3, %4)")
598
            .arg(frequency).arg(inputname).arg(modulation).arg(si_std));
599
600
    int ioctlval = 0;
601
602
    if (modulation == "8vsb")
603
        SetFormat("ATSC");
604
    modulation = (is_dtv) ? "digital" : modulation;
605
606
    int inputnum = GetInputByName(inputname);
607
608
    bool ok = true;
609
    if ((inputnum >= 0) && (GetCurrentInputNum() != inputnum))
610
        ok = SwitchToInput(inputnum, false);
611
    else if (GetCurrentInputNum() < 0)
612
        ok = SwitchToInput(0, false);
613
614
    if (!ok)
615
        return false;
616
617
    // If the frequency is a center frequency and not
618
    // a visual carrier frequency, convert it.
619
    int offset = frequency % 1000000;
620
    offset = (offset > 500000) ? 1000000 - offset : offset;
621
    bool is_visual_carrier = (offset > 150000) && (offset < 350000);
622
    if (!is_visual_carrier && currentFormat == "ATSC")
623
    {
624
        VERBOSE(VB_CHANNEL,  QString("Channel(%1): ").arg(device) +
625
                QString("Converting frequency from center frequency "
626
                        "(%1 Hz) to visual carrier frequency (%2 Hz).")
627
                .arg(frequency).arg(frequency - 1750000));
628
        frequency -= 1750000; // convert to visual carrier
629
    }        
630
631
    // Video4Linux version 2 tuning
632
    if (usingv4l2)
633
    {
634
        bool isTunerCapLow = false;
635
        struct v4l2_modulator mod;
636
        bzero(&mod, sizeof(mod));
637
        mod.index = 0;
638
        ioctlval = ioctl(videofd, VIDIOC_G_MODULATOR, &mod);
639
        if (ioctlval >= 0)
640
        {
641
            isTunerCapLow = (mod.capability & V4L2_TUNER_CAP_LOW);
642
            VERBOSE(VB_CHANNEL, "  name: "<<mod.name);
643
            VERBOSE(VB_CHANNEL, "CapLow: "<<isTunerCapLow);
644
        }
645
646
        struct v4l2_frequency vf;
647
        bzero(&vf, sizeof(vf));
648
649
        vf.tuner = 0; // use first tuner
650
        vf.frequency = (isTunerCapLow) ?
651
            ((int)(frequency / 62.5)) : (frequency / 62500);
652
653
        if (modulation.lower() == "digital")
654
        {
655
            VERBOSE(VB_CHANNEL, "using digital modulation");
656
            vf.type = V4L2_TUNER_DIGITAL_TV;
657
            if (ioctl(videofd, VIDIOC_S_FREQUENCY, &vf)>=0)
658
                return true;
659
            VERBOSE(VB_CHANNEL, "digital modulation failed");
660
        }
661
662
        vf.type = V4L2_TUNER_ANALOG_TV;
663
664
        ioctlval = ioctl(videofd, VIDIOC_S_FREQUENCY, &vf);
665
        if (ioctlval < 0)
666
        {
667
            VERBOSE(VB_IMPORTANT,
668
                    QString("Channel(%1)::Tune(): Error %2 "
669
                            "while setting frequency (v2): %3")
670
                    .arg(device).arg(ioctlval).arg(strerror(errno)));
671
            return false;
672
        }
673
        ioctlval = ioctl(videofd, VIDIOC_G_FREQUENCY, &vf);
674
675
        if (ioctlval >= 0)
676
        {
677
            VERBOSE(VB_CHANNEL, QString(
678
                        "Channel(%1)::Tune(): Frequency is now %2")
679
                    .arg(device).arg(vf.frequency * 62500));
680
        }
681
682
        return true;
683
    }
684
685
    // Video4Linux version 1 tuning
686
    uint freq = frequency / 62500;
687
    ioctlval = ioctl(videofd, VIDIOCSFREQ, &freq);
688
    if (ioctlval < 0)
689
    {
690
        VERBOSE(VB_IMPORTANT,
691
                QString("Channel(%1)::Tune(): Error %2 "
692
                        "while setting frequency (v1): %3")
693
                .arg(device).arg(ioctlval).arg(strerror(errno)));
694
        return false;
695
    }
696
697
    SetSIStandard(si_std);
698
699
    return true;
700
}
701
702
/** \fn V4LChannel::Retune(void)
703
 *  \brief Retunes to last tuned frequency.
704
 *
705
 *  NOTE: This only works for V4L2 and only for analog tuning.
706
 */
707
bool V4LChannel::Retune(void)
708
{
709
    if (usingv4l2)
710
    {
711
        struct v4l2_frequency vf;
712
        bzero(&vf, sizeof(vf));
713
714
        vf.tuner = 0; // use first tuner
715
        vf.type = V4L2_TUNER_ANALOG_TV;
716
717
        // Get the last tuned frequency
718
        int ioctlval = ioctl(videofd, VIDIOC_G_FREQUENCY, &vf);
719
        if (ioctlval < 0)
720
        {
721
            VERBOSE(VB_IMPORTANT, LOC_ERR + "Retune failed (1)" + ENO);
722
            return false;
723
        }
724
725
        // Set the last tuned frequency again...
726
        ioctlval = ioctl(videofd, VIDIOC_S_FREQUENCY, &vf);
727
        if (ioctlval < 0)
728
        {
729
            VERBOSE(VB_IMPORTANT, LOC_ERR + "Retune failed (2)" + ENO);
730
            return false;
731
        }
732
733
        return true;
734
    }
735
736
    return false;
737
}
738
739
// documented in dtvchannel.h
740
bool V4LChannel::TuneMultiplex(uint mplexid, QString inputname)
741
{
742
    VERBOSE(VB_CHANNEL, LOC + QString("TuneMultiplex(%1)").arg(mplexid));
743
744
    QString  modulation;
745
    QString  si_std;
746
    uint64_t frequency;
747
    uint     transportid;
748
    uint     dvb_networkid;
749
750
    if (!ChannelUtil::GetTuningParams(
751
            mplexid, modulation, frequency,
752
            transportid, dvb_networkid, si_std))
753
    {
754
        VERBOSE(VB_IMPORTANT, LOC_ERR + "TuneMultiplex(): " +
755
                QString("Could not find tuning parameters for multiplex %1.")
756
                .arg(mplexid));
757
758
        return false;
759
    }
760
761
    if (!Tune(frequency, inputname, modulation, si_std))
762
        return false;
763
764
    return true;
765
}
766
767
QString V4LChannel::GetFormatForChannel(QString channum, QString inputname)
768
{
769
    MSqlQuery query(MSqlQuery::InitCon());
770
    query.prepare(
771
        "SELECT tvformat "
772
        "FROM channel, cardinput "
773
        "WHERE channum            = :CHANNUM   AND "
774
        "      inputname          = :INPUTNAME AND "
775
        "      cardinput.cardid   = :CARDID    AND "
776
        "      cardinput.sourceid = channel.sourceid");
777
    query.bindValue(":CHANNUM",   channum);
778
    query.bindValue(":INPUTNAME", inputname);
779
    query.bindValue(":CARDID",    GetCardID());
780
781
    QString fmt = QString::null;
782
    if (!query.exec() || !query.isActive())
783
        MythContext::DBError("SwitchToInput:find format", query);
784
    else if (query.next())
785
        fmt = query.value(0).toString();
786
    return fmt;
787
}
788
789
bool V4LChannel::SetInputAndFormat(int inputNum, QString newFmt)
790
{
791
    InputMap::const_iterator it = inputs.find(inputNum);
792
    if (it == inputs.end() || (*it)->inputNumV4L < 0)
793
        return false;
794
795
    int inputNumV4L = (*it)->inputNumV4L;
796
    bool usingv4l1 = !usingv4l2;
797
    bool ok = true;
798
799
    QString msg =
800
        QString("SetInputAndFormat(%1, %2) ").arg(inputNum).arg(newFmt);
801
802
    if (usingv4l2)
803
    {
804
        VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v2)");
805
806
        int ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
807
808
        // ConvertX (wis-go7007) requires streaming to be disabled
809
        // before an input switch, do this if initial switch failed.
810
        bool streamingDisabled = false;
811
        int  streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
812
        if ((ioctlval < 0) && (errno == EBUSY))
813
        {
814
            ioctlval = ioctl(videofd, VIDIOC_STREAMOFF, &streamType);
815
            if (ioctlval < 0)
816
            {
817
                VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
818
                        "\n\t\t\twhile disabling streaming (v4l v2)" + ENO);
819
820
                ok = false;
821
                ioctlval = 0;
822
            }
823
            else
824
            {
825
                streamingDisabled = true;
826
827
                // Resend the input switch ioctl.
828
                ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
829
            }
830
        }
831
832
        if (ioctlval < 0)
833
        {
834
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
835
                    "\n\t\t\twhile setting input (v4l v2)" + ENO);
836
837
            ok = false;
838
        }
839
840
        v4l2_std_id vid_mode = format_to_mode(newFmt, 2);
841
        ioctlval = ioctl(videofd, VIDIOC_S_STD, &vid_mode);
842
        if (ioctlval < 0)
843
        {
844
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
845
                    "\n\t\t\twhile setting format (v4l v2)" + ENO);
846
847
            ok = false;
848
        }
849
850
        // ConvertX (wis-go7007) requires streaming to be disabled
851
        // before an input switch, here we try to re-enable streaming.
852
        if (streamingDisabled)
853
        {
854
            ioctlval = ioctl(videofd, VIDIOC_STREAMON, &streamType);
855
            if (ioctlval < 0)
856
            {
857
                VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
858
                        "\n\t\t\twhile reenabling streaming (v4l v2)" + ENO);
859
860
                ok = false;
861
            }
862
        }
863
    }
864
865
    if (usingv4l1)
866
    {
867
        VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v1)");
868
869
        // read in old settings
870
        struct video_channel set;
871
        bzero(&set, sizeof(set));
872
        ioctl(videofd, VIDIOCGCHAN, &set);
873
874
        // set new settings
875
        set.channel = inputNumV4L;
876
        set.norm    = format_to_mode(newFmt, 1);
877
        int ioctlval = ioctl(videofd, VIDIOCSCHAN, &set);
878
879
        ok = (ioctlval >= 0);
880
        if (!ok)
881
        {
882
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg + 
883
                    "\n\t\t\twhile setting format (v4l v1)" + ENO);
884
        }
885
        else if (usingv4l2)
886
        {
887
            VERBOSE(VB_IMPORTANT, LOC + msg +
888
                    "\n\t\t\tSetting video mode with v4l version 1 worked");
889
        }
890
    }
891
    return ok;
892
}
893
894
bool V4LChannel::SwitchToInput(int inputnum, bool setstarting)
895
{
896
    InputMap::const_iterator it = inputs.find(inputnum);
897
    if (it == inputs.end())
898
        return false;
899
900
    QString tuneFreqId = (*it)->tuneToChannel;
901
    QString channum    = (*it)->startChanNum;
902
    QString inputname  = (*it)->name;
903
904
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::SwitchToInput(in %2, '%3')")
905
            .arg(device).arg(inputnum)
906
            .arg(setstarting ? channum : QString("")));
907
908
    uint mplexid_restriction;
909
    if (!IsInputAvailable(inputnum, mplexid_restriction))
910
        return false;
911
912
    QString newFmt = mode_to_format((*it)->videoModeV4L2, 2);
913
914
    // If we are setting a channel, get its video mode...
915
    bool chanValid  = (channum != "Undefined") && !channum.isEmpty();
916
    if (setstarting && chanValid)
917
    {
918
        QString tmp = GetFormatForChannel(channum, inputname);
919
        if (tmp != "Default" && !tmp.isEmpty())
920
            newFmt = tmp;
921
    }
922
923
    bool ok = SetInputAndFormat(inputnum, newFmt);
924
925
    // Try to set ATSC mode if NTSC fails
926
    if (!ok && newFmt == "NTSC")
927
        ok = SetInputAndFormat(inputnum, "ATSC");
928
929
    if (!ok)
930
    {
931
        VERBOSE(VB_IMPORTANT, LOC + "SetInputAndFormat() failed");
932
        return false;
933
    }
934
935
    currentFormat     = newFmt;
936
    is_dtv            = newFmt == "ATSC";
937
    currentInputID = inputnum;
938
    curchannelname    = ""; // this will be set by SetChannelByString
939
940
    if (!tuneFreqId.isEmpty() && tuneFreqId != "Undefined")
941
        ok = TuneTo(tuneFreqId, 0);
942
943
    if (!ok)
944
        return false;
945
946
    if (setstarting && chanValid)
947
        ok = SetChannelByString(channum);
948
    else if (setstarting && !chanValid)
949
    {
950
        VERBOSE(VB_IMPORTANT, LOC +
951
                QString("SwitchToInput(in %2, set ch): ").arg(inputnum) +
952
                QString("\n\t\t\tDefault channel '%1' is not valid.")
953
                .arg(channum));
954
        ok = false;
955
    }
956
957
    return ok;
958
}
959
960
static unsigned short *get_v4l1_field(
961
    int v4l2_attrib, struct video_picture &vid_pic)
962
{
963
    switch (v4l2_attrib)
964
    {
965
        case V4L2_CID_CONTRAST:
966
            return &vid_pic.contrast;
967
        case V4L2_CID_BRIGHTNESS:
968
            return &vid_pic.brightness;
969
        case V4L2_CID_SATURATION:
970
            return &vid_pic.colour;
971
        case V4L2_CID_HUE:
972
            return &vid_pic.hue;
973
        default:
974
            VERBOSE(VB_IMPORTANT, "get_v4l1_field: "
975
                    "invalid attribute argument "<<v4l2_attrib);
976
    }
977
    return NULL;
978
}
979
980
static int get_v4l2_attribute(const QString &db_col_name)
981
{
982
    if ("brightness" == db_col_name)
983
        return V4L2_CID_BRIGHTNESS;
984
    else if ("contrast" == db_col_name)
985
        return V4L2_CID_CONTRAST;
986
    else if ("colour" == db_col_name)
987
        return V4L2_CID_SATURATION;
988
    else if ("hue" == db_col_name)
989
        return V4L2_CID_HUE;
990
    return -1;
991
}
992
993
bool V4LChannel::InitPictureAttribute(const QString db_col_name)
994
{
995
    if (!pParent || is_dtv)
996
        return false;
997
998
    int v4l2_attrib = get_v4l2_attribute(db_col_name);
999
    if (v4l2_attrib == -1)
1000
        return false;
1001
1002
    int cfield = ChannelUtil::GetChannelValueInt(
1003
        db_col_name, GetCurrentSourceID(), curchannelname);
1004
    int sfield = CardUtil::GetValueInt(
1005
        db_col_name, GetCardID());
1006
1007
    if ((cfield == -1) || (sfield == -1))
1008
        return false;
1009
1010
    int field = (cfield + sfield) & 0xFFFF;
1011
1012
    QString loc = LOC +
1013
        QString("InitPictureAttribute(%1): ").arg(db_col_name, 10);
1014
    QString loc_err = LOC_ERR +
1015
        QString("InitPictureAttribute(%1): ").arg(db_col_name, 10);
1016
1017
    if (usingv4l2)
1018
    {
1019
        struct v4l2_control ctrl;
1020
        struct v4l2_queryctrl qctrl;
1021
        bzero(&ctrl, sizeof(ctrl));
1022
        bzero(&qctrl, sizeof(qctrl));
1023
1024
        ctrl.id = qctrl.id = v4l2_attrib;
1025
        if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1026
        {
1027
            VERBOSE(VB_IMPORTANT, loc_err + "failed to query controls." + ENO);
1028
            return false;
1029
        }
1030
1031
        float new_range = qctrl.maximum - qctrl.minimum;
1032
        float old_range = 65535 - 0;
1033
        float scl_range = new_range / old_range;
1034
        float dfl       = (qctrl.default_value - qctrl.minimum) / new_range;
1035
        int   norm_dfl  = (0x10000 + (int)(dfl * old_range) - 32768) & 0xFFFF;
1036
1037
        if (pict_attr_default.find(db_col_name) == pict_attr_default.end())
1038
        {
1039
            if (device_name == "pcHDTV HD3000 HDTV")
1040
            {
1041
                pict_attr_default["brightness"] = 9830;
1042
                pict_attr_default["contrast"]   = 39322;
1043
                pict_attr_default["colour"]     = 45875;
1044
                pict_attr_default["hue"]        = 0;
1045
            }
1046
            else
1047
            {
1048
                pict_attr_default[db_col_name] = norm_dfl;
1049
            }
1050
        }
1051
1052
        int dfield = pict_attr_default[db_col_name];
1053
        field      = (cfield + sfield + dfield) & 0xFFFF;
1054
        int value0 = (int) ((scl_range * field) + qctrl.minimum);
1055
        int value1 = min(value0, (int)qctrl.maximum);
1056
        ctrl.value = max(value1, (int)qctrl.minimum);
1057
1058
#if DEBUG_ATTRIB
1059
        VERBOSE(VB_CHANNEL, loc + QString(" %1\n\t\t\t"
1060
                                          "[%2,%3] dflt(%4, %5, %6)")
1061
                .arg(value0).arg(qctrl.minimum, 5).arg(qctrl.maximum, 5)
1062
                .arg(qctrl.default_value, 5).arg(dfl, 4, 'f', 2)
1063
                .arg(norm_dfl));
1064
#endif
1065
1066
        if (ioctl(videofd, VIDIOC_S_CTRL, &ctrl) < 0)
1067
        {
1068
            VERBOSE(VB_IMPORTANT, loc_err + "failed to set controls" + ENO);
1069
            return false;
1070
        }
1071
1072
        return true;
1073
    }
1074
1075
    // V4L1
1076
    unsigned short *setfield;
1077
    struct video_picture vid_pic;
1078
    bzero(&vid_pic, sizeof(vid_pic));
1079
1080
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1081
    {
1082
        VERBOSE(VB_IMPORTANT, loc_err + "failed to query controls." + ENO);
1083
        return false;
1084
    }
1085
    setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1086
1087
    if (!setfield)
1088
        return false;
1089
1090
    *setfield = field;
1091
    if (ioctl(videofd, VIDIOCSPICT, &vid_pic) < 0)
1092
    {
1093
        VERBOSE(VB_IMPORTANT, loc_err + "failed to set controls." + ENO);
1094
        return false;
1095
    }
1096
1097
    return true;
1098
}
1099
1100
bool V4LChannel::InitPictureAttributes(void)
1101
{
1102
    return (InitPictureAttribute("brightness") &&
1103
            InitPictureAttribute("contrast")   &&
1104
            InitPictureAttribute("colour")     &&
1105
            InitPictureAttribute("hue"));
1106
}
1107
1108
int V4LChannel::GetPictureAttribute(PictureAttribute attr) const
1109
{
1110
    QString db_col_name = toDBString(attr);
1111
    if (db_col_name.isEmpty())
1112
        return -1;
1113
1114
    int cfield = ChannelUtil::GetChannelValueInt(
1115
        db_col_name, GetCurrentSourceID(), curchannelname);
1116
    int sfield = CardUtil::GetValueInt(
1117
        db_col_name, GetCardID());
1118
    int dfield = 0;
1119
1120
    if (pict_attr_default.find(db_col_name) != pict_attr_default.end())
1121
        dfield = pict_attr_default[db_col_name];
1122
1123
    int val = (cfield + sfield + dfield) & 0xFFFF;
1124
1125
#if DEBUG_ATTRIB
1126
    VERBOSE(VB_CHANNEL, QString(
1127
                "GetPictureAttribute(%1) -> cdb %2 rdb %3 d %4 -> %5")
1128
            .arg(db_col_name).arg(cfield).arg(sfield)
1129
            .arg(dfield).arg(val));
1130
#endif
1131
1132
    return val;
1133
}
1134
1135
static int get_v4l2_attribute_value(int videofd, int v4l2_attrib)
1136
{
1137
    struct v4l2_control ctrl;
1138
    struct v4l2_queryctrl qctrl;
1139
    bzero(&ctrl, sizeof(ctrl));
1140
    bzero(&qctrl, sizeof(qctrl));
1141
1142
    ctrl.id = qctrl.id = v4l2_attrib;
1143
    if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1144
    {
1145
        VERBOSE(VB_IMPORTANT, "get_v4l2_attribute_value: "
1146
                "failed to query controls (1)" + ENO);
1147
        return -1;
1148
    }
1149
1150
    if (ioctl(videofd, VIDIOC_G_CTRL, &ctrl) < 0)
1151
    {
1152
        VERBOSE(VB_IMPORTANT, "get_v4l2_attribute_value: "
1153
                "failed to get controls (2)" + ENO);
1154
        return -1;
1155
    }
1156
1157
    float mult = 65535.0 / (qctrl.maximum - qctrl.minimum);
1158
    return min(max((int)(mult * (ctrl.value - qctrl.minimum)), 0), 65525);
1159
}
1160
1161
static int get_v4l1_attribute_value(int videofd, int v4l2_attrib)
1162
{
1163
    struct video_picture vid_pic;
1164
    bzero(&vid_pic, sizeof(vid_pic));
1165
1166
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1167
    {
1168
        VERBOSE(VB_IMPORTANT, "get_v4l1_attribute_value: "
1169
                "failed to get picture control (1)" + ENO);
1170
        return -1;
1171
    }
1172
1173
    unsigned short *setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1174
    if (setfield)
1175
        return *setfield;
1176
1177
    return -1;
1178
}
1179
1180
static int get_attribute_value(bool usingv4l2, int videofd, int v4l2_attrib)
1181
{
1182
    if (usingv4l2)
1183
        return get_v4l2_attribute_value(videofd, v4l2_attrib);
1184
    return get_v4l1_attribute_value(videofd, v4l2_attrib);
1185
}
1186
1187
static int set_v4l2_attribute_value(int videofd, int v4l2_attrib, int newvalue)
1188
{
1189
    struct v4l2_control ctrl;
1190
    struct v4l2_queryctrl qctrl;
1191
    bzero(&ctrl, sizeof(ctrl));
1192
    bzero(&qctrl, sizeof(qctrl));
1193
1194
    ctrl.id = qctrl.id = v4l2_attrib;
1195
    if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1196
    {
1197
        VERBOSE(VB_IMPORTANT, "set_v4l2_attribute_value: "
1198
                "failed to query control" + ENO);
1199
        return -1;
1200
    }
1201
1202
    float mult = (qctrl.maximum - qctrl.minimum) / 65535.0;
1203
    ctrl.value = (int)(mult * newvalue + qctrl.minimum);
1204
    ctrl.value = min(ctrl.value, qctrl.maximum);
1205
    ctrl.value = max(ctrl.value, qctrl.minimum);
1206
1207
    if (ioctl(videofd, VIDIOC_S_CTRL, &ctrl) < 0)
1208
    {
1209
        VERBOSE(VB_IMPORTANT, "set_v4l2_attribute_value: "
1210
                "failed to set control" + ENO);
1211
        return -1;
1212
    }
1213
1214
    return 0;
1215
}
1216
1217
static int set_v4l1_attribute_value(int videofd, int v4l2_attrib, int newvalue)
1218
{
1219
    unsigned short *setfield;
1220
    struct video_picture vid_pic;
1221
    bzero(&vid_pic, sizeof(vid_pic));
1222
1223
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1224
    {
1225
        VERBOSE(VB_IMPORTANT, "set_v4l1_attribute_value: "
1226
                "failed to get picture control." + ENO);
1227
        return -1;
1228
    }
1229
    setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1230
    if (newvalue != -1 && setfield)
1231
    {
1232
        *setfield = newvalue;
1233
        if (ioctl(videofd, VIDIOCSPICT, &vid_pic) < 0)
1234
        {
1235
            VERBOSE(VB_IMPORTANT, "set_v4l1_attribute_value: "
1236
                    "failed to set picture control." + ENO);
1237
            return -1;
1238
        }
1239
    }
1240
    else
1241
    {
1242
        // ???
1243
        return -1;
1244
    }
1245
1246
    return 0;
1247
}
1248
1249
static int set_attribute_value(bool usingv4l2, int videofd,
1250
                               int v4l2_attrib, int newvalue)
1251
{
1252
    if (usingv4l2)
1253
        return set_v4l2_attribute_value(videofd, v4l2_attrib, newvalue);
1254
    return set_v4l1_attribute_value(videofd, v4l2_attrib, newvalue);
1255
}
1256
1257
int V4LChannel::ChangePictureAttribute(
1258
    PictureAdjustType type, PictureAttribute attr, bool up)
1259
{
1260
    if (!pParent || is_dtv)
1261
        return -1;
1262
1263
    QString db_col_name = toDBString(attr);
1264
    if (db_col_name.isEmpty())
1265
        return -1;
1266
1267
    int v4l2_attrib = get_v4l2_attribute(db_col_name);
1268
    if (v4l2_attrib == -1)
1269
        return -1;
1270
1271
    // get the old attribute value from the hardware, this is
1272
    // just a sanity check on whether this attribute exists
1273
    if (get_attribute_value(usingv4l2, videofd, v4l2_attrib) < 0)
1274
        return -1;
1275
1276
    int old_value = GetPictureAttribute(attr);
1277
    int new_value = old_value + ((up) ? 655 : -655);
1278
1279
    // make sure we are within bounds (wrap around for hue)
1280
    if (V4L2_CID_HUE == v4l2_attrib)
1281
        new_value &= 0xffff;
1282
    new_value = min(max(new_value, 0), 65535);
1283
1284
#if DEBUG_ATTRIB
1285
    VERBOSE(VB_CHANNEL, QString(
1286
                "ChangePictureAttribute(%1,%2,%3) cur %4 -> new %5")
1287
            .arg(type).arg(db_col_name).arg(up)
1288
            .arg(old_value).arg(new_value));
1289
#endif
1290
1291
    // actually set the new attribute value on the hardware
1292
    if (set_attribute_value(usingv4l2, videofd, v4l2_attrib, new_value) < 0)
1293
        return -1;
1294
1295
    // tell the DB about the new attribute value
1296
    if (kAdjustingPicture_Channel == type)
1297
    {
1298
        int adj_value = ChannelUtil::GetChannelValueInt(
1299
            db_col_name, GetCurrentSourceID(), curchannelname);
1300
1301
        int tmp = new_value - old_value + adj_value;
1302
        tmp = (tmp < 0)      ? tmp + 0x10000 : tmp;
1303
        tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;
1304
        ChannelUtil::SetChannelValue(db_col_name, QString::number(tmp),
1305
                                     GetCurrentSourceID(), curchannelname);
1306
    }
1307
    else if (kAdjustingPicture_Recording == type)
1308
    {
1309
        int adj_value = CardUtil::GetValueInt(
1310
            db_col_name, GetCardID());
1311
1312
        int tmp = new_value - old_value + adj_value;
1313
        tmp = (tmp < 0)      ? tmp + 0x10000 : tmp;
1314
        tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;
1315
        CardUtil::SetValue(db_col_name, GetCardID(),
1316
                           GetCurrentSourceID(), tmp);
1317
    }
1318
1319
    return new_value;
1320
}
(-)mythtv/libs/libmythtv/remoteencoder.h (-1 / +1 lines)
Lines 23-29 Link Here
23
    int GetRecorderNumber(void);
23
    int GetRecorderNumber(void);
24
24
25
    ProgramInfo *GetRecording(void);
25
    ProgramInfo *GetRecording(void);
26
    bool IsRecording(void);
26
    bool IsRecording(bool *ok = NULL);
27
    float GetFrameRate(void);
27
    float GetFrameRate(void);
28
    long long GetFramesWritten(void);
28
    long long GetFramesWritten(void);
29
    /// \brief Return value last returned by GetFramesWritten().
29
    /// \brief Return value last returned by GetFramesWritten().
(-)mythtv/libs/libmythtv/cardutil.cpp (-8 / +107 lines)
Lines 114-119 Link Here
114
    return count > 0;
114
    return count > 0;
115
}
115
}
116
116
117
QStringList CardUtil::GetCardTypes(void)
118
{
119
    QStringList cardtypes;
120
121
    MSqlQuery query(MSqlQuery::InitCon());
122
    query.prepare("SELECT DISTINCT cardtype "
123
                  "FROM capturecard "
124
                  "ORDER BY cardtype");
125
126
    if (!query.exec())
127
    {
128
        MythContext::DBError("CardUtil::GetCardTypes()", query);
129
    }
130
    else
131
    {
132
        while (query.next())
133
            cardtypes.push_back(query.value(0).toString());
134
    }
135
136
    return cardtypes;
137
}
138
117
/** \fn CardUtil::GetVideoDevices(const QString&, QString)
139
/** \fn CardUtil::GetVideoDevices(const QString&, QString)
118
 *  \brief Returns the videodevices of the matching cards, duplicates removed
140
 *  \brief Returns the videodevices of the matching cards, duplicates removed
119
 *  \param rawtype  Card type as used in DB or empty string for all cardids
141
 *  \param rawtype  Card type as used in DB or empty string for all cardids
Lines 1365-1371 Link Here
1365
    return !card.isEmpty();
1387
    return !card.isEmpty();
1366
}
1388
}
1367
1389
1368
InputNames CardUtil::probeV4LInputs(int videofd, bool &ok)
1390
InputNames CardUtil::ProbeV4LVideoInputs(int videofd, bool &ok)
1369
{
1391
{
1370
    (void) videofd;
1392
    (void) videofd;
1371
1393
Lines 1430-1435 Link Here
1430
    return list;
1452
    return list;
1431
}
1453
}
1432
1454
1455
InputNames CardUtil::ProbeV4LAudioInputs(int videofd, bool &ok)
1456
{
1457
    (void) videofd;
1458
1459
    InputNames list;
1460
    ok = false;
1461
1462
#ifdef USING_V4L
1463
    bool usingv4l2 = hasV4L2(videofd);
1464
1465
    // V4L v2 query
1466
    struct v4l2_audio ain;
1467
    bzero(&ain, sizeof(ain));
1468
    while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMAUDIO, &ain) >= 0))
1469
    {
1470
        QString input((char *)ain.name);
1471
        list[ain.index] = input;
1472
        ain.index++;
1473
    }
1474
    if (ain.index)
1475
    {
1476
        ok = true;
1477
        return list;
1478
    }
1479
1480
    ok = true;
1481
#else // if !USING_V4L
1482
    list[-1] += QObject::tr(
1483
        "ERROR, Compile with V4L support to query audio inputs");
1484
#endif // !USING_V4L
1485
    return list;
1486
}
1487
1433
InputNames CardUtil::GetConfiguredDVBInputs(uint cardid)
1488
InputNames CardUtil::GetConfiguredDVBInputs(uint cardid)
1434
{
1489
{
1435
    InputNames list;
1490
    InputNames list;
Lines 1450-1456 Link Here
1450
    return list;
1505
    return list;
1451
}
1506
}
1452
1507
1453
QStringList CardUtil::probeInputs(QString device, QString cardtype)
1508
QStringList CardUtil::ProbeVideoInputs(QString device, QString cardtype)
1454
{
1509
{
1455
    QStringList ret;
1510
    QStringList ret;
1456
1511
Lines 1462-1476 Link Here
1462
        ret += "MPEG2TS";
1517
        ret += "MPEG2TS";
1463
    }
1518
    }
1464
    else if ("DVB" == cardtype)
1519
    else if ("DVB" == cardtype)
1465
        ret += probeDVBInputs(device);
1520
        ret += ProbeDVBInputs(device);
1466
    else
1521
    else
1467
        ret += probeV4LInputs(device);
1522
        ret += ProbeV4LVideoInputs(device);
1468
1523
1469
    return ret;
1524
    return ret;
1470
}
1525
}
1471
1526
1472
QStringList CardUtil::probeV4LInputs(QString device)
1527
QStringList CardUtil::ProbeAudioInputs(QString device, QString cardtype)
1473
{
1528
{
1529
    VERBOSE(VB_IMPORTANT, QString("ProbeAudioInputs(%1,%2)").arg(device).arg(cardtype));
1530
    QStringList ret;
1531
1532
    if ("HDPVR" == cardtype)
1533
        ret += ProbeV4LAudioInputs(device);
1534
1535
    return ret;
1536
}
1537
1538
QStringList CardUtil::ProbeV4LVideoInputs(QString device)
1539
{
1474
    bool ok;
1540
    bool ok;
1475
    QStringList ret;
1541
    QStringList ret;
1476
    int videofd = open(device.ascii(), O_RDWR);
1542
    int videofd = open(device.ascii(), O_RDWR);
Lines 1480-1486 Link Here
1480
                           "to probe its inputs.").arg(device);
1546
                           "to probe its inputs.").arg(device);
1481
        return ret;
1547
        return ret;
1482
    }
1548
    }
1483
    InputNames list = CardUtil::probeV4LInputs(videofd, ok);
1549
    InputNames list = CardUtil::ProbeV4LVideoInputs(videofd, ok);
1484
    close(videofd);
1550
    close(videofd);
1485
1551
1486
    if (!ok)
1552
    if (!ok)
Lines 1499-1508 Link Here
1499
    return ret;
1565
    return ret;
1500
}
1566
}
1501
1567
1502
QStringList CardUtil::probeDVBInputs(QString device)
1568
QStringList CardUtil::ProbeV4LAudioInputs(QString device)
1503
{
1569
{
1570
    VERBOSE(VB_IMPORTANT, QString("ProbeV4LAudioInputs(%1)").arg(device));
1571
1572
    bool ok;
1504
    QStringList ret;
1573
    QStringList ret;
1574
    int videofd = open(device.ascii(), O_RDWR);
1575
    if (videofd < 0)
1576
    {
1577
        VERBOSE(VB_IMPORTANT, QString("ProbeAudioInputs() -> couldn't open device"));
1578
        ret += QObject::tr("Could not open '%1' "
1579
                           "to probe its inputs.").arg(device);
1580
        return ret;
1581
    }
1582
    InputNames list = CardUtil::ProbeV4LAudioInputs(videofd, ok);
1583
    close(videofd);
1505
1584
1585
    if (!ok)
1586
    {
1587
        ret += list[-1];
1588
        return ret;
1589
    }
1590
1591
    InputNames::iterator it;
1592
    for (it = list.begin(); it != list.end(); ++it)
1593
    {
1594
        if (it.key() >= 0)
1595
            ret += *it;
1596
    }
1597
1598
    return ret;
1599
}
1600
1601
QStringList CardUtil::ProbeDVBInputs(QString device)
1602
{
1603
    QStringList ret;
1604
1506
#ifdef USING_DVB
1605
#ifdef USING_DVB
1507
    uint cardid = CardUtil::GetFirstCardID(device);
1606
    uint cardid = CardUtil::GetFirstCardID(device);
1508
    if (!cardid)
1607
    if (!cardid)
Lines 1587-1593 Link Here
1587
        inputs += "MPEG2TS";
1686
        inputs += "MPEG2TS";
1588
    }
1687
    }
1589
    else if ("DVB" != cardtype)
1688
    else if ("DVB" != cardtype)
1590
        inputs += probeV4LInputs(device);
1689
        inputs += ProbeV4LVideoInputs(device);
1591
1690
1592
    QString dev_label = GetDeviceLabel(cardid, cardtype, device);
1691
    QString dev_label = GetDeviceLabel(cardid, cardtype, device);
1593
1692
(-)mythtv/libs/libmythtv/siscan.h (-2 / +2 lines)
Lines 20-26 Link Here
20
20
21
class ChannelBase;
21
class ChannelBase;
22
class DTVChannel;
22
class DTVChannel;
23
class Channel;
23
class V4LChannel;
24
class DVBChannel;
24
class DVBChannel;
25
class HDHRChannel;
25
class HDHRChannel;
26
26
Lines 116-122 Link Here
116
  private:
116
  private:
117
    // some useful gets
117
    // some useful gets
118
    DTVChannel       *GetDTVChannel(void);
118
    DTVChannel       *GetDTVChannel(void);
119
    Channel          *GetChannel(void);
119
    V4LChannel       *GetV4LChannel(void);
120
    DVBChannel       *GetDVBChannel(void);
120
    DVBChannel       *GetDVBChannel(void);
121
121
122
    /// \brief Called by SpawnScanner to run scanning thread
122
    /// \brief Called by SpawnScanner to run scanning thread
(-)mythtv/libs/libmythtv/videosource.cpp (-1 / +81 lines)
Lines 1446-1451 Link Here
1446
    input->fillSelections(device);
1446
    input->fillSelections(device);
1447
}
1447
}
1448
1448
1449
HDPVRConfigurationGroup::HDPVRConfigurationGroup(CaptureCard &a_parent) :
1450
    VerticalConfigurationGroup(false, true, false, false),
1451
    parent(a_parent), cardinfo(new TransLabelSetting()),
1452
    videoinput(new TunerCardInput(parent)),
1453
    audioinput(new TunerCardAudioInput(parent, QString::null, "HDPVR"))
1454
{
1455
    VideoDevice *device =
1456
        new VideoDevice(parent, 0, 15, QString::null, "hdpvr");
1457
1458
    cardinfo->setLabel(tr("Probed info"));
1459
1460
    addChild(device);
1461
    addChild(cardinfo);
1462
    addChild(videoinput);
1463
    addChild(audioinput);
1464
1465
    connect(device, SIGNAL(valueChanged(const QString&)),
1466
            this,   SLOT(  probeCard(   const QString&)));
1467
1468
    probeCard(device->getValue());
1469
}
1470
1471
void HDPVRConfigurationGroup::probeCard(const QString &device)
1472
{
1473
    QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
1474
1475
    int videofd = open(device.ascii(), O_RDWR);
1476
    if (videofd >= 0)
1477
    {
1478
        if (!CardUtil::GetV4LInfo(videofd, cn, dn))
1479
            ci = cn = tr("Failed to probe");
1480
        else if (!dn.isEmpty())
1481
            ci = cn + "  [" + dn + "]";
1482
        close(videofd);
1483
    }
1484
1485
    cardinfo->setValue(ci);
1486
    videoinput->fillSelections(device);
1487
    audioinput->fillSelections(device);
1488
}
1489
1449
CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) :
1490
CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) :
1450
    TriggeredConfigurationGroup(true, true, false, false)
1491
    TriggeredConfigurationGroup(true, true, false, false)
1451
{
1492
{
Lines 1462-1467 Link Here
1462
# ifdef USING_IVTV
1503
# ifdef USING_IVTV
1463
    addTarget("MPEG",      new MPEGConfigurationGroup(parent));
1504
    addTarget("MPEG",      new MPEGConfigurationGroup(parent));
1464
# endif // USING_IVTV
1505
# endif // USING_IVTV
1506
# ifdef USING_HDPVR
1507
    addTarget("HDPVR",     new HDPVRConfigurationGroup(parent));
1508
# endif // USING_HDPVR
1465
#endif // USING_V4L
1509
#endif // USING_V4L
1466
1510
1467
#ifdef USING_DVB
1511
#ifdef USING_DVB
Lines 1639-1644 Link Here
1639
    setting->addSelection(
1683
    setting->addSelection(
1640
        QObject::tr("MPEG-2 encoder card (PVR-x50, PVR-500)"), "MPEG");
1684
        QObject::tr("MPEG-2 encoder card (PVR-x50, PVR-500)"), "MPEG");
1641
# endif // USING_IVTV
1685
# endif // USING_IVTV
1686
# ifdef USING_HDPVR
1687
    setting->addSelection(
1688
        QObject::tr("H.264 encoder card (HD-PVR)"), "HDPVR");
1689
# endif // USING_HDPVR
1642
#endif // USING_V4L
1690
#endif // USING_V4L
1643
1691
1644
#ifdef USING_DVB
1692
#ifdef USING_DVB
Lines 2850-2861 Link Here
2850
2898
2851
    last_device = device;
2899
    last_device = device;
2852
    QStringList inputs =
2900
    QStringList inputs =
2853
        CardUtil::probeInputs(device, last_cardtype);
2901
        CardUtil::ProbeVideoInputs(device, last_cardtype);
2854
2902
2855
    for (QStringList::iterator i = inputs.begin(); i != inputs.end(); ++i)
2903
    for (QStringList::iterator i = inputs.begin(); i != inputs.end(); ++i)
2856
        addSelection(*i);
2904
        addSelection(*i);
2857
}
2905
}
2858
2906
2907
TunerCardAudioInput::TunerCardAudioInput(const CaptureCard &parent,
2908
                                         QString dev, QString type) :
2909
    ComboBoxSetting(this), CaptureCardDBStorage(this, parent, "audiodevice"),
2910
    last_device(dev), last_cardtype(type)
2911
{
2912
    setLabel(QObject::tr("Audio input"));
2913
    int cardid = parent.getCardID();
2914
    if (cardid <= 0)
2915
        return;
2916
2917
    last_cardtype = CardUtil::GetRawCardType(cardid);
2918
    last_device   = CardUtil::GetAudioDevice(cardid);
2919
}
2920
2921
void TunerCardAudioInput::fillSelections(const QString &device)
2922
{
2923
    clearSelections();
2924
2925
    if (device.isEmpty())
2926
        return;
2927
2928
    last_device = device;
2929
    QStringList inputs =
2930
        CardUtil::ProbeAudioInputs(device, last_cardtype);
2931
2932
    for (uint i = 0; i < inputs.size(); i++)
2933
    {
2934
        addSelection(inputs[i], QString::number(i),
2935
                     last_device == QString::number(i));
2936
    }
2937
}
2938
2859
DVBConfigurationGroup::DVBConfigurationGroup(CaptureCard& a_parent) :
2939
DVBConfigurationGroup::DVBConfigurationGroup(CaptureCard& a_parent) :
2860
    VerticalConfigurationGroup(false, true, false, false),
2940
    VerticalConfigurationGroup(false, true, false, false),
2861
    parent(a_parent),
2941
    parent(a_parent),
(-)mythtv/libs/libmythtv/remoteencoder.cpp (-1 / +15 lines)
Lines 89-102 Link Here
89
    return sock;
89
    return sock;
90
}
90
}
91
91
92
bool RemoteEncoder::IsRecording(void)
92
bool RemoteEncoder::IsRecording(bool *ok)
93
{
93
{
94
    QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
94
    QStringList strlist = QString("QUERY_RECORDER %1").arg(recordernum);
95
    strlist << "IS_RECORDING";
95
    strlist << "IS_RECORDING";
96
96
97
    SendReceiveStringList(strlist);
97
    SendReceiveStringList(strlist);
98
98
99
    if (strlist.isEmpty())
100
    {
101
        VERBOSE(VB_IMPORTANT,
102
                "RemoteEncoder::IsRecording(), Error: No Reply.");
103
        if (ok)
104
            *ok = false;
105
106
        return false;
107
    }
108
99
    bool retval = strlist[0].toInt();
109
    bool retval = strlist[0].toInt();
110
111
    if (ok)
112
        *ok = true;
113
100
    return retval;
114
    return retval;
101
}
115
}
102
116
(-)mythtv/libs/libmythtv/profilegroup.cpp (-36 / +32 lines)
Lines 4-9 Link Here
4
#include "libmyth/mythcontext.h"
4
#include "libmyth/mythcontext.h"
5
#include "libmyth/mythdbcon.h"
5
#include "libmyth/mythdbcon.h"
6
#include <qsqldatabase.h>
6
#include <qsqldatabase.h>
7
#include "cardutil.h"
7
#include <qheader.h>
8
#include <qheader.h>
8
#include <qcursor.h>
9
#include <qcursor.h>
9
#include <qlayout.h>
10
#include <qlayout.h>
Lines 66-117 Link Here
66
    load();
67
    load();
67
}
68
}
68
69
69
void ProfileGroup::fillSelections(SelectSetting* setting) {
70
void ProfileGroup::fillSelections(SelectSetting* setting)
70
    QStringList cardtypes;
71
{
71
    QString transcodeID;
72
    QStringList cardtypes = CardUtil::GetCardTypes();
73
    QString     tid       = QString::null;
72
74
73
    MSqlQuery result(MSqlQuery::InitCon());
75
    MSqlQuery result(MSqlQuery::InitCon());
76
    result.prepare(
77
        "SELECT name, id, hostname, is_default, cardtype "
78
        "FROM profilegroups");
74
79
75
    result.prepare("SELECT DISTINCT cardtype FROM capturecard;");
80
    if (!result.exec())
76
77
    if (result.exec() && result.isActive() && result.size() > 0)
78
    {
81
    {
79
        while (result.next())
82
        MythContext::DBError("ProfileGroup::fillSelections", result);
80
        {
83
        return;
81
            cardtypes.append(result.value(0).toString());
82
        }
83
    }
84
    }
84
85
85
    result.prepare("SELECT name,id,hostname,is_default,cardtype "
86
    while (result.next())
86
                      "FROM profilegroups;");
87
    {
88
        QString name       = result.value(0).toString();
89
        QString id         = result.value(1).toString();
90
        QString hostname   = result.value(2).toString();
91
        bool    is_default = (bool) result.value(3).toInt();
92
        QString cardtype   = result.value(4).toString();
87
93
88
    if (result.exec() && result.isActive() && result.size() > 0)
94
        // Only show default profiles that match installed cards
89
        while (result.next())
95
        bool have_cardtype = cardtypes.contains(cardtype);
96
        if (is_default && (cardtype == "TRANSCODE") && !have_cardtype)
90
        {
97
        {
91
            // Only show default profiles that match installed cards
98
            tid = id;
92
            if (result.value(3).toInt())
99
        }
93
            {
100
        else if (have_cardtype)
94
               bool match = false;
101
        {
95
               for(QStringList::Iterator it = cardtypes.begin();
102
            if (!hostname.isEmpty())
96
                         it != cardtypes.end(); it++)
103
                name += QString(" (%1)").arg(result.value(2).toString());
97
                   if (result.value(4).toString() == *it)
98
                       match = true;
99
104
100
               if (! match)
105
            setting->addSelection(name, id);
101
               {
102
                   if (result.value(4).toString() == "TRANSCODE")
103
                       transcodeID = result.value(1).toString();
104
                   continue;
105
               }
106
            }
107
            QString value = QString::fromUtf8(result.value(0).toString());
108
            if (result.value(2).toString() != NULL &&
109
                result.value(2).toString() != "")
110
                value += QString(" (%1)").arg(result.value(2).toString());
111
            setting->addSelection(value, result.value(1).toString());
112
        }
106
        }
113
    if (! transcodeID.isNull())
107
    }
114
        setting->addSelection(QObject::tr("Transcoders"), transcodeID);
108
109
    if (!tid.isEmpty())
110
        setting->addSelection(QObject::tr("Transcoders"), tid);
115
}
111
}
116
112
117
QString ProfileGroup::getName(int group)
113
QString ProfileGroup::getName(int group)
(-)mythtv/libs/libmythtv/scanwizardscanner.h (-1 / +1 lines)
Lines 50-56 Link Here
50
class ScanProgressPopup;
50
class ScanProgressPopup;
51
51
52
class ChannelBase;
52
class ChannelBase;
53
class Channel;
53
class V4LChannel;
54
class DVBChannel;
54
class DVBChannel;
55
class SignalMonitorValue;
55
class SignalMonitorValue;
56
56
(-)mythtv/libs/libmythtv/analogsignalmonitor.h (-2 / +2 lines)
Lines 7-19 Link Here
7
// MythTV headers
7
// MythTV headers
8
#include "signalmonitor.h"
8
#include "signalmonitor.h"
9
9
10
class Channel;
10
class V4LChannel;
11
11
12
class AnalogSignalMonitor : public SignalMonitor
12
class AnalogSignalMonitor : public SignalMonitor
13
{
13
{
14
  public:
14
  public:
15
    AnalogSignalMonitor(
15
    AnalogSignalMonitor(
16
        int db_cardnum, Channel *_channel,
16
        int db_cardnum, V4LChannel *_channel,
17
        uint64_t _flags = kDTVSigMon_WaitForSig,
17
        uint64_t _flags = kDTVSigMon_WaitForSig,
18
        const char *_name = "AnalogSignalMonitor");
18
        const char *_name = "AnalogSignalMonitor");
19
19
(-)mythtv/libs/libmythtv/mpegrecorder.cpp (-296 / +837 lines)
Lines 3-8 Link Here
3
// C headers
3
// C headers
4
#include <ctime>
4
#include <ctime>
5
5
6
// C++ headers
7
#include <algorithm>
8
#include <vector>
9
using namespace std;
10
6
// POSIX headers
11
// POSIX headers
7
#include <pthread.h>
12
#include <pthread.h>
8
#include <fcntl.h>
13
#include <fcntl.h>
Lines 15-23 Link Here
15
#include <sys/ioctl.h>
20
#include <sys/ioctl.h>
16
#include <sys/time.h>
21
#include <sys/time.h>
17
22
18
#include <algorithm>
19
using namespace std;
20
21
// avlib headers
23
// avlib headers
22
extern "C" {
24
extern "C" {
23
#include "../libavcodec/avcodec.h"
25
#include "../libavcodec/avcodec.h"
Lines 73-85 Link Here
73
    "Square", "4:3", "16:9", "2.21:1", 0
75
    "Square", "4:3", "16:9", "2.21:1", 0
74
};
76
};
75
77
76
const unsigned int MpegRecorder::kBuildBufferMaxSize = 1024 * 1024;
77
78
MpegRecorder::MpegRecorder(TVRec *rec) :
78
MpegRecorder::MpegRecorder(TVRec *rec) :
79
    RecorderBase(rec),
79
    DTVRecorder(rec),
80
    // Debugging variables
80
    // Debugging variables
81
    deviceIsMpegFile(false),
81
    deviceIsMpegFile(false),
82
    bufferSize(4096),
83
    // Driver info
82
    // Driver info
84
    card(QString::null),      driver(QString::null),
83
    card(QString::null),      driver(QString::null),
85
    version(0),               usingv4l2(false),
84
    version(0),               usingv4l2(false),
Lines 87-97 Link Here
87
    requires_special_pause(false),
86
    requires_special_pause(false),
88
    // State
87
    // State
89
    recording(false),         encoding(false),
88
    recording(false),         encoding(false),
90
    errored(false),
89
    needs_resolution(false),  start_stop_encoding_lock(true),
90
    recording_wait_lock(),    recording_wait(),
91
    // Pausing state
91
    // Pausing state
92
    cleartimeonpause(false),
92
    cleartimeonpause(false),
93
    // Number of frames written
94
    framesWritten(0),
95
    // Encoding info
93
    // Encoding info
96
    width(720),               height(480),
94
    width(720),               height(480),
97
    bitrate(4500),            maxbitrate(6000),
95
    bitrate(4500),            maxbitrate(6000),
Lines 100-114 Link Here
100
    audbitratel1(14),         audbitratel2(14),
98
    audbitratel1(14),         audbitratel2(14),
101
    audbitratel3(10),
99
    audbitratel3(10),
102
    audvolume(80),            language(0),
100
    audvolume(80),            language(0),
101
    low_mpeg4avgbitrate(4500),    low_mpeg4peakbitrate(6000),
102
    medium_mpeg4avgbitrate(9000), medium_mpeg4peakbitrate(13500),
103
    high_mpeg4avgbitrate(13500),  high_mpeg4peakbitrate(20200),
103
    // Input file descriptors
104
    // Input file descriptors
104
    chanfd(-1),               readfd(-1),
105
    chanfd(-1),               readfd(-1),
105
    // Keyframe tracking inforamtion
106
    _device_read_buffer(NULL),
106
    keyframedist(15),         gopset(false),
107
    // TS packet handling
107
    leftovers(0),             lastpackheaderpos(0),
108
    _stream_data(NULL)
108
    lastseqstart(0),          numgops(0),
109
    // buffer used for ...
110
    buildbuffer(new unsigned char[kBuildBufferMaxSize + 1]),
111
    buildbuffersize(0)
112
{
109
{
113
    SetPositionMapType(MARK_GOP_START);
110
    SetPositionMapType(MARK_GOP_START);
114
}
111
}
Lines 116-126 Link Here
116
MpegRecorder::~MpegRecorder()
113
MpegRecorder::~MpegRecorder()
117
{
114
{
118
    TeardownAll();
115
    TeardownAll();
119
    delete [] buildbuffer;
120
}
116
}
121
117
122
void MpegRecorder::TeardownAll(void)
118
void MpegRecorder::TeardownAll(void)
123
{
119
{
120
    StopRecording();
121
124
    if (chanfd >= 0)
122
    if (chanfd >= 0)
125
    {
123
    {
126
        close(chanfd);
124
        close(chanfd);
Lines 191-196 Link Here
191
    }
189
    }
192
    else if (opt == "mpeg2audvolume")
190
    else if (opt == "mpeg2audvolume")
193
        audvolume = value;
191
        audvolume = value;
192
    else if (opt.right(16) == "_mpeg4avgbitrate")
193
    {
194
        if (opt.left(3) == "low")
195
            low_mpeg4avgbitrate = value;
196
        else if (opt.left(6) == "medium")
197
            medium_mpeg4avgbitrate = value;
198
        else if (opt.left(4) == "high")
199
            high_mpeg4avgbitrate = value;
200
        else
201
            RecorderBase::SetOption(opt, value);
202
    }
203
    else if (opt.right(17) == "_mpeg4peakbitrate")
204
    {
205
        if (opt.left(3) == "low")
206
            low_mpeg4peakbitrate = value;
207
        else if (opt.left(6) == "medium")
208
            medium_mpeg4peakbitrate = value;
209
        else if (opt.left(4) == "high")
210
            high_mpeg4peakbitrate = value;
211
        else
212
            RecorderBase::SetOption(opt, value);
213
    }
194
    else
214
    else
195
        RecorderBase::SetOption(opt, value);
215
        RecorderBase::SetOption(opt, value);
196
}
216
}
Lines 287-292 Link Here
287
        SetOption("videodevice", videodev);
307
        SetOption("videodevice", videodev);
288
    }
308
    }
289
309
310
    SetOption("audiodevice", audiodev);
311
290
    SetOption("tvformat", gContext->GetSetting("TVFormat"));
312
    SetOption("tvformat", gContext->GetSetting("TVFormat"));
291
    SetOption("vbiformat", gContext->GetSetting("VbiFormat"));
313
    SetOption("vbiformat", gContext->GetSetting("VbiFormat"));
292
314
Lines 305-312 Link Here
305
327
306
    SetIntOption(profile, "width");
328
    SetIntOption(profile, "width");
307
    SetIntOption(profile, "height");
329
    SetIntOption(profile, "height");
330
331
    SetIntOption(profile, "low_mpeg4avgbitrate");
332
    SetIntOption(profile, "low_mpeg4peakbitrate");
333
    SetIntOption(profile, "medium_mpeg4avgbitrate");
334
    SetIntOption(profile, "medium_mpeg4peakbitrate");
335
    SetIntOption(profile, "high_mpeg4avgbitrate");
336
    SetIntOption(profile, "high_mpeg4peakbitrate");
308
}
337
}
309
338
339
// same as the base class, it just doesn't complain if an option is missing
340
void MpegRecorder::SetIntOption(RecordingProfile *profile, const QString &name)
341
{
342
    const Setting *setting = profile->byName(name);
343
    if (setting)
344
        SetOption(name, setting->getValue().toInt());
345
}
346
347
// same as the base class, it just doesn't complain if an option is missing
348
void MpegRecorder::SetStrOption(RecordingProfile *profile, const QString &name)
349
{
350
    const Setting *setting = profile->byName(name);
351
    if (setting)
352
        SetOption(name, setting->getValue());
353
}
354
310
bool MpegRecorder::OpenMpegFileAsInput(void)
355
bool MpegRecorder::OpenMpegFileAsInput(void)
311
{
356
{
312
    chanfd = readfd = open(videodevice.ascii(), O_RDONLY);
357
    chanfd = readfd = open(videodevice.ascii(), O_RDONLY);
Lines 324-329 Link Here
324
bool MpegRecorder::OpenV4L2DeviceAsInput(void)
369
bool MpegRecorder::OpenV4L2DeviceAsInput(void)
325
{
370
{
326
    chanfd = open(videodevice.ascii(), O_RDWR);
371
    chanfd = open(videodevice.ascii(), O_RDWR);
372
    // open implicitly starts encoding, so we need the lock..
373
    QMutexLocker locker(&start_stop_encoding_lock);
374
327
    if (chanfd < 0)
375
    if (chanfd < 0)
328
    {
376
    {
329
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device. " + ENO);
377
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device. " + ENO);
Lines 334-348 Link Here
334
    {
382
    {
335
        if (driver == "ivtv")
383
        if (driver == "ivtv")
336
        {
384
        {
385
            bufferSize    = 4096;
337
            usingv4l2     = (version >= IVTV_KERNEL_VERSION(0, 8, 0));
386
            usingv4l2     = (version >= IVTV_KERNEL_VERSION(0, 8, 0));
338
            has_v4l2_vbi  = (version >= IVTV_KERNEL_VERSION(0, 3, 8));
387
            has_v4l2_vbi  = (version >= IVTV_KERNEL_VERSION(0, 3, 8));
339
            has_buggy_vbi = true;
388
            has_buggy_vbi = true;
340
            requires_special_pause =
389
            requires_special_pause =
341
                (version >= IVTV_KERNEL_VERSION(0, 10, 0));
390
                (version >= IVTV_KERNEL_VERSION(0, 10, 0));
342
        }
391
        }
392
        else if (driver == "hdpvr")
393
        {
394
            bufferSize = 1500 * TSPacket::SIZE;
395
            usingv4l2 = true;
396
            requires_special_pause = true;
397
398
            bzero(_stream_id,  sizeof(_stream_id));
399
            bzero(_pid_status, sizeof(_pid_status));
400
            memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
401
        }
343
        else
402
        else
344
        {
403
        {
345
            VERBOSE(VB_IMPORTANT, "\n\nNot ivtv driver??\n\n");
404
            VERBOSE(VB_IMPORTANT, "\n\nNot ivtv or hdpvr driver??\n\n");
346
            usingv4l2 = has_v4l2_vbi = true;
405
            usingv4l2 = has_v4l2_vbi = true;
347
            has_buggy_vbi = requires_special_pause = false;
406
            has_buggy_vbi = requires_special_pause = false;
348
        }
407
        }
Lines 352-357 Link Here
352
                                     "has_buggy_vbi(%3)")
411
                                     "has_buggy_vbi(%3)")
353
            .arg(usingv4l2).arg(has_v4l2_vbi).arg(has_buggy_vbi));
412
            .arg(usingv4l2).arg(has_v4l2_vbi).arg(has_buggy_vbi));
354
413
414
415
    if ((driver != "hdpvr") && !SetFormat(chanfd))
416
        return false;
417
418
    if (driver != "hdpvr")
419
    {
420
        SetLanguageMode(chanfd);        // we don't care if this fails...
421
        SetRecordingVolume(chanfd); // we don't care if this fails...
422
    }
423
424
    bool ok = true;
425
    if (usingv4l2)
426
        ok = SetV4L2DeviceOptions(chanfd);
427
    else
428
    {
429
        ok = SetIVTVDeviceOptions(chanfd);
430
        if (!ok)
431
            usingv4l2 = ok = SetV4L2DeviceOptions(chanfd);
432
    }
433
434
    if (!ok)
435
        return false;
436
437
    SetVBIOptions(chanfd);
438
439
    readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
440
441
    if (readfd < 0)
442
    {
443
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO);
444
        return false;
445
    }
446
447
    if (_device_read_buffer)
448
    {
449
        if (_device_read_buffer->IsRunning())
450
            _device_read_buffer->Stop();
451
        
452
        delete _device_read_buffer;
453
        _device_read_buffer = NULL;
454
    }
455
456
    _device_read_buffer = new DeviceReadBuffer(this);
457
    
458
    if (!_device_read_buffer)
459
    {
460
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
461
        _error = true;
462
        return false;   
463
    }
464
465
    if (!_device_read_buffer->Setup(videodevice.ascii(), readfd))
466
    {
467
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
468
        _error = true;
469
        return false;
470
    }
471
472
    VERBOSE(VB_RECORD, LOC + "DRB ready");
473
474
    return true;
475
}
476
477
478
bool MpegRecorder::SetFormat(int chanfd)
479
{
355
    struct v4l2_format vfmt;
480
    struct v4l2_format vfmt;
356
    bzero(&vfmt, sizeof(vfmt));
481
    bzero(&vfmt, sizeof(vfmt));
357
482
Lines 372-385 Link Here
372
        return false;
497
        return false;
373
    }
498
    }
374
499
375
    // Set audio language mode
500
    return true;
376
    bool do_audmode_set = true;
501
}
502
503
/// Set audio language mode
504
bool MpegRecorder::SetLanguageMode(int chanfd)
505
{
377
    struct v4l2_tuner vt;
506
    struct v4l2_tuner vt;
378
    bzero(&vt, sizeof(struct v4l2_tuner));
507
    bzero(&vt, sizeof(struct v4l2_tuner));
379
    if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
508
    if (ioctl(chanfd, VIDIOC_G_TUNER, &vt) < 0)
380
    {
509
    {
381
        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
510
        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get audio mode" + ENO);
382
        do_audmode_set = false;
511
        return false;
383
    }
512
    }
384
513
385
    switch (language)
514
    switch (language)
Lines 401-418 Link Here
401
    }
530
    }
402
531
403
    int audio_layer = GetFilteredAudioLayer();
532
    int audio_layer = GetFilteredAudioLayer();
404
    if (do_audmode_set && (2 == language) && (1 == audio_layer))
533
    bool success = true;
534
    if ((2 == language) && (1 == audio_layer))
405
    {
535
    {
406
        VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio."
536
        VERBOSE(VB_GENERAL, "Dual audio mode incompatible with Layer I audio."
407
                "\n\t\t\tFalling back to Main Language");
537
                "\n\t\t\tFalling back to Main Language");
408
        vt.audmode = V4L2_TUNER_MODE_LANG1;
538
        vt.audmode = V4L2_TUNER_MODE_LANG1;
539
        success = false;
409
    }
540
    }
410
541
411
    if (do_audmode_set && ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
542
    if (ioctl(chanfd, VIDIOC_S_TUNER, &vt) < 0)
412
    {
543
    {
413
        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
544
        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to set audio mode" + ENO);
545
        success = false;
414
    }
546
    }
415
547
548
    return success;
549
}
550
551
bool MpegRecorder::SetRecordingVolume(int chanfd)
552
{
416
    // Get volume min/max values
553
    // Get volume min/max values
417
    struct v4l2_queryctrl qctrl;
554
    struct v4l2_queryctrl qctrl;
418
    qctrl.id = V4L2_CID_AUDIO_VOLUME;
555
    qctrl.id = V4L2_CID_AUDIO_VOLUME;
Lines 440-467 Link Here
440
        VERBOSE(VB_IMPORTANT, LOC_WARN +
577
        VERBOSE(VB_IMPORTANT, LOC_WARN +
441
                "Unable to set recording volume" + ENO + "\n\t\t\t" +
578
                "Unable to set recording volume" + ENO + "\n\t\t\t" +
442
                "If you are using an AverMedia M179 card this is normal.");
579
                "If you are using an AverMedia M179 card this is normal.");
443
    }
444
445
    bool ok = true;
446
    if (usingv4l2)
447
        ok = SetV4L2DeviceOptions(chanfd);
448
    else
449
    {
450
        ok = SetIVTVDeviceOptions(chanfd);
451
        if (!ok)
452
            usingv4l2 = ok = SetV4L2DeviceOptions(chanfd);
453
    }
454
455
    if (!ok)
456
        return false;
580
        return false;
457
458
    SetVBIOptions(chanfd);
459
460
    readfd = open(videodevice.ascii(), O_RDWR | O_NONBLOCK);
461
    if (readfd < 0)
462
    {
463
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Can't open video device." + ENO);
464
        return false;
465
    }
581
    }
466
582
467
    return true;
583
    return true;
Lines 578-584 Link Here
578
        return false;
694
        return false;
579
    }
695
    }
580
696
581
    keyframedist = (ivtvcodec.framerate) ? 12 : keyframedist;
697
    _keyframedist = (ivtvcodec.framerate) ? 12 : _keyframedist;
582
698
583
    return true;
699
    return true;
584
}
700
}
Lines 602-684 Link Here
602
    }
718
    }
603
}
719
}
604
720
605
bool MpegRecorder::SetV4L2DeviceOptions(int chanfd)
721
static void add_ext_ctrl(vector<struct v4l2_ext_control> &ctrl_list,
722
                         uint32_t id, int32_t value)
606
{
723
{
607
    static const uint kNumControls = 7;
724
    struct v4l2_ext_control tmp_ctrl;
608
    struct v4l2_ext_controls ctrls;
725
    bzero(&tmp_ctrl, sizeof(struct v4l2_ext_control));
609
    struct v4l2_ext_control ext_ctrl[kNumControls];
726
    tmp_ctrl.id    = id;
610
    QString control_description[kNumControls] =
727
    tmp_ctrl.value = value;
728
    ctrl_list.push_back(tmp_ctrl);
729
}
730
731
static void set_ctrls(int fd, vector<struct v4l2_ext_control> &ext_ctrls)
732
{
733
    static QMutex control_description_lock;
734
    static QMap<uint32_t,QString> control_description;
735
    
736
    control_description_lock.lock();
737
    if (control_description.isEmpty())
611
    {
738
    {
612
        "Audio Sampling Frequency",
739
        control_description[V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ] =
613
        "Video Aspect ratio",
740
            "Audio Sampling Frequency";
614
        "Audio Encoding",
741
        control_description[V4L2_CID_MPEG_VIDEO_ASPECT] =
615
        "Audio L2 Bitrate",
742
            "Video Aspect ratio";
616
        "Video Peak Bitrate",
743
        control_description[V4L2_CID_MPEG_AUDIO_ENCODING] =
617
        "Video Average Bitrate",
744
            "Audio Encoding";
618
        "MPEG Stream type",
745
        control_description[V4L2_CID_MPEG_AUDIO_L2_BITRATE] =
619
    };
746
            "Audio L2 Bitrate";
747
        control_description[V4L2_CID_MPEG_VIDEO_BITRATE_PEAK] =
748
            "Video Peak Bitrate";
749
        control_description[V4L2_CID_MPEG_VIDEO_BITRATE] =
750
            "Video Average Bitrate";
751
        control_description[V4L2_CID_MPEG_STREAM_TYPE] =
752
            "MPEG Stream type";
753
        control_description[V4L2_CID_MPEG_VIDEO_BITRATE_MODE] =
754
            "MPEG Bitrate mode";
755
    }
756
    control_description_lock.unlock();
620
757
758
    for (uint i = 0; i < ext_ctrls.size(); i++)
759
    {
760
        struct v4l2_ext_controls ctrls;
761
        bzero(&ctrls, sizeof(struct v4l2_ext_controls));
762
763
        int value = ext_ctrls[i].value;
764
765
        ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
766
        ctrls.count       = 1;
767
        ctrls.controls    = &ext_ctrls[i];
768
            
769
        if (ioctl(fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
770
        {
771
            QMutexLocker locker(&control_description_lock);
772
            VERBOSE(VB_IMPORTANT, QString("mpegrecorder.cpp:set_ctrls(): ") +
773
                    QString("Could not set %1 to %2")
774
                    .arg(control_description[ext_ctrls[i].id]).arg(value) +
775
                    ENO);
776
        }
777
    }
778
}
779
780
bool MpegRecorder::SetV4L2DeviceOptions(int chanfd)
781
{
782
    vector<struct v4l2_ext_control> ext_ctrls;
783
621
    // Set controls
784
    // Set controls
622
    bzero(&ctrls,    sizeof(struct v4l2_ext_controls));
785
    if (driver != "hdpvr")
623
    bzero(&ext_ctrl, sizeof(struct v4l2_ext_control) * kNumControls);
786
    {
787
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
788
                     GetFilteredAudioSampleRate());
789
        
790
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_ASPECT,
791
                     aspectratio - 1);
624
792
625
    uint audio_layer = GetFilteredAudioLayer();
793
        uint audio_layer = GetFilteredAudioLayer();
626
    uint audbitrate  = GetFilteredAudioBitRate(audio_layer);
794
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_ENCODING,
795
                     audio_layer - 1);
796
        
797
        uint audbitrate  = GetFilteredAudioBitRate(audio_layer);
798
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_AUDIO_L2_BITRATE,
799
                     audbitrate - 1);
627
800
628
    ext_ctrl[0].id    = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
801
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_STREAM_TYPE,
629
    ext_ctrl[0].value = GetFilteredAudioSampleRate();
802
                     streamtype_ivtv_to_v4l2(GetFilteredStreamType()));
630
803
631
    ext_ctrl[1].id    = V4L2_CID_MPEG_VIDEO_ASPECT;
804
    }
632
    ext_ctrl[1].value = aspectratio - 1;
805
    else
806
    {
807
        maxbitrate = high_mpeg4peakbitrate;
808
        bitrate    = high_mpeg4avgbitrate;
809
    }
810
    maxbitrate = std::max(maxbitrate, bitrate);
633
811
634
    ext_ctrl[2].id    = V4L2_CID_MPEG_AUDIO_ENCODING;
812
    if (driver == "hdpvr")
635
    ext_ctrl[2].value = audio_layer - 1;
813
    {
814
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
815
                     (maxbitrate == bitrate) ?
816
                     V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
817
                     V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
818
    }
636
819
637
    ext_ctrl[3].id    = V4L2_CID_MPEG_AUDIO_L2_BITRATE;
820
    add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
638
    ext_ctrl[3].value = audbitrate - 1;
821
                 bitrate * 1000);
639
822
640
    ext_ctrl[4].id    = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK;
823
    add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
641
    ext_ctrl[4].value = maxbitrate * 1000;
824
                 maxbitrate * 1000);
642
825
643
    ext_ctrl[5].id    = V4L2_CID_MPEG_VIDEO_BITRATE;
826
    set_ctrls(chanfd, ext_ctrls);
644
    ext_ctrl[5].value = (bitrate = min(bitrate, maxbitrate)) * 1000;
645
827
646
    ext_ctrl[6].id    = V4L2_CID_MPEG_STREAM_TYPE;
828
    bool ok;
647
    ext_ctrl[6].value = streamtype_ivtv_to_v4l2(GetFilteredStreamType());
829
    int audioinput = audiodevice.toUInt(&ok);
830
    if (ok)
831
    {
832
        struct v4l2_audio ain;
833
        bzero(&ain, sizeof(ain));
834
        ain.index = audioinput;
835
        if (ioctl(chanfd, VIDIOC_ENUMAUDIO, &ain) < 0)
836
        {
837
            VERBOSE(VB_IMPORTANT, LOC_WARN +
838
                    "Unable to get audio input.");
839
        }
840
        else
841
        {
842
            ain.index = audioinput;
843
            if (ioctl(chanfd, VIDIOC_S_AUDIO, &ain) < 0)
844
            {
845
                VERBOSE(VB_IMPORTANT, LOC_WARN +
846
                        "Unable to set audio input.");
847
            }
848
        }
849
    }
648
850
649
    for (uint i = 0; i < kNumControls; i++)
851
    if (driver != "hdpvr")
650
    {
852
    {
651
        int value = ext_ctrl[i].value;
853
        // Get GOP size in frames
854
        struct v4l2_ext_control ext_ctrl;
855
        struct v4l2_ext_controls ctrls;
652
856
857
        bzero(&ext_ctrl, sizeof(struct v4l2_ext_control));
858
        bzero(&ctrls, sizeof(struct v4l2_ext_controls));
859
860
        ext_ctrl.id    = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
861
        ext_ctrl.value = 0;
862
653
        ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
863
        ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
654
        ctrls.count       = 1;
864
        ctrls.count       = 1;
655
        ctrls.controls    = ext_ctrl + i;
865
        ctrls.controls    = &ext_ctrl;
656
866
657
        if (ioctl(chanfd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0)
867
        if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0)
658
        {
868
        {
659
            VERBOSE(VB_IMPORTANT, LOC_ERR +
869
            VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get "
660
                    QString("Could not set %1 to %2")
870
                    "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO);
661
                    .arg(control_description[i]).arg(value) + ENO);
871
            ext_ctrl.value = 12;
662
        }
872
        }
663
    }
664
873
665
    // Get controls
874
        _keyframedist = ext_ctrl.value;
666
    ext_ctrl[0].id    = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
667
    ext_ctrl[0].value = 0;
668
669
    ctrls.ctrl_class  = V4L2_CTRL_CLASS_MPEG;
670
    ctrls.count       = 1;
671
    ctrls.controls    = ext_ctrl;
672
673
    if (ioctl(chanfd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0)
674
    {
675
        VERBOSE(VB_IMPORTANT, LOC_WARN + "Unable to get "
676
                "V4L2_CID_MPEG_VIDEO_GOP_SIZE, defaulting to 12" + ENO);
677
        ext_ctrl[0].value = 12;
678
    }
875
    }
679
876
680
    keyframedist = ext_ctrl[0].value;
681
682
    return true;
877
    return true;
683
}
878
}
684
879
Lines 687-692 Link Here
687
    if (!vbimode)
882
    if (!vbimode)
688
        return true;
883
        return true;
689
884
885
    if (driver == "hdpvr")
886
        return true;
887
690
    if (has_buggy_vbi)
888
    if (has_buggy_vbi)
691
    {
889
    {
692
        cout<<" *********************** WARNING ***********************"<<endl;
890
        cout<<" *********************** WARNING ***********************"<<endl;
Lines 809-829 Link Here
809
{
1007
{
810
    if (!Open())
1008
    if (!Open())
811
    {
1009
    {
812
	errored = true;
1010
        _error = true;
813
	return;
1011
        return;
814
    }
1012
    }
815
1013
816
    if (!SetupRecording())
1014
    bool has_select = true;
1015
    
1016
#if defined(__FreeBSD__)
1017
    // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
1018
    has_select = false;
1019
#endif
1020
1021
    _start_code = 0xffffffff;
1022
    _last_gop_seen = 0;
1023
    _frames_written_count = 0;
1024
1025
    if (driver == "hdpvr")
817
    {
1026
    {
818
        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup recording.");
1027
        SetPositionMapType(MARK_GOP_BYFRAME);
819
	errored = true;
1028
820
	return;
1029
        int progNum = 1;
1030
        MPEGStreamData *sd = new MPEGStreamData(progNum, true);
1031
        sd->SetRecordingType(_recording_type);
1032
        SetStreamData(sd);
1033
1034
        _stream_data->AddAVListener(this);
1035
        _stream_data->AddWritingListener(this);
1036
1037
        // Make sure the first things in the file are a PAT & PMT
1038
        _wait_for_keyframe_option = false;
1039
        HandleSingleProgramPAT(_stream_data->PATSingleProgram());
1040
        HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
1041
        _wait_for_keyframe_option = true;
821
    }
1042
    }
1043
    else
1044
    {
1045
        SetPositionMapType(MARK_GOP_START);
1046
    }
822
1047
823
    encoding = true;
1048
    encoding = true;
824
    recording = true;
1049
    recording = true;
825
    unsigned char *buffer = new unsigned char[bufferSize + 1];
1050
    unsigned char *buffer = new unsigned char[bufferSize + 1];
826
    int ret;
1051
    int len;
1052
    uint remainder = 0;
827
1053
828
    MythTimer elapsedTimer;
1054
    MythTimer elapsedTimer;
829
    float elapsed;
1055
    float elapsed;
Lines 833-1056 Link Here
833
1059
834
    if (deviceIsMpegFile)
1060
    if (deviceIsMpegFile)
835
        elapsedTimer.start();
1061
        elapsedTimer.start();
1062
    else if (_device_read_buffer)
1063
        _device_read_buffer->Start();
836
1064
837
    while (encoding)
1065
    needs_resolution = (driver == "hdpvr");
1066
1067
    while (encoding && !_error)
838
    {
1068
    {
839
        if (PauseAndWait(100))
1069
        if (PauseAndWait(100))
840
            continue;
1070
            continue;
1071
        HandleResolutionChanges();
841
1072
842
        if ((deviceIsMpegFile) && (framesWritten))
1073
        if (deviceIsMpegFile)
843
        {
1074
        {
844
            elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1075
            if (GetFramesWritten())
845
            while ((framesWritten / elapsed) > 30)
846
            {
1076
            {
847
                usleep(50000);
848
                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1077
                elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1078
                while ((GetFramesWritten() / elapsed) > 30)
1079
                {
1080
                    usleep(50000);
1081
                    elapsed = (elapsedTimer.elapsed() / 1000.0) + 1;
1082
                }
849
            }
1083
            }
850
        }
1084
        }
1085
        else
1086
        {
1087
            if (readfd < 0)
1088
            {
1089
                if (!Open())
1090
                {
1091
                    _error = true;
1092
                    return;
1093
                }
851
1094
852
        if (readfd < 0)
1095
                if (readfd < 0)
853
            readfd = open(videodevice.ascii(), O_RDWR);
1096
                {
1097
                    VERBOSE(VB_IMPORTANT, LOC_ERR +
1098
                            QString("Failed to open device '%1'")
1099
                            .arg(videodevice));
1100
                    continue;
1101
                }
1102
            }
1103
        }
854
1104
855
        tv.tv_sec = 5;
1105
        if (_device_read_buffer)
856
        tv.tv_usec = 0;
857
        FD_ZERO(&rdset);
858
        FD_SET(readfd, &rdset);
859
860
#if defined(__FreeBSD__)
861
        // HACK. FreeBSD PVR150/500 driver doesn't currently support select()
862
#else
863
        switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
864
        {
1106
        {
865
            case -1:
1107
            len = _device_read_buffer->Read(
866
                if (errno == EINTR)
1108
                    &(buffer[remainder]), bufferSize - remainder);
867
                    continue;
868
1109
869
                VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
1110
            // Check for DRB errors
870
                continue;
1111
            if (_device_read_buffer->IsErrored())
1112
            {
1113
                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
871
1114
872
            case 0:
1115
                _device_read_buffer->Stop();
873
                VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
874
                        "ivtv driver has stopped responding");
875
1116
876
                if (close(readfd) != 0)
1117
                QMutexLocker locker(&start_stop_encoding_lock);
1118
1119
                StopEncoding(readfd);
1120
1121
                // Make sure the next things in the file are a PAT & PMT
1122
                if (_stream_data->PATSingleProgram() &&
1123
                    _stream_data->PMTSingleProgram())
877
                {
1124
                {
878
                    VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
1125
                    bool tmp = _wait_for_keyframe_option;
1126
                    _wait_for_keyframe_option = false;
1127
                    HandleSingleProgramPAT(_stream_data->PATSingleProgram());
1128
                    HandleSingleProgramPMT(_stream_data->PMTSingleProgram());
1129
                    _wait_for_keyframe_option = tmp;
879
                }
1130
                }
880
1131
881
                readfd = -1; // Force PVR card to be reopened on next iteration
1132
                if (StartEncoding(readfd))
882
                continue;
1133
                {
1134
                    _device_read_buffer->Start();
1135
                }
1136
                else
1137
                {
1138
                    if (0 != close(readfd))
1139
                        VERBOSE(VB_IMPORTANT, LOC_ERR + "Close error" + ENO);
883
1140
884
           default: break;
1141
                    // Force card to be reopened on next iteration..
1142
                    readfd = -1;
1143
                }
1144
            }
1145
            else if (_device_read_buffer->IsEOF())
1146
            {
1147
                VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
1148
                _error = true;
1149
            }
885
        }
1150
        }
886
#endif
1151
        else
1152
        {
1153
            if (has_select)
1154
            {
1155
                tv.tv_sec = 5;
1156
                tv.tv_usec = 0;
1157
                FD_ZERO(&rdset);
1158
                FD_SET(readfd, &rdset);
887
1159
888
        ret = read(readfd, buffer, bufferSize);
1160
                switch (select(readfd + 1, &rdset, NULL, NULL, &tv))
1161
                {
1162
                    case -1:
1163
                        if (errno == EINTR)
1164
                            continue;
889
1165
890
        if ((ret == 0) &&
1166
                        VERBOSE(VB_IMPORTANT, LOC_ERR + "Select error" + ENO);
891
            (deviceIsMpegFile))
1167
                        continue;
892
        {
893
            close(readfd);
894
            readfd = open(videodevice.ascii(), O_RDONLY);
895
1168
896
            if (readfd >= 0)
1169
                    case 0:
897
                ret = read(readfd, buffer, bufferSize);
1170
                        VERBOSE(VB_IMPORTANT, LOC_ERR + "select timeout - "
898
            if (ret <= 0)
1171
                                "driver has stopped responding");
1172
1173
                        if (close(readfd) != 0)
1174
                        {
1175
                            VERBOSE(VB_IMPORTANT, LOC_ERR +
1176
                                    "Close error" + ENO);
1177
                        }
1178
1179
                        // Force card to be reopened on next iteration..
1180
                        readfd = -1;
1181
                        continue;
1182
1183
                    default:
1184
                        break;
1185
                }                
1186
            }
1187
1188
            len = read(readfd, &(buffer[remainder]), bufferSize - remainder);
1189
1190
            if (len < 0 && !has_select)
899
            {
1191
            {
900
                encoding = false;
1192
                usleep(25 * 1000);
901
                continue;
1193
                continue;
902
            }
1194
            }
1195
1196
            if ((len == 0) && (deviceIsMpegFile))
1197
            {
1198
                close(readfd);
1199
                readfd = open(videodevice.ascii(), O_RDONLY);
1200
1201
                if (readfd >= 0)
1202
                {
1203
                    len = read(readfd,
1204
                               &(buffer[remainder]), bufferSize - remainder);
1205
                }
1206
1207
                if (len <= 0)
1208
                {
1209
                    encoding = false;
1210
                    continue;
1211
                }
1212
            }
1213
            else if (len < 0 && errno != EAGAIN)
1214
            {
1215
                VERBOSE(VB_IMPORTANT,
1216
                        LOC_ERR + QString("error reading from: %1")
1217
                        .arg(videodevice) + ENO);
1218
                continue;
1219
            }
903
        }
1220
        }
904
        else if (ret < 0 && errno != EAGAIN)
1221
1222
        if (len > 0)
905
        {
1223
        {
906
            VERBOSE(VB_IMPORTANT, LOC_ERR + QString("error reading from: %1")
1224
            len += remainder;
907
                    .arg(videodevice) + ENO);
908
1225
909
            continue;
1226
            if (driver == "hdpvr") {
1227
                remainder = _stream_data->ProcessData(buffer, len);
1228
                int start_remain = len - remainder;
1229
                if (remainder && (start_remain >= remainder))
1230
                    memcpy(buffer, buffer+start_remain, remainder);
1231
                else if (remainder)
1232
                    memmove(buffer, buffer+start_remain, remainder);
1233
            }
1234
            else
1235
            {
1236
                FindPSKeyFrames(buffer, len);
1237
            }
910
        }
1238
        }
911
        else if (ret > 0)
912
        {
913
            ProcessData(buffer, ret);
914
        }
915
    }
1239
    }
916
1240
1241
    if (_device_read_buffer)
1242
    {
1243
        if (_device_read_buffer->IsRunning())
1244
            _device_read_buffer->Stop();
1245
1246
        delete _device_read_buffer;
1247
        _device_read_buffer = NULL;
1248
    }
1249
    StopEncoding(readfd);
1250
917
    FinishRecording();
1251
    FinishRecording();
918
1252
919
    delete[] buffer;
1253
    delete[] buffer;
1254
    SetStreamData(NULL);
920
    recording = false;
1255
    recording = false;
1256
    QMutexLocker locker(&recording_wait_lock);
1257
    recording_wait.wakeAll();
921
}
1258
}
922
1259
923
bool MpegRecorder::SetupRecording(void)
1260
bool MpegRecorder::ProcessTSPacket(const TSPacket &tspacket_real)
924
{
1261
{
925
    leftovers = 0xFFFFFFFF;
1262
    const uint pid = tspacket_real.PID();
926
    numgops = 0;
927
    lastseqstart = 0;
928
    return true;
929
}
930
1263
931
void MpegRecorder::FinishRecording(void)
1264
    TSPacket *tspacket_fake = NULL;
932
{
1265
    if ((driver == "hdpvr") && (pid == 0x1001)) // PCRPID for HD-PVR
933
    ringBuffer->WriterFlush();
934
935
    if (curRecording)
936
    {
1266
    {
937
        curRecording->SetFilesize(ringBuffer->GetRealFileSize());
1267
        tspacket_fake = tspacket_real.CreateClone();
938
        SavePositionMap(true);
1268
        uint cc = (_continuity_counter[pid] == 0xFF) ?
1269
            0 : (_continuity_counter[pid] + 1) & 0xf;
1270
        tspacket_fake->SetContinuityCounter(cc);
939
    }
1271
    }
940
    positionMapLock.lock();
941
    positionMap.clear();
942
    positionMapDelta.clear();
943
    positionMapLock.unlock();
944
}
945
1272
946
#define PACK_HEADER   0x000001BA
1273
    const TSPacket *tspacket = (tspacket_fake) ?
947
#define GOP_START     0x000001B8
1274
        tspacket_fake : &tspacket_real;
948
#define SEQ_START     0x000001B3
949
#define SLICE_MIN     0x00000101
950
#define SLICE_MAX     0x000001af
951
1275
952
void MpegRecorder::ProcessData(unsigned char *buffer, int len)
1276
    // Check continuity counter
953
{
1277
    if ((pid != 0x1fff) && !CheckCC(pid, tspacket->ContinuityCounter()))
954
    unsigned char *bufptr = buffer, *bufstart = buffer;
1278
    {
955
    unsigned int state = leftovers, v = 0;
1279
        VERBOSE(VB_RECORD, LOC +
956
    int leftlen = len;
1280
                QString("PID 0x%1 discontinuity detected").arg(pid,0,16));
1281
        _continuity_error_count++;
1282
    }
957
1283
958
    while (bufptr < buffer + len)
1284
    // Only write the packet
1285
    // if audio/video key-frames have been found
1286
    if (!(_wait_for_keyframe_option && _first_keyframe < 0))
959
    {
1287
    {
960
        v = *bufptr++;
1288
        _buffer_packets = true;
961
        if (state == 0x000001)
962
        {
963
            state = ((state << 8) | v) & 0xFFFFFF;
964
            
965
            if (state == PACK_HEADER)
966
            {
967
                long long startpos = ringBuffer->GetWritePosition();
968
                startpos += buildbuffersize + bufptr - bufstart - 4;
969
                lastpackheaderpos = startpos;
970
1289
971
                int curpos = bufptr - bufstart - 4;
1290
        BufferedWrite(*tspacket);
972
                if (curpos < 0)
1291
    }
973
                {
974
                    // header was split
975
                    buildbuffersize += curpos;
976
                    if (buildbuffersize > 0)
977
                        ringBuffer->Write(buildbuffer, buildbuffersize);
978
1292
979
                    buildbuffersize = 4;
1293
    if (tspacket_fake)
980
                    memcpy(buildbuffer, &state, 4);
1294
        delete tspacket_fake;
981
1295
982
                    leftlen = leftlen - curpos + 4;
1296
    return true;
983
                    bufstart = bufptr;
1297
}
984
                }
985
                else
986
                {
987
                    // header was entirely in this packet
988
                    memcpy(buildbuffer + buildbuffersize, bufstart, curpos);
989
                    buildbuffersize += curpos;
990
                    bufstart += curpos;
991
                    leftlen -= curpos;
992
1298
993
                    if (buildbuffersize > 0)
1299
bool MpegRecorder::ProcessVideoTSPacket(const TSPacket &tspacket)
994
                        ringBuffer->Write(buildbuffer, buildbuffersize);
1300
{
1301
    _buffer_packets = !FindH264Keyframes(&tspacket);
1302
    if (!_seen_sps)
1303
        return true;
995
1304
996
                    buildbuffersize = 0;
1305
    return ProcessAVTSPacket(tspacket);
997
                }
1306
}
998
            }
999
1307
1000
            if (state == SEQ_START)
1308
bool MpegRecorder::ProcessAudioTSPacket(const TSPacket &tspacket)
1001
            {
1309
{
1002
                lastseqstart = lastpackheaderpos;
1310
    _buffer_packets = !FindAudioKeyframes(&tspacket);
1003
            }
1311
    return ProcessAVTSPacket(tspacket);
1312
}
1004
1313
1005
            if (state == GOP_START && lastseqstart == lastpackheaderpos)
1314
/// Common code for processing either audio or video packets
1006
            {
1315
bool MpegRecorder::ProcessAVTSPacket(const TSPacket &tspacket)
1007
                framesWritten = numgops * keyframedist;
1316
{
1008
                numgops++;
1317
    const uint pid = tspacket.PID();
1009
                HandleKeyframe();
1318
1010
            }
1319
    // Check continuity counter
1011
        }
1320
    if ((pid != 0x1fff) && !CheckCC(pid, tspacket.ContinuityCounter()))
1012
        else
1321
    {
1013
            state = ((state << 8) | v) & 0xFFFFFF;
1322
        VERBOSE(VB_RECORD, LOC +
1323
                QString("PID 0x%1 discontinuity detected").arg(pid,0,16));
1324
        _continuity_error_count++;
1014
    }
1325
    }
1015
1326
1016
    leftovers = state;
1327
    // Sync recording start to first keyframe
1328
    if (_wait_for_keyframe_option && _first_keyframe < 0)
1329
        return true;
1017
1330
1018
    if (buildbuffersize + leftlen > kBuildBufferMaxSize)
1331
    // Sync streams to the first Payload Unit Start Indicator
1332
    // _after_ first keyframe iff _wait_for_keyframe_option is true
1333
    if (!(_pid_status[pid] & kPayloadStartSeen) && tspacket.HasPayload())
1019
    {
1334
    {
1020
        ringBuffer->Write(buildbuffer, buildbuffersize);
1335
        if (!tspacket.PayloadStart())
1021
        buildbuffersize = 0;
1336
            return true; // not payload start - drop packet
1337
1338
        VERBOSE(VB_RECORD,
1339
                QString("PID 0x%1 Found Payload Start").arg(pid,0,16));
1340
1341
        _pid_status[pid] |= kPayloadStartSeen;
1022
    }
1342
    }
1023
1343
1024
    // copy remaining..
1344
    BufferedWrite(tspacket);
1025
    memcpy(buildbuffer + buildbuffersize, bufstart, leftlen);
1345
1026
    buildbuffersize += leftlen;
1346
    return true;
1027
}
1347
}
1028
1348
1029
void MpegRecorder::StopRecording(void)
1349
void MpegRecorder::StopRecording(void)
1030
{
1350
{
1031
    encoding = false;
1351
    QMutexLocker locker(&recording_wait_lock);
1352
    if (encoding) {
1353
        encoding = false;
1354
        recording_wait.wait(&recording_wait_lock);
1355
    }
1032
}
1356
}
1033
1357
1034
void MpegRecorder::ResetForNewFile(void)
1358
void MpegRecorder::ResetForNewFile(void)
1035
{
1359
{
1036
    errored = false;
1360
    DTVRecorder::ResetForNewFile();
1037
    framesWritten = 0;
1038
    numgops = 0;
1039
    lastseqstart = lastpackheaderpos = 0;
1040
1361
1041
    positionMap.clear();
1362
    bzero(_stream_id,  sizeof(_stream_id));
1042
    positionMapDelta.clear();
1363
    bzero(_pid_status, sizeof(_pid_status));
1364
    memset(_continuity_counter, 0xff, sizeof(_continuity_counter));
1043
}
1365
}
1044
1366
1045
void MpegRecorder::Reset(void)
1367
void MpegRecorder::Reset(void)
1046
{
1368
{
1369
    VERBOSE(VB_RECORD, LOC + "Reset(void)");
1047
    ResetForNewFile();
1370
    ResetForNewFile();
1048
1371
1049
    leftovers = 0xFFFFFFFF;
1372
    _start_code = 0xffffffff;
1050
    buildbuffersize = 0;
1051
1373
1052
    if (curRecording)
1374
    if (curRecording)
1053
        curRecording->ClearPositionMap(MARK_GOP_START);
1375
    {
1376
        curRecording->ClearPositionMap(
1377
            (driver == "hdpvr") ? MARK_GOP_BYFRAME : MARK_GOP_START);
1378
    }
1379
    if (_stream_data)
1380
        _stream_data->Reset(_stream_data->DesiredProgram());
1054
}
1381
}
1055
1382
1056
void MpegRecorder::Pause(bool clear)
1383
void MpegRecorder::Pause(bool clear)
Lines 1064-1152 Link Here
1064
{
1391
{
1065
    if (request_pause)
1392
    if (request_pause)
1066
    {
1393
    {
1394
        QMutex waitlock;
1395
        waitlock.lock();
1396
1067
        if (!paused)
1397
        if (!paused)
1068
        {
1398
        {
1069
            if (requires_special_pause)
1399
            if (_device_read_buffer)
1070
            {
1400
            {
1071
                // Some ivtv drivers require streaming to be disabled before
1401
                QMutex drb_lock;
1072
                // an input switch and other channel format setting.
1402
                drb_lock.lock();
1073
                struct v4l2_encoder_cmd command;
1403
1074
                memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
1404
                _device_read_buffer->SetRequestPause(true);
1075
                command.cmd = V4L2_ENC_CMD_STOP;
1405
1076
                ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
1406
                pauseWait.wait(&drb_lock, timeout);
1077
            }
1407
            }
1408
            else
1409
            {
1410
                paused = true;
1411
                pauseWait.wakeAll();
1412
            }
1078
1413
1079
            paused = true;
1414
            // Some drivers require streaming to be disabled before
1080
            pauseWait.wakeAll();
1415
            // an input switch and other channel format setting.
1416
            if (requires_special_pause)
1417
                StopEncoding(readfd);
1418
1081
            if (tvrec)
1419
            if (tvrec)
1082
                tvrec->RecorderPaused();
1420
                tvrec->RecorderPaused();
1083
        }
1421
        }
1422
1084
        unpauseWait.wait(timeout);
1423
        unpauseWait.wait(timeout);
1085
    }
1424
    }
1086
    if (!request_pause)
1425
    if (!request_pause)
1087
    {
1426
    {
1088
        if (paused)
1427
        if (paused)
1089
        {
1428
        {
1429
            // Some drivers require streaming to be disabled before
1430
            // an input switch and other channel format setting.
1090
            if (requires_special_pause)
1431
            if (requires_special_pause)
1091
            {
1432
                StartEncoding(readfd);
1092
                // Some ivtv drivers require streaming to be disabled before
1433
1093
                // an input switch and other channel format setting.
1434
            if (_device_read_buffer)
1094
                struct v4l2_encoder_cmd command;
1435
                _device_read_buffer->SetRequestPause(false);
1095
                command.cmd = V4L2_ENC_CMD_START;
1436
1096
                ioctl(readfd, VIDIOC_ENCODER_CMD, &command);
1437
            if (_stream_data)
1097
            }
1438
                _stream_data->Reset(_stream_data->DesiredProgram());
1098
        }
1439
        }
1099
        paused = false;
1440
        paused = false;
1100
    }
1441
    }
1101
    return paused;
1442
    return paused;
1102
}
1443
}
1103
1444
1104
long long MpegRecorder::GetKeyframePosition(long long desired)
1445
bool MpegRecorder::StartEncoding(int fd)
1105
{
1446
{
1106
    QMutexLocker locker(&positionMapLock);
1447
    QMutexLocker locker(&start_stop_encoding_lock);
1107
    long long ret = -1;
1108
1448
1109
    if (positionMap.find(desired) != positionMap.end())
1449
    struct v4l2_encoder_cmd command;
1110
        ret = positionMap[desired];
1450
    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
1451
    command.cmd = V4L2_ENC_CMD_START;
1111
1452
1112
    return ret;
1453
    VERBOSE(VB_RECORD, LOC + "StartEncoding");
1454
    needs_resolution = (driver == "hdpvr");
1455
1456
    for (int idx = 0; idx < 10; ++idx)
1457
    {
1458
        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
1459
        {
1460
            VERBOSE(VB_RECORD, LOC + "Encoding started");
1461
            return true;
1462
        }
1463
1464
        if (errno != EAGAIN)
1465
        {
1466
            VERBOSE(VB_IMPORTANT, LOC_ERR + "StartEncoding" + ENO);
1467
            return false;
1468
        }
1469
1470
        usleep(250 * 1000);
1471
    }
1472
1473
    VERBOSE(VB_IMPORTANT, LOC_ERR + "StartEncoding - giving up" + ENO);
1474
    return false;
1113
}
1475
}
1114
1476
1115
// documented in recorderbase.h
1477
bool MpegRecorder::StopEncoding(int fd)
1116
void MpegRecorder::SetNextRecording(const ProgramInfo *progInf, RingBuffer *rb)
1117
{
1478
{
1118
    // First we do some of the time consuming stuff we can do now
1479
    QMutexLocker locker(&start_stop_encoding_lock);
1119
    SavePositionMap(true);
1120
    ringBuffer->WriterFlush();
1121
	if (curRecording)
1122
        curRecording->SetFilesize(ringBuffer->GetRealFileSize());
1123
1480
1124
    // Then we set the next info
1481
    struct v4l2_encoder_cmd command;
1482
    memset(&command, 0, sizeof(struct v4l2_encoder_cmd));
1483
    command.cmd = V4L2_ENC_CMD_STOP;
1484
1485
    VERBOSE(VB_RECORD, LOC + "StopEncoding");
1486
1487
    for (int idx = 0; idx < 10; ++idx)
1125
    {
1488
    {
1126
        QMutexLocker locker(&nextRingBufferLock);
1489
1127
        nextRecording = NULL;
1490
        if (ioctl(fd, VIDIOC_ENCODER_CMD, &command) == 0)
1128
        if (progInf)
1491
        {
1129
            nextRecording = new ProgramInfo(*progInf);
1492
            VERBOSE(VB_RECORD, LOC + "Encoding stopped");
1130
        nextRingBuffer = rb;
1493
            return true;
1494
        }
1495
1496
        if (errno != EAGAIN)
1497
        {
1498
            VERBOSE(VB_IMPORTANT, LOC_ERR + "StopEncoding" + ENO);
1499
            return false;
1500
        }
1501
1502
        usleep(250 * 1000);
1131
    }
1503
    }
1504
1505
    VERBOSE(VB_IMPORTANT, LOC_ERR + "StopEncoding - giving up" + ENO);
1506
    return false;
1132
}
1507
}
1133
1508
1134
/** \fn MpegRecorder::HandleKeyframe(void)
1509
void MpegRecorder::SetStreamData(MPEGStreamData *data)
1135
 *  \brief This save the current frame to the position maps
1136
 *         and handles ringbuffer switching.
1137
 */
1138
void MpegRecorder::HandleKeyframe(void)
1139
{
1510
{
1140
    // Add key frame to position map
1511
    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- begin");
1141
    positionMapLock.lock();
1512
1142
    if (!positionMap.contains(numgops))
1513
    if (data == _stream_data)
1143
    {
1514
    {
1144
        positionMapDelta[numgops] = lastpackheaderpos;
1515
        VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 0");
1145
        positionMap[numgops]      = lastpackheaderpos;
1516
1517
        return;
1146
    }
1518
    }
1147
    positionMapLock.unlock();
1148
1519
1149
    // Perform ringbuffer switch if needed.
1520
    MPEGStreamData *old_data = _stream_data;
1150
    CheckForRingBufferSwitch();
1521
    _stream_data = data;
1522
    if (old_data)
1523
        delete old_data;
1524
1525
    if (data)
1526
    {
1527
        data->AddMPEGSPListener(this);
1528
        data->SetDesiredProgram(1);
1529
    }
1530
1531
    VERBOSE(VB_RECORD, LOC + "SetStreamData("<<data<<") -- end 1");
1151
}
1532
}
1152
1533
1534
void MpegRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
1535
{
1536
    if (!pat)
1537
    {
1538
        VERBOSE(VB_RECORD, LOC + "HandleSingleProgramPAT(NULL)");
1539
        return;
1540
    }
1541
1542
    if (!ringBuffer)
1543
        return;
1544
1545
//    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
1546
1547
    uint next_cc = (pat->tsheader()->ContinuityCounter()+1)&0xf;
1548
    pat->tsheader()->SetContinuityCounter(next_cc);
1549
    DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));
1550
1551
//    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
1552
1553
#if 0
1554
    if (posB[0] + posB[1] * TSPacket::SIZE > 
1555
        posA[0] + posA[1] * TSPacket::SIZE)
1556
    {
1557
        VERBOSE(VB_RECORD, LOC + "Wrote PAT @"
1558
                << posA[0] << " + " << (posA[1] * TSPacket::SIZE));
1559
    }
1560
    else
1561
    {
1562
        VERBOSE(VB_RECORD, LOC + "Saw PAT but did not write to disk yet");
1563
    }
1564
#endif
1565
}
1566
1567
void MpegRecorder::HandleSingleProgramPMT(ProgramMapTable *pmt)
1568
{
1569
    if (!pmt)
1570
{
1571
        return;
1572
    }
1573
1574
    // collect stream types for H.264 (MPEG-4 AVC) keyframe detection
1575
    for (uint i = 0; i < pmt->StreamCount(); i++)
1576
        _stream_id[pmt->StreamPID(i)] = pmt->StreamType(i);
1577
1578
    if (!ringBuffer)
1579
        return;
1580
1581
    unsigned char buf[8 * 1024];
1582
    uint next_cc = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
1583
    pmt->tsheader()->SetContinuityCounter(next_cc);
1584
    uint size = pmt->WriteAsTSPackets(buf, next_cc);
1585
1586
    uint posA[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
1587
1588
    for (uint i = 0; i < size ; i += TSPacket::SIZE)
1589
        DTVRecorder::BufferedWrite(*(reinterpret_cast<TSPacket*>(&buf[i])));
1590
1591
    uint posB[2] = { ringBuffer->GetWritePosition(), _payload_buffer.size() };
1592
1593
#if 0
1594
    if (posB[0] + posB[1] * TSPacket::SIZE > 
1595
        posA[0] + posA[1] * TSPacket::SIZE)
1596
    {
1597
        VERBOSE(VB_RECORD, LOC + "Wrote PMT @"
1598
                << posA[0] << " + " << (posA[1] * TSPacket::SIZE));
1599
    }
1600
    else
1601
    {
1602
        VERBOSE(VB_RECORD, LOC + "Saw PMT but did not write to disk yet");
1603
    }
1604
#endif
1605
}
1606
1607
void MpegRecorder::HandleResolutionChanges(void)
1608
{
1609
    if (!needs_resolution)
1610
        return;
1611
1612
    VERBOSE(VB_RECORD, LOC + "Checking Resolution");
1613
    struct v4l2_format vfmt;
1614
    memset(&vfmt, 0, sizeof(vfmt));
1615
    vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1616
            
1617
    uint pix = 0;
1618
    if (0 == ioctl(chanfd, VIDIOC_G_FMT, &vfmt))
1619
    {
1620
        VERBOSE(VB_RECORD, LOC + QString("Got Resolution %1x%2")
1621
                .arg(vfmt.fmt.pix.width).arg(vfmt.fmt.pix.height));
1622
        pix = vfmt.fmt.pix.width * vfmt.fmt.pix.height;
1623
        needs_resolution = false;
1624
    }
1625
1626
    if (!pix)
1627
        return; // nothing to do, we don't have a resolution yet
1628
1629
    int old_max = maxbitrate, old_avg = bitrate;
1630
    if (pix <= 768*568)
1631
    {
1632
        maxbitrate = low_mpeg4peakbitrate;
1633
        bitrate    = low_mpeg4avgbitrate;
1634
    }
1635
    else if (pix >= 1920*1080)
1636
    {
1637
        maxbitrate = high_mpeg4peakbitrate;
1638
        bitrate    = high_mpeg4avgbitrate;
1639
    }
1640
    else
1641
    {
1642
        maxbitrate = medium_mpeg4peakbitrate;
1643
        bitrate    = medium_mpeg4avgbitrate;
1644
    }
1645
    maxbitrate = std::max(maxbitrate, bitrate);
1646
1647
    if ((old_max != maxbitrate) || (old_avg != bitrate))
1648
    {
1649
        if (old_max == old_avg)
1650
        {
1651
            VERBOSE(VB_RECORD, LOC +
1652
                    QString("Old bitrate %1 CBR").arg(old_avg));
1653
        }
1654
        else
1655
        {
1656
            VERBOSE(VB_RECORD, LOC +
1657
                    QString("Old bitrate %1/%2 VBR")
1658
                    .arg(old_avg).arg(old_max));
1659
        }
1660
1661
        if (maxbitrate == bitrate)
1662
        {
1663
            VERBOSE(VB_RECORD, LOC + QString("New bitrate %1 kbps CBR")
1664
                    .arg(bitrate));
1665
        }
1666
        else
1667
        {
1668
            VERBOSE(VB_RECORD, LOC + QString("New bitrate %1/%2 kbps VBR")
1669
                    .arg(bitrate).arg(maxbitrate));
1670
        }
1671
1672
        vector<struct v4l2_ext_control> ext_ctrls;
1673
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
1674
                     (maxbitrate == bitrate) ?
1675
                     V4L2_MPEG_VIDEO_BITRATE_MODE_CBR :
1676
                     V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
1677
1678
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE,
1679
                     bitrate * 1000);
1680
1681
        add_ext_ctrl(ext_ctrls, V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
1682
                     maxbitrate * 1000);
1683
1684
        set_ctrls(readfd, ext_ctrls);
1685
    }
1686
1687
    // Restart streaming. Shouldn't be needed? seems to be with current driver.
1688
    QMutexLocker locker(&start_stop_encoding_lock);
1689
    StopEncoding(readfd);
1690
    StartEncoding(readfd);
1691
1692
    needs_resolution = false;
1693
}
(-)mythtv/libs/libmythtv/tv_rec.cpp (-6 / +14 lines)
Lines 61-67 Link Here
61
#include "firewirerecorder.h"
61
#include "firewirerecorder.h"
62
62
63
#ifdef USING_V4L
63
#ifdef USING_V4L
64
#include "channel.h"
64
#include "v4lchannel.h"
65
#endif
65
#endif
66
66
67
#define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */
67
#define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */
Lines 202-215 Link Here
202
    else // "V4L" or "MPEG", ie, analog TV
202
    else // "V4L" or "MPEG", ie, analog TV
203
    {
203
    {
204
#ifdef USING_V4L
204
#ifdef USING_V4L
205
        channel = new Channel(this, genOpt.videodev);
205
        channel = new V4LChannel(this, genOpt.videodev);
206
        if (!channel->Open())
206
        if (!channel->Open())
207
            return false;
207
            return false;
208
        InitChannel(genOpt.defaultinput, startchannel);
208
        InitChannel(genOpt.defaultinput, startchannel);
209
        CloseChannel();
209
        CloseChannel();
210
        init_run = true;
210
        init_run = true;
211
#endif
211
#endif
212
        if (genOpt.cardtype != "MPEG")
212
        if ((genOpt.cardtype != "MPEG") && (genOpt.cardtype != "HDPVR"))
213
            rbFileExt = "nuv";
213
            rbFileExt = "nuv";
214
    }
214
    }
215
215
Lines 958-964 Link Here
958
 *  \brief Allocates and initializes the RecorderBase instance.
958
 *  \brief Allocates and initializes the RecorderBase instance.
959
 *
959
 *
960
 *  Based on the card type, one of the possible recorders are started.
960
 *  Based on the card type, one of the possible recorders are started.
961
 *  If the card type is "MPEG" a MpegRecorder is started,
961
 *  If the card type is "MPEG" or "HDPVR" a MpegRecorder is started,
962
 *  if the card type is "HDHOMERUN" a HDHRRecorder is started,
962
 *  if the card type is "HDHOMERUN" a HDHRRecorder is started,
963
 *  if the card type is "FIREWIRE" a FirewireRecorder is started,
963
 *  if the card type is "FIREWIRE" a FirewireRecorder is started,
964
 *  if the card type is "DVB" a DVBRecorder is started,
964
 *  if the card type is "DVB" a DVBRecorder is started,
Lines 976-981 Link Here
976
        recorder = new MpegRecorder(this);
976
        recorder = new MpegRecorder(this);
977
#endif // USING_IVTV
977
#endif // USING_IVTV
978
    }
978
    }
979
    else if (genOpt.cardtype == "HDPVR")
980
    {
981
#ifdef USING_HDPVR
982
        recorder = new MpegRecorder(this);
983
#endif // USING_HDPVR
984
    }
979
    else if (genOpt.cardtype == "FIREWIRE")
985
    else if (genOpt.cardtype == "FIREWIRE")
980
    {
986
    {
981
#ifdef USING_FIREWIRE
987
#ifdef USING_FIREWIRE
Lines 1230-1239 Link Here
1230
#endif // USING_FIREWIRE
1236
#endif // USING_FIREWIRE
1231
}
1237
}
1232
1238
1233
Channel *TVRec::GetV4LChannel(void)
1239
V4LChannel *TVRec::GetV4LChannel(void)
1234
{
1240
{
1235
#ifdef USING_V4L
1241
#ifdef USING_V4L
1236
    return dynamic_cast<Channel*>(channel);
1242
    return dynamic_cast<V4LChannel*>(channel);
1237
#else
1243
#else
1238
    return NULL;
1244
    return NULL;
1239
#endif // USING_V4L
1245
#endif // USING_V4L
Lines 2536-2541 Link Here
2536
    long long bitrate;
2542
    long long bitrate;
2537
    if (genOpt.cardtype == "MPEG")
2543
    if (genOpt.cardtype == "MPEG")
2538
        bitrate = 10080000LL; // use DVD max bit rate
2544
        bitrate = 10080000LL; // use DVD max bit rate
2545
    if (genOpt.cardtype == "HDPVR")
2546
        bitrate = 20200000LL; // Peek bit rate for HD-PVR
2539
    else if (genOpt.cardtype == "DBOX2")
2547
    else if (genOpt.cardtype == "DBOX2")
2540
        bitrate = 10080000LL; // use DVD max bit rate
2548
        bitrate = 10080000LL; // use DVD max bit rate
2541
    else if (!CardUtil::IsEncoder(genOpt.cardtype))
2549
    else if (!CardUtil::IsEncoder(genOpt.cardtype))
(-)mythtv/libs/libmythtv/DeviceReadBuffer.cpp (-2 / +3 lines)
Lines 138-146 Link Here
138
138
139
void DeviceReadBuffer::SetPaused(bool val)
139
void DeviceReadBuffer::SetPaused(bool val)
140
{
140
{
141
    lock.lock();
141
    QMutexLocker locker(&lock);
142
    paused = val;
142
    paused = val;
143
    lock.unlock();
144
    if (val)
143
    if (val)
145
        pauseWait.wakeAll();
144
        pauseWait.wakeAll();
146
    else
145
    else
Lines 155-160 Link Here
155
154
156
bool DeviceReadBuffer::WaitForUnpause(int timeout)
155
bool DeviceReadBuffer::WaitForUnpause(int timeout)
157
{
156
{
157
    QMutexLocker locker(&lock);
158
158
    if (IsPaused())
159
    if (IsPaused())
159
        unpauseWait.wait(timeout);
160
        unpauseWait.wait(timeout);
160
    return IsPaused();
161
    return IsPaused();
(-)mythtv/libs/libmythtv/recordingprofile.cpp (-24 / +69 lines)
Lines 652-683 Link Here
652
    };
652
    };
653
};
653
};
654
654
655
class MPEG2bitrate : public SliderSetting, public CodecParamStorage
655
class AverageBitrate : public SliderSetting, public CodecParamStorage
656
{
656
{
657
  public:
657
  public:
658
    MPEG2bitrate(const RecordingProfile &parent) :
658
    AverageBitrate(const RecordingProfile &parent,
659
        SliderSetting(this, 1000, 16000, 100),
659
                   QString setting = "mpeg2bitrate",
660
        CodecParamStorage(this, parent, "mpeg2bitrate")
660
                   uint min_br = 1000, uint max_br = 16000,
661
                   uint default_br = 4500, uint increment = 100,
662
                   QString label = QString::null) :
663
        SliderSetting(this, min_br, max_br, increment),
664
        CodecParamStorage(this, parent, setting)
661
    {
665
    {
662
666
        if (label.isEmpty())
663
        setLabel(QObject::tr("Bitrate"));
667
            label = QObject::tr("Avg. Bitrate");
664
        setValue(4500);
668
        setLabel(label);
665
        setHelpText(QObject::tr("Bitrate in kilobits/second.  2200Kbps is "
669
        setValue(default_br);
666
                    "approximately 1 Gigabyte per hour."));
670
        setHelpText(QObject::tr(
671
                        "Average bit rate in kilobits/second. "
672
                        "2200Kbps is approximately 1 Gigabyte per hour."));
667
    };
673
    };
668
};
674
};
669
675
670
class MPEG2maxBitrate : public SliderSetting, public CodecParamStorage
676
class PeakBitrate : public SliderSetting, public CodecParamStorage
671
{
677
{
672
  public:
678
  public:
673
    MPEG2maxBitrate(const RecordingProfile &parent) :
679
    PeakBitrate(const RecordingProfile &parent,
674
        SliderSetting(this, 1000, 16000, 100),
680
                QString setting = "mpeg2maxbitrate",
675
        CodecParamStorage(this, parent, "mpeg2maxbitrate")
681
                uint min_br = 1000, uint max_br = 16000,
682
                uint default_br = 6000, uint increment = 100,
683
                QString label = QString::null) :
684
        SliderSetting(this, min_br, max_br, increment),
685
        CodecParamStorage(this, parent, setting)
676
    {
686
    {
677
687
        if (label.isEmpty())
678
        setLabel(QObject::tr("Max. Bitrate"));
688
            label = QObject::tr("Max. Bitrate");
679
        setValue(6000);
689
        setLabel(label);
680
        setHelpText(QObject::tr("Maximum Bitrate in kilobits/second.  "
690
        setValue(default_br);
691
        setHelpText(QObject::tr("Maximum bit rate in kilobits/second. "
681
                    "2200Kbps is approximately 1 Gigabyte per hour."));
692
                    "2200Kbps is approximately 1 Gigabyte per hour."));
682
    };
693
    };
683
};
694
};
Lines 819-825 Link Here
819
830
820
        params = new VerticalConfigurationGroup(false);
831
        params = new VerticalConfigurationGroup(false);
821
        params->setLabel(QObject::tr("MPEG-2 Parameters"));
832
        params->setLabel(QObject::tr("MPEG-2 Parameters"));
822
        params->addChild(new MPEG2bitrate(parent));
833
        params->addChild(new AverageBitrate(parent));
823
        params->addChild(new ScaleBitrate(parent));
834
        params->addChild(new ScaleBitrate(parent));
824
        //params->addChild(new MPEG4MaxQuality(parent));
835
        //params->addChild(new MPEG4MaxQuality(parent));
825
        //params->addChild(new MPEG4MinQuality(parent));
836
        //params->addChild(new MPEG4MinQuality(parent));
Lines 843-859 Link Here
843
        params->setLabel(QObject::tr("MPEG-2 Hardware Encoder"));
854
        params->setLabel(QObject::tr("MPEG-2 Hardware Encoder"));
844
        params->addChild(new MPEG2streamType(parent));
855
        params->addChild(new MPEG2streamType(parent));
845
        params->addChild(new MPEG2aspectRatio(parent));
856
        params->addChild(new MPEG2aspectRatio(parent));
846
        params->addChild(new MPEG2bitrate(parent));
857
        params->addChild(new AverageBitrate(parent));
847
        params->addChild(new MPEG2maxBitrate(parent));
858
        params->addChild(new PeakBitrate(parent));
848
859
849
        addTarget("MPEG-2 Hardware Encoder", params);
860
        addTarget("MPEG-2 Hardware Encoder", params);
861
862
        params = new VerticalConfigurationGroup(false);
863
        params->setLabel(QObject::tr("MPEG-4 AVC Hardware Encoder"));
864
        ConfigurationGroup *h0 = new HorizontalConfigurationGroup(
865
            true, false, true, true);
866
        h0->setLabel(QObject::tr("Low Resolution"));
867
        h0->addChild(new AverageBitrate(parent, "low_mpeg4avgbitrate",
868
                                        1000, 13500, 4500, 500));
869
        h0->addChild(new PeakBitrate(parent, "low_mpeg4peakbitrate",
870
                                     1100, 20200, 6000, 500));
871
        params->addChild(h0);
872
        ConfigurationGroup *h1 = new HorizontalConfigurationGroup(
873
            true, false, true, true);
874
        h1->setLabel(QObject::tr("Medium Resolution"));
875
        h1->addChild(new AverageBitrate(parent, "medium_mpeg4avgbitrate",
876
                                        1000, 13500, 9000, 500));
877
        h1->addChild(new PeakBitrate(parent, "medium_mpeg4peakbitrate",
878
                                     1100, 20200, 11000, 500));
879
        params->addChild(h1);
880
        ConfigurationGroup *h2 = new HorizontalConfigurationGroup(
881
            true, false, true, true);
882
        h2->setLabel(QObject::tr("High Resolution"));
883
        h2->addChild(new AverageBitrate(parent, "high_mpeg4avgbitrate",
884
                                        1000, 13500, 13500, 500));
885
        h2->addChild(new PeakBitrate(parent, "high_mpeg4peakbitrate",
886
                                     1100, 20200, 20200, 500));
887
        params->addChild(h2);
888
        addTarget("MPEG-4 AVC Hardware Encoder", params);
850
    }
889
    }
851
890
852
    void selectCodecs(QString groupType)
891
    void selectCodecs(QString groupType)
853
    {
892
    {
854
        if (!groupType.isNull())
893
        if (!groupType.isNull())
855
        {
894
        {
856
            if (groupType == "MPEG")
895
            if (groupType == "HDPVR")
896
               codecName->addSelection("MPEG-4 AVC Hardware Encoder");
897
            else if (groupType == "MPEG")
857
               codecName->addSelection("MPEG-2 Hardware Encoder");
898
               codecName->addSelection("MPEG-2 Hardware Encoder");
858
            else if (groupType == "MJPEG")
899
            else if (groupType == "MJPEG")
859
                codecName->addSelection("Hardware MJPEG");
900
                codecName->addSelection("Hardware MJPEG");
Lines 1210-1222 Link Here
1210
    if (isEncoder)
1251
    if (isEncoder)
1211
    {
1252
    {
1212
        QString tvFormat = gContext->GetSetting("TVFormat");
1253
        QString tvFormat = gContext->GetSetting("TVFormat");
1213
        addChild(new ImageSize(*this, tvFormat, profileName));
1254
        if (type.upper() != "HDPVR")
1255
            addChild(new ImageSize(*this, tvFormat, profileName));
1214
1256
1215
        videoSettings = new VideoCompressionSettings(*this, profileName);
1257
        videoSettings = new VideoCompressionSettings(*this, profileName);
1216
        addChild(videoSettings);
1258
        addChild(videoSettings);
1217
1259
1218
        audioSettings = new AudioCompressionSettings(*this, profileName);
1260
        if (type.upper() != "HDPVR")
1219
        addChild(audioSettings);
1261
        {
1262
            audioSettings = new AudioCompressionSettings(*this, profileName);
1263
            addChild(audioSettings);
1264
        }
1220
1265
1221
        if (profileName && profileName.left(11) == "Transcoders")
1266
        if (profileName && profileName.left(11) == "Transcoders")
1222
        {
1267
        {
(-)mythtv/libs/libmythtv/tv_rec.h (-2 / +2 lines)
Lines 37-43 Link Here
37
class DTVChannel;
37
class DTVChannel;
38
class DVBChannel;
38
class DVBChannel;
39
class FirewireChannel;
39
class FirewireChannel;
40
class Channel;
40
class V4LChannel;
41
class HDHRChannel;
41
class HDHRChannel;
42
42
43
class MPEGStreamData;
43
class MPEGStreamData;
Lines 281-287 Link Here
281
    HDHRChannel  *GetHDHRChannel(void);
281
    HDHRChannel  *GetHDHRChannel(void);
282
    DVBChannel   *GetDVBChannel(void);
282
    DVBChannel   *GetDVBChannel(void);
283
    FirewireChannel *GetFirewireChannel(void);
283
    FirewireChannel *GetFirewireChannel(void);
284
    Channel      *GetV4LChannel(void);
284
    V4LChannel   *GetV4LChannel(void);
285
285
286
    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
286
    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
287
    bool SetupDTVSignalMonitor(void);
287
    bool SetupDTVSignalMonitor(void);
(-)mythtv/libs/libmythtv/scanwizardhelpers.cpp (+3 lines)
Lines 58-63 Link Here
58
# ifdef USING_IVTV
58
# ifdef USING_IVTV
59
    cardTypes += ",'MPEG'";
59
    cardTypes += ",'MPEG'";
60
# endif // USING_IVTV
60
# endif // USING_IVTV
61
# ifdef USING_HDPVR
62
    cardTypes += ",'HDPVR'";
63
# endif // USING_HDPVR
61
#endif // USING_V4L
64
#endif // USING_V4L
62
65
63
#ifdef USING_IPTV
66
#ifdef USING_IPTV
(-)mythtv/libs/libmythtv/channel.cpp (-1320 lines)
Lines 1-1320 Link Here
1
// Std C headers
2
#include <cstdio>
3
#include <cstdlib>
4
#include <cerrno>
5
6
// POSIX headers
7
#include <unistd.h>
8
#include <fcntl.h>
9
#include <sys/ioctl.h>
10
#include <sys/types.h>
11
#include <sys/stat.h>
12
#include <sys/wait.h>
13
14
// C++ headers
15
#include <algorithm>
16
#include <iostream>
17
using namespace std;
18
19
// Qt headers
20
#include <qsqldatabase.h>
21
22
// MythTV headers
23
#include "videodev_myth.h"
24
#include "channel.h"
25
#include "frequencies.h"
26
#include "tv_rec.h"
27
#include "mythcontext.h"
28
#include "mythdbcon.h"
29
#include "channelutil.h"
30
#include "cardutil.h"
31
32
#define DEBUG_ATTRIB 1
33
34
#define LOC QString("Channel(%1): ").arg(device)
35
#define LOC_WARN QString("Channel(%1) Warning: ").arg(device)
36
#define LOC_ERR QString("Channel(%1) Error: ").arg(device)
37
38
static int format_to_mode(const QString& fmt, int v4l_version);
39
static QString mode_to_format(int mode, int v4l_version);
40
41
/** \class Channel
42
 *  \brief Class implementing ChannelBase interface to tuning hardware
43
 *         when using Video4Linux based drivers.
44
 */
45
46
Channel::Channel(TVRec *parent, const QString &videodevice)
47
    : DTVChannel(parent),
48
      device(videodevice),          videofd(-1),
49
      device_name(QString::null),   driver_name(QString::null),
50
      curList(NULL),                totalChannels(0),
51
      currentFormat(""),            is_dtv(false),
52
      usingv4l2(false),             defaultFreqTable(1)
53
{
54
}
55
56
Channel::~Channel(void)
57
{
58
    Close();
59
}
60
61
bool Channel::Init(QString &inputname, QString &startchannel, bool setchan)
62
{
63
    if (setchan)
64
    {
65
        SetFormat(gContext->GetSetting("TVFormat"));
66
        SetDefaultFreqTable(gContext->GetSetting("FreqTable"));
67
    }
68
    return ChannelBase::Init(inputname, startchannel, setchan);
69
}
70
71
bool Channel::Open(void)
72
{
73
#if FAKE_VIDEO
74
    return true;
75
#endif
76
    if (videofd >= 0)
77
        return true;
78
79
    videofd = open(device.ascii(), O_RDWR);
80
    if (videofd < 0)
81
    {
82
         VERBOSE(VB_IMPORTANT,
83
                 QString("Channel(%1)::Open(): Can't open video device, "
84
                         "error \"%2\"").arg(device).arg(strerror(errno)));
85
         return false;
86
    }
87
88
    usingv4l2 = CardUtil::hasV4L2(videofd);
89
    CardUtil::GetV4LInfo(videofd, device_name, driver_name);
90
    VERBOSE(VB_CHANNEL, LOC + QString("Device name '%1' driver '%2'.")
91
            .arg(device_name).arg(driver_name));
92
93
    if (!InitializeInputs())
94
    {
95
        Close();
96
        return false;
97
    }
98
99
    SetFormat("Default");
100
101
    return true;
102
}
103
104
void Channel::Close(void)
105
{
106
    if (videofd >= 0)
107
        close(videofd);
108
    videofd = -1;
109
}
110
111
void Channel::SetFd(int fd)
112
{
113
    if (fd != videofd)
114
        Close();
115
    videofd = (fd >= 0) ? fd : -1;
116
}
117
118
static int format_to_mode(const QString &fmt, int v4l_version)
119
{
120
    if (2 == v4l_version)
121
    {
122
        if (fmt == "PAL-BG")
123
            return V4L2_STD_PAL_BG;
124
        else if (fmt == "PAL-D")
125
            return V4L2_STD_PAL_D;
126
        else if (fmt == "PAL-DK")
127
            return V4L2_STD_PAL_DK;
128
        else if (fmt == "PAL-I")
129
            return V4L2_STD_PAL_I;
130
        else if (fmt == "PAL-60")
131
            return V4L2_STD_PAL_60;
132
        else if (fmt == "SECAM")
133
            return V4L2_STD_SECAM;
134
        else if (fmt == "SECAM-D")
135
            return V4L2_STD_SECAM_D;
136
        else if (fmt == "PAL-NC")
137
            return V4L2_STD_PAL_Nc;
138
        else if (fmt == "PAL-M")
139
            return V4L2_STD_PAL_M;
140
        else if (fmt == "PAL-N")
141
            return V4L2_STD_PAL_N;
142
        else if (fmt == "NTSC-JP")
143
            return V4L2_STD_NTSC_M_JP;
144
        // generics...
145
        else if (fmt.left(4) == "NTSC")
146
            return V4L2_STD_NTSC;
147
        else if (fmt.left(4) == "ATSC")
148
            return V4L2_STD_NTSC; // We've dropped V4L ATSC support...
149
        else if (fmt.left(3) == "PAL")
150
            return V4L2_STD_PAL;
151
        return V4L2_STD_NTSC;
152
    }
153
    else if (1 == v4l_version)
154
    {
155
        if (fmt == "NTSC-JP")
156
            return 6;
157
        else if (fmt.left(5) == "SECAM")
158
            return VIDEO_MODE_SECAM;
159
        else if (fmt == "PAL-NC")
160
            return 3;
161
        else if (fmt == "PAL-M")
162
            return 4;
163
        else if (fmt == "PAL-N")
164
            return 5;
165
        // generics...
166
        else if (fmt.left(3) == "PAL")
167
            return VIDEO_MODE_PAL;
168
        else if (fmt.left(4) == "NTSC")
169
            return VIDEO_MODE_NTSC;
170
        else if (fmt.left(4) == "ATSC")
171
            return VIDEO_MODE_NTSC; // We've dropped V4L ATSC support...
172
        return VIDEO_MODE_NTSC;
173
    }
174
175
    VERBOSE(VB_IMPORTANT,
176
            "format_to_mode() does not recognize V4L" << v4l_version);
177
178
    return V4L2_STD_NTSC; // assume V4L version 2
179
}
180
181
static QString mode_to_format(int mode, int v4l_version)
182
{
183
    if (2 == v4l_version)
184
    {
185
        if (mode == V4L2_STD_NTSC)
186
            return "NTSC";
187
        else if (mode == V4L2_STD_NTSC_M_JP)
188
            return "NTSC-JP";
189
        else if (mode == V4L2_STD_PAL)
190
            return "PAL";
191
        else if (mode == V4L2_STD_PAL_60)
192
            return "PAL-60";
193
        else if (mode == V4L2_STD_PAL_BG)
194
            return "PAL-BG";
195
        else if (mode == V4L2_STD_PAL_D)
196
            return "PAL-D";
197
        else if (mode == V4L2_STD_PAL_DK)
198
            return "PAL-DK";
199
        else if (mode == V4L2_STD_PAL_I)
200
            return "PAL-I";
201
        else if (mode == V4L2_STD_PAL_M)
202
            return "PAL-M";
203
        else if (mode == V4L2_STD_PAL_N)
204
            return "PAL-N";
205
        else if (mode == V4L2_STD_PAL_Nc)
206
            return "PAL-NC";
207
        else if (mode == V4L2_STD_SECAM)
208
            return "SECAM";
209
        else if (mode == V4L2_STD_SECAM_D)
210
            return "SECAM-D";
211
        // generic..
212
        else if ((V4L2_STD_NTSC_M      == mode) ||
213
                 (V4L2_STD_NTSC_443    == mode) ||
214
                 (V4L2_STD_NTSC_M_KR   == mode))
215
            return "NTSC";
216
        else if ((V4L2_STD_PAL_B       == mode) ||
217
                 (V4L2_STD_PAL_B1      == mode) ||
218
                 (V4L2_STD_PAL_G       == mode) ||
219
                 (V4L2_STD_PAL_H       == mode) ||
220
                 (V4L2_STD_PAL_D1      == mode) ||
221
                 (V4L2_STD_PAL_K       == mode))
222
            return "PAL";
223
        else if ((V4L2_STD_SECAM_B     == mode) ||
224
                 (V4L2_STD_SECAM_DK    == mode) ||
225
                 (V4L2_STD_SECAM_G     == mode) ||
226
                 (V4L2_STD_SECAM_H     == mode) ||
227
                 (V4L2_STD_SECAM_K     == mode) ||
228
                 (V4L2_STD_SECAM_K1    == mode) ||
229
                 (V4L2_STD_SECAM_L     == mode) ||
230
                 (V4L2_STD_SECAM_LC    == mode))
231
            return "SECAM";
232
        else if ((V4L2_STD_ATSC        == mode) ||
233
                 (V4L2_STD_ATSC_8_VSB  == mode) ||
234
                 (V4L2_STD_ATSC_16_VSB == mode))
235
        {
236
            // We've dropped V4L ATSC support, but this still needs to be
237
            // returned here so we will change the mode if the device is
238
            // in ATSC mode already.
239
            return "ATSC";
240
        }
241
    }
242
    else if (1 == v4l_version)
243
    {
244
        if (mode == VIDEO_MODE_NTSC)
245
            return "NTSC";
246
        else if (mode == VIDEO_MODE_ATSC)
247
            return "ATSC";
248
        else if (mode == VIDEO_MODE_PAL)
249
            return "PAL";
250
        else if (mode == VIDEO_MODE_SECAM)
251
            return "SECAM";
252
        else if (mode == 3)
253
            return "PAL-NC";
254
        else if (mode == 4)
255
            return "PAL-M";
256
        else if (mode == 5)
257
            return "PAL-N";
258
        else if (mode == 6)
259
            return "NTSC-JP";
260
    }
261
    else
262
    {
263
        VERBOSE(VB_IMPORTANT,
264
                "mode_to_format() does not recognize V4L" << v4l_version);
265
    }
266
267
    return "Unknown";
268
}
269
270
/** \fn Channel::InitializeInputs(void)
271
 *  This enumerates the inputs, converts the format
272
 *  string to something the hardware understands, and
273
 *  if the parent pointer is valid retrieves the
274
 *  channels from the database.
275
 */
276
bool Channel::InitializeInputs(void)
277
{
278
    // Get Inputs from DB
279
    if (!ChannelBase::InitializeInputs())
280
        return false;
281
282
    // Get global TVFormat setting
283
    QString fmt = gContext->GetSetting("TVFormat");
284
    VERBOSE(VB_CHANNEL, QString("Global TVFormat Setting '%1'").arg(fmt));
285
    int videomode_v4l1 = format_to_mode(fmt.upper(), 1);
286
    int videomode_v4l2 = format_to_mode(fmt.upper(), 2);
287
288
    bool ok = false;
289
    InputNames v4l_inputs = CardUtil::probeV4LInputs(videofd, ok);
290
291
    // Insert info from hardware
292
    uint valid_cnt = 0;
293
    InputMap::const_iterator it;
294
    for (it = inputs.begin(); it != inputs.end(); ++it)
295
    {
296
        InputNames::const_iterator v4l_it = v4l_inputs.begin();
297
        for (; v4l_it != v4l_inputs.end(); ++v4l_it)
298
        {
299
            if (*v4l_it == (*it)->name)
300
            {
301
                (*it)->inputNumV4L   = v4l_it.key();
302
                (*it)->videoModeV4L1 = videomode_v4l1;
303
                (*it)->videoModeV4L2 = videomode_v4l2;
304
                valid_cnt++;
305
            }
306
        }
307
    }
308
309
    // print em
310
    for (it = inputs.begin(); it != inputs.end(); ++it)
311
    {
312
        VERBOSE(VB_CHANNEL, LOC + QString("Input #%1: '%2' schan(%3) "
313
                                          "tun(%4) v4l1(%5) v4l2(%6)")
314
                .arg(it.key()).arg((*it)->name).arg((*it)->startChanNum)
315
                .arg((*it)->tuneToChannel)
316
                .arg(mode_to_format((*it)->videoModeV4L1,1))
317
                .arg(mode_to_format((*it)->videoModeV4L2,2)));
318
    }
319
320
    return valid_cnt;
321
}
322
323
/** \fn Channel::SetFormat(const QString &format)
324
 *  \brief Initializes tuner and modulator variables
325
 *
326
 *  \param format One of twelve formats:
327
 *                "NTSC",   "NTSC-JP", "ATSC",
328
 *                "SECAM",
329
 *                "PAL",    "PAL-BG",  "PAL-DK",   "PAL-I",
330
 *                "PAL-60", "PAL-NC",  "PAL-M", or "PAL-N"
331
 */
332
void Channel::SetFormat(const QString &format)
333
{
334
    if (!Open())
335
        return;
336
337
    int inputNum = currentInputID;
338
    if (currentInputID < 0)
339
        inputNum = GetNextInputNum();
340
341
    QString fmt = format;
342
    if ((fmt == "Default") || format.isEmpty())
343
    {
344
        InputMap::const_iterator it = inputs.find(inputNum);
345
        if (it != inputs.end())
346
            fmt = mode_to_format((*it)->videoModeV4L2, 2);
347
    }
348
349
    VERBOSE(VB_CHANNEL, LOC + QString("SetFormat(%1) fmt(%2) input(%3)")
350
            .arg(format).arg(fmt).arg(inputNum));
351
352
    if ((fmt == currentFormat) || SetInputAndFormat(inputNum, fmt))
353
    {
354
        currentFormat = fmt;
355
        is_dtv        = (fmt == "ATSC");
356
    }
357
}
358
359
int Channel::SetDefaultFreqTable(const QString &name)
360
{
361
    defaultFreqTable = SetFreqTable(name);
362
    return defaultFreqTable;
363
}
364
365
void Channel::SetFreqTable(const int index)
366
{
367
    curList = chanlists[index].list;
368
    totalChannels = chanlists[index].count;
369
}
370
371
int Channel::SetFreqTable(const QString &name)
372
{
373
    int i = 0;
374
    char *listname = (char *)chanlists[i].name;
375
376
    curList = NULL;
377
    while (listname != NULL)
378
    {
379
        if (name == listname)
380
        {
381
            SetFreqTable(i);
382
            return i;
383
        }
384
        i++;
385
        listname = (char *)chanlists[i].name;
386
    }
387
388
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::SetFreqTable(): Invalid "
389
                                "frequency table name %2, using %3.").
390
            arg(device).arg(name).arg((char *)chanlists[1].name));
391
    SetFreqTable(1);
392
    return 1;
393
}
394
395
int Channel::GetCurrentChannelNum(const QString &channame)
396
{
397
    for (int i = 0; i < totalChannels; i++)
398
    {
399
        if (channame == curList[i].name)
400
            return i;
401
    }
402
403
    VERBOSE(VB_IMPORTANT, LOC_ERR +
404
            QString("GetCurrentChannelNum(%1): "
405
                    "Failed to find Channel").arg(channame));
406
407
    return -1;
408
}
409
410
void Channel::SaveCachedPids(const pid_cache_t &pid_cache) const
411
{
412
    int chanid = GetChanID();
413
    if (chanid > 0)
414
        DTVChannel::SaveCachedPids(chanid, pid_cache);
415
}
416
417
void Channel::GetCachedPids(pid_cache_t &pid_cache) const
418
{
419
    int chanid = GetChanID();
420
    if (chanid > 0)
421
        DTVChannel::GetCachedPids(chanid, pid_cache);
422
}
423
424
bool Channel::SetChannelByString(const QString &channum)
425
{
426
    QString loc = LOC + QString("SetChannelByString(%1)").arg(channum);
427
    QString loc_err = loc + ", Error: ";
428
    VERBOSE(VB_CHANNEL, loc);
429
    
430
    if (!Open())
431
    {
432
        VERBOSE(VB_IMPORTANT, loc_err + "Channel object "
433
                "will not open, can not change channels.");
434
435
        return false;
436
    }
437
438
    QString inputName;
439
    if (!CheckChannel(channum, inputName))
440
    {
441
        VERBOSE(VB_IMPORTANT, loc_err +
442
                "CheckChannel failed.\n\t\t\tPlease verify the channel "
443
                "in the 'mythtv-setup' Channel Editor.");
444
445
        return false;
446
    }
447
448
    // If CheckChannel filled in the inputName then we need to
449
    // change inputs and return, since the act of changing
450
    // inputs will change the channel as well.
451
    if (!inputName.isEmpty())
452
        return ChannelBase::SwitchToInput(inputName, channum);
453
454
    ClearDTVInfo();
455
456
    InputMap::const_iterator it = inputs.find(currentInputID);
457
    if (it == inputs.end())
458
        return false;
459
460
    uint mplexid_restriction;
461
    if (!IsInputAvailable(currentInputID, mplexid_restriction))
462
        return false;
463
464
    // Fetch tuning data from the database.
465
    QString tvformat, modulation, freqtable, freqid, dtv_si_std;
466
    int finetune;
467
    uint64_t frequency;
468
    int mpeg_prog_num;
469
    uint atsc_major, atsc_minor, mplexid, tsid, netid;
470
471
    if (!ChannelUtil::GetChannelData(
472
        (*it)->sourceid, channum,
473
        tvformat, modulation, freqtable, freqid,
474
        finetune, frequency,
475
        dtv_si_std, mpeg_prog_num, atsc_major, atsc_minor, tsid, netid,
476
        mplexid, commfree))
477
    {
478
        return false;
479
    }
480
481
    if (mplexid_restriction && (mplexid != mplexid_restriction))
482
        return false;
483
484
    // If the frequency is zeroed out, don't use it directly.
485
    bool ok = (frequency > 0);
486
487
    if (!ok)
488
    {
489
        frequency = (freqid.toInt(&ok) + finetune) * 1000;
490
        mplexid = 0;
491
    }
492
    bool isFrequency = ok && (frequency > 10000000);
493
494
    // If we are tuning to a freqid, rather than an actual frequency,
495
    // we need to set the frequency table to use.
496
    if (!isFrequency)
497
    {
498
        if (freqtable == "default" || freqtable.isEmpty())
499
            SetFreqTable(defaultFreqTable);
500
        else
501
            SetFreqTable(freqtable);
502
    }
503
504
    // Set NTSC, PAL, ATSC, etc.
505
    SetFormat(tvformat);
506
507
    // If a tuneToChannel is set make sure we're still on it
508
    if (!(*it)->tuneToChannel.isEmpty() && (*it)->tuneToChannel != "Undefined")
509
        TuneTo((*it)->tuneToChannel, 0);
510
511
    // Tune to proper frequency
512
    if ((*it)->externalChanger.isEmpty())
513
    {
514
        if ((*it)->name.contains("composite", false) ||
515
            (*it)->name.contains("s-video", false))
516
        {
517
            VERBOSE(VB_GENERAL, LOC_WARN + "You have not set "
518
                    "an external channel changing"
519
                    "\n\t\t\tscript for a composite or s-video "
520
                    "input. Channel changing will do nothing.");
521
        }
522
        else if (isFrequency)
523
        {
524
            if (!Tune(frequency, "", (is_dtv) ? "8vsb" : "analog", dtv_si_std))
525
            {
526
                return false;
527
            }
528
        }
529
        else
530
        {
531
            if (!TuneTo(freqid, finetune))
532
                return false;
533
        }
534
    }
535
    else if (!ChangeExternalChannel(freqid))
536
        return false;
537
538
    // Set the current channum to the new channel's channum
539
    curchannelname = QDeepCopy<QString>(channum);
540
541
    // Setup filters & recording picture attributes for framegrabing recorders
542
    // now that the new curchannelname has been established.
543
    if (pParent)
544
        pParent->SetVideoFiltersForChannel(GetCurrentSourceID(), channum);
545
    InitPictureAttributes();
546
547
    // Set the major and minor channel for any additional multiplex tuning
548
    SetDTVInfo(atsc_major, atsc_minor, netid, tsid, mpeg_prog_num);
549
550
    // Set this as the future start channel for this source
551
    inputs[currentInputID]->startChanNum = QDeepCopy<QString>(curchannelname);
552
553
    return true;
554
}
555
556
bool Channel::TuneTo(const QString &channum, int finetune)
557
{
558
    int i = GetCurrentChannelNum(channum);
559
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::TuneTo(%2): "
560
                                "curList[%3].freq(%4)")
561
            .arg(device).arg(channum).arg(i)
562
            .arg((i != -1) ? curList[i].freq : -1));
563
564
    if (i == -1)
565
    {
566
        VERBOSE(VB_IMPORTANT, QString("Channel(%1)::TuneTo(%2): Error, "
567
                                      "failed to find channel.")
568
                .arg(device).arg(channum));
569
        return false;
570
    }
571
572
    int frequency = (curList[i].freq + finetune) * 1000;
573
574
    return Tune(frequency, "", "analog", "analog");
575
}
576
577
bool Channel::Tune(const DTVMultiplex &tuning, QString inputname)
578
{
579
    return Tune(tuning.frequency - 1750000, // to visual carrier
580
                inputname, tuning.modulation.toString(), tuning.sistandard);
581
}
582
583
/** \fn Channel::Tune(uint,QString,QString,QString)
584
 *  \brief Tunes to a specific frequency (Hz) on a particular input, using
585
 *         the specified modulation.
586
 *
587
 *  Note: This function always uses modulator zero.
588
 *
589
 *  \param frequency Frequency in Hz, this is divided by 62.5 kHz or 62.5 Hz
590
 *                   depending on the modulator and sent to the hardware.
591
 *  \param inputname Name of the input (Television, Antenna 1, etc.)
592
 *  \param modulation "radio", "analog", or "digital"
593
 */
594
bool Channel::Tune(uint frequency, QString inputname,
595
                   QString modulation, QString si_std)
596
{
597
    VERBOSE(VB_CHANNEL, LOC + QString("Tune(%1, %2, %3, %4)")
598
            .arg(frequency).arg(inputname).arg(modulation).arg(si_std));
599
600
    int ioctlval = 0;
601
602
    if (modulation == "8vsb")
603
        SetFormat("ATSC");
604
    modulation = (is_dtv) ? "digital" : modulation;
605
606
    int inputnum = GetInputByName(inputname);
607
608
    bool ok = true;
609
    if ((inputnum >= 0) && (GetCurrentInputNum() != inputnum))
610
        ok = SwitchToInput(inputnum, false);
611
    else if (GetCurrentInputNum() < 0)
612
        ok = SwitchToInput(0, false);
613
614
    if (!ok)
615
        return false;
616
617
    // If the frequency is a center frequency and not
618
    // a visual carrier frequency, convert it.
619
    int offset = frequency % 1000000;
620
    offset = (offset > 500000) ? 1000000 - offset : offset;
621
    bool is_visual_carrier = (offset > 150000) && (offset < 350000);
622
    if (!is_visual_carrier && currentFormat == "ATSC")
623
    {
624
        VERBOSE(VB_CHANNEL,  QString("Channel(%1): ").arg(device) +
625
                QString("Converting frequency from center frequency "
626
                        "(%1 Hz) to visual carrier frequency (%2 Hz).")
627
                .arg(frequency).arg(frequency - 1750000));
628
        frequency -= 1750000; // convert to visual carrier
629
    }        
630
631
    // Video4Linux version 2 tuning
632
    if (usingv4l2)
633
    {
634
        bool isTunerCapLow = false;
635
        struct v4l2_modulator mod;
636
        bzero(&mod, sizeof(mod));
637
        mod.index = 0;
638
        ioctlval = ioctl(videofd, VIDIOC_G_MODULATOR, &mod);
639
        if (ioctlval >= 0)
640
        {
641
            isTunerCapLow = (mod.capability & V4L2_TUNER_CAP_LOW);
642
            VERBOSE(VB_CHANNEL, "  name: "<<mod.name);
643
            VERBOSE(VB_CHANNEL, "CapLow: "<<isTunerCapLow);
644
        }
645
646
        struct v4l2_frequency vf;
647
        bzero(&vf, sizeof(vf));
648
649
        vf.tuner = 0; // use first tuner
650
        vf.frequency = (isTunerCapLow) ?
651
            ((int)(frequency / 62.5)) : (frequency / 62500);
652
653
        if (modulation.lower() == "digital")
654
        {
655
            VERBOSE(VB_CHANNEL, "using digital modulation");
656
            vf.type = V4L2_TUNER_DIGITAL_TV;
657
            if (ioctl(videofd, VIDIOC_S_FREQUENCY, &vf)>=0)
658
                return true;
659
            VERBOSE(VB_CHANNEL, "digital modulation failed");
660
        }
661
662
        vf.type = V4L2_TUNER_ANALOG_TV;
663
664
        ioctlval = ioctl(videofd, VIDIOC_S_FREQUENCY, &vf);
665
        if (ioctlval < 0)
666
        {
667
            VERBOSE(VB_IMPORTANT,
668
                    QString("Channel(%1)::Tune(): Error %2 "
669
                            "while setting frequency (v2): %3")
670
                    .arg(device).arg(ioctlval).arg(strerror(errno)));
671
            return false;
672
        }
673
        ioctlval = ioctl(videofd, VIDIOC_G_FREQUENCY, &vf);
674
675
        if (ioctlval >= 0)
676
        {
677
            VERBOSE(VB_CHANNEL, QString(
678
                        "Channel(%1)::Tune(): Frequency is now %2")
679
                    .arg(device).arg(vf.frequency * 62500));
680
        }
681
682
        return true;
683
    }
684
685
    // Video4Linux version 1 tuning
686
    uint freq = frequency / 62500;
687
    ioctlval = ioctl(videofd, VIDIOCSFREQ, &freq);
688
    if (ioctlval < 0)
689
    {
690
        VERBOSE(VB_IMPORTANT,
691
                QString("Channel(%1)::Tune(): Error %2 "
692
                        "while setting frequency (v1): %3")
693
                .arg(device).arg(ioctlval).arg(strerror(errno)));
694
        return false;
695
    }
696
697
    SetSIStandard(si_std);
698
699
    return true;
700
}
701
702
/** \fn Channel::Retune(void)
703
 *  \brief Retunes to last tuned frequency.
704
 *
705
 *  NOTE: This only works for V4L2 and only for analog tuning.
706
 */
707
bool Channel::Retune(void)
708
{
709
    if (usingv4l2)
710
    {
711
        struct v4l2_frequency vf;
712
        bzero(&vf, sizeof(vf));
713
714
        vf.tuner = 0; // use first tuner
715
        vf.type = V4L2_TUNER_ANALOG_TV;
716
717
        // Get the last tuned frequency
718
        int ioctlval = ioctl(videofd, VIDIOC_G_FREQUENCY, &vf);
719
        if (ioctlval < 0)
720
        {
721
            VERBOSE(VB_IMPORTANT, LOC_ERR + "Retune failed (1)" + ENO);
722
            return false;
723
        }
724
725
        // Set the last tuned frequency again...
726
        ioctlval = ioctl(videofd, VIDIOC_S_FREQUENCY, &vf);
727
        if (ioctlval < 0)
728
        {
729
            VERBOSE(VB_IMPORTANT, LOC_ERR + "Retune failed (2)" + ENO);
730
            return false;
731
        }
732
733
        return true;
734
    }
735
736
    return false;
737
}
738
739
// documented in dtvchannel.h
740
bool Channel::TuneMultiplex(uint mplexid, QString inputname)
741
{
742
    VERBOSE(VB_CHANNEL, LOC + QString("TuneMultiplex(%1)").arg(mplexid));
743
744
    QString  modulation;
745
    QString  si_std;
746
    uint64_t frequency;
747
    uint     transportid;
748
    uint     dvb_networkid;
749
750
    if (!ChannelUtil::GetTuningParams(
751
            mplexid, modulation, frequency,
752
            transportid, dvb_networkid, si_std))
753
    {
754
        VERBOSE(VB_IMPORTANT, LOC_ERR + "TuneMultiplex(): " +
755
                QString("Could not find tuning parameters for multiplex %1.")
756
                .arg(mplexid));
757
758
        return false;
759
    }
760
761
    if (!Tune(frequency, inputname, modulation, si_std))
762
        return false;
763
764
    return true;
765
}
766
767
QString Channel::GetFormatForChannel(QString channum, QString inputname)
768
{
769
    MSqlQuery query(MSqlQuery::InitCon());
770
    query.prepare(
771
        "SELECT tvformat "
772
        "FROM channel, cardinput "
773
        "WHERE channum            = :CHANNUM   AND "
774
        "      inputname          = :INPUTNAME AND "
775
        "      cardinput.cardid   = :CARDID    AND "
776
        "      cardinput.sourceid = channel.sourceid");
777
    query.bindValue(":CHANNUM",   channum);
778
    query.bindValue(":INPUTNAME", inputname);
779
    query.bindValue(":CARDID",    GetCardID());
780
781
    QString fmt = QString::null;
782
    if (!query.exec() || !query.isActive())
783
        MythContext::DBError("SwitchToInput:find format", query);
784
    else if (query.next())
785
        fmt = query.value(0).toString();
786
    return fmt;
787
}
788
789
bool Channel::SetInputAndFormat(int inputNum, QString newFmt)
790
{
791
    InputMap::const_iterator it = inputs.find(inputNum);
792
    if (it == inputs.end() || (*it)->inputNumV4L < 0)
793
        return false;
794
795
    int inputNumV4L = (*it)->inputNumV4L;
796
    bool usingv4l1 = !usingv4l2;
797
    bool ok = true;
798
799
    QString msg =
800
        QString("SetInputAndFormat(%1, %2) ").arg(inputNum).arg(newFmt);
801
802
    if (usingv4l2)
803
    {
804
        VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v2)");
805
806
        int ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
807
808
        // ConvertX (wis-go7007) requires streaming to be disabled
809
        // before an input switch, do this if initial switch failed.
810
        bool streamingDisabled = false;
811
        int  streamType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
812
        if ((ioctlval < 0) && (errno == EBUSY))
813
        {
814
            ioctlval = ioctl(videofd, VIDIOC_STREAMOFF, &streamType);
815
            if (ioctlval < 0)
816
            {
817
                VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
818
                        "\n\t\t\twhile disabling streaming (v4l v2)" + ENO);
819
820
                ok = false;
821
                ioctlval = 0;
822
            }
823
            else
824
            {
825
                streamingDisabled = true;
826
827
                // Resend the input switch ioctl.
828
                ioctlval = ioctl(videofd, VIDIOC_S_INPUT, &inputNumV4L);
829
            }
830
        }
831
832
        if (ioctlval < 0)
833
        {
834
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
835
                    "\n\t\t\twhile setting input (v4l v2)" + ENO);
836
837
            ok = false;
838
        }
839
840
        v4l2_std_id vid_mode = format_to_mode(newFmt, 2);
841
        ioctlval = ioctl(videofd, VIDIOC_S_STD, &vid_mode);
842
        if (ioctlval < 0)
843
        {
844
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
845
                    "\n\t\t\twhile setting format (v4l v2)" + ENO);
846
847
            ok = false;
848
        }
849
850
        // ConvertX (wis-go7007) requires streaming to be disabled
851
        // before an input switch, here we try to re-enable streaming.
852
        if (streamingDisabled)
853
        {
854
            ioctlval = ioctl(videofd, VIDIOC_STREAMON, &streamType);
855
            if (ioctlval < 0)
856
            {
857
                VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
858
                        "\n\t\t\twhile reenabling streaming (v4l v2)" + ENO);
859
860
                ok = false;
861
            }
862
        }
863
    }
864
865
    if (usingv4l1)
866
    {
867
        VERBOSE(VB_CHANNEL, LOC + msg + "(v4l v1)");
868
869
        // read in old settings
870
        struct video_channel set;
871
        bzero(&set, sizeof(set));
872
        ioctl(videofd, VIDIOCGCHAN, &set);
873
874
        // set new settings
875
        set.channel = inputNumV4L;
876
        set.norm    = format_to_mode(newFmt, 1);
877
        int ioctlval = ioctl(videofd, VIDIOCSCHAN, &set);
878
879
        ok = (ioctlval >= 0);
880
        if (!ok)
881
        {
882
            VERBOSE(VB_IMPORTANT, LOC_ERR + msg + 
883
                    "\n\t\t\twhile setting format (v4l v1)" + ENO);
884
        }
885
        else if (usingv4l2)
886
        {
887
            VERBOSE(VB_IMPORTANT, LOC + msg +
888
                    "\n\t\t\tSetting video mode with v4l version 1 worked");
889
        }
890
    }
891
    return ok;
892
}
893
894
bool Channel::SwitchToInput(int inputnum, bool setstarting)
895
{
896
    InputMap::const_iterator it = inputs.find(inputnum);
897
    if (it == inputs.end())
898
        return false;
899
900
    QString tuneFreqId = (*it)->tuneToChannel;
901
    QString channum    = (*it)->startChanNum;
902
    QString inputname  = (*it)->name;
903
904
    VERBOSE(VB_CHANNEL, QString("Channel(%1)::SwitchToInput(in %2, '%3')")
905
            .arg(device).arg(inputnum)
906
            .arg(setstarting ? channum : QString("")));
907
908
    uint mplexid_restriction;
909
    if (!IsInputAvailable(inputnum, mplexid_restriction))
910
        return false;
911
912
    QString newFmt = mode_to_format((*it)->videoModeV4L2, 2);
913
914
    // If we are setting a channel, get its video mode...
915
    bool chanValid  = (channum != "Undefined") && !channum.isEmpty();
916
    if (setstarting && chanValid)
917
    {
918
        QString tmp = GetFormatForChannel(channum, inputname);
919
        if (tmp != "Default" && !tmp.isEmpty())
920
            newFmt = tmp;
921
    }
922
923
    bool ok = SetInputAndFormat(inputnum, newFmt);
924
925
    // Try to set ATSC mode if NTSC fails
926
    if (!ok && newFmt == "NTSC")
927
        ok = SetInputAndFormat(inputnum, "ATSC");
928
929
    if (!ok)
930
    {
931
        VERBOSE(VB_IMPORTANT, LOC + "SetInputAndFormat() failed");
932
        return false;
933
    }
934
935
    currentFormat     = newFmt;
936
    is_dtv            = newFmt == "ATSC";
937
    currentInputID = inputnum;
938
    curchannelname    = ""; // this will be set by SetChannelByString
939
940
    if (!tuneFreqId.isEmpty() && tuneFreqId != "Undefined")
941
        ok = TuneTo(tuneFreqId, 0);
942
943
    if (!ok)
944
        return false;
945
946
    if (setstarting && chanValid)
947
        ok = SetChannelByString(channum);
948
    else if (setstarting && !chanValid)
949
    {
950
        VERBOSE(VB_IMPORTANT, LOC +
951
                QString("SwitchToInput(in %2, set ch): ").arg(inputnum) +
952
                QString("\n\t\t\tDefault channel '%1' is not valid.")
953
                .arg(channum));
954
        ok = false;
955
    }
956
957
    return ok;
958
}
959
960
static unsigned short *get_v4l1_field(
961
    int v4l2_attrib, struct video_picture &vid_pic)
962
{
963
    switch (v4l2_attrib)
964
    {
965
        case V4L2_CID_CONTRAST:
966
            return &vid_pic.contrast;
967
        case V4L2_CID_BRIGHTNESS:
968
            return &vid_pic.brightness;
969
        case V4L2_CID_SATURATION:
970
            return &vid_pic.colour;
971
        case V4L2_CID_HUE:
972
            return &vid_pic.hue;
973
        default:
974
            VERBOSE(VB_IMPORTANT, "get_v4l1_field: "
975
                    "invalid attribute argument "<<v4l2_attrib);
976
    }
977
    return NULL;
978
}
979
980
static int get_v4l2_attribute(const QString &db_col_name)
981
{
982
    if ("brightness" == db_col_name)
983
        return V4L2_CID_BRIGHTNESS;
984
    else if ("contrast" == db_col_name)
985
        return V4L2_CID_CONTRAST;
986
    else if ("colour" == db_col_name)
987
        return V4L2_CID_SATURATION;
988
    else if ("hue" == db_col_name)
989
        return V4L2_CID_HUE;
990
    return -1;
991
}
992
993
bool Channel::InitPictureAttribute(const QString db_col_name)
994
{
995
    if (!pParent || is_dtv)
996
        return false;
997
998
    int v4l2_attrib = get_v4l2_attribute(db_col_name);
999
    if (v4l2_attrib == -1)
1000
        return false;
1001
1002
    int cfield = ChannelUtil::GetChannelValueInt(
1003
        db_col_name, GetCurrentSourceID(), curchannelname);
1004
    int sfield = CardUtil::GetValueInt(
1005
        db_col_name, GetCardID());
1006
1007
    if ((cfield == -1) || (sfield == -1))
1008
        return false;
1009
1010
    int field = (cfield + sfield) & 0xFFFF;
1011
1012
    QString loc = LOC +
1013
        QString("InitPictureAttribute(%1): ").arg(db_col_name, 10);
1014
    QString loc_err = LOC_ERR +
1015
        QString("InitPictureAttribute(%1): ").arg(db_col_name, 10);
1016
1017
    if (usingv4l2)
1018
    {
1019
        struct v4l2_control ctrl;
1020
        struct v4l2_queryctrl qctrl;
1021
        bzero(&ctrl, sizeof(ctrl));
1022
        bzero(&qctrl, sizeof(qctrl));
1023
1024
        ctrl.id = qctrl.id = v4l2_attrib;
1025
        if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1026
        {
1027
            VERBOSE(VB_IMPORTANT, loc_err + "failed to query controls." + ENO);
1028
            return false;
1029
        }
1030
1031
        float new_range = qctrl.maximum - qctrl.minimum;
1032
        float old_range = 65535 - 0;
1033
        float scl_range = new_range / old_range;
1034
        float dfl       = (qctrl.default_value - qctrl.minimum) / new_range;
1035
        int   norm_dfl  = (0x10000 + (int)(dfl * old_range) - 32768) & 0xFFFF;
1036
1037
        if (pict_attr_default.find(db_col_name) == pict_attr_default.end())
1038
        {
1039
            if (device_name == "pcHDTV HD3000 HDTV")
1040
            {
1041
                pict_attr_default["brightness"] = 9830;
1042
                pict_attr_default["contrast"]   = 39322;
1043
                pict_attr_default["colour"]     = 45875;
1044
                pict_attr_default["hue"]        = 0;
1045
            }
1046
            else
1047
            {
1048
                pict_attr_default[db_col_name] = norm_dfl;
1049
            }
1050
        }
1051
1052
        int dfield = pict_attr_default[db_col_name];
1053
        field      = (cfield + sfield + dfield) & 0xFFFF;
1054
        int value0 = (int) ((scl_range * field) + qctrl.minimum);
1055
        int value1 = min(value0, (int)qctrl.maximum);
1056
        ctrl.value = max(value1, (int)qctrl.minimum);
1057
1058
#if DEBUG_ATTRIB
1059
        VERBOSE(VB_CHANNEL, loc + QString(" %1\n\t\t\t"
1060
                                          "[%2,%3] dflt(%4, %5, %6)")
1061
                .arg(value0).arg(qctrl.minimum, 5).arg(qctrl.maximum, 5)
1062
                .arg(qctrl.default_value, 5).arg(dfl, 4, 'f', 2)
1063
                .arg(norm_dfl));
1064
#endif
1065
1066
        if (ioctl(videofd, VIDIOC_S_CTRL, &ctrl) < 0)
1067
        {
1068
            VERBOSE(VB_IMPORTANT, loc_err + "failed to set controls" + ENO);
1069
            return false;
1070
        }
1071
1072
        return true;
1073
    }
1074
1075
    // V4L1
1076
    unsigned short *setfield;
1077
    struct video_picture vid_pic;
1078
    bzero(&vid_pic, sizeof(vid_pic));
1079
1080
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1081
    {
1082
        VERBOSE(VB_IMPORTANT, loc_err + "failed to query controls." + ENO);
1083
        return false;
1084
    }
1085
    setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1086
1087
    if (!setfield)
1088
        return false;
1089
1090
    *setfield = field;
1091
    if (ioctl(videofd, VIDIOCSPICT, &vid_pic) < 0)
1092
    {
1093
        VERBOSE(VB_IMPORTANT, loc_err + "failed to set controls." + ENO);
1094
        return false;
1095
    }
1096
1097
    return true;
1098
}
1099
1100
bool Channel::InitPictureAttributes(void)
1101
{
1102
    return (InitPictureAttribute("brightness") &&
1103
            InitPictureAttribute("contrast")   &&
1104
            InitPictureAttribute("colour")     &&
1105
            InitPictureAttribute("hue"));
1106
}
1107
1108
int Channel::GetPictureAttribute(PictureAttribute attr) const
1109
{
1110
    QString db_col_name = toDBString(attr);
1111
    if (db_col_name.isEmpty())
1112
        return -1;
1113
1114
    int cfield = ChannelUtil::GetChannelValueInt(
1115
        db_col_name, GetCurrentSourceID(), curchannelname);
1116
    int sfield = CardUtil::GetValueInt(
1117
        db_col_name, GetCardID());
1118
    int dfield = 0;
1119
1120
    if (pict_attr_default.find(db_col_name) != pict_attr_default.end())
1121
        dfield = pict_attr_default[db_col_name];
1122
1123
    int val = (cfield + sfield + dfield) & 0xFFFF;
1124
1125
#if DEBUG_ATTRIB
1126
    VERBOSE(VB_CHANNEL, QString(
1127
                "GetPictureAttribute(%1) -> cdb %2 rdb %3 d %4 -> %5")
1128
            .arg(db_col_name).arg(cfield).arg(sfield)
1129
            .arg(dfield).arg(val));
1130
#endif
1131
1132
    return val;
1133
}
1134
1135
static int get_v4l2_attribute_value(int videofd, int v4l2_attrib)
1136
{
1137
    struct v4l2_control ctrl;
1138
    struct v4l2_queryctrl qctrl;
1139
    bzero(&ctrl, sizeof(ctrl));
1140
    bzero(&qctrl, sizeof(qctrl));
1141
1142
    ctrl.id = qctrl.id = v4l2_attrib;
1143
    if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1144
    {
1145
        VERBOSE(VB_IMPORTANT, "get_v4l2_attribute_value: "
1146
                "failed to query controls (1)" + ENO);
1147
        return -1;
1148
    }
1149
1150
    if (ioctl(videofd, VIDIOC_G_CTRL, &ctrl) < 0)
1151
    {
1152
        VERBOSE(VB_IMPORTANT, "get_v4l2_attribute_value: "
1153
                "failed to get controls (2)" + ENO);
1154
        return -1;
1155
    }
1156
1157
    float mult = 65535.0 / (qctrl.maximum - qctrl.minimum);
1158
    return min(max((int)(mult * (ctrl.value - qctrl.minimum)), 0), 65525);
1159
}
1160
1161
static int get_v4l1_attribute_value(int videofd, int v4l2_attrib)
1162
{
1163
    struct video_picture vid_pic;
1164
    bzero(&vid_pic, sizeof(vid_pic));
1165
1166
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1167
    {
1168
        VERBOSE(VB_IMPORTANT, "get_v4l1_attribute_value: "
1169
                "failed to get picture control (1)" + ENO);
1170
        return -1;
1171
    }
1172
1173
    unsigned short *setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1174
    if (setfield)
1175
        return *setfield;
1176
1177
    return -1;
1178
}
1179
1180
static int get_attribute_value(bool usingv4l2, int videofd, int v4l2_attrib)
1181
{
1182
    if (usingv4l2)
1183
        return get_v4l2_attribute_value(videofd, v4l2_attrib);
1184
    return get_v4l1_attribute_value(videofd, v4l2_attrib);
1185
}
1186
1187
static int set_v4l2_attribute_value(int videofd, int v4l2_attrib, int newvalue)
1188
{
1189
    struct v4l2_control ctrl;
1190
    struct v4l2_queryctrl qctrl;
1191
    bzero(&ctrl, sizeof(ctrl));
1192
    bzero(&qctrl, sizeof(qctrl));
1193
1194
    ctrl.id = qctrl.id = v4l2_attrib;
1195
    if (ioctl(videofd, VIDIOC_QUERYCTRL, &qctrl) < 0)
1196
    {
1197
        VERBOSE(VB_IMPORTANT, "set_v4l2_attribute_value: "
1198
                "failed to query control" + ENO);
1199
        return -1;
1200
    }
1201
1202
    float mult = (qctrl.maximum - qctrl.minimum) / 65535.0;
1203
    ctrl.value = (int)(mult * newvalue + qctrl.minimum);
1204
    ctrl.value = min(ctrl.value, qctrl.maximum);
1205
    ctrl.value = max(ctrl.value, qctrl.minimum);
1206
1207
    if (ioctl(videofd, VIDIOC_S_CTRL, &ctrl) < 0)
1208
    {
1209
        VERBOSE(VB_IMPORTANT, "set_v4l2_attribute_value: "
1210
                "failed to set control" + ENO);
1211
        return -1;
1212
    }
1213
1214
    return 0;
1215
}
1216
1217
static int set_v4l1_attribute_value(int videofd, int v4l2_attrib, int newvalue)
1218
{
1219
    unsigned short *setfield;
1220
    struct video_picture vid_pic;
1221
    bzero(&vid_pic, sizeof(vid_pic));
1222
1223
    if (ioctl(videofd, VIDIOCGPICT, &vid_pic) < 0)
1224
    {
1225
        VERBOSE(VB_IMPORTANT, "set_v4l1_attribute_value: "
1226
                "failed to get picture control." + ENO);
1227
        return -1;
1228
    }
1229
    setfield = get_v4l1_field(v4l2_attrib, vid_pic);
1230
    if (newvalue != -1 && setfield)
1231
    {
1232
        *setfield = newvalue;
1233
        if (ioctl(videofd, VIDIOCSPICT, &vid_pic) < 0)
1234
        {
1235
            VERBOSE(VB_IMPORTANT, "set_v4l1_attribute_value: "
1236
                    "failed to set picture control." + ENO);
1237
            return -1;
1238
        }
1239
    }
1240
    else
1241
    {
1242
        // ???
1243
        return -1;
1244
    }
1245
1246
    return 0;
1247
}
1248
1249
static int set_attribute_value(bool usingv4l2, int videofd,
1250
                               int v4l2_attrib, int newvalue)
1251
{
1252
    if (usingv4l2)
1253
        return set_v4l2_attribute_value(videofd, v4l2_attrib, newvalue);
1254
    return set_v4l1_attribute_value(videofd, v4l2_attrib, newvalue);
1255
}
1256
1257
int Channel::ChangePictureAttribute(
1258
    PictureAdjustType type, PictureAttribute attr, bool up)
1259
{
1260
    if (!pParent || is_dtv)
1261
        return -1;
1262
1263
    QString db_col_name = toDBString(attr);
1264
    if (db_col_name.isEmpty())
1265
        return -1;
1266
1267
    int v4l2_attrib = get_v4l2_attribute(db_col_name);
1268
    if (v4l2_attrib == -1)
1269
        return -1;
1270
1271
    // get the old attribute value from the hardware, this is
1272
    // just a sanity check on whether this attribute exists
1273
    if (get_attribute_value(usingv4l2, videofd, v4l2_attrib) < 0)
1274
        return -1;
1275
1276
    int old_value = GetPictureAttribute(attr);
1277
    int new_value = old_value + ((up) ? 655 : -655);
1278
1279
    // make sure we are within bounds (wrap around for hue)
1280
    if (V4L2_CID_HUE == v4l2_attrib)
1281
        new_value &= 0xffff;
1282
    new_value = min(max(new_value, 0), 65535);
1283
1284
#if DEBUG_ATTRIB
1285
    VERBOSE(VB_CHANNEL, QString(
1286
                "ChangePictureAttribute(%1,%2,%3) cur %4 -> new %5")
1287
            .arg(type).arg(db_col_name).arg(up)
1288
            .arg(old_value).arg(new_value));
1289
#endif
1290
1291
    // actually set the new attribute value on the hardware
1292
    if (set_attribute_value(usingv4l2, videofd, v4l2_attrib, new_value) < 0)
1293
        return -1;
1294
1295
    // tell the DB about the new attribute value
1296
    if (kAdjustingPicture_Channel == type)
1297
    {
1298
        int adj_value = ChannelUtil::GetChannelValueInt(
1299
            db_col_name, GetCurrentSourceID(), curchannelname);
1300
1301
        int tmp = new_value - old_value + adj_value;
1302
        tmp = (tmp < 0)      ? tmp + 0x10000 : tmp;
1303
        tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;
1304
        ChannelUtil::SetChannelValue(db_col_name, QString::number(tmp),
1305
                                     GetCurrentSourceID(), curchannelname);
1306
    }
1307
    else if (kAdjustingPicture_Recording == type)
1308
    {
1309
        int adj_value = CardUtil::GetValueInt(
1310
            db_col_name, GetCardID());
1311
1312
        int tmp = new_value - old_value + adj_value;
1313
        tmp = (tmp < 0)      ? tmp + 0x10000 : tmp;
1314
        tmp = (tmp > 0xffff) ? tmp - 0x10000 : tmp;
1315
        CardUtil::SetValue(db_col_name, GetCardID(),
1316
                           GetCurrentSourceID(), tmp);
1317
    }
1318
1319
    return new_value;
1320
}

Return to bug 259009