Ticket #2975: 2975-v1.patch

File 2975-v1.patch, 59.9 KB (added by danielk, 13 years ago)

Removal patch (must mark {pc,}hdtv*.{h,cpp} for deletion bfr commit)

  • libs/libmythtv/pchdtvsignalmonitor.h

     
    1 // -*- Mode: c++ -*-
    2 // Copyright (c) 2005, Daniel Thor Kristjansson
    3 
    4 #ifndef PCHDTVSIGNALMONITOR_H
    5 #define PCHDTVSIGNALMONITOR_H
    6 
    7 #include "dtvsignalmonitor.h"
    8 
    9 class Channel;
    10 
    11 class pcHDTVSignalMonitor: public DTVSignalMonitor
    12 {
    13     Q_OBJECT
    14   public:
    15     pcHDTVSignalMonitor(int db_cardnum, Channel *_channel,
    16                         uint _flags = kDTVSigMon_WaitForSig,
    17                         const char *_name = "pcHDTVSignalMonitor");
    18     ~pcHDTVSignalMonitor();
    19 
    20     void Stop();
    21 
    22   public slots:
    23     void deleteLater(void);
    24 
    25   private:
    26     pcHDTVSignalMonitor();
    27     pcHDTVSignalMonitor(const pcHDTVSignalMonitor&);
    28 
    29     virtual void UpdateValues();
    30 
    31     static int GetSignal(int fd, uint input, bool usingv4l2);
    32 
    33     static void *TableMonitorThread(void *param);
    34     void RunTableMonitor();
    35 
    36     bool      usingv4l2;
    37     bool      dtvMonitorRunning;
    38     pthread_t table_monitor_thread;
    39 };
    40 
    41 #endif // PCHDTVSIGNALMONITOR_H
  • libs/libmythtv/hdtvrecorder.h

     
    1 // -*- Mode: c++ -*-
    2 /**
    3  *  HDTVRecorder
    4  *  Copyright (c) 2003-2004 by Brandon Beattie, Doug Larrick,
    5  *    Jason Hoos, and Daniel Thor Kristjansson
    6  *  Device ringbuffer added by John Poet
    7  *  Distributed as part of MythTV under GPL v2 and later.
    8  */
    9 
    10 #ifndef HDTVRECORDER_H_
    11 #define HDTVRECORDER_H_
    12 
    13 #include "dtvrecorder.h"
    14 #include "tsstats.h"
    15 #include "streamlisteners.h"
    16 
    17 struct AVFormatContext;
    18 struct AVPacket;
    19 
    20 /** \class HDTVRecorder
    21  *  \brief This is a specialization of DTVRecorder used to
    22  *         handle streams from bttv drivers, such as the
    23  *         vendor drivers for the the HD-2000 and HD-3000.
    24  *
    25  *  \sa DTVRecorder, DVBRecorder
    26  */
    27 class HDTVRecorder : public DTVRecorder,
    28                      public MPEGSingleProgramStreamListener,
    29                      public ATSCMainStreamListener
    30 {
    31     friend class ATSCStreamData;
    32     friend class TSPacketProcessor;
    33 
    34   public:
    35     enum {report_loops = 20000};
    36 
    37     HDTVRecorder(TVRec *rec);
    38    ~HDTVRecorder();
    39 
    40     void SetOptionsFromProfile(RecordingProfile *profile,
    41                                const QString &videodev,
    42                                const QString &audiodev,
    43                                const QString &vbidev);
    44 
    45     void StartRecording(void);
    46     void StopRecording(void);
    47 
    48     void Pause(bool clear = false);
    49     bool IsPaused(void) const;
    50 
    51     void Reset(void);
    52 
    53     bool Open(void);
    54 
    55     void SetStreamData(MPEGStreamData*);
    56     MPEGStreamData* GetStreamData(void);
    57     ATSCStreamData* GetATSCStreamData(void) { return _atsc_stream_data; }
    58 
    59     void HandleSingleProgramPAT(ProgramAssociationTable*);
    60     void HandleSingleProgramPMT(ProgramMapTable*);
    61 
    62     void HandleSTT(const SystemTimeTable*) {}
    63     void HandleMGT(const MasterGuideTable*);
    64     void HandleVCT(uint, const VirtualChannelTable*);
    65 
    66   private:
    67     void TeardownAll(void);
    68 
    69     int  ProcessData    (const unsigned char *buffer, uint len);
    70     int  ResyncStream   (const unsigned char *buffer, uint pos, uint len);
    71     bool ProcessTSPacket(const TSPacket &tspacket);
    72 
    73     static void *boot_ringbuffer(void *);
    74     void fill_ringbuffer(void);
    75     int ringbuf_read(unsigned char *buffer, size_t count);
    76 
    77  private:
    78     ATSCStreamData* _atsc_stream_data;
    79 
    80     // statistics
    81     TSStats _ts_stats;
    82     long long _resync_count;
    83     size_t loop;
    84 
    85     // Data for managing the device ringbuffer
    86     struct {
    87         pthread_t        thread;
    88         mutable pthread_mutex_t lock;
    89         mutable pthread_mutex_t lock_stats;
    90 
    91         bool             run;
    92         bool             eof;
    93         bool             error;
    94         bool             request_pause;
    95         bool             paused;
    96         size_t           size;
    97         size_t           used;
    98         size_t           max_used;
    99         size_t           avg_used;
    100         size_t           avg_cnt;
    101         size_t           dev_read_size;
    102         size_t           min_read;
    103         unsigned char  * buffer;
    104         unsigned char  * readPtr;
    105         unsigned char  * writePtr;
    106         unsigned char  * endPtr;
    107     } ringbuf;
    108 };
    109 
    110 #endif
  • libs/libmythtv/hdtvrecorder.cpp

     
    1 /* HDTVRecorder
    2    Version 0.1
    3    July 4th, 2003
    4    GPL License (c)
    5    By Brandon Beattie
    6 
    7    Portions of this code taken from mpegrecorder
    8 
    9    Modified Oct. 2003 by Doug Larrick
    10    * decodes MPEG-TS locally (does not use libavformat) for flexibility
    11    * output format is MPEG-TS omitting unneeded PIDs, for smaller files
    12      and no audio stutter on stations with >1 audio stream
    13    * Emits proper keyframe data to recordedmarkup db, enabling seeking
    14 
    15    Oct. 22, 2003:
    16    * delay until GOP before writing output stream at start and reset
    17      (i.e. channel change)
    18    * Rewrite PIDs after channel change to be the same as before, so
    19      decoder can follow
    20 
    21    Oct. 27, 2003 by Jason Hoos:
    22    * if no GOP is detected within the first 30 frames of the stream, then
    23      assume that it's safe to treat a picture start as a GOP.
    24 
    25    Oct. 30, 2003 by Jason Hoos:
    26    * added code to rewrite PIDs in the MPEG PAT and PMT tables.  fixes
    27      a problem with stations (particularly, WGN in Chicago) that list their
    28      programs in reverse order in the PAT, which was confusing ffmpeg
    29      (ffmpeg was looking for program 5, but only program 2 was left in
    30      the stream, so it choked).
    31 
    32    Nov. 3, 2003 by Doug Larrick:
    33    * code to enable selecting a program number for stations with
    34      multiple programs
    35    * always renumber PIDs to match outgoing program number (#1:
    36      0x10 (base), 0x11 (video), 0x14 (audio))
    37    * change expected keyframe distance to 30 frames to see if this
    38      lets people seek past halfway in recordings
    39 
    40    Jan 30, 2004 by Daniel Kristjansson
    41    * broke out tspacket to handle TS packets
    42    * added CRC check on PAT & PMT packets
    43    Sept 27, 2004
    44    * added decoding of most ATSC Tables
    45    * added multiple audio support
    46 
    47 
    48    References / example code:
    49      ATSC standards a.54, a.69 (www.atsc.org)
    50      ts2pes from mpegutils from dvb (www.linuxtv.org)
    51      bbinfo from Brent Beyeler, beyeler@home.com
    52 */
    53 
    54 // C includes
    55 #include <cstdio>
    56 #include <cstdlib>
    57 #include <cerrno>
    58 #include <ctime>
    59 #include <fcntl.h>
    60 #include <pthread.h>
    61 #include <unistd.h>
    62 
    63 // C system includes
    64 #include <sys/types.h>
    65 #include <sys/stat.h>
    66 #include <sys/ioctl.h>
    67 #include <sys/time.h>
    68 
    69 // C++ includes
    70 #include <iostream>
    71 using namespace std;
    72 
    73 // MythTV system include
    74 #include "videodev_myth.h"
    75 
    76 // MythTV includes
    77 #include "hdtvrecorder.h"
    78 #include "RingBuffer.h"
    79 #include "mythcontext.h"
    80 #include "mythdbcon.h"
    81 #include "programinfo.h"
    82 #include "channel.h"
    83 #include "mpegtables.h"
    84 #include "atsctables.h"
    85 #include "atscstreamdata.h"
    86 #include "tv_rec.h"
    87 
    88 // AVLib/FFMPEG includes
    89 #include "../libavcodec/avcodec.h"
    90 #include "../libavformat/avformat.h"
    91 #include "../libavformat/mpegts.h"
    92 
    93 #define REPORT_RING_STATS 1
    94 
    95 #define DEFAULT_SUBCHANNEL 1
    96 
    97 #define WHACK_A_BUG_VIDEO 0
    98 #define WHACK_A_BUG_AUDIO 0
    99 
    100 #if FAKE_VIDEO
    101     static int fake_video_index = 0;
    102 #define FAKE_VIDEO_NUM 4
    103     static const char* FAKE_VIDEO_FILES[FAKE_VIDEO_NUM] =
    104         {
    105             "/video/abc.ts",
    106             "/video/wb.ts",
    107             "/video/abc2.ts",
    108             "/video/nbc.ts",
    109         };
    110 #endif
    111 
    112 HDTVRecorder::HDTVRecorder(TVRec *rec)
    113     : DTVRecorder(rec),
    114       _atsc_stream_data(NULL),
    115       _resync_count(0)
    116 {
    117     SetStreamData(new ATSCStreamData(-1, DEFAULT_SUBCHANNEL));
    118 
    119     _buffer_size = TSPacket::SIZE * 1500;
    120     if ((_buffer = new unsigned char[_buffer_size])) {
    121         // make valgrind happy, initialize buffer memory
    122         memset(_buffer, 0xFF, _buffer_size);
    123     }
    124 
    125     VERBOSE(VB_RECORD, QString("HD buffer size %1 KB").arg(_buffer_size/1024));
    126 
    127     ringbuf.run = false;
    128     ringbuf.buffer = 0;
    129     pthread_mutex_init(&ringbuf.lock, NULL);
    130     pthread_mutex_init(&ringbuf.lock_stats, NULL);
    131     loop = random() % (report_loops / 2);
    132 }
    133 
    134 void HDTVRecorder::TeardownAll(void)
    135 {
    136     // Make SURE that the ringbuffer thread is cleaned up
    137     StopRecording();
    138 
    139     if (_stream_fd >= 0)
    140     {
    141         close(_stream_fd);
    142         _stream_fd = -1;
    143     }
    144    
    145     SetStreamData(NULL);
    146 
    147     if (_buffer)
    148     {
    149         delete[] _buffer;
    150         _buffer = NULL;
    151     }
    152 }
    153 
    154 HDTVRecorder::~HDTVRecorder()
    155 {
    156     TeardownAll();
    157     pthread_mutex_destroy(&ringbuf.lock);
    158     pthread_mutex_destroy(&ringbuf.lock_stats);
    159 }
    160 
    161 void HDTVRecorder::SetOptionsFromProfile(RecordingProfile *profile,
    162                                          const QString &videodev,
    163                                          const QString &audiodev,
    164                                          const QString &vbidev)
    165 {
    166     (void)audiodev;
    167     (void)vbidev;
    168     (void)profile;
    169 
    170     SetOption("videodevice", videodev);
    171     SetOption("tvformat", gContext->GetSetting("TVFormat"));
    172     SetOption("vbiformat", gContext->GetSetting("VbiFormat"));
    173 }
    174 
    175 bool HDTVRecorder::Open()
    176 {
    177     if (!_atsc_stream_data || !_buffer)
    178         return false;
    179 
    180 #if FAKE_VIDEO
    181     // open file instead of device
    182     if (_stream_fd >=0 && close(_stream_fd))
    183     {
    184         VERBOSE(VB_IMPORTANT,
    185                 QString("HDTVRecorder::Open(): Error, failed to close "
    186                         "existing fd (%1)").arg(strerror(errno)));
    187         return false;
    188     }
    189 
    190     _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);
    191     VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));
    192     fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;
    193 #else
    194     if (_stream_fd <= 0)
    195         _stream_fd = open(videodevice.ascii(), O_RDWR);
    196 #endif
    197     if (_stream_fd <= 0)
    198     {
    199         VERBOSE(VB_IMPORTANT, QString("Can't open video device: %1 chanfd = %2")
    200                 .arg(videodevice).arg(_stream_fd));
    201         perror("open video:");
    202     }
    203     return (_stream_fd>0);
    204 }
    205 
    206 void HDTVRecorder::SetStreamData(MPEGStreamData *xdata)
    207 {
    208     ATSCStreamData *data = dynamic_cast<ATSCStreamData*>(xdata);
    209 
    210     if (data == _atsc_stream_data)
    211         return;
    212 
    213     ATSCStreamData *old_data = _atsc_stream_data;
    214     _atsc_stream_data = data;
    215     if (old_data)
    216         delete old_data;
    217 
    218     if (data)
    219     {
    220         data->AddMPEGSPListener(this);
    221         data->AddATSCMainListener(this);
    222     }
    223 }
    224 
    225 MPEGStreamData *HDTVRecorder::GetStreamData(void)
    226 {
    227     return _atsc_stream_data;
    228 }
    229 
    230 bool readchan(int chanfd, unsigned char* buffer, int dlen) {
    231     int len = read(chanfd, buffer, dlen); // read next byte
    232     if (dlen != len)
    233     {
    234         if (len < 0)
    235         {
    236             VERBOSE(VB_IMPORTANT, QString("HD1 error reading from device"));
    237             perror("read");
    238         }
    239         else if (len == 0)
    240             VERBOSE(VB_IMPORTANT, QString("HD2 end of file found in packet"));
    241         else
    242             VERBOSE(VB_IMPORTANT, QString("HD3 partial read. This shouldn't happen!"));
    243     }
    244     return (dlen == len);
    245 }
    246 
    247 bool syncchan(int chanfd, int dlen, int keepsync) {
    248     unsigned char b[188];
    249     int i, j;
    250     for (i=0; i<dlen; i++) {
    251         if (!readchan(chanfd, b, 1))
    252             break;
    253         if (SYNC_BYTE == b[0])
    254         {
    255             if (readchan(chanfd, &b[1], TSPacket::SIZE-1)) {
    256                 i += (TSPacket::SIZE - 1);
    257                 for (j=0; j<keepsync; j++)
    258                 {
    259                     if (!readchan(chanfd, b, TSPacket::SIZE))
    260                         return false;
    261                     i += TSPacket::SIZE;
    262                     if (SYNC_BYTE != b[0])
    263                         break;
    264                 }
    265                 if (j==keepsync)
    266                 {
    267                     VERBOSE(VB_RECORD,
    268                             QString("HD4 obtained device stream sync after reading %1 bytes").
    269                             arg(dlen));
    270                     return true;
    271                 }
    272                 continue;
    273             }
    274             break;
    275         }
    276     }
    277     VERBOSE(VB_IMPORTANT, QString("HD5 Error: could not obtain sync"));
    278     return false;
    279 }
    280 
    281 void * HDTVRecorder::boot_ringbuffer(void * arg)
    282 {
    283     HDTVRecorder *dtv = (HDTVRecorder *)arg;
    284     dtv->fill_ringbuffer();
    285     return NULL;
    286 }
    287 
    288 void HDTVRecorder::fill_ringbuffer(void)
    289 {
    290     int       errcnt = 0;
    291     int       len;
    292     size_t    unused, used;
    293     size_t    contiguous;
    294     size_t    read_size;
    295     bool      run, request_pause, paused;
    296 
    297     pthread_mutex_lock(&ringbuf.lock);
    298     ringbuf.run = true;
    299     pthread_mutex_unlock(&ringbuf.lock);
    300 
    301     for (;;)
    302     {
    303         pthread_mutex_lock(&ringbuf.lock);
    304         run = ringbuf.run;
    305         unused = ringbuf.size - ringbuf.used;
    306         request_pause = ringbuf.request_pause;
    307         paused = ringbuf.paused;
    308         pthread_mutex_unlock(&ringbuf.lock);
    309 
    310         if (!run)
    311             break;
    312 
    313         if (request_pause)
    314         {
    315             pthread_mutex_lock(&ringbuf.lock);
    316             ringbuf.paused = true;
    317             pthread_mutex_unlock(&ringbuf.lock);
    318 
    319             pauseWait.wakeAll();
    320             if (tvrec)
    321                 tvrec->RecorderPaused();
    322 
    323             usleep(1000);
    324             continue;
    325         }
    326         else if (paused)
    327         {
    328             pthread_mutex_lock(&ringbuf.lock);
    329             ringbuf.writePtr = ringbuf.readPtr = ringbuf.buffer;
    330             ringbuf.used = 0;
    331             ringbuf.paused = false;
    332             pthread_mutex_unlock(&ringbuf.lock);
    333         }
    334 
    335         contiguous = ringbuf.endPtr - ringbuf.writePtr;
    336 
    337         while (unused < TSPacket::SIZE && contiguous > TSPacket::SIZE)
    338         {
    339             usleep(500);
    340 
    341             pthread_mutex_lock(&ringbuf.lock);
    342             unused = ringbuf.size - ringbuf.used;
    343             request_pause = ringbuf.request_pause;
    344             pthread_mutex_unlock(&ringbuf.lock);
    345 
    346             if (request_pause)
    347                 break;
    348         }
    349         if (request_pause)
    350             continue;
    351 
    352         read_size = unused > contiguous ? contiguous : unused;
    353         if (read_size > ringbuf.dev_read_size)
    354             read_size = ringbuf.dev_read_size;
    355 
    356         len = read(_stream_fd, ringbuf.writePtr, read_size);
    357 
    358         if (len < 0)
    359         {
    360             if (errno == EINTR)
    361                 continue;
    362 
    363             VERBOSE(VB_IMPORTANT, QString("HD7 error reading from %1")
    364                     .arg(videodevice));
    365             perror("read");
    366             if (++errcnt > 5)
    367             {
    368                 pthread_mutex_lock(&ringbuf.lock);
    369                 ringbuf.error = true;
    370                 pthread_mutex_unlock(&ringbuf.lock);
    371 
    372                 break;
    373             }
    374 
    375             usleep(500);
    376             continue;
    377         }
    378         else if (len == 0)
    379         {
    380             if (++errcnt > 5)
    381             {
    382                 VERBOSE(VB_IMPORTANT, QString("HD8 %1 end of file found.")
    383                         .arg(videodevice));
    384 
    385                 pthread_mutex_lock(&ringbuf.lock);
    386                 ringbuf.eof = true;
    387                 pthread_mutex_unlock(&ringbuf.lock);
    388 
    389                 break;
    390             }
    391             usleep(500);
    392             continue;
    393         }
    394 
    395         errcnt = 0;
    396 
    397         pthread_mutex_lock(&ringbuf.lock);
    398         ringbuf.used += len;
    399         used = ringbuf.used;
    400         ringbuf.writePtr += len;
    401         pthread_mutex_unlock(&ringbuf.lock);
    402 
    403 #ifdef REPORT_RING_STATS
    404         pthread_mutex_lock(&ringbuf.lock_stats);
    405 
    406         if (ringbuf.max_used < used)
    407             ringbuf.max_used = used;
    408 
    409         ringbuf.avg_used = ((ringbuf.avg_used * ringbuf.avg_cnt) + used)
    410                            / ++ringbuf.avg_cnt;
    411         pthread_mutex_unlock(&ringbuf.lock_stats);
    412 #endif
    413 
    414         if (ringbuf.writePtr == ringbuf.endPtr)
    415             ringbuf.writePtr = ringbuf.buffer;
    416     }
    417 
    418     close(_stream_fd);
    419     _stream_fd = -1;
    420 }
    421 
    422 /* read count bytes from ring into buffer */
    423 int HDTVRecorder::ringbuf_read(unsigned char *buffer, size_t count)
    424 {
    425     size_t          avail;
    426     size_t          cnt = count;
    427     size_t          min_read;
    428     unsigned char  *cPtr = buffer;
    429 
    430     bool            dev_error = false;
    431     bool            dev_eof = false;
    432 
    433     pthread_mutex_lock(&ringbuf.lock);
    434     avail = ringbuf.used;
    435     pthread_mutex_unlock(&ringbuf.lock);
    436 
    437     min_read = cnt < ringbuf.min_read ? cnt : ringbuf.min_read;
    438 
    439     while (min_read > avail)
    440     {
    441         usleep(50000);
    442 
    443         if (request_pause || dev_error || dev_eof)
    444             return 0;
    445 
    446         pthread_mutex_lock(&ringbuf.lock);
    447         dev_error = ringbuf.error;
    448         dev_eof = ringbuf.eof;
    449         avail = ringbuf.used;
    450         pthread_mutex_unlock(&ringbuf.lock);
    451     }
    452     if (cnt > avail)
    453         cnt = avail;
    454 
    455     if (ringbuf.readPtr + cnt > ringbuf.endPtr)
    456     {
    457         size_t      len;
    458 
    459         // Process as two pieces
    460         len = ringbuf.endPtr - ringbuf.readPtr;
    461         memcpy(cPtr, ringbuf.readPtr, len);
    462         cPtr += len;
    463         len = cnt - len;
    464 
    465         // Wrap arround to begining of buffer
    466         ringbuf.readPtr = ringbuf.buffer;
    467         memcpy(cPtr, ringbuf.readPtr, len);
    468         ringbuf.readPtr += len;
    469     }
    470     else
    471     {
    472         memcpy(cPtr, ringbuf.readPtr, cnt);
    473         ringbuf.readPtr += cnt;
    474     }
    475 
    476     pthread_mutex_lock(&ringbuf.lock);
    477     ringbuf.used -= cnt;
    478     pthread_mutex_unlock(&ringbuf.lock);
    479 
    480     if (ringbuf.readPtr == ringbuf.endPtr)
    481         ringbuf.readPtr = ringbuf.buffer;
    482     else
    483     {
    484 #ifdef REPORT_RING_STATS
    485         size_t samples, avg, max;
    486 
    487         if (++loop == report_loops)
    488         {
    489             loop = 0;
    490             pthread_mutex_lock(&ringbuf.lock_stats);
    491             avg = ringbuf.avg_used;
    492             samples = ringbuf.avg_cnt;
    493             max = ringbuf.max_used;
    494             ringbuf.avg_used = 0;
    495             ringbuf.avg_cnt = 0;
    496             ringbuf.max_used = 0;
    497             pthread_mutex_unlock(&ringbuf.lock_stats);
    498 
    499             VERBOSE(VB_IMPORTANT, QString("%1 ringbuf avg %2% max %3%"
    500                                           " samples %4")
    501                     .arg(videodevice)
    502                     .arg((static_cast<double>(avg)
    503                           / ringbuf.size) * 100.0)
    504                     .arg((static_cast<double>(max)
    505                           / ringbuf.size) * 100.0)
    506                     .arg(samples));
    507         }
    508         else
    509 #endif
    510             usleep(25);
    511     }
    512 
    513     return cnt;
    514 }
    515 
    516 void HDTVRecorder::StartRecording(void)
    517 {
    518     bool            pause;
    519     bool            dev_error, dev_eof;
    520     int             len;
    521 
    522     const int unsyncpackets = 50; // unsynced packets to look at before giving up
    523     const int syncpackets   = 10; // synced packets to require before starting recording
    524 
    525     VERBOSE(VB_RECORD, QString("StartRecording"));
    526 
    527     if (!Open())
    528     {
    529         _error = true;       
    530         return;
    531     }
    532 
    533     _request_recording = true;
    534     _recording = true;
    535 
    536     // Setup device ringbuffer
    537     delete[] ringbuf.buffer;
    538 
    539 //    ringbuf.size = 60 * 1024 * TSPacket::SIZE;
    540     ringbuf.size = gContext->GetNumSetting("HDRingbufferSize", 50*188);
    541     ringbuf.size *= 1024;
    542 
    543     if ((ringbuf.buffer =
    544          new unsigned char[ringbuf.size + TSPacket::SIZE]) == NULL)
    545     {
    546         VERBOSE(VB_IMPORTANT, "Failed to allocate HDTVRecorder ring buffer.");
    547         _error = true;
    548         return;
    549     }
    550 
    551     memset(ringbuf.buffer, 0xFF, ringbuf.size + TSPacket::SIZE);
    552     ringbuf.endPtr = ringbuf.buffer + ringbuf.size;
    553     ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;
    554     ringbuf.dev_read_size = TSPacket::SIZE * 48;
    555     ringbuf.min_read = TSPacket::SIZE * 4;
    556     ringbuf.used = 0;
    557     ringbuf.max_used = 0;
    558     ringbuf.avg_used = 0;
    559     ringbuf.avg_cnt = 0;
    560     ringbuf.request_pause = false;
    561     ringbuf.paused = false;
    562     ringbuf.error = false;
    563     ringbuf.eof = false;
    564 
    565     VERBOSE(VB_RECORD, QString("HD ring buffer size %1 KB")
    566             .arg(ringbuf.size/1024));
    567 
    568     // sync device stream so it starts with a valid ts packet
    569     if (!syncchan(_stream_fd, TSPacket::SIZE*unsyncpackets, syncpackets))
    570     {
    571         _error = true;
    572         return;
    573     }
    574 
    575     // create thread to fill the ringbuffer
    576     pthread_create(&ringbuf.thread, NULL, boot_ringbuffer,
    577                    reinterpret_cast<void *>(this));
    578 
    579     int remainder = 0;
    580     // TRANSFER DATA
    581     while (_request_recording)
    582     {
    583         pthread_mutex_lock(&ringbuf.lock);
    584         dev_error = ringbuf.error;
    585         dev_eof = ringbuf.eof;
    586         pause = ringbuf.paused;
    587         pthread_mutex_unlock(&ringbuf.lock);
    588 
    589         if (request_pause)
    590         {
    591             pthread_mutex_lock(&ringbuf.lock);
    592             ringbuf.request_pause = true;
    593             pthread_mutex_unlock(&ringbuf.lock);
    594 
    595             usleep(1000);
    596             continue;
    597         }
    598         else if (pause)
    599         {
    600             pthread_mutex_lock(&ringbuf.lock);
    601             ringbuf.request_pause = false;
    602             pthread_mutex_unlock(&ringbuf.lock);
    603 
    604             usleep(1500);
    605             continue;
    606         }
    607 
    608         if (dev_error)
    609         {
    610             VERBOSE(VB_IMPORTANT, "HDTV: device error detected");
    611             _error = true;
    612             break;
    613         }
    614 
    615         if (dev_eof)
    616             break;
    617 
    618         len = ringbuf_read(&(_buffer[remainder]), _buffer_size - remainder);
    619 
    620         if (len == 0)
    621             continue;
    622 
    623         len += remainder;
    624         remainder = ProcessData(_buffer, len);
    625         if (remainder > 0 && (len > remainder)) // leftover bytes
    626             memmove(_buffer, &(_buffer[len - remainder]), remainder);
    627     }
    628 
    629     FinishRecording();
    630     _recording = false;
    631 }
    632 
    633 void HDTVRecorder::StopRecording(void)
    634 {
    635     TVRec *rec = tvrec;
    636     tvrec = NULL; // don't notify of pause..
    637 
    638     bool ok = true;
    639     if (!IsPaused())
    640     {
    641         Pause();
    642         ok = WaitForPause(250);
    643     }
    644 
    645     _request_recording = false;
    646 
    647     pthread_mutex_lock(&ringbuf.lock);
    648     bool run = ringbuf.run;
    649     ringbuf.run = false;
    650     pthread_mutex_unlock(&ringbuf.lock);
    651 
    652     if (run)
    653         pthread_join(ringbuf.thread, NULL);
    654 
    655     if (!ok)
    656     {
    657         // Better to have a memory leak, then a segfault?
    658         VERBOSE(VB_IMPORTANT, "DTV ringbuffer not cleaned up!\n");
    659     }
    660     else
    661     {
    662         delete[] ringbuf.buffer;
    663         ringbuf.buffer = 0;
    664     }
    665     tvrec = rec;
    666 }
    667 
    668 void HDTVRecorder::Pause(bool /*clear*/)
    669 {
    670     pthread_mutex_lock(&ringbuf.lock);
    671     ringbuf.paused = false;
    672     pthread_mutex_unlock(&ringbuf.lock);
    673     request_pause = true;
    674 }
    675 
    676 bool HDTVRecorder::IsPaused(void) const
    677 {
    678     pthread_mutex_lock(&ringbuf.lock);
    679     bool paused = ringbuf.paused;
    680     pthread_mutex_unlock(&ringbuf.lock);
    681 
    682     return paused;
    683 }
    684 
    685 int HDTVRecorder::ResyncStream(const unsigned char *buffer,
    686                                uint curr_pos, uint len)
    687 {
    688     // Search for two sync bytes 188 bytes apart,
    689     uint pos = curr_pos;
    690     uint nextpos = pos + TSPacket::SIZE;
    691     if (nextpos >= len)
    692         return -1; // not enough bytes; caller should try again
    693    
    694     while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE)
    695     {
    696         pos++;
    697         nextpos++;
    698         if (nextpos == len)
    699             return -2; // not found
    700     }
    701 
    702     return pos;
    703 }
    704 
    705 void HDTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)
    706 {
    707     if (!pat)
    708         return;
    709 
    710     int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;
    711     pat->tsheader()->SetContinuityCounter(next);
    712     BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));
    713 }
    714 
    715 void HDTVRecorder::HandleSingleProgramPMT(ProgramMapTable* pmt)
    716 {
    717     if (!pmt)
    718         return;
    719 
    720     int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;
    721     pmt->tsheader()->SetContinuityCounter(next);
    722     BufferedWrite(*(reinterpret_cast<TSPacket*>(pmt->tsheader())));
    723 }
    724 
    725 /** \fn HDTVRecorder::HandleMGT(const MasterGuideTable*)
    726  *  \brief Handles Master Guide Table, by enabling the
    727  *         scanning of all PIDs listed.
    728  */
    729 void HDTVRecorder::HandleMGT(const MasterGuideTable *mgt)
    730 {
    731     for (unsigned int i=0; i<mgt->TableCount(); i++)
    732         GetStreamData()->AddListeningPID(mgt->TablePID(i));
    733 }
    734 
    735 /** \fn HDTVRecorder::HandleVCT(uint, const VirtualChannelTable*)
    736  *  \brief Handles Virtual Channel Tables by finding the program
    737  *         number to use.
    738  *  \bug Assumes there is only one VCT, may break on Cable.
    739  */
    740 void HDTVRecorder::HandleVCT(uint /*tsid*/, const VirtualChannelTable *vct)
    741 {
    742     if (vct->ChannelCount() < 1)
    743     {
    744         VERBOSE(VB_IMPORTANT,
    745                 "HDTVRecorder::HandleVCT: table has no channels");
    746         return;
    747     }
    748 
    749     bool found = false;   
    750     VERBOSE(VB_RECORD, QString("Desired channel %1_%2")
    751             .arg(GetATSCStreamData()->DesiredMajorChannel())
    752             .arg(GetATSCStreamData()->DesiredMinorChannel()));
    753     for (uint i = 0; i < vct->ChannelCount(); i++)
    754     {
    755         int maj = GetATSCStreamData()->DesiredMajorChannel();
    756         int min = GetATSCStreamData()->DesiredMinorChannel();
    757         if ((maj == -1 || vct->MajorChannel(i) == (uint)maj) &&
    758             (vct->MinorChannel(i) == (uint)min))
    759         {
    760             uint pnum = (uint) GetATSCStreamData()->DesiredProgram();
    761             if (vct->ProgramNumber(i) != pnum)
    762             {
    763                 VERBOSE(VB_RECORD,
    764                         QString("Resetting desired program from %1"
    765                                 " to %2")
    766                         .arg(GetATSCStreamData()->DesiredProgram())
    767                         .arg(vct->ProgramNumber(i)));
    768                 // Do a (partial?) reset here if old desired
    769                 // program is not 0?
    770                 GetATSCStreamData()->SetDesiredProgram(vct->ProgramNumber(i));
    771             }
    772             found = true;
    773         }
    774     }
    775     if (!found)
    776     {
    777         VERBOSE(VB_IMPORTANT,
    778                 QString("Desired channel %1_%2 not found;"
    779                         " using %3_%4 instead.")
    780                 .arg(GetATSCStreamData()->DesiredMajorChannel())
    781                 .arg(GetATSCStreamData()->DesiredMinorChannel())
    782                 .arg(vct->MajorChannel(0))
    783                 .arg(vct->MinorChannel(0)));
    784         VERBOSE(VB_IMPORTANT, vct->toString());
    785         GetATSCStreamData()->SetDesiredProgram(vct->ProgramNumber(0));
    786     }
    787 }
    788 
    789 bool HDTVRecorder::ProcessTSPacket(const TSPacket &tspacket)
    790 {
    791     bool ok = !tspacket.TransportError();
    792     if (ok && !tspacket.ScramplingControl())
    793     {
    794         if (tspacket.HasAdaptationField())
    795             GetStreamData()->HandleAdaptationFieldControl(&tspacket);
    796         if (tspacket.HasPayload())
    797         {
    798             const unsigned int lpid = tspacket.PID();
    799             // Pass or reject frames based on PID, and parse info from them
    800             if (lpid == GetStreamData()->VideoPIDSingleProgram())
    801             {
    802                 _buffer_packets = !FindMPEG2Keyframes(&tspacket);
    803                 BufferedWrite(tspacket);
    804             }
    805             else if (GetStreamData()->IsAudioPID(lpid))
    806                 BufferedWrite(tspacket);
    807             else if (GetStreamData()->IsListeningPID(lpid))
    808                 GetStreamData()->HandleTSTables(&tspacket);
    809             else if (GetStreamData()->IsWritingPID(lpid))
    810                 BufferedWrite(tspacket);
    811             else if (GetATSCStreamData()->VersionMGT()>=0)
    812                 _ts_stats.IncrPIDCount(lpid);
    813         }
    814     }
    815     return ok;
    816 }
    817 
    818 int HDTVRecorder::ProcessData(const unsigned char *buffer, uint len)
    819 {
    820     uint pos = 0;
    821 
    822     while (pos + 187 < len) // while we have a whole packet left
    823     {
    824         if (buffer[pos] != SYNC_BYTE)
    825         {
    826             _resync_count++;
    827             if (25 == _resync_count)
    828                 VERBOSE(VB_RECORD, QString("Resyncing many of times, suppressing error messages"));
    829             else if (25 > _resync_count)
    830                 VERBOSE(VB_RECORD, QString("Resyncing"));
    831             int newpos = ResyncStream(buffer, pos, len);
    832             if (newpos == -1)
    833                 return len - pos;
    834             if (newpos == -2)
    835                 return TSPacket::SIZE;
    836 
    837             pos = newpos;
    838         }
    839 
    840         const TSPacket *pkt = reinterpret_cast<const TSPacket*>(&buffer[pos]);
    841         if (ProcessTSPacket(*pkt))
    842         {
    843             pos += TSPacket::SIZE; // Advance to next TS packet
    844             _ts_stats.IncrTSPacketCount();
    845             if (0 == _ts_stats.TSPacketCount()%1000000)
    846                 VERBOSE(VB_RECORD, _ts_stats.toString());
    847         }
    848         else
    849         { // Let it resync in case of dropped bytes
    850             pos++;
    851         }
    852     }
    853 
    854     return len - pos;
    855 }
    856 
    857 void HDTVRecorder::Reset(void)
    858 {
    859     VERBOSE(VB_RECORD, "HDTVRecorder::Reset(void)");
    860     DTVRecorder::Reset();
    861 
    862     _error = false;
    863     _resync_count = 0;
    864     _ts_stats.Reset();
    865 
    866     if (curRecording)
    867     {
    868         curRecording->ClearPositionMap(MARK_GOP_BYFRAME);
    869     }
    870 
    871     if (_stream_fd >= 0)
    872     {
    873         if (!IsPaused())
    874         {
    875             Pause();
    876             WaitForPause();
    877         }
    878         int ret = close(_stream_fd);
    879         if (ret < 0)
    880         {
    881             perror("close");
    882             return;
    883         }
    884 #if FAKE_VIDEO
    885         // open file instead of device
    886         _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);
    887         VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));
    888         fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;
    889 #else
    890         _stream_fd = open(videodevice.ascii(), O_RDWR);
    891 #endif
    892         if (_stream_fd < 0)
    893         {
    894             VERBOSE(VB_IMPORTANT, QString("HD1 Can't open video device: %1 chanfd = %2").
    895                     arg(videodevice).arg(_stream_fd));
    896             perror("open video");
    897             return;
    898         }
    899         else
    900         {
    901             pthread_mutex_lock(&ringbuf.lock);
    902             ringbuf.used = 0;
    903             ringbuf.max_used = 0;
    904             ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;
    905             pthread_mutex_unlock(&ringbuf.lock);
    906         }
    907         Unpause();
    908     }
    909 }
  • libs/libmythtv/cardutil.h

     
    4848        ATSC,
    4949        V4L,
    5050        MPEG,
    51         HDTV,
    5251        FIREWIRE,
    5352        HDHOMERUN,
    5453        CRC_IP,
     
    7574            return V4L;
    7675        if ("MPEG" == name)
    7776            return MPEG;
    78         if ("HDTV" == name)
    79             return HDTV;
    8077        if ("FIREWIRE" == name)
    8178            return FIREWIRE;
    8279        if ("HDHOMERUN" == name)
     
    9188    static bool         IsEncoder(const QString &rawtype)
    9289    {
    9390        return
    94             (rawtype != "DVB")       && (rawtype != "HDTV")    &&
    95             (rawtype != "FIREWIRE")  && (rawtype != "DBOX2")   &&
    96             (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") &&
    97             (rawtype != "CRC_IP");
     91            (rawtype != "DVB")       && (rawtype != "FIREWIRE")  &&
     92            (rawtype != "DBOX2")     && (rawtype != "HDHOMERUN") &&
     93            (rawtype != "FREEBOX")   && (rawtype != "CRC_IP");
    9894    }
    9995
    10096    static bool         IsUnscanable(const QString &rawtype)
     
    107103    static bool         IsEITCapable(const QString &rawtype)
    108104    {
    109105        return
    110             (rawtype == "DVB")       || (rawtype == "HDTV")  ||
    111             (rawtype == "HDHOMERUN");
     106            (rawtype == "DVB")       || (rawtype == "HDHOMERUN");
    112107    }
    113108
    114109    static int          GetCardID(const QString &videodevice,
  • libs/libmythtv/videosource.h

     
    366366    TunerCardInput    *input;
    367367};
    368368
    369 class pcHDTVConfigurationGroup: public VerticalConfigurationGroup
    370 {
    371     Q_OBJECT
    372 
    373   public:
    374     pcHDTVConfigurationGroup(CaptureCard& a_parent);
    375 
    376   public slots:
    377     void probeCard(const QString &device);
    378 
    379   private:
    380     CaptureCard       &parent;
    381     TransLabelSetting *cardinfo;
    382     TunerCardInput    *input;
    383 };
    384 
    385369class DVBInput;
    386370class DVBCardName;
    387371class DVBCardType;
  • libs/libmythtv/libmythtv.pro

     
    369369    # Support for Video4Linux devices
    370370    using_v4l {
    371371        HEADERS += channel.h                   analogsignalmonitor.h
    372         HEADERS += hdtvrecorder.h              pchdtvsignalmonitor.h
    373372        SOURCES += channel.cpp                 analogsignalmonitor.h
    374         SOURCES += hdtvrecorder.cpp            pchdtvsignalmonitor.cpp
    375373
    376374        DEFINES += USING_V4L
    377375    }
  • libs/libmythtv/dvbrecorder.h

     
    5353 *  \brief This is a specialization of DTVRecorder used to
    5454 *         handle streams from DVB drivers.
    5555 *
    56  *  \sa DTVRecorder, HDTVRecorder
     56 *  \sa DTVRecorder
    5757 */
    5858class DVBRecorder :
    5959    public DTVRecorder,
  • libs/libmythtv/dbcheck.cpp

     
    1010#include "mythdbcon.h"
    1111
    1212/// This is the DB schema version expected by the running MythTV instance.
    13 const QString currentDatabaseVersion = "1177";
     13const QString currentDatabaseVersion = "1178";
    1414
    1515static bool UpdateDBVersionNumber(const QString &newnumber);
    1616static bool performActualUpdate(const QString updates[], QString version,
     
    9797
    9898The 'cardtype' is an important field for all cards as it guides the
    9999interpretation of the rest of the fields, it has several possible
    100 values: "V4L", "MJPEG", "HDTV", "DVB", "MPEG", "FIREWIRE", "GO7007"
     100values: "V4L", "MJPEG", "DVB", "MPEG", "FIREWIRE", "GO7007"
    101101and  "DBOX2".
    102102"V4L" indicates a V4L compatible device, this could be a
    103103true V4L device or something like a Firewire camera with the
    104104"firewire->v4l" driver.
    105105"MJPEG" describes a Matrox G200 or DC10 card which captures
    106106individual frames a JPEG images.
    107 "HDTV" describes a pcHDTV HD-2000 or HD-3000 when using the V4L
    108 drivers.
    109107"DVB" can describe any card supported by the Linux DVB
    110108drivers, including the pcHDTV and other ATSC cards.
    111109The "MPEG" type describes a device using the ivtv drivers such as
     
    135133
    136134The 'signal_timeout' and 'channel_timeout' indicate in
    137135milliseconds how long it should take to get a signal and
    138 channel lock respectively. Signal lock detection is
    139 currently only supported on "DVB" and "HDTV" card types.
     136channel lock respectively.
    140137
    141138The 'dvb_swfilter', 'dvb_sat_type', 'dvb_wait_for_seqstart',
    142139'skipbtaudio', 'dvb_on_demand', and 'dvb_diseqc_type' columns
     
    209206a unique number from 0 to 99.
    210207
    211208The 'channum' field contains the channel number to be input to jump
    212 to a channel. With HDTV using video4linux drivers this field has
    213 a special meaning. If the field contains only numeric characters
    214 then the digits up to the last digit are used as the major channel
    215 number and the last digit is used as the minor channel number.
    216 If it contains an underscore (_), the default, then the digits before
    217 the underscore are used as the major channel, and the ones after
    218 it as the minor channel. If it contains a minus sign (-), then
    219 the digits after the minus sign are used as the program number.
     209to a channel.
    220210
    221211The 'sourceid' field contains the \ref videosource_table key, which
    222212specifies which listings service to use and which input on which video
     
    28572847            return false;
    28582848    }
    28592849
     2850    if (dbver == "1177")
     2851    {
     2852        QString thequery =
     2853            "SELECT cardid "
     2854            "FROM capturecard "
     2855            "WHERE cardtype='HDTV'";
     2856
     2857        MSqlQuery query(MSqlQuery::InitCon());
     2858        query.prepare(thequery);
     2859        if (!query.exec())
     2860        {
     2861            QString msg =
     2862                QString("DB Error (Performing database upgrade): \n"
     2863                        "Query was: %1 \nError was: %2 \nnew version: %3")
     2864                .arg(thequery)
     2865                .arg(MythContext::DBErrorMessage(query.lastError()))
     2866                .arg("1178");
     2867            VERBOSE(VB_IMPORTANT, msg);
     2868            return false;
     2869        }
     2870
     2871        QString in = "(";
     2872
     2873        while (query.next())
     2874            in += query.value(0).toString() + ",";
     2875
     2876        thequery = "";
     2877        if (in.length() > 2)
     2878        {
     2879            in.truncate(in.length() - 1);
     2880            thequery =
     2881                "DELETE FROM cardinput "
     2882                "WHERE cardid IN " + in + ")";
     2883        }
     2884
     2885        const QString updates[] = {
     2886"DELETE FROM capturecard WHERE cardtype = 'HDTV';",
     2887thequery,
     2888""
     2889};
     2890        if (!performActualUpdate(updates, "1178", dbver))
     2891            return false;
     2892    }
     2893
    28602894//"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22
    28612895//"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22
    28622896//"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22
  • libs/libmythtv/scanwizardscanner.cpp

     
    4747
    4848#ifdef USING_V4L
    4949#include "channel.h"
    50 #include "pchdtvsignalmonitor.h"
    5150#include "analogsignalmonitor.h"
    5251#endif
    5352
     
    423422    type = (CardUtil::OFDM == cardtype) ? DTVConfParser::OFDM : type;
    424423    type = (CardUtil::QPSK == cardtype) ? DTVConfParser::QPSK : type;
    425424    type = (CardUtil::QAM  == cardtype) ? DTVConfParser::QAM  : type;
    426     type = ((CardUtil::ATSC == cardtype) || (CardUtil::HDTV == cardtype) ||
    427             (CardUtil::HDHOMERUN == cardtype)) ? DTVConfParser::ATSC : type;
     425    type = ((CardUtil::ATSC == cardtype) ||(CardUtil::HDHOMERUN == cardtype)) ?
     426        DTVConfParser::ATSC : type;
    428427
    429428    if (type == DTVConfParser::UNKNOWN)
    430429        return;
     
    493492#endif
    494493
    495494#ifdef USING_V4L
    496     if (("HDTV" == card_type) || ("V4L" == card_type) || ("MPEG" == card_type))
     495    if (("V4L" == card_type) || ("MPEG" == card_type))
    497496        channel = new Channel(NULL, device);
    498497#endif
    499498
  • libs/libmythtv/dtvrecorder.h

     
    11// -*- Mode: c++ -*-
    22/**
    3  *  DTVRecorder -- base class for DVBRecorder and HDTVRecorder
     3 *  DTVRecorder -- base class for Digital Television recorders
    44 *  Copyright (c) 2003-2004 by Brandon Beattie, Doug Larrick,
    55 *    Jason Hoos, and Daniel Thor Kristjansson
    66 *  Distributed as part of MythTV under GPL v2 and later.
  • libs/libmythtv/dtvrecorder.cpp

     
    11/**
    2  *  DTVRecorder -- base class for DVBRecorder and HDTVRecorder
     2 *  DTVRecorder -- base class for Digital Televison recorders
    33 *  Copyright 2003-2004 by Brandon Beattie, Doug Larrick,
    44 *    Jason Hoos, and Daniel Thor Kristjansson
    55 *  Distributed as part of MythTV under GPL v2 and later.
    66 */
    77
    8 using namespace std;
    9 
    108#include "RingBuffer.h"
    119#include "programinfo.h"
    1210#include "mpegtables.h"
     
    2018
    2119/** \class DTVRecorder
    2220 *  \brief This is a specialization of RecorderBase used to
    23  *         handle DVB and ATSC streams.
     21 *         handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams.
    2422 *
    25  *  This class is an abstract class. If you are using a
    26  *  pcHDTV card with the bttv drivers, ATSC streams are
    27  *  handled by the HDTVRecorder. If you are using DVB
    28  *  drivers DVBRecorder is used. If you are using firewire
    29  *  cable box input the FirewireRecorder is used.
    30  *
    31  *  \sa DVBRecorder, HDTVRecorder, FirewireRecorder, DBox2Recorder
     23 *  \sa DBox2Recorder, DVBRecorder, FirewireRecorder,
     24        HDHRRecoreder, IPTVRecorder
    3225 */
    3326
    3427DTVRecorder::DTVRecorder(TVRec *rec) :
  • libs/libmythtv/pchdtvsignalmonitor.cpp

     
    1 // -*- Mode: c++ -*-
    2 // Copyright (c) 2005, Daniel Thor Kristjansson
    3 
    4 #include <cerrno>
    5 #include <unistd.h>
    6 #include <sys/ioctl.h>
    7 
    8 #include "videodev_myth.h"
    9 #include "mythcontext.h"
    10 #include "pchdtvsignalmonitor.h"
    11 #include "channel.h"
    12 #include "atscstreamdata.h"
    13 #include "mpegtables.h"
    14 #include "atsctables.h"
    15 
    16 #undef DBG_SM
    17 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
    18     "pcHDTVSM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
    19 
    20 /** \fn pcHDTVSignalMonitor::pcHDTVSignalMonitor(int,Channel*,uint,const char*)
    21  *  \brief Initializes signal lock and signal values.
    22  *
    23  *   Start() must be called to actually begin continuous signal
    24  *   monitoring. The timeout is initialized to the value of
    25  *   the "ATSCCheckSignalWait" setting in milliseconds, and
    26  *   the threshold is initialized to the value of the
    27  *   "ATSCCheckSignalThreshold" setting as a percentage.
    28  *
    29  *  \param _db_cardnum     Recorder number to monitor,
    30  *                         if this is less than 0, SIGNAL events will not be
    31  *                         sent to the frontend even if SetNotifyFrontend(true)
    32  *                         is called.
    33  *  \param _channel        Channel class of device you want monitored
    34  *  \param _flags          SignalMonitorFlags to start with
    35  *  \param _name           Instance name for Qt signal/slot debugging
    36  */
    37 pcHDTVSignalMonitor::pcHDTVSignalMonitor(int db_cardnum, Channel *_channel,
    38                                          uint _flags, const char *_name)
    39     : DTVSignalMonitor(db_cardnum, _channel, _flags, _name),
    40       usingv4l2(false), dtvMonitorRunning(false)
    41 {
    42     int wait      = gContext->GetNumSetting("ATSCCheckSignalWait", 5000);
    43     int threshold = gContext->GetNumSetting("ATSCCheckSignalThreshold", 65);
    44 
    45     signalLock.SetTimeout(wait);
    46     signalStrength.SetTimeout(wait);
    47     signalStrength.SetThreshold(threshold);
    48 
    49     usingv4l2 = CardUtil::hasV4L2(channel->GetFd());
    50 }
    51 
    52 pcHDTVSignalMonitor::~pcHDTVSignalMonitor()
    53 {
    54     Stop();
    55 }
    56 
    57 void pcHDTVSignalMonitor::deleteLater(void)
    58 {
    59     disconnect(); // disconnect signals we may be sending...
    60     Stop();
    61     DTVSignalMonitor::deleteLater();
    62 }
    63 
    64 /** \fn pcHDTVSignalMonitor::Stop()
    65  *  \brief Stops signal monitoring and table monitoring threads.
    66  */
    67 void pcHDTVSignalMonitor::Stop()
    68 {
    69     DBG_SM("Stop()", "begin");
    70     SignalMonitor::Stop();
    71     if (dtvMonitorRunning)
    72     {
    73         dtvMonitorRunning = false;
    74         pthread_join(table_monitor_thread, NULL);
    75     }
    76     DBG_SM("Stop()", "end");
    77 }
    78 
    79 void *pcHDTVSignalMonitor::TableMonitorThread(void *param)
    80 {
    81     pcHDTVSignalMonitor *mon = (pcHDTVSignalMonitor*) param;
    82     mon->RunTableMonitor();
    83     return NULL;
    84 }
    85 
    86 void pcHDTVSignalMonitor::RunTableMonitor()
    87 {
    88     dtvMonitorRunning = true;
    89     int remainder = 0;
    90     int buffer_size = TSPacket::SIZE * 15000;
    91     unsigned char *buffer = new unsigned char[buffer_size];
    92     if (!buffer)
    93         return;
    94     bzero(buffer, buffer_size);
    95 
    96     DBG_SM("RunTableMonitor()", "begin (# of pids "
    97             <<GetStreamData()->ListeningPIDs().size()<<")");
    98     while (dtvMonitorRunning && GetStreamData())
    99     {
    100         long long len = read(
    101             channel->GetFd(), &(buffer[remainder]), buffer_size - remainder);
    102 
    103         if ((0 == len) || (-1 == len))
    104         {
    105             usleep(100);
    106             continue;
    107         }
    108 
    109         len += remainder;
    110         remainder = GetStreamData()->ProcessData(buffer, len);
    111         if (remainder > 0 && (len > remainder)) // leftover bytes
    112             memmove(buffer, &(buffer[len - remainder]), remainder);
    113     }
    114     DBG_SM("RunTableMonitor()", "end");
    115 }
    116 
    117 #define EMIT(SIGNAL_FUNC, SIGNAL_VAL) \
    118     do { statusLock.lock(); \
    119          SignalMonitorValue val = SIGNAL_VAL; \
    120          statusLock.unlock(); \
    121          emit SIGNAL_FUNC(val); } while (false)
    122 
    123 /** \fn pcHDTVSignalMonitor::UpdateValues()
    124  *  \brief Queries signal strength and emits status Qt signals.
    125  *
    126  *   This uses GetSignal(int,uint,bool) to actually collect the signal values.
    127  *   It is automatically called by MonitorLoop(), after Start() has been uset
    128  *   to start the signal monitoring thread.
    129  */
    130 void pcHDTVSignalMonitor::UpdateValues()
    131 {
    132     if (!running || exit)
    133         return;
    134 
    135     if (dtvMonitorRunning)
    136     {
    137         EMIT(StatusSignalLock, signalLock);
    138         EMIT(StatusSignalStrength, signalStrength);
    139         if (IsAllGood())
    140             emit AllGood();
    141         // TODO dtv signals...
    142         update_done = true;
    143         return;
    144     }
    145 
    146     bool isLocked = false;
    147     int sig = GetSignal(
    148         channel->GetFd(), channel->GetCurrentInputNum(), usingv4l2);
    149 
    150     {
    151         QMutexLocker locker(&statusLock);
    152         signalStrength.SetValue(sig);
    153         signalLock.SetValue(signalStrength.IsGood());
    154         isLocked = signalLock.IsGood();
    155     }
    156 
    157     if (isLocked && GetStreamData() &&
    158         HasAnyFlag(kDTVSigMon_WaitForPAT | kDTVSigMon_WaitForPMT |
    159                    kDTVSigMon_WaitForMGT | kDTVSigMon_WaitForVCT |
    160                    kDTVSigMon_WaitForNIT | kDTVSigMon_WaitForSDT))
    161     {
    162         pthread_create(&table_monitor_thread, NULL,
    163                        TableMonitorThread, this);
    164         DBG_SM("UpdateValues", "Waiting for table monitor to start");
    165         while (!dtvMonitorRunning)
    166             usleep(50);
    167         DBG_SM("UpdateValues", "Table monitor started");
    168     }
    169 
    170     EMIT(StatusSignalLock, signalLock);
    171     EMIT(StatusSignalStrength, signalStrength);
    172     if (IsAllGood())
    173         emit AllGood();
    174 
    175     update_done = true;
    176 }
    177 
    178 #undef EMIT
    179 
    180 template<typename V>
    181 V clamp(V val, V minv, V maxv) { return std::min(maxv, std::max(minv, val)); }
    182 
    183 /** \fn pcHDTVSignalMonitor::GetSignal(int,uint,bool)
    184  *  \brief Returns ATSC signal strength as a percentage from 0 to 100%.
    185  *
    186  *  \param fd        File descriptor of V4L device.
    187  *  \param input     Input of device to monitor.
    188  *  \param usingv4l2 If true use V4L version 2 ioctls,
    189  *                   else use V4L version 1 ioctls.
    190  *  \return ATSC signal strength 0-100. >75 is good.
    191  */
    192 int pcHDTVSignalMonitor::GetSignal(int fd, uint input, bool usingv4l2)
    193 {
    194     // the 0 == input test works around a bug in the pcHDTV v4l2 support
    195     if (usingv4l2 && (0 == input))
    196     {
    197         struct v4l2_tuner vsig;
    198         memset(&vsig, 0, sizeof(vsig));
    199 
    200         //setting index doesn't currently work with pcHDTV drivers....
    201         //vsig.index = input;
    202 
    203         int ioctlval = ioctl(fd, VIDIOC_G_TUNER, &vsig);
    204         if (ioctlval != -1)
    205         {
    206             VERBOSE(VB_CHANNEL,
    207                     QString("pcHDTV::GetSignal_v4l2(fd %1, input %2, v4l%3): "
    208                             "raw signal(%4)")
    209                     .arg(fd).arg(input).arg(usingv4l2 ? 2 : 1).arg(vsig.signal));
    210 
    211             return clamp(vsig.signal, 0, 100);
    212         }
    213         else
    214         {
    215             VERBOSE(VB_IMPORTANT,
    216                     QString("pcHDTV::GetSignal_v4l2(fd %1, input %2, v4l%3): "
    217                             "error(%4)")
    218                     .arg(fd).arg(input).arg(usingv4l2 ? 2 : 1).arg(strerror(errno)));
    219             // falling through to v4l v1
    220         }
    221     }
    222 
    223     struct video_signal vsig;
    224     memset(&vsig, 0, sizeof(vsig));
    225 
    226     int ioctlval = ioctl(fd, VIDIOCGSIGNAL, &vsig);
    227     if (ioctlval == -1)
    228     {
    229         VERBOSE(VB_IMPORTANT,
    230                 QString("pcHDTV::GetSignal_v4l1(fd %1, input %2, v4l%3): "
    231                         "error(%4)")
    232                 .arg(fd).arg(input).arg(usingv4l2 ? 2 : 1).arg(strerror(errno)));
    233         return 0;
    234     }
    235 
    236     int signal = (input == 0) ? vsig.strength : vsig.aux;
    237     int retsig = 0;
    238 
    239     if ((signal & 0xff) == 0x43)
    240         retsig = clamp(101 - (signal >> 9), 0, 100);
    241 
    242     VERBOSE(VB_CHANNEL,
    243             QString("pcHDTV::GetSignal_v4l1(fd %1, input %2, v4l%3): "
    244                     "processed signal(%4)")
    245             .arg(fd).arg(input).arg(usingv4l2 ? 2 : 1).arg(retsig));
    246 
    247     return retsig;
    248 }
  • libs/libmythtv/datadirect.cpp

     
    18371837    minor = channum.right(channum.length() - (chansep + 1)).toInt();
    18381838
    18391839    freq = get_center_frequency("atsc", "vsb8", "us", freqid);
    1840 
    1841     // Check if this is connected to an HDTV card.
    1842     MSqlQuery query(MSqlQuery::DDCon());
    1843     query.prepare(
    1844         "SELECT cardtype "
    1845         "FROM capturecard, cardinput "
    1846         "WHERE cardinput.cardid = capturecard.cardid AND "
    1847         "      sourceid         = :SOURCEID");
    1848     query.bindValue(":SOURCEID", sourceid);
    1849 
    1850     if (query.exec() && query.isActive() && query.next() &&
    1851         query.value(0).toString() == "HDTV")
    1852     {
    1853         freq -= 1750000; // convert to visual carrier freq.
    1854     }
    18551840}
    18561841
    18571842static QString process_dd_station(
  • libs/libmythtv/channelutil.cpp

     
    895895        QString("SELECT chanid FROM channel "
    896896                "WHERE sourceid=%1 AND serviceID=%1 AND mplexid=%2")
    897897        .arg(source_id).arg(program_number).arg(mplexid),
    898         // find based on OLD pcHDTV formatted major and minor channels
    899         QString("SELECT chanid FROM channel "
    900                 "WHERE sourceid=%1 AND channum='%2_%3'")
    901         .arg(source_id).arg(major_channel).arg(minor_channel),
    902         // find based on OLD pcHDTV formatted major channel and program number
    903         QString("SELECT chanid FROM channel "
    904                 "WHERE sourceid=%1 AND channum='%2-%3'")
    905         .arg(source_id).arg(major_channel).arg(program_number),
    906         // find based on OLD DVB formatted major and minor channels
    907         QString("SELECT chanid FROM channel "
    908                 "WHERE sourceid=%1 AND channum='%2%3'")
    909         .arg(source_id).arg(major_channel).arg(minor_channel),
    910898    };
    911899
    912900    for (uint i = 0; i < 6; i++)
  • libs/libmythtv/signalmonitor.cpp

     
    1919#endif
    2020
    2121#ifdef USING_V4L
    22 #   include "pchdtvsignalmonitor.h"
    2322#   include "analogsignalmonitor.h"
    2423#   include "channel.h"
    2524#endif
     
    5655 *   Additional signals may be implemented, see DTVSignalMonitor and
    5756 *   DVBSignalMonitor for example.
    5857 *
    59  *  \sa DTVSignalMonitor DVBSignalMonitor, HDTVSignalMonitor, SignalMonitorValue
     58 *  \sa AnalocSignalMonitor, DTVSignalMonitor, DVBSignalMonitor,
     59        HDHRSignalMonitor, SignalMonitorValue
    6060 */
    6161
    6262void ALRMhandler(int /*sig*/)
     
    8989#endif
    9090
    9191#ifdef USING_V4L
    92     if (cardtype.upper() == "HDTV")
    93     {
    94         Channel *hdtvc = dynamic_cast<Channel*>(channel);
    95         if (hdtvc)
    96             signalMonitor = new pcHDTVSignalMonitor(db_cardnum, hdtvc);
    97     }
    9892    if ((cardtype.upper() == "V4L") ||
    9993        (cardtype.upper() == "MPEG"))
    10094    {
  • libs/libmythtv/videosource.cpp

     
    12981298    input->fillSelections(device);
    12991299}
    13001300
    1301 pcHDTVConfigurationGroup::pcHDTVConfigurationGroup(CaptureCard& a_parent) :
    1302     VerticalConfigurationGroup(false, true, false, false),
    1303     parent(a_parent), cardinfo(new TransLabelSetting()),
    1304     input(new TunerCardInput(parent))
    1305 {
    1306     VideoDevice    *atsc_device     = new VideoDevice(parent, 0, 64);
    1307     SignalTimeout  *signal_timeout  = new SignalTimeout(parent, 500, 250);
    1308     ChannelTimeout *channel_timeout = new ChannelTimeout(parent, 2000, 1750);
    1309 
    1310     addChild(atsc_device);
    1311     addChild(cardinfo);
    1312     addChild(signal_timeout);
    1313     addChild(channel_timeout);
    1314     addChild(input);
    1315 
    1316     connect(atsc_device, SIGNAL(valueChanged(const QString&)),
    1317             this,        SLOT(  probeCard(   const QString&)));
    1318 
    1319     probeCard(atsc_device->getValue());
    1320 }
    1321 
    1322 void pcHDTVConfigurationGroup::probeCard(const QString &device)
    1323 {
    1324     QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
    1325 
    1326     int videofd = open(device.ascii(), O_RDWR);
    1327     if (videofd >= 0)
    1328     {
    1329         if (!CardUtil::GetV4LInfo(videofd, cn, dn))
    1330             ci = cn = tr("Failed to probe");
    1331         else if (!dn.isEmpty())
    1332             ci = cn + "  [" + dn + "]";
    1333         close(videofd);
    1334     }
    1335 
    1336     cardinfo->setValue(ci);
    1337     input->fillSelections(device);
    1338 }
    1339 
    13401301CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) :
    13411302    TriggeredConfigurationGroup(true, true, false, false)
    13421303{
     
    13501311   
    13511312#ifdef USING_V4L
    13521313    addTarget("V4L",       new V4LConfigurationGroup(parent));
    1353     addTarget("HDTV",      new pcHDTVConfigurationGroup(parent));
    13541314# ifdef USING_IVTV
    13551315    addTarget("MPEG",      new MPEGConfigurationGroup(parent));
    13561316# endif // USING_IVTV
     
    14691429        QObject::tr("DVB DTV capture card (v3.x)"), "DVB");
    14701430#endif // USING_DVB
    14711431
    1472 #ifdef USING_V4L
    1473     setting->addSelection(
    1474         QObject::tr("pcHDTV DTV capture card (w/V4L drivers)"), "HDTV");
    1475 #endif // USING_V4L
    1476 
    14771432#ifdef USING_FIREWIRE
    14781433    setting->addSelection(
    14791434        QObject::tr("FireWire cable box"), "FIREWIRE");
  • libs/libmythtv/tv_rec.cpp

     
    5353#include "recorderbase.h"
    5454#include "NuppelVideoRecorder.h"
    5555#include "mpegrecorder.h"
    56 #include "hdtvrecorder.h"
    5756#include "dvbrecorder.h"
    5857#include "dbox2recorder.h"
    5958#include "hdhrrecorder.h"
     
    196195        init_run = true;
    197196#endif
    198197    }   
    199     else // "V4L" or "MPEG", ie, analog TV, or "HDTV"
     198    else // "V4L" or "MPEG", ie, analog TV
    200199    {
    201200#ifdef USING_V4L
    202201        channel = new Channel(this, genOpt.videodev);
     
    206205        CloseChannel();
    207206        init_run = true;
    208207#endif
    209         if (genOpt.cardtype != "HDTV" && genOpt.cardtype != "MPEG")
     208        if (genOpt.cardtype != "MPEG")
    210209            rbFileExt = "nuv";
    211210    }
    212211
     
    794793 *
    795794 *  Based on the card type, one of the possible recorders are started.
    796795 *  If the card type is "MPEG" a MpegRecorder is started,
    797  *  if the card type is "HDTV" a HDTVRecorder is started,
     796 *  if the card type is "HDHOMERUN" a HDHRRecorder is started,
    798797 *  if the card type is "FIREWIRE" a FirewireRecorder is started,
    799798 *  if the card type is "DVB" a DVBRecorder is started,
    800799 *  otherwise a NuppelVideoRecorder is started.
     
    811810        recorder = new MpegRecorder(this);
    812811#endif // USING_IVTV
    813812    }
    814     else if (genOpt.cardtype == "HDTV")
    815     {
    816 #ifdef USING_V4L
    817         recorder = new HDTVRecorder(this);
    818         ringBuffer->SetWriteBufferSize(4*1024*1024);
    819         recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
    820 #endif // USING_V4L
    821     }
    822813    else if (genOpt.cardtype == "FIREWIRE")
    823814    {
    824815#ifdef USING_FIREWIRE
     
    17961787 *  \brief This creates a SignalMonitor instance if one is needed and
    17971788 *         begins signal monitoring.
    17981789 *
    1799  *   If the channel exists and the cardtype is "DVB", "HDTV" or "HDHomeRun"
     1790 *   If the channel exists and the cardtype is "DVB" or "HDHomeRun"
    18001791 *   a SignalMonitor instance is created and SignalMonitor::Start()
    18011792 *   is called to start the signal monitoring thread.
    18021793 *
  • libs/libmythtv/transporteditor.cpp

     
    226226    {
    227227        CardUtil::CARD_TYPES typeA = cardtypes[i - 1];
    228228        typeA = (CardUtil::HDHOMERUN == typeA) ? CardUtil::ATSC : typeA;
    229         typeA = (CardUtil::HDTV      == typeA) ? CardUtil::ATSC : typeA;
    230229        typeA = (CardUtil::MPEG      == typeA) ? CardUtil::V4L  : typeA;
    231230
    232231        CardUtil::CARD_TYPES typeB = cardtypes[i + 0];
    233232        typeB = (CardUtil::HDHOMERUN == typeB) ? CardUtil::ATSC : typeB;
    234         typeB = (CardUtil::HDTV      == typeB) ? CardUtil::ATSC : typeB;
    235233        typeB = (CardUtil::MPEG      == typeB) ? CardUtil::V4L  : typeB;
    236234
    237235        if (typeA == typeB)
     
    526524        addSelection("QAM-64",   "qam_64");
    527525        addSelection("QAM-256",  "qam_256");
    528526    }
    529     else if (CardUtil::HDTV == nType)
    530     {
    531         addSelection("8-VSB",    "8vsb");
    532         setVisible(false);
    533     }
    534527    else
    535528    {
    536529        addSelection(QObject::tr("Analog"), "analog");
     
    731724        right->addChild(new DVBForwardErrorCorrection(id));
    732725    }
    733726    else if (CardUtil::ATSC      == nType ||
    734              CardUtil::HDTV      == nType ||
    735727             CardUtil::HDHOMERUN == nType)
    736728    {
    737729        left->addChild(new DTVStandard(id, false, true));
  • libs/libmythtv/tv_rec.h

     
    2525class RecorderBase;
    2626class DTVRecorder;
    2727class DVBRecorder;
    28 class HDTVRecorder;
    2928class HDHRRecorder;
    3029
    3130class SignalMonitor;
  • libs/libmythtv/scanwizardhelpers.cpp

     
    5454#ifdef USING_V4L
    5555    if (!cardTypes.isEmpty())
    5656        cardTypes += ",";
    57     cardTypes += "'V4L','HDTV'";
     57    cardTypes += "'V4L'";
    5858# ifdef USING_IVTV
    5959    cardTypes += ",'MPEG'";
    6060# endif // USING_IVTV
     
    412412                     QString::number(DVBUtilsImport));
    413413        break;
    414414    case CardUtil::ATSC:
    415     case CardUtil::HDTV:
    416415    case CardUtil::HDHOMERUN:
    417416        addSelection(tr("Full Scan"),
    418417                     QString::number(FullScan_ATSC), true);
  • libs/libmythtv/channel.cpp

     
    343343
    344344int Channel::GetCurrentChannelNum(const QString &channame)
    345345{
    346     // remove part after '-' for (HDTV subchannels)
    347     QString real_channame = channame;
    348     int pos = channame.find('-');
    349     if (pos != -1)
    350         real_channame.truncate(pos);
    351 
    352346    for (int i = 0; i < totalChannels; i++)
    353347    {
    354         if (real_channame == curList[i].name)
     348        if (channame == curList[i].name)
    355349            return i;
    356350    }
    357     VERBOSE(VB_IMPORTANT,
    358             QString("Channel::GetCurrentChannelNum(%1): "
    359                     "Failed to find Channel '%2'")
    360             .arg(channame).arg(real_channame));
    361351
     352    VERBOSE(VB_IMPORTANT, LOC_ERR +
     353            QString("GetCurrentChannelNum(%1): "
     354                    "Failed to find Channel").arg(channame));
     355
    362356    return -1;
    363357}
    364358
     
    815809            VERBOSE(VB_IMPORTANT, LOC_ERR + msg +
    816810                    "\n\t\t\twhile setting format (v4l v2)" + ENO);
    817811
    818             // Fall through to try v4l version 1, pcHDTV 1.4 (for HD-2000)
    819             // drivers don't work with VIDIOC_S_STD ioctl.
    820             usingv4l1 = true;
    821812            ok = false;
    822813        }
    823814