Ticket #2975: 2975-v2.patch

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

Updated patch

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

     
    4949        ATSC,
    5050        V4L,
    5151        MPEG,
    52         HDTV,
    5352        FIREWIRE,
    5453        HDHOMERUN,
    5554        FREEBOX,
     
    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)
     
    8986    static bool         IsEncoder(const QString &rawtype)
    9087    {
    9188        return
    92             (rawtype != "DVB")       && (rawtype != "HDTV")    &&
     89            (rawtype != "DVB")       &&
    9390            (rawtype != "FIREWIRE")  && (rawtype != "DBOX2")   &&
    9491            (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX");
    9592    }
     
    103100    static bool         IsEITCapable(const QString &rawtype)
    104101    {
    105102        return
    106             (rawtype == "DVB")       || (rawtype == "HDTV")  ||
    107             (rawtype == "HDHOMERUN");
     103            (rawtype == "DVB")       || (rawtype == "HDHOMERUN");
    108104    }
    109105
    110106    static bool         IsTuningDigital(const QString &rawtype)
    111107    {
    112108        return
    113             (rawtype == "DVB")       || (rawtype == "HDTV")  ||
    114             (rawtype == "HDHOMERUN");
     109            (rawtype == "DVB")       || (rawtype == "HDHOMERUN");
    115110    }
    116111
    117112    static bool         IsTuningAnalog(const QString &rawtype)
  • libs/libmythtv/videosource.h

     
    385385    TunerCardInput    *input;
    386386};
    387387
    388 class pcHDTVConfigurationGroup: public VerticalConfigurationGroup
    389 {
    390     Q_OBJECT
    391 
    392   public:
    393     pcHDTVConfigurationGroup(CaptureCard& a_parent);
    394 
    395   public slots:
    396     void probeCard(const QString &device);
    397 
    398   private:
    399     CaptureCard       &parent;
    400     TransLabelSetting *cardinfo;
    401     TunerCardInput    *input;
    402 };
    403 
    404388class DVBInput;
    405389class DVBCardName;
    406390class DVBCardType;
  • libs/libmythtv/libmythtv.pro

     
    388388    # Support for Video4Linux devices
    389389    using_v4l {
    390390        HEADERS += channel.h                   analogsignalmonitor.h
    391         HEADERS += hdtvrecorder.h              pchdtvsignalmonitor.h
    392391        SOURCES += channel.cpp                 analogsignalmonitor.h
    393         SOURCES += hdtvrecorder.cpp            pchdtvsignalmonitor.cpp
    394392
    395393        DEFINES += USING_V4L
    396394    }
  • 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

     
    1111#include "datadirect.h" // for DataDirectProcessor::FixProgramIDs
    1212
    1313/// This is the DB schema version expected by the running MythTV instance.
    14 const QString currentDatabaseVersion = "1197";
     14const QString currentDatabaseVersion = "1198";
    1515
    1616static bool UpdateDBVersionNumber(const QString &newnumber);
    1717static bool performActualUpdate(const QString updates[], QString version,
     
    100100
    101101The 'cardtype' is an important field for all cards as it guides the
    102102interpretation of the rest of the fields, it has several possible
    103 values: "V4L", "MJPEG", "HDTV", "DVB", "MPEG", "FIREWIRE", "GO7007"
     103values: "V4L", "MJPEG", "DVB", "MPEG", "FIREWIRE", "GO7007"
    104104and  "DBOX2".
    105105"V4L" indicates a V4L compatible device, this could be a
    106106true V4L device or something like a Firewire camera with the
    107107"firewire->v4l" driver.
    108108"MJPEG" describes a Matrox G200 or DC10 card which captures
    109109individual frames a JPEG images.
    110 "HDTV" describes a pcHDTV HD-2000 or HD-3000 when using the V4L
    111 drivers.
    112110"DVB" can describe any card supported by the Linux DVB
    113111drivers, including the pcHDTV and other ATSC cards.
    114112The "MPEG" type describes a device using the ivtv drivers such as
     
    138136
    139137The 'signal_timeout' and 'channel_timeout' indicate in
    140138milliseconds how long it should take to get a signal and
    141 channel lock respectively. Signal lock detection is
    142 currently only supported on "DVB" and "HDTV" card types.
     139channel lock respectively.
    143140
    144141The 'dvb_swfilter', 'dvb_sat_type', 'dvb_wait_for_seqstart',
    145142'skipbtaudio', 'dvb_on_demand', and 'dvb_diseqc_type' columns
     
    212209a unique number from 0 to 99.
    213210
    214211The 'channum' field contains the channel number to be input to jump
    215 to a channel. With HDTV using video4linux drivers this field has
    216 a special meaning. If the field contains only numeric characters
    217 then the digits up to the last digit are used as the major channel
    218 number and the last digit is used as the minor channel number.
    219 If it contains an underscore (_), the default, then the digits before
    220 the underscore are used as the major channel, and the ones after
    221 it as the minor channel. If it contains a minus sign (-), then
    222 the digits after the minus sign are used as the program number.
     212to a channel.
    223213
    224214The 'sourceid' field contains the \ref videosource_table key, which
    225215specifies which listings service to use and which input on which video
     
    32023192            return false;
    32033193    }
    32043194
     3195    if (dbver == "1197")
     3196    {
     3197        QString thequery =
     3198            "SELECT cardid "
     3199            "FROM capturecard "
     3200            "WHERE cardtype='HDTV'";
     3201
     3202        MSqlQuery query(MSqlQuery::InitCon());
     3203        query.prepare(thequery);
     3204        if (!query.exec())
     3205        {
     3206            QString msg =
     3207                QString("DB Error (Performing database upgrade): \n"
     3208                        "Query was: %1 \nError was: %2 \nnew version: %3")
     3209                .arg(thequery)
     3210                .arg(MythContext::DBErrorMessage(query.lastError()))
     3211                .arg("1198");
     3212            VERBOSE(VB_IMPORTANT, msg);
     3213            return false;
     3214        }
     3215
     3216        QString in = "(";
     3217
     3218        while (query.next())
     3219            in += query.value(0).toString() + ",";
     3220
     3221        thequery = "";
     3222        if (in.length() > 2)
     3223        {
     3224            in.truncate(in.length() - 1);
     3225            thequery =
     3226                "DELETE FROM cardinput "
     3227                "WHERE cardid IN " + in + ")";
     3228        }
     3229
     3230        const QString updates[] = {
     3231"DELETE FROM capturecard WHERE cardtype = 'HDTV';",
     3232thequery,
     3233""
     3234};
     3235        if (!performActualUpdate(updates, "1198", dbver))
     3236            return false;
     3237    }
     3238
    32053239//"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22
    32063240//"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22
    32073241//"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"
     
    2523
    2624/** \class DTVRecorder
    2725 *  \brief This is a specialization of RecorderBase used to
    28  *         handle DVB and ATSC streams.
     26 *         handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams.
    2927 *
    30  *  This class is an abstract class. If you are using a
    31  *  pcHDTV card with the bttv drivers, ATSC streams are
    32  *  handled by the HDTVRecorder. If you are using DVB
    33  *  drivers DVBRecorder is used. If you are using firewire
    34  *  cable box input the FirewireRecorder is used.
    35  *
    36  *  \sa DVBRecorder, HDTVRecorder, FirewireRecorder, DBox2Recorder
     28 *  \sa DBox2Recorder, DVBRecorder, FirewireRecorder,
     29        HDHRRecoreder, IPTVRecorder
    3730 */
    3831
    3932DTVRecorder::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

     
    21162116    minor = channum.right(channum.length() - (chansep + 1)).toInt();
    21172117
    21182118    freq = get_center_frequency("atsc", "vsb8", "us", freqid);
    2119 
    2120     // Check if this is connected to an HDTV card.
    2121     MSqlQuery query(MSqlQuery::DDCon());
    2122     query.prepare(
    2123         "SELECT cardtype "
    2124         "FROM capturecard, cardinput "
    2125         "WHERE cardinput.cardid = capturecard.cardid AND "
    2126         "      sourceid         = :SOURCEID");
    2127     query.bindValue(":SOURCEID", sourceid);
    2128 
    2129     if (query.exec() && query.isActive() && query.next() &&
    2130         query.value(0).toString() == "HDTV")
    2131     {
    2132         freq -= 1750000; // convert to visual carrier freq.
    2133     }
    21342119}
    21352120
    21362121static 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

     
    2121#endif
    2222
    2323#ifdef USING_V4L
    24 #   include "pchdtvsignalmonitor.h"
    2524#   include "analogsignalmonitor.h"
    2625#   include "channel.h"
    2726#endif
     
    5857 *   Additional signals may be implemented, see DTVSignalMonitor and
    5958 *   DVBSignalMonitor for example.
    6059 *
    61  *  \sa DTVSignalMonitor DVBSignalMonitor, HDTVSignalMonitor, SignalMonitorValue
     60 *  \sa AnalocSignalMonitor, DTVSignalMonitor, DVBSignalMonitor,
     61        HDHRSignalMonitor, SignalMonitorValue
    6262 */
    6363
    6464void ALRMhandler(int /*sig*/)
     
    9191#endif
    9292
    9393#ifdef USING_V4L
    94     if (cardtype.upper() == "HDTV")
    95     {
    96         Channel *hdtvc = dynamic_cast<Channel*>(channel);
    97         if (hdtvc)
    98             signalMonitor = new pcHDTVSignalMonitor(db_cardnum, hdtvc);
    99     }
    10094    if ((cardtype.upper() == "V4L") ||
    10195        (cardtype.upper() == "MPEG"))
    10296    {
  • libs/libmythtv/videosource.cpp

     
    13281328    input->fillSelections(device);
    13291329}
    13301330
    1331 pcHDTVConfigurationGroup::pcHDTVConfigurationGroup(CaptureCard& a_parent) :
    1332     VerticalConfigurationGroup(false, true, false, false),
    1333     parent(a_parent), cardinfo(new TransLabelSetting()),
    1334     input(new TunerCardInput(parent))
    1335 {
    1336     VideoDevice    *atsc_device     = new VideoDevice(parent, 0, 64);
    1337     SignalTimeout  *signal_timeout  = new SignalTimeout(parent, 500, 250);
    1338     ChannelTimeout *channel_timeout = new ChannelTimeout(parent, 2000, 1750);
    1339 
    1340     addChild(atsc_device);
    1341     addChild(cardinfo);
    1342     addChild(signal_timeout);
    1343     addChild(channel_timeout);
    1344     addChild(input);
    1345 
    1346     connect(atsc_device, SIGNAL(valueChanged(const QString&)),
    1347             this,        SLOT(  probeCard(   const QString&)));
    1348 
    1349     probeCard(atsc_device->getValue());
    1350 }
    1351 
    1352 void pcHDTVConfigurationGroup::probeCard(const QString &device)
    1353 {
    1354     QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
    1355 
    1356     int videofd = open(device.ascii(), O_RDWR);
    1357     if (videofd >= 0)
    1358     {
    1359         if (!CardUtil::GetV4LInfo(videofd, cn, dn))
    1360             ci = cn = tr("Failed to probe");
    1361         else if (!dn.isEmpty())
    1362             ci = cn + "  [" + dn + "]";
    1363         close(videofd);
    1364     }
    1365 
    1366     cardinfo->setValue(ci);
    1367     input->fillSelections(device);
    1368 }
    1369 
    13701331CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) :
    13711332    TriggeredConfigurationGroup(true, true, false, false)
    13721333{
     
    13801341   
    13811342#ifdef USING_V4L
    13821343    addTarget("V4L",       new V4LConfigurationGroup(parent));
    1383     addTarget("HDTV",      new pcHDTVConfigurationGroup(parent));
    13841344# ifdef USING_IVTV
    13851345    addTarget("MPEG",      new MPEGConfigurationGroup(parent));
    13861346# endif // USING_IVTV
     
    14991459        QObject::tr("DVB DTV capture card (v3.x)"), "DVB");
    15001460#endif // USING_DVB
    15011461
    1502 #ifdef USING_V4L
    1503     setting->addSelection(
    1504         QObject::tr("pcHDTV DTV capture card (w/V4L drivers)"), "HDTV");
    1505 #endif // USING_V4L
    1506 
    15071462#ifdef USING_FIREWIRE
    15081463    setting->addSelection(
    15091464        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"
     
    195194        init_run = true;
    196195#endif
    197196    }   
    198     else // "V4L" or "MPEG", ie, analog TV, or "HDTV"
     197    else // "V4L" or "MPEG", ie, analog TV
    199198    {
    200199#ifdef USING_V4L
    201200        channel = new Channel(this, genOpt.videodev);
     
    205204        CloseChannel();
    206205        init_run = true;
    207206#endif
    208         if (genOpt.cardtype != "HDTV" && genOpt.cardtype != "MPEG")
     207        if (genOpt.cardtype != "MPEG")
    209208            rbFileExt = "nuv";
    210209    }
    211210
     
    796795 *
    797796 *  Based on the card type, one of the possible recorders are started.
    798797 *  If the card type is "MPEG" a MpegRecorder is started,
    799  *  if the card type is "HDTV" a HDTVRecorder is started,
     798 *  if the card type is "HDHOMERUN" a HDHRRecorder is started,
    800799 *  if the card type is "FIREWIRE" a FirewireRecorder is started,
    801800 *  if the card type is "DVB" a DVBRecorder is started,
    802801 *  otherwise a NuppelVideoRecorder is started.
     
    813812        recorder = new MpegRecorder(this);
    814813#endif // USING_IVTV
    815814    }
    816     else if (genOpt.cardtype == "HDTV")
    817     {
    818 #ifdef USING_V4L
    819         recorder = new HDTVRecorder(this);
    820         ringBuffer->SetWriteBufferSize(4*1024*1024);
    821         recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);
    822 #endif // USING_V4L
    823     }
    824815    else if (genOpt.cardtype == "FIREWIRE")
    825816    {
    826817#ifdef USING_FIREWIRE
     
    18001791 *  \brief This creates a SignalMonitor instance if one is needed and
    18011792 *         begins signal monitoring.
    18021793 *
    1803  *   If the channel exists and the cardtype is "DVB", "HDTV" or "HDHomeRun"
     1794 *   If the channel exists and the cardtype is "DVB" or "HDHomeRun"
    18041795 *   a SignalMonitor instance is created and SignalMonitor::Start()
    18051796 *   is called to start the signal monitoring thread.
    18061797 *
  • 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)
     
    524522        addSelection("QAM-64",   "qam_64");
    525523        addSelection("QAM-256",  "qam_256");
    526524    }
    527     else if (CardUtil::HDTV == nType)
    528     {
    529         addSelection("8-VSB",    "8vsb");
    530         setVisible(false);
    531     }
    532525    else
    533526    {
    534527        addSelection(QObject::tr("Analog"), "analog");
     
    729722        right->addChild(new DVBForwardErrorCorrection(id));
    730723    }
    731724    else if (CardUtil::ATSC      == nType ||
    732              CardUtil::HDTV      == nType ||
    733725             CardUtil::HDHOMERUN == nType)
    734726    {
    735727        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