Ticket #2975: 2975-v2.patch
| File 2975-v2.patch, 59.9 KB (added by , 18 years ago) |
|---|
-
libs/libmythtv/pchdtvsignalmonitor.h
1 // -*- Mode: c++ -*-2 // Copyright (c) 2005, Daniel Thor Kristjansson3 4 #ifndef PCHDTVSIGNALMONITOR_H5 #define PCHDTVSIGNALMONITOR_H6 7 #include "dtvsignalmonitor.h"8 9 class Channel;10 11 class pcHDTVSignalMonitor: public DTVSignalMonitor12 {13 Q_OBJECT14 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 * HDTVRecorder4 * Copyright (c) 2003-2004 by Brandon Beattie, Doug Larrick,5 * Jason Hoos, and Daniel Thor Kristjansson6 * Device ringbuffer added by John Poet7 * 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 HDTVRecorder21 * \brief This is a specialization of DTVRecorder used to22 * handle streams from bttv drivers, such as the23 * vendor drivers for the the HD-2000 and HD-3000.24 *25 * \sa DTVRecorder, DVBRecorder26 */27 class HDTVRecorder : public DTVRecorder,28 public MPEGSingleProgramStreamListener,29 public ATSCMainStreamListener30 {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 // statistics81 TSStats _ts_stats;82 long long _resync_count;83 size_t loop;84 85 // Data for managing the device ringbuffer86 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 /* HDTVRecorder2 Version 0.13 July 4th, 20034 GPL License (c)5 By Brandon Beattie6 7 Portions of this code taken from mpegrecorder8 9 Modified Oct. 2003 by Doug Larrick10 * decodes MPEG-TS locally (does not use libavformat) for flexibility11 * output format is MPEG-TS omitting unneeded PIDs, for smaller files12 and no audio stutter on stations with >1 audio stream13 * Emits proper keyframe data to recordedmarkup db, enabling seeking14 15 Oct. 22, 2003:16 * delay until GOP before writing output stream at start and reset17 (i.e. channel change)18 * Rewrite PIDs after channel change to be the same as before, so19 decoder can follow20 21 Oct. 27, 2003 by Jason Hoos:22 * if no GOP is detected within the first 30 frames of the stream, then23 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. fixes27 a problem with stations (particularly, WGN in Chicago) that list their28 programs in reverse order in the PAT, which was confusing ffmpeg29 (ffmpeg was looking for program 5, but only program 2 was left in30 the stream, so it choked).31 32 Nov. 3, 2003 by Doug Larrick:33 * code to enable selecting a program number for stations with34 multiple programs35 * 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 this38 lets people seek past halfway in recordings39 40 Jan 30, 2004 by Daniel Kristjansson41 * broke out tspacket to handle TS packets42 * added CRC check on PAT & PMT packets43 Sept 27, 200444 * added decoding of most ATSC Tables45 * added multiple audio support46 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.com52 */53 54 // C includes55 #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 includes64 #include <sys/types.h>65 #include <sys/stat.h>66 #include <sys/ioctl.h>67 #include <sys/time.h>68 69 // C++ includes70 #include <iostream>71 using namespace std;72 73 // MythTV system include74 #include "videodev_myth.h"75 76 // MythTV includes77 #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 includes89 extern "C" {90 #include "../libavcodec/avcodec.h"91 #include "../libavformat/avformat.h"92 #include "../libavformat/mpegts.h"93 }94 95 #define REPORT_RING_STATS 196 97 #define DEFAULT_SUBCHANNEL 198 99 #define WHACK_A_BUG_VIDEO 0100 #define WHACK_A_BUG_AUDIO 0101 102 #if FAKE_VIDEO103 static int fake_video_index = 0;104 #define FAKE_VIDEO_NUM 4105 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 #endif113 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 memory124 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 up139 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_VIDEO183 // open file instead of device184 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 #else196 if (_stream_fd <= 0)197 _stream_fd = open(videodevice.ascii(), O_RDWR);198 #endif199 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 byte234 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 else244 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_STATS406 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 #endif415 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 pieces462 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 buffer468 ringbuf.readPtr = ringbuf.buffer;469 memcpy(cPtr, ringbuf.readPtr, len);470 ringbuf.readPtr += len;471 }472 else473 {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 else485 {486 #ifdef REPORT_RING_STATS487 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 else511 #endif512 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 up525 const int syncpackets = 10; // synced packets to require before starting recording526 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 ringbuffer539 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 packet571 if (!syncchan(_stream_fd, TSPacket::SIZE*unsyncpackets, syncpackets))572 {573 _error = true;574 return;575 }576 577 // create thread to fill the ringbuffer578 pthread_create(&ringbuf.thread, NULL, boot_ringbuffer,579 reinterpret_cast<void *>(this));580 581 int remainder = 0;582 // TRANSFER DATA583 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 bytes628 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 else663 {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) const679 {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 again695 696 while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE)697 {698 pos++;699 nextpos++;700 if (nextpos == len)701 return -2; // not found702 }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 the729 * 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 program739 * 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 desired771 // 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 them802 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 left825 {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 packet846 _ts_stats.IncrTSPacketCount();847 if (0 == _ts_stats.TSPacketCount()%1000000)848 VERBOSE(VB_RECORD, _ts_stats.toString());849 }850 else851 { // Let it resync in case of dropped bytes852 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_VIDEO887 // open file instead of device888 _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 #else892 _stream_fd = open(videodevice.ascii(), O_RDWR);893 #endif894 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 else902 {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
49 49 ATSC, 50 50 V4L, 51 51 MPEG, 52 HDTV,53 52 FIREWIRE, 54 53 HDHOMERUN, 55 54 FREEBOX, … … 75 74 return V4L; 76 75 if ("MPEG" == name) 77 76 return MPEG; 78 if ("HDTV" == name)79 return HDTV;80 77 if ("FIREWIRE" == name) 81 78 return FIREWIRE; 82 79 if ("HDHOMERUN" == name) … … 89 86 static bool IsEncoder(const QString &rawtype) 90 87 { 91 88 return 92 (rawtype != "DVB") && (rawtype != "HDTV") &&89 (rawtype != "DVB") && 93 90 (rawtype != "FIREWIRE") && (rawtype != "DBOX2") && 94 91 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX"); 95 92 } … … 103 100 static bool IsEITCapable(const QString &rawtype) 104 101 { 105 102 return 106 (rawtype == "DVB") || (rawtype == "HDTV") || 107 (rawtype == "HDHOMERUN"); 103 (rawtype == "DVB") || (rawtype == "HDHOMERUN"); 108 104 } 109 105 110 106 static bool IsTuningDigital(const QString &rawtype) 111 107 { 112 108 return 113 (rawtype == "DVB") || (rawtype == "HDTV") || 114 (rawtype == "HDHOMERUN"); 109 (rawtype == "DVB") || (rawtype == "HDHOMERUN"); 115 110 } 116 111 117 112 static bool IsTuningAnalog(const QString &rawtype) -
libs/libmythtv/videosource.h
385 385 TunerCardInput *input; 386 386 }; 387 387 388 class pcHDTVConfigurationGroup: public VerticalConfigurationGroup389 {390 Q_OBJECT391 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 404 388 class DVBInput; 405 389 class DVBCardName; 406 390 class DVBCardType; -
libs/libmythtv/libmythtv.pro
388 388 # Support for Video4Linux devices 389 389 using_v4l { 390 390 HEADERS += channel.h analogsignalmonitor.h 391 HEADERS += hdtvrecorder.h pchdtvsignalmonitor.h392 391 SOURCES += channel.cpp analogsignalmonitor.h 393 SOURCES += hdtvrecorder.cpp pchdtvsignalmonitor.cpp394 392 395 393 DEFINES += USING_V4L 396 394 } -
libs/libmythtv/dvbrecorder.h
53 53 * \brief This is a specialization of DTVRecorder used to 54 54 * handle streams from DVB drivers. 55 55 * 56 * \sa DTVRecorder , HDTVRecorder56 * \sa DTVRecorder 57 57 */ 58 58 class DVBRecorder : 59 59 public DTVRecorder, -
libs/libmythtv/dbcheck.cpp
11 11 #include "datadirect.h" // for DataDirectProcessor::FixProgramIDs 12 12 13 13 /// This is the DB schema version expected by the running MythTV instance. 14 const QString currentDatabaseVersion = "119 7";14 const QString currentDatabaseVersion = "1198"; 15 15 16 16 static bool UpdateDBVersionNumber(const QString &newnumber); 17 17 static bool performActualUpdate(const QString updates[], QString version, … … 100 100 101 101 The 'cardtype' is an important field for all cards as it guides the 102 102 interpretation of the rest of the fields, it has several possible 103 values: "V4L", "MJPEG", " HDTV", "DVB", "MPEG", "FIREWIRE", "GO7007"103 values: "V4L", "MJPEG", "DVB", "MPEG", "FIREWIRE", "GO7007" 104 104 and "DBOX2". 105 105 "V4L" indicates a V4L compatible device, this could be a 106 106 true V4L device or something like a Firewire camera with the 107 107 "firewire->v4l" driver. 108 108 "MJPEG" describes a Matrox G200 or DC10 card which captures 109 109 individual frames a JPEG images. 110 "HDTV" describes a pcHDTV HD-2000 or HD-3000 when using the V4L111 drivers.112 110 "DVB" can describe any card supported by the Linux DVB 113 111 drivers, including the pcHDTV and other ATSC cards. 114 112 The "MPEG" type describes a device using the ivtv drivers such as … … 138 136 139 137 The 'signal_timeout' and 'channel_timeout' indicate in 140 138 milliseconds 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. 139 channel lock respectively. 143 140 144 141 The 'dvb_swfilter', 'dvb_sat_type', 'dvb_wait_for_seqstart', 145 142 'skipbtaudio', 'dvb_on_demand', and 'dvb_diseqc_type' columns … … 212 209 a unique number from 0 to 99. 213 210 214 211 The '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. 212 to a channel. 223 213 224 214 The 'sourceid' field contains the \ref videosource_table key, which 225 215 specifies which listings service to use and which input on which video … … 3202 3192 return false; 3203 3193 } 3204 3194 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';", 3232 thequery, 3233 "" 3234 }; 3235 if (!performActualUpdate(updates, "1198", dbver)) 3236 return false; 3237 } 3238 3205 3239 //"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22 3206 3240 //"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22 3207 3241 //"ALTER TABLE recordedmarkup DROP COLUMN offset;" in 0.22 -
libs/libmythtv/scanwizardscanner.cpp
47 47 48 48 #ifdef USING_V4L 49 49 #include "channel.h" 50 #include "pchdtvsignalmonitor.h"51 50 #include "analogsignalmonitor.h" 52 51 #endif 53 52 … … 423 422 type = (CardUtil::OFDM == cardtype) ? DTVConfParser::OFDM : type; 424 423 type = (CardUtil::QPSK == cardtype) ? DTVConfParser::QPSK : type; 425 424 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; 428 427 429 428 if (type == DTVConfParser::UNKNOWN) 430 429 return; … … 493 492 #endif 494 493 495 494 #ifdef USING_V4L 496 if ((" HDTV" == card_type) || ("V4L" == card_type) || ("MPEG" == card_type))495 if (("V4L" == card_type) || ("MPEG" == card_type)) 497 496 channel = new Channel(NULL, device); 498 497 #endif 499 498 -
libs/libmythtv/dtvrecorder.h
1 1 // -*- Mode: c++ -*- 2 2 /** 3 * DTVRecorder -- base class for D VBRecorder and HDTVRecorder3 * DTVRecorder -- base class for Digital Television recorders 4 4 * Copyright (c) 2003-2004 by Brandon Beattie, Doug Larrick, 5 5 * Jason Hoos, and Daniel Thor Kristjansson 6 6 * Distributed as part of MythTV under GPL v2 and later. -
libs/libmythtv/dtvrecorder.cpp
1 1 /** 2 * DTVRecorder -- base class for D VBRecorder and HDTVRecorder2 * DTVRecorder -- base class for Digital Televison recorders 3 3 * Copyright 2003-2004 by Brandon Beattie, Doug Larrick, 4 4 * Jason Hoos, and Daniel Thor Kristjansson 5 5 * Distributed as part of MythTV under GPL v2 and later. 6 6 */ 7 7 8 using namespace std;9 10 8 #include "RingBuffer.h" 11 9 #include "programinfo.h" 12 10 #include "mpegtables.h" … … 25 23 26 24 /** \class DTVRecorder 27 25 * \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. 29 27 * 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 37 30 */ 38 31 39 32 DTVRecorder::DTVRecorder(TVRec *rec) : -
libs/libmythtv/pchdtvsignalmonitor.cpp
1 // -*- Mode: c++ -*-2 // Copyright (c) 2005, Daniel Thor Kristjansson3 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_SM17 #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 signal24 * monitoring. The timeout is initialized to the value of25 * the "ATSCCheckSignalWait" setting in milliseconds, and26 * the threshold is initialized to the value of the27 * "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 be31 * sent to the frontend even if SetNotifyFrontend(true)32 * is called.33 * \param _channel Channel class of device you want monitored34 * \param _flags SignalMonitorFlags to start with35 * \param _name Instance name for Qt signal/slot debugging36 */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 bytes112 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 uset128 * 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 EMIT179 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 support195 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 else214 {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 v1220 }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
2116 2116 minor = channum.right(channum.length() - (chansep + 1)).toInt(); 2117 2117 2118 2118 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 }2134 2119 } 2135 2120 2136 2121 static QString process_dd_station( -
libs/libmythtv/channelutil.cpp
895 895 QString("SELECT chanid FROM channel " 896 896 "WHERE sourceid=%1 AND serviceID=%1 AND mplexid=%2") 897 897 .arg(source_id).arg(program_number).arg(mplexid), 898 // find based on OLD pcHDTV formatted major and minor channels899 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 number903 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 channels907 QString("SELECT chanid FROM channel "908 "WHERE sourceid=%1 AND channum='%2%3'")909 .arg(source_id).arg(major_channel).arg(minor_channel),910 898 }; 911 899 912 900 for (uint i = 0; i < 6; i++) -
libs/libmythtv/signalmonitor.cpp
21 21 #endif 22 22 23 23 #ifdef USING_V4L 24 # include "pchdtvsignalmonitor.h"25 24 # include "analogsignalmonitor.h" 26 25 # include "channel.h" 27 26 #endif … … 58 57 * Additional signals may be implemented, see DTVSignalMonitor and 59 58 * DVBSignalMonitor for example. 60 59 * 61 * \sa DTVSignalMonitor DVBSignalMonitor, HDTVSignalMonitor, SignalMonitorValue 60 * \sa AnalocSignalMonitor, DTVSignalMonitor, DVBSignalMonitor, 61 HDHRSignalMonitor, SignalMonitorValue 62 62 */ 63 63 64 64 void ALRMhandler(int /*sig*/) … … 91 91 #endif 92 92 93 93 #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 }100 94 if ((cardtype.upper() == "V4L") || 101 95 (cardtype.upper() == "MPEG")) 102 96 { -
libs/libmythtv/videosource.cpp
1328 1328 input->fillSelections(device); 1329 1329 } 1330 1330 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 1370 1331 CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) : 1371 1332 TriggeredConfigurationGroup(true, true, false, false) 1372 1333 { … … 1380 1341 1381 1342 #ifdef USING_V4L 1382 1343 addTarget("V4L", new V4LConfigurationGroup(parent)); 1383 addTarget("HDTV", new pcHDTVConfigurationGroup(parent));1384 1344 # ifdef USING_IVTV 1385 1345 addTarget("MPEG", new MPEGConfigurationGroup(parent)); 1386 1346 # endif // USING_IVTV … … 1499 1459 QObject::tr("DVB DTV capture card (v3.x)"), "DVB"); 1500 1460 #endif // USING_DVB 1501 1461 1502 #ifdef USING_V4L1503 setting->addSelection(1504 QObject::tr("pcHDTV DTV capture card (w/V4L drivers)"), "HDTV");1505 #endif // USING_V4L1506 1507 1462 #ifdef USING_FIREWIRE 1508 1463 setting->addSelection( 1509 1464 QObject::tr("FireWire cable box"), "FIREWIRE"); -
libs/libmythtv/tv_rec.cpp
53 53 #include "recorderbase.h" 54 54 #include "NuppelVideoRecorder.h" 55 55 #include "mpegrecorder.h" 56 #include "hdtvrecorder.h"57 56 #include "dvbrecorder.h" 58 57 #include "dbox2recorder.h" 59 58 #include "hdhrrecorder.h" … … 195 194 init_run = true; 196 195 #endif 197 196 } 198 else // "V4L" or "MPEG", ie, analog TV , or "HDTV"197 else // "V4L" or "MPEG", ie, analog TV 199 198 { 200 199 #ifdef USING_V4L 201 200 channel = new Channel(this, genOpt.videodev); … … 205 204 CloseChannel(); 206 205 init_run = true; 207 206 #endif 208 if (genOpt.cardtype != " HDTV" && genOpt.cardtype != "MPEG")207 if (genOpt.cardtype != "MPEG") 209 208 rbFileExt = "nuv"; 210 209 } 211 210 … … 796 795 * 797 796 * Based on the card type, one of the possible recorders are started. 798 797 * If the card type is "MPEG" a MpegRecorder is started, 799 * if the card type is "HD TV" a HDTVRecorder is started,798 * if the card type is "HDHOMERUN" a HDHRRecorder is started, 800 799 * if the card type is "FIREWIRE" a FirewireRecorder is started, 801 800 * if the card type is "DVB" a DVBRecorder is started, 802 801 * otherwise a NuppelVideoRecorder is started. … … 813 812 recorder = new MpegRecorder(this); 814 813 #endif // USING_IVTV 815 814 } 816 else if (genOpt.cardtype == "HDTV")817 {818 #ifdef USING_V4L819 recorder = new HDTVRecorder(this);820 ringBuffer->SetWriteBufferSize(4*1024*1024);821 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);822 #endif // USING_V4L823 }824 815 else if (genOpt.cardtype == "FIREWIRE") 825 816 { 826 817 #ifdef USING_FIREWIRE … … 1800 1791 * \brief This creates a SignalMonitor instance if one is needed and 1801 1792 * begins signal monitoring. 1802 1793 * 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" 1804 1795 * a SignalMonitor instance is created and SignalMonitor::Start() 1805 1796 * is called to start the signal monitoring thread. 1806 1797 * -
libs/libmythtv/transporteditor.cpp
226 226 { 227 227 CardUtil::CARD_TYPES typeA = cardtypes[i - 1]; 228 228 typeA = (CardUtil::HDHOMERUN == typeA) ? CardUtil::ATSC : typeA; 229 typeA = (CardUtil::HDTV == typeA) ? CardUtil::ATSC : typeA;230 229 typeA = (CardUtil::MPEG == typeA) ? CardUtil::V4L : typeA; 231 230 232 231 CardUtil::CARD_TYPES typeB = cardtypes[i + 0]; 233 232 typeB = (CardUtil::HDHOMERUN == typeB) ? CardUtil::ATSC : typeB; 234 typeB = (CardUtil::HDTV == typeB) ? CardUtil::ATSC : typeB;235 233 typeB = (CardUtil::MPEG == typeB) ? CardUtil::V4L : typeB; 236 234 237 235 if (typeA == typeB) … … 524 522 addSelection("QAM-64", "qam_64"); 525 523 addSelection("QAM-256", "qam_256"); 526 524 } 527 else if (CardUtil::HDTV == nType)528 {529 addSelection("8-VSB", "8vsb");530 setVisible(false);531 }532 525 else 533 526 { 534 527 addSelection(QObject::tr("Analog"), "analog"); … … 729 722 right->addChild(new DVBForwardErrorCorrection(id)); 730 723 } 731 724 else if (CardUtil::ATSC == nType || 732 CardUtil::HDTV == nType ||733 725 CardUtil::HDHOMERUN == nType) 734 726 { 735 727 left->addChild(new DTVStandard(id, false, true)); -
libs/libmythtv/tv_rec.h
25 25 class RecorderBase; 26 26 class DTVRecorder; 27 27 class DVBRecorder; 28 class HDTVRecorder;29 28 class HDHRRecorder; 30 29 31 30 class SignalMonitor; -
libs/libmythtv/scanwizardhelpers.cpp
54 54 #ifdef USING_V4L 55 55 if (!cardTypes.isEmpty()) 56 56 cardTypes += ","; 57 cardTypes += "'V4L' ,'HDTV'";57 cardTypes += "'V4L'"; 58 58 # ifdef USING_IVTV 59 59 cardTypes += ",'MPEG'"; 60 60 # endif // USING_IVTV … … 412 412 QString::number(DVBUtilsImport)); 413 413 break; 414 414 case CardUtil::ATSC: 415 case CardUtil::HDTV:416 415 case CardUtil::HDHOMERUN: 417 416 addSelection(tr("Full Scan"), 418 417 QString::number(FullScan_ATSC), true); -
libs/libmythtv/channel.cpp
343 343 344 344 int Channel::GetCurrentChannelNum(const QString &channame) 345 345 { 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 352 346 for (int i = 0; i < totalChannels; i++) 353 347 { 354 if ( real_channame == curList[i].name)348 if (channame == curList[i].name) 355 349 return i; 356 350 } 357 VERBOSE(VB_IMPORTANT,358 QString("Channel::GetCurrentChannelNum(%1): "359 "Failed to find Channel '%2'")360 .arg(channame).arg(real_channame));361 351 352 VERBOSE(VB_IMPORTANT, LOC_ERR + 353 QString("GetCurrentChannelNum(%1): " 354 "Failed to find Channel").arg(channame)); 355 362 356 return -1; 363 357 } 364 358 … … 815 809 VERBOSE(VB_IMPORTANT, LOC_ERR + msg + 816 810 "\n\t\t\twhile setting format (v4l v2)" + ENO); 817 811 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;821 812 ok = false; 822 813 } 823 814
