Ticket #2975: 2975-v1.patch
| File 2975-v1.patch, 59.9 KB (added by , 19 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 #include "../libavcodec/avcodec.h"90 #include "../libavformat/avformat.h"91 #include "../libavformat/mpegts.h"92 93 #define REPORT_RING_STATS 194 95 #define DEFAULT_SUBCHANNEL 196 97 #define WHACK_A_BUG_VIDEO 098 #define WHACK_A_BUG_AUDIO 099 100 #if FAKE_VIDEO101 static int fake_video_index = 0;102 #define FAKE_VIDEO_NUM 4103 static const char* FAKE_VIDEO_FILES[FAKE_VIDEO_NUM] =104 {105 "/video/abc.ts",106 "/video/wb.ts",107 "/video/abc2.ts",108 "/video/nbc.ts",109 };110 #endif111 112 HDTVRecorder::HDTVRecorder(TVRec *rec)113 : DTVRecorder(rec),114 _atsc_stream_data(NULL),115 _resync_count(0)116 {117 SetStreamData(new ATSCStreamData(-1, DEFAULT_SUBCHANNEL));118 119 _buffer_size = TSPacket::SIZE * 1500;120 if ((_buffer = new unsigned char[_buffer_size])) {121 // make valgrind happy, initialize buffer memory122 memset(_buffer, 0xFF, _buffer_size);123 }124 125 VERBOSE(VB_RECORD, QString("HD buffer size %1 KB").arg(_buffer_size/1024));126 127 ringbuf.run = false;128 ringbuf.buffer = 0;129 pthread_mutex_init(&ringbuf.lock, NULL);130 pthread_mutex_init(&ringbuf.lock_stats, NULL);131 loop = random() % (report_loops / 2);132 }133 134 void HDTVRecorder::TeardownAll(void)135 {136 // Make SURE that the ringbuffer thread is cleaned up137 StopRecording();138 139 if (_stream_fd >= 0)140 {141 close(_stream_fd);142 _stream_fd = -1;143 }144 145 SetStreamData(NULL);146 147 if (_buffer)148 {149 delete[] _buffer;150 _buffer = NULL;151 }152 }153 154 HDTVRecorder::~HDTVRecorder()155 {156 TeardownAll();157 pthread_mutex_destroy(&ringbuf.lock);158 pthread_mutex_destroy(&ringbuf.lock_stats);159 }160 161 void HDTVRecorder::SetOptionsFromProfile(RecordingProfile *profile,162 const QString &videodev,163 const QString &audiodev,164 const QString &vbidev)165 {166 (void)audiodev;167 (void)vbidev;168 (void)profile;169 170 SetOption("videodevice", videodev);171 SetOption("tvformat", gContext->GetSetting("TVFormat"));172 SetOption("vbiformat", gContext->GetSetting("VbiFormat"));173 }174 175 bool HDTVRecorder::Open()176 {177 if (!_atsc_stream_data || !_buffer)178 return false;179 180 #if FAKE_VIDEO181 // open file instead of device182 if (_stream_fd >=0 && close(_stream_fd))183 {184 VERBOSE(VB_IMPORTANT,185 QString("HDTVRecorder::Open(): Error, failed to close "186 "existing fd (%1)").arg(strerror(errno)));187 return false;188 }189 190 _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);191 VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));192 fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;193 #else194 if (_stream_fd <= 0)195 _stream_fd = open(videodevice.ascii(), O_RDWR);196 #endif197 if (_stream_fd <= 0)198 {199 VERBOSE(VB_IMPORTANT, QString("Can't open video device: %1 chanfd = %2")200 .arg(videodevice).arg(_stream_fd));201 perror("open video:");202 }203 return (_stream_fd>0);204 }205 206 void HDTVRecorder::SetStreamData(MPEGStreamData *xdata)207 {208 ATSCStreamData *data = dynamic_cast<ATSCStreamData*>(xdata);209 210 if (data == _atsc_stream_data)211 return;212 213 ATSCStreamData *old_data = _atsc_stream_data;214 _atsc_stream_data = data;215 if (old_data)216 delete old_data;217 218 if (data)219 {220 data->AddMPEGSPListener(this);221 data->AddATSCMainListener(this);222 }223 }224 225 MPEGStreamData *HDTVRecorder::GetStreamData(void)226 {227 return _atsc_stream_data;228 }229 230 bool readchan(int chanfd, unsigned char* buffer, int dlen) {231 int len = read(chanfd, buffer, dlen); // read next byte232 if (dlen != len)233 {234 if (len < 0)235 {236 VERBOSE(VB_IMPORTANT, QString("HD1 error reading from device"));237 perror("read");238 }239 else if (len == 0)240 VERBOSE(VB_IMPORTANT, QString("HD2 end of file found in packet"));241 else242 VERBOSE(VB_IMPORTANT, QString("HD3 partial read. This shouldn't happen!"));243 }244 return (dlen == len);245 }246 247 bool syncchan(int chanfd, int dlen, int keepsync) {248 unsigned char b[188];249 int i, j;250 for (i=0; i<dlen; i++) {251 if (!readchan(chanfd, b, 1))252 break;253 if (SYNC_BYTE == b[0])254 {255 if (readchan(chanfd, &b[1], TSPacket::SIZE-1)) {256 i += (TSPacket::SIZE - 1);257 for (j=0; j<keepsync; j++)258 {259 if (!readchan(chanfd, b, TSPacket::SIZE))260 return false;261 i += TSPacket::SIZE;262 if (SYNC_BYTE != b[0])263 break;264 }265 if (j==keepsync)266 {267 VERBOSE(VB_RECORD,268 QString("HD4 obtained device stream sync after reading %1 bytes").269 arg(dlen));270 return true;271 }272 continue;273 }274 break;275 }276 }277 VERBOSE(VB_IMPORTANT, QString("HD5 Error: could not obtain sync"));278 return false;279 }280 281 void * HDTVRecorder::boot_ringbuffer(void * arg)282 {283 HDTVRecorder *dtv = (HDTVRecorder *)arg;284 dtv->fill_ringbuffer();285 return NULL;286 }287 288 void HDTVRecorder::fill_ringbuffer(void)289 {290 int errcnt = 0;291 int len;292 size_t unused, used;293 size_t contiguous;294 size_t read_size;295 bool run, request_pause, paused;296 297 pthread_mutex_lock(&ringbuf.lock);298 ringbuf.run = true;299 pthread_mutex_unlock(&ringbuf.lock);300 301 for (;;)302 {303 pthread_mutex_lock(&ringbuf.lock);304 run = ringbuf.run;305 unused = ringbuf.size - ringbuf.used;306 request_pause = ringbuf.request_pause;307 paused = ringbuf.paused;308 pthread_mutex_unlock(&ringbuf.lock);309 310 if (!run)311 break;312 313 if (request_pause)314 {315 pthread_mutex_lock(&ringbuf.lock);316 ringbuf.paused = true;317 pthread_mutex_unlock(&ringbuf.lock);318 319 pauseWait.wakeAll();320 if (tvrec)321 tvrec->RecorderPaused();322 323 usleep(1000);324 continue;325 }326 else if (paused)327 {328 pthread_mutex_lock(&ringbuf.lock);329 ringbuf.writePtr = ringbuf.readPtr = ringbuf.buffer;330 ringbuf.used = 0;331 ringbuf.paused = false;332 pthread_mutex_unlock(&ringbuf.lock);333 }334 335 contiguous = ringbuf.endPtr - ringbuf.writePtr;336 337 while (unused < TSPacket::SIZE && contiguous > TSPacket::SIZE)338 {339 usleep(500);340 341 pthread_mutex_lock(&ringbuf.lock);342 unused = ringbuf.size - ringbuf.used;343 request_pause = ringbuf.request_pause;344 pthread_mutex_unlock(&ringbuf.lock);345 346 if (request_pause)347 break;348 }349 if (request_pause)350 continue;351 352 read_size = unused > contiguous ? contiguous : unused;353 if (read_size > ringbuf.dev_read_size)354 read_size = ringbuf.dev_read_size;355 356 len = read(_stream_fd, ringbuf.writePtr, read_size);357 358 if (len < 0)359 {360 if (errno == EINTR)361 continue;362 363 VERBOSE(VB_IMPORTANT, QString("HD7 error reading from %1")364 .arg(videodevice));365 perror("read");366 if (++errcnt > 5)367 {368 pthread_mutex_lock(&ringbuf.lock);369 ringbuf.error = true;370 pthread_mutex_unlock(&ringbuf.lock);371 372 break;373 }374 375 usleep(500);376 continue;377 }378 else if (len == 0)379 {380 if (++errcnt > 5)381 {382 VERBOSE(VB_IMPORTANT, QString("HD8 %1 end of file found.")383 .arg(videodevice));384 385 pthread_mutex_lock(&ringbuf.lock);386 ringbuf.eof = true;387 pthread_mutex_unlock(&ringbuf.lock);388 389 break;390 }391 usleep(500);392 continue;393 }394 395 errcnt = 0;396 397 pthread_mutex_lock(&ringbuf.lock);398 ringbuf.used += len;399 used = ringbuf.used;400 ringbuf.writePtr += len;401 pthread_mutex_unlock(&ringbuf.lock);402 403 #ifdef REPORT_RING_STATS404 pthread_mutex_lock(&ringbuf.lock_stats);405 406 if (ringbuf.max_used < used)407 ringbuf.max_used = used;408 409 ringbuf.avg_used = ((ringbuf.avg_used * ringbuf.avg_cnt) + used)410 / ++ringbuf.avg_cnt;411 pthread_mutex_unlock(&ringbuf.lock_stats);412 #endif413 414 if (ringbuf.writePtr == ringbuf.endPtr)415 ringbuf.writePtr = ringbuf.buffer;416 }417 418 close(_stream_fd);419 _stream_fd = -1;420 }421 422 /* read count bytes from ring into buffer */423 int HDTVRecorder::ringbuf_read(unsigned char *buffer, size_t count)424 {425 size_t avail;426 size_t cnt = count;427 size_t min_read;428 unsigned char *cPtr = buffer;429 430 bool dev_error = false;431 bool dev_eof = false;432 433 pthread_mutex_lock(&ringbuf.lock);434 avail = ringbuf.used;435 pthread_mutex_unlock(&ringbuf.lock);436 437 min_read = cnt < ringbuf.min_read ? cnt : ringbuf.min_read;438 439 while (min_read > avail)440 {441 usleep(50000);442 443 if (request_pause || dev_error || dev_eof)444 return 0;445 446 pthread_mutex_lock(&ringbuf.lock);447 dev_error = ringbuf.error;448 dev_eof = ringbuf.eof;449 avail = ringbuf.used;450 pthread_mutex_unlock(&ringbuf.lock);451 }452 if (cnt > avail)453 cnt = avail;454 455 if (ringbuf.readPtr + cnt > ringbuf.endPtr)456 {457 size_t len;458 459 // Process as two pieces460 len = ringbuf.endPtr - ringbuf.readPtr;461 memcpy(cPtr, ringbuf.readPtr, len);462 cPtr += len;463 len = cnt - len;464 465 // Wrap arround to begining of buffer466 ringbuf.readPtr = ringbuf.buffer;467 memcpy(cPtr, ringbuf.readPtr, len);468 ringbuf.readPtr += len;469 }470 else471 {472 memcpy(cPtr, ringbuf.readPtr, cnt);473 ringbuf.readPtr += cnt;474 }475 476 pthread_mutex_lock(&ringbuf.lock);477 ringbuf.used -= cnt;478 pthread_mutex_unlock(&ringbuf.lock);479 480 if (ringbuf.readPtr == ringbuf.endPtr)481 ringbuf.readPtr = ringbuf.buffer;482 else483 {484 #ifdef REPORT_RING_STATS485 size_t samples, avg, max;486 487 if (++loop == report_loops)488 {489 loop = 0;490 pthread_mutex_lock(&ringbuf.lock_stats);491 avg = ringbuf.avg_used;492 samples = ringbuf.avg_cnt;493 max = ringbuf.max_used;494 ringbuf.avg_used = 0;495 ringbuf.avg_cnt = 0;496 ringbuf.max_used = 0;497 pthread_mutex_unlock(&ringbuf.lock_stats);498 499 VERBOSE(VB_IMPORTANT, QString("%1 ringbuf avg %2% max %3%"500 " samples %4")501 .arg(videodevice)502 .arg((static_cast<double>(avg)503 / ringbuf.size) * 100.0)504 .arg((static_cast<double>(max)505 / ringbuf.size) * 100.0)506 .arg(samples));507 }508 else509 #endif510 usleep(25);511 }512 513 return cnt;514 }515 516 void HDTVRecorder::StartRecording(void)517 {518 bool pause;519 bool dev_error, dev_eof;520 int len;521 522 const int unsyncpackets = 50; // unsynced packets to look at before giving up523 const int syncpackets = 10; // synced packets to require before starting recording524 525 VERBOSE(VB_RECORD, QString("StartRecording"));526 527 if (!Open())528 {529 _error = true;530 return;531 }532 533 _request_recording = true;534 _recording = true;535 536 // Setup device ringbuffer537 delete[] ringbuf.buffer;538 539 // ringbuf.size = 60 * 1024 * TSPacket::SIZE;540 ringbuf.size = gContext->GetNumSetting("HDRingbufferSize", 50*188);541 ringbuf.size *= 1024;542 543 if ((ringbuf.buffer =544 new unsigned char[ringbuf.size + TSPacket::SIZE]) == NULL)545 {546 VERBOSE(VB_IMPORTANT, "Failed to allocate HDTVRecorder ring buffer.");547 _error = true;548 return;549 }550 551 memset(ringbuf.buffer, 0xFF, ringbuf.size + TSPacket::SIZE);552 ringbuf.endPtr = ringbuf.buffer + ringbuf.size;553 ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;554 ringbuf.dev_read_size = TSPacket::SIZE * 48;555 ringbuf.min_read = TSPacket::SIZE * 4;556 ringbuf.used = 0;557 ringbuf.max_used = 0;558 ringbuf.avg_used = 0;559 ringbuf.avg_cnt = 0;560 ringbuf.request_pause = false;561 ringbuf.paused = false;562 ringbuf.error = false;563 ringbuf.eof = false;564 565 VERBOSE(VB_RECORD, QString("HD ring buffer size %1 KB")566 .arg(ringbuf.size/1024));567 568 // sync device stream so it starts with a valid ts packet569 if (!syncchan(_stream_fd, TSPacket::SIZE*unsyncpackets, syncpackets))570 {571 _error = true;572 return;573 }574 575 // create thread to fill the ringbuffer576 pthread_create(&ringbuf.thread, NULL, boot_ringbuffer,577 reinterpret_cast<void *>(this));578 579 int remainder = 0;580 // TRANSFER DATA581 while (_request_recording)582 {583 pthread_mutex_lock(&ringbuf.lock);584 dev_error = ringbuf.error;585 dev_eof = ringbuf.eof;586 pause = ringbuf.paused;587 pthread_mutex_unlock(&ringbuf.lock);588 589 if (request_pause)590 {591 pthread_mutex_lock(&ringbuf.lock);592 ringbuf.request_pause = true;593 pthread_mutex_unlock(&ringbuf.lock);594 595 usleep(1000);596 continue;597 }598 else if (pause)599 {600 pthread_mutex_lock(&ringbuf.lock);601 ringbuf.request_pause = false;602 pthread_mutex_unlock(&ringbuf.lock);603 604 usleep(1500);605 continue;606 }607 608 if (dev_error)609 {610 VERBOSE(VB_IMPORTANT, "HDTV: device error detected");611 _error = true;612 break;613 }614 615 if (dev_eof)616 break;617 618 len = ringbuf_read(&(_buffer[remainder]), _buffer_size - remainder);619 620 if (len == 0)621 continue;622 623 len += remainder;624 remainder = ProcessData(_buffer, len);625 if (remainder > 0 && (len > remainder)) // leftover bytes626 memmove(_buffer, &(_buffer[len - remainder]), remainder);627 }628 629 FinishRecording();630 _recording = false;631 }632 633 void HDTVRecorder::StopRecording(void)634 {635 TVRec *rec = tvrec;636 tvrec = NULL; // don't notify of pause..637 638 bool ok = true;639 if (!IsPaused())640 {641 Pause();642 ok = WaitForPause(250);643 }644 645 _request_recording = false;646 647 pthread_mutex_lock(&ringbuf.lock);648 bool run = ringbuf.run;649 ringbuf.run = false;650 pthread_mutex_unlock(&ringbuf.lock);651 652 if (run)653 pthread_join(ringbuf.thread, NULL);654 655 if (!ok)656 {657 // Better to have a memory leak, then a segfault?658 VERBOSE(VB_IMPORTANT, "DTV ringbuffer not cleaned up!\n");659 }660 else661 {662 delete[] ringbuf.buffer;663 ringbuf.buffer = 0;664 }665 tvrec = rec;666 }667 668 void HDTVRecorder::Pause(bool /*clear*/)669 {670 pthread_mutex_lock(&ringbuf.lock);671 ringbuf.paused = false;672 pthread_mutex_unlock(&ringbuf.lock);673 request_pause = true;674 }675 676 bool HDTVRecorder::IsPaused(void) const677 {678 pthread_mutex_lock(&ringbuf.lock);679 bool paused = ringbuf.paused;680 pthread_mutex_unlock(&ringbuf.lock);681 682 return paused;683 }684 685 int HDTVRecorder::ResyncStream(const unsigned char *buffer,686 uint curr_pos, uint len)687 {688 // Search for two sync bytes 188 bytes apart,689 uint pos = curr_pos;690 uint nextpos = pos + TSPacket::SIZE;691 if (nextpos >= len)692 return -1; // not enough bytes; caller should try again693 694 while (buffer[pos] != SYNC_BYTE || buffer[nextpos] != SYNC_BYTE)695 {696 pos++;697 nextpos++;698 if (nextpos == len)699 return -2; // not found700 }701 702 return pos;703 }704 705 void HDTVRecorder::HandleSingleProgramPAT(ProgramAssociationTable *pat)706 {707 if (!pat)708 return;709 710 int next = (pat->tsheader()->ContinuityCounter()+1)&0xf;711 pat->tsheader()->SetContinuityCounter(next);712 BufferedWrite(*(reinterpret_cast<TSPacket*>(pat->tsheader())));713 }714 715 void HDTVRecorder::HandleSingleProgramPMT(ProgramMapTable* pmt)716 {717 if (!pmt)718 return;719 720 int next = (pmt->tsheader()->ContinuityCounter()+1)&0xf;721 pmt->tsheader()->SetContinuityCounter(next);722 BufferedWrite(*(reinterpret_cast<TSPacket*>(pmt->tsheader())));723 }724 725 /** \fn HDTVRecorder::HandleMGT(const MasterGuideTable*)726 * \brief Handles Master Guide Table, by enabling the727 * scanning of all PIDs listed.728 */729 void HDTVRecorder::HandleMGT(const MasterGuideTable *mgt)730 {731 for (unsigned int i=0; i<mgt->TableCount(); i++)732 GetStreamData()->AddListeningPID(mgt->TablePID(i));733 }734 735 /** \fn HDTVRecorder::HandleVCT(uint, const VirtualChannelTable*)736 * \brief Handles Virtual Channel Tables by finding the program737 * number to use.738 * \bug Assumes there is only one VCT, may break on Cable.739 */740 void HDTVRecorder::HandleVCT(uint /*tsid*/, const VirtualChannelTable *vct)741 {742 if (vct->ChannelCount() < 1)743 {744 VERBOSE(VB_IMPORTANT,745 "HDTVRecorder::HandleVCT: table has no channels");746 return;747 }748 749 bool found = false;750 VERBOSE(VB_RECORD, QString("Desired channel %1_%2")751 .arg(GetATSCStreamData()->DesiredMajorChannel())752 .arg(GetATSCStreamData()->DesiredMinorChannel()));753 for (uint i = 0; i < vct->ChannelCount(); i++)754 {755 int maj = GetATSCStreamData()->DesiredMajorChannel();756 int min = GetATSCStreamData()->DesiredMinorChannel();757 if ((maj == -1 || vct->MajorChannel(i) == (uint)maj) &&758 (vct->MinorChannel(i) == (uint)min))759 {760 uint pnum = (uint) GetATSCStreamData()->DesiredProgram();761 if (vct->ProgramNumber(i) != pnum)762 {763 VERBOSE(VB_RECORD,764 QString("Resetting desired program from %1"765 " to %2")766 .arg(GetATSCStreamData()->DesiredProgram())767 .arg(vct->ProgramNumber(i)));768 // Do a (partial?) reset here if old desired769 // program is not 0?770 GetATSCStreamData()->SetDesiredProgram(vct->ProgramNumber(i));771 }772 found = true;773 }774 }775 if (!found)776 {777 VERBOSE(VB_IMPORTANT,778 QString("Desired channel %1_%2 not found;"779 " using %3_%4 instead.")780 .arg(GetATSCStreamData()->DesiredMajorChannel())781 .arg(GetATSCStreamData()->DesiredMinorChannel())782 .arg(vct->MajorChannel(0))783 .arg(vct->MinorChannel(0)));784 VERBOSE(VB_IMPORTANT, vct->toString());785 GetATSCStreamData()->SetDesiredProgram(vct->ProgramNumber(0));786 }787 }788 789 bool HDTVRecorder::ProcessTSPacket(const TSPacket &tspacket)790 {791 bool ok = !tspacket.TransportError();792 if (ok && !tspacket.ScramplingControl())793 {794 if (tspacket.HasAdaptationField())795 GetStreamData()->HandleAdaptationFieldControl(&tspacket);796 if (tspacket.HasPayload())797 {798 const unsigned int lpid = tspacket.PID();799 // Pass or reject frames based on PID, and parse info from them800 if (lpid == GetStreamData()->VideoPIDSingleProgram())801 {802 _buffer_packets = !FindMPEG2Keyframes(&tspacket);803 BufferedWrite(tspacket);804 }805 else if (GetStreamData()->IsAudioPID(lpid))806 BufferedWrite(tspacket);807 else if (GetStreamData()->IsListeningPID(lpid))808 GetStreamData()->HandleTSTables(&tspacket);809 else if (GetStreamData()->IsWritingPID(lpid))810 BufferedWrite(tspacket);811 else if (GetATSCStreamData()->VersionMGT()>=0)812 _ts_stats.IncrPIDCount(lpid);813 }814 }815 return ok;816 }817 818 int HDTVRecorder::ProcessData(const unsigned char *buffer, uint len)819 {820 uint pos = 0;821 822 while (pos + 187 < len) // while we have a whole packet left823 {824 if (buffer[pos] != SYNC_BYTE)825 {826 _resync_count++;827 if (25 == _resync_count)828 VERBOSE(VB_RECORD, QString("Resyncing many of times, suppressing error messages"));829 else if (25 > _resync_count)830 VERBOSE(VB_RECORD, QString("Resyncing"));831 int newpos = ResyncStream(buffer, pos, len);832 if (newpos == -1)833 return len - pos;834 if (newpos == -2)835 return TSPacket::SIZE;836 837 pos = newpos;838 }839 840 const TSPacket *pkt = reinterpret_cast<const TSPacket*>(&buffer[pos]);841 if (ProcessTSPacket(*pkt))842 {843 pos += TSPacket::SIZE; // Advance to next TS packet844 _ts_stats.IncrTSPacketCount();845 if (0 == _ts_stats.TSPacketCount()%1000000)846 VERBOSE(VB_RECORD, _ts_stats.toString());847 }848 else849 { // Let it resync in case of dropped bytes850 pos++;851 }852 }853 854 return len - pos;855 }856 857 void HDTVRecorder::Reset(void)858 {859 VERBOSE(VB_RECORD, "HDTVRecorder::Reset(void)");860 DTVRecorder::Reset();861 862 _error = false;863 _resync_count = 0;864 _ts_stats.Reset();865 866 if (curRecording)867 {868 curRecording->ClearPositionMap(MARK_GOP_BYFRAME);869 }870 871 if (_stream_fd >= 0)872 {873 if (!IsPaused())874 {875 Pause();876 WaitForPause();877 }878 int ret = close(_stream_fd);879 if (ret < 0)880 {881 perror("close");882 return;883 }884 #if FAKE_VIDEO885 // open file instead of device886 _stream_fd = open(FAKE_VIDEO_FILES[fake_video_index], O_RDWR);887 VERBOSE(VB_IMPORTANT, QString("Opened fake video source %1").arg(FAKE_VIDEO_FILES[fake_video_index]));888 fake_video_index = (fake_video_index+1)%FAKE_VIDEO_NUM;889 #else890 _stream_fd = open(videodevice.ascii(), O_RDWR);891 #endif892 if (_stream_fd < 0)893 {894 VERBOSE(VB_IMPORTANT, QString("HD1 Can't open video device: %1 chanfd = %2").895 arg(videodevice).arg(_stream_fd));896 perror("open video");897 return;898 }899 else900 {901 pthread_mutex_lock(&ringbuf.lock);902 ringbuf.used = 0;903 ringbuf.max_used = 0;904 ringbuf.readPtr = ringbuf.writePtr = ringbuf.buffer;905 pthread_mutex_unlock(&ringbuf.lock);906 }907 Unpause();908 }909 } -
libs/libmythtv/cardutil.h
48 48 ATSC, 49 49 V4L, 50 50 MPEG, 51 HDTV,52 51 FIREWIRE, 53 52 HDHOMERUN, 54 53 CRC_IP, … … 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) … … 91 88 static bool IsEncoder(const QString &rawtype) 92 89 { 93 90 return 94 (rawtype != "DVB") && (rawtype != "HDTV") && 95 (rawtype != "FIREWIRE") && (rawtype != "DBOX2") && 96 (rawtype != "HDHOMERUN") && (rawtype != "FREEBOX") && 97 (rawtype != "CRC_IP"); 91 (rawtype != "DVB") && (rawtype != "FIREWIRE") && 92 (rawtype != "DBOX2") && (rawtype != "HDHOMERUN") && 93 (rawtype != "FREEBOX") && (rawtype != "CRC_IP"); 98 94 } 99 95 100 96 static bool IsUnscanable(const QString &rawtype) … … 107 103 static bool IsEITCapable(const QString &rawtype) 108 104 { 109 105 return 110 (rawtype == "DVB") || (rawtype == "HDTV") || 111 (rawtype == "HDHOMERUN"); 106 (rawtype == "DVB") || (rawtype == "HDHOMERUN"); 112 107 } 113 108 114 109 static int GetCardID(const QString &videodevice, -
libs/libmythtv/videosource.h
366 366 TunerCardInput *input; 367 367 }; 368 368 369 class pcHDTVConfigurationGroup: public VerticalConfigurationGroup370 {371 Q_OBJECT372 373 public:374 pcHDTVConfigurationGroup(CaptureCard& a_parent);375 376 public slots:377 void probeCard(const QString &device);378 379 private:380 CaptureCard &parent;381 TransLabelSetting *cardinfo;382 TunerCardInput *input;383 };384 385 369 class DVBInput; 386 370 class DVBCardName; 387 371 class DVBCardType; -
libs/libmythtv/libmythtv.pro
369 369 # Support for Video4Linux devices 370 370 using_v4l { 371 371 HEADERS += channel.h analogsignalmonitor.h 372 HEADERS += hdtvrecorder.h pchdtvsignalmonitor.h373 372 SOURCES += channel.cpp analogsignalmonitor.h 374 SOURCES += hdtvrecorder.cpp pchdtvsignalmonitor.cpp375 373 376 374 DEFINES += USING_V4L 377 375 } -
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
10 10 #include "mythdbcon.h" 11 11 12 12 /// This is the DB schema version expected by the running MythTV instance. 13 const QString currentDatabaseVersion = "117 7";13 const QString currentDatabaseVersion = "1178"; 14 14 15 15 static bool UpdateDBVersionNumber(const QString &newnumber); 16 16 static bool performActualUpdate(const QString updates[], QString version, … … 97 97 98 98 The 'cardtype' is an important field for all cards as it guides the 99 99 interpretation of the rest of the fields, it has several possible 100 values: "V4L", "MJPEG", " HDTV", "DVB", "MPEG", "FIREWIRE", "GO7007"100 values: "V4L", "MJPEG", "DVB", "MPEG", "FIREWIRE", "GO7007" 101 101 and "DBOX2". 102 102 "V4L" indicates a V4L compatible device, this could be a 103 103 true V4L device or something like a Firewire camera with the 104 104 "firewire->v4l" driver. 105 105 "MJPEG" describes a Matrox G200 or DC10 card which captures 106 106 individual frames a JPEG images. 107 "HDTV" describes a pcHDTV HD-2000 or HD-3000 when using the V4L108 drivers.109 107 "DVB" can describe any card supported by the Linux DVB 110 108 drivers, including the pcHDTV and other ATSC cards. 111 109 The "MPEG" type describes a device using the ivtv drivers such as … … 135 133 136 134 The 'signal_timeout' and 'channel_timeout' indicate in 137 135 milliseconds how long it should take to get a signal and 138 channel lock respectively. Signal lock detection is 139 currently only supported on "DVB" and "HDTV" card types. 136 channel lock respectively. 140 137 141 138 The 'dvb_swfilter', 'dvb_sat_type', 'dvb_wait_for_seqstart', 142 139 'skipbtaudio', 'dvb_on_demand', and 'dvb_diseqc_type' columns … … 209 206 a unique number from 0 to 99. 210 207 211 208 The 'channum' field contains the channel number to be input to jump 212 to a channel. With HDTV using video4linux drivers this field has 213 a special meaning. If the field contains only numeric characters 214 then the digits up to the last digit are used as the major channel 215 number and the last digit is used as the minor channel number. 216 If it contains an underscore (_), the default, then the digits before 217 the underscore are used as the major channel, and the ones after 218 it as the minor channel. If it contains a minus sign (-), then 219 the digits after the minus sign are used as the program number. 209 to a channel. 220 210 221 211 The 'sourceid' field contains the \ref videosource_table key, which 222 212 specifies which listings service to use and which input on which video … … 2857 2847 return false; 2858 2848 } 2859 2849 2850 if (dbver == "1177") 2851 { 2852 QString thequery = 2853 "SELECT cardid " 2854 "FROM capturecard " 2855 "WHERE cardtype='HDTV'"; 2856 2857 MSqlQuery query(MSqlQuery::InitCon()); 2858 query.prepare(thequery); 2859 if (!query.exec()) 2860 { 2861 QString msg = 2862 QString("DB Error (Performing database upgrade): \n" 2863 "Query was: %1 \nError was: %2 \nnew version: %3") 2864 .arg(thequery) 2865 .arg(MythContext::DBErrorMessage(query.lastError())) 2866 .arg("1178"); 2867 VERBOSE(VB_IMPORTANT, msg); 2868 return false; 2869 } 2870 2871 QString in = "("; 2872 2873 while (query.next()) 2874 in += query.value(0).toString() + ","; 2875 2876 thequery = ""; 2877 if (in.length() > 2) 2878 { 2879 in.truncate(in.length() - 1); 2880 thequery = 2881 "DELETE FROM cardinput " 2882 "WHERE cardid IN " + in + ")"; 2883 } 2884 2885 const QString updates[] = { 2886 "DELETE FROM capturecard WHERE cardtype = 'HDTV';", 2887 thequery, 2888 "" 2889 }; 2890 if (!performActualUpdate(updates, "1178", dbver)) 2891 return false; 2892 } 2893 2860 2894 //"ALTER TABLE cardinput DROP COLUMN preference;" in 0.22 2861 2895 //"ALTER TABLE channel DROP COLUMN atscsrcid;" in 0.22 2862 2896 //"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" … … 20 18 21 19 /** \class DTVRecorder 22 20 * \brief This is a specialization of RecorderBase used to 23 * handle DVB and ATSC streams.21 * handle MPEG-2, MPEG-4, MPEG-4 AVC, DVB and ATSC streams. 24 22 * 25 * This class is an abstract class. If you are using a 26 * pcHDTV card with the bttv drivers, ATSC streams are 27 * handled by the HDTVRecorder. If you are using DVB 28 * drivers DVBRecorder is used. If you are using firewire 29 * cable box input the FirewireRecorder is used. 30 * 31 * \sa DVBRecorder, HDTVRecorder, FirewireRecorder, DBox2Recorder 23 * \sa DBox2Recorder, DVBRecorder, FirewireRecorder, 24 HDHRRecoreder, IPTVRecorder 32 25 */ 33 26 34 27 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
1837 1837 minor = channum.right(channum.length() - (chansep + 1)).toInt(); 1838 1838 1839 1839 freq = get_center_frequency("atsc", "vsb8", "us", freqid); 1840 1841 // Check if this is connected to an HDTV card.1842 MSqlQuery query(MSqlQuery::DDCon());1843 query.prepare(1844 "SELECT cardtype "1845 "FROM capturecard, cardinput "1846 "WHERE cardinput.cardid = capturecard.cardid AND "1847 " sourceid = :SOURCEID");1848 query.bindValue(":SOURCEID", sourceid);1849 1850 if (query.exec() && query.isActive() && query.next() &&1851 query.value(0).toString() == "HDTV")1852 {1853 freq -= 1750000; // convert to visual carrier freq.1854 }1855 1840 } 1856 1841 1857 1842 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
19 19 #endif 20 20 21 21 #ifdef USING_V4L 22 # include "pchdtvsignalmonitor.h"23 22 # include "analogsignalmonitor.h" 24 23 # include "channel.h" 25 24 #endif … … 56 55 * Additional signals may be implemented, see DTVSignalMonitor and 57 56 * DVBSignalMonitor for example. 58 57 * 59 * \sa DTVSignalMonitor DVBSignalMonitor, HDTVSignalMonitor, SignalMonitorValue 58 * \sa AnalocSignalMonitor, DTVSignalMonitor, DVBSignalMonitor, 59 HDHRSignalMonitor, SignalMonitorValue 60 60 */ 61 61 62 62 void ALRMhandler(int /*sig*/) … … 89 89 #endif 90 90 91 91 #ifdef USING_V4L 92 if (cardtype.upper() == "HDTV")93 {94 Channel *hdtvc = dynamic_cast<Channel*>(channel);95 if (hdtvc)96 signalMonitor = new pcHDTVSignalMonitor(db_cardnum, hdtvc);97 }98 92 if ((cardtype.upper() == "V4L") || 99 93 (cardtype.upper() == "MPEG")) 100 94 { -
libs/libmythtv/videosource.cpp
1298 1298 input->fillSelections(device); 1299 1299 } 1300 1300 1301 pcHDTVConfigurationGroup::pcHDTVConfigurationGroup(CaptureCard& a_parent) :1302 VerticalConfigurationGroup(false, true, false, false),1303 parent(a_parent), cardinfo(new TransLabelSetting()),1304 input(new TunerCardInput(parent))1305 {1306 VideoDevice *atsc_device = new VideoDevice(parent, 0, 64);1307 SignalTimeout *signal_timeout = new SignalTimeout(parent, 500, 250);1308 ChannelTimeout *channel_timeout = new ChannelTimeout(parent, 2000, 1750);1309 1310 addChild(atsc_device);1311 addChild(cardinfo);1312 addChild(signal_timeout);1313 addChild(channel_timeout);1314 addChild(input);1315 1316 connect(atsc_device, SIGNAL(valueChanged(const QString&)),1317 this, SLOT( probeCard( const QString&)));1318 1319 probeCard(atsc_device->getValue());1320 }1321 1322 void pcHDTVConfigurationGroup::probeCard(const QString &device)1323 {1324 QString cn = tr("Failed to open"), ci = cn, dn = QString::null;1325 1326 int videofd = open(device.ascii(), O_RDWR);1327 if (videofd >= 0)1328 {1329 if (!CardUtil::GetV4LInfo(videofd, cn, dn))1330 ci = cn = tr("Failed to probe");1331 else if (!dn.isEmpty())1332 ci = cn + " [" + dn + "]";1333 close(videofd);1334 }1335 1336 cardinfo->setValue(ci);1337 input->fillSelections(device);1338 }1339 1340 1301 CaptureCardGroup::CaptureCardGroup(CaptureCard &parent) : 1341 1302 TriggeredConfigurationGroup(true, true, false, false) 1342 1303 { … … 1350 1311 1351 1312 #ifdef USING_V4L 1352 1313 addTarget("V4L", new V4LConfigurationGroup(parent)); 1353 addTarget("HDTV", new pcHDTVConfigurationGroup(parent));1354 1314 # ifdef USING_IVTV 1355 1315 addTarget("MPEG", new MPEGConfigurationGroup(parent)); 1356 1316 # endif // USING_IVTV … … 1469 1429 QObject::tr("DVB DTV capture card (v3.x)"), "DVB"); 1470 1430 #endif // USING_DVB 1471 1431 1472 #ifdef USING_V4L1473 setting->addSelection(1474 QObject::tr("pcHDTV DTV capture card (w/V4L drivers)"), "HDTV");1475 #endif // USING_V4L1476 1477 1432 #ifdef USING_FIREWIRE 1478 1433 setting->addSelection( 1479 1434 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" … … 196 195 init_run = true; 197 196 #endif 198 197 } 199 else // "V4L" or "MPEG", ie, analog TV , or "HDTV"198 else // "V4L" or "MPEG", ie, analog TV 200 199 { 201 200 #ifdef USING_V4L 202 201 channel = new Channel(this, genOpt.videodev); … … 206 205 CloseChannel(); 207 206 init_run = true; 208 207 #endif 209 if (genOpt.cardtype != " HDTV" && genOpt.cardtype != "MPEG")208 if (genOpt.cardtype != "MPEG") 210 209 rbFileExt = "nuv"; 211 210 } 212 211 … … 794 793 * 795 794 * Based on the card type, one of the possible recorders are started. 796 795 * If the card type is "MPEG" a MpegRecorder is started, 797 * if the card type is "HD TV" a HDTVRecorder is started,796 * if the card type is "HDHOMERUN" a HDHRRecorder is started, 798 797 * if the card type is "FIREWIRE" a FirewireRecorder is started, 799 798 * if the card type is "DVB" a DVBRecorder is started, 800 799 * otherwise a NuppelVideoRecorder is started. … … 811 810 recorder = new MpegRecorder(this); 812 811 #endif // USING_IVTV 813 812 } 814 else if (genOpt.cardtype == "HDTV")815 {816 #ifdef USING_V4L817 recorder = new HDTVRecorder(this);818 ringBuffer->SetWriteBufferSize(4*1024*1024);819 recorder->SetOption("wait_for_seqstart", genOpt.wait_for_seqstart);820 #endif // USING_V4L821 }822 813 else if (genOpt.cardtype == "FIREWIRE") 823 814 { 824 815 #ifdef USING_FIREWIRE … … 1796 1787 * \brief This creates a SignalMonitor instance if one is needed and 1797 1788 * begins signal monitoring. 1798 1789 * 1799 * If the channel exists and the cardtype is "DVB" , "HDTV"or "HDHomeRun"1790 * If the channel exists and the cardtype is "DVB" or "HDHomeRun" 1800 1791 * a SignalMonitor instance is created and SignalMonitor::Start() 1801 1792 * is called to start the signal monitoring thread. 1802 1793 * -
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) … … 526 524 addSelection("QAM-64", "qam_64"); 527 525 addSelection("QAM-256", "qam_256"); 528 526 } 529 else if (CardUtil::HDTV == nType)530 {531 addSelection("8-VSB", "8vsb");532 setVisible(false);533 }534 527 else 535 528 { 536 529 addSelection(QObject::tr("Analog"), "analog"); … … 731 724 right->addChild(new DVBForwardErrorCorrection(id)); 732 725 } 733 726 else if (CardUtil::ATSC == nType || 734 CardUtil::HDTV == nType ||735 727 CardUtil::HDHOMERUN == nType) 736 728 { 737 729 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
