00001
00002
00003 #include <cassert>
00004
00005
00006 #include <pthread.h>
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <sys/select.h>
00010 #include <sys/ioctl.h>
00011
00012
00013 #include <qstring.h>
00014 #include <qdeepcopy.h>
00015
00016
00017 #include "dvbstreamhandler.h"
00018 #include "dvbchannel.h"
00019 #include "dtvsignalmonitor.h"
00020 #include "streamlisteners.h"
00021 #include "mpegstreamdata.h"
00022 #include "cardutil.h"
00023 #include "dvbtypes.h"
00024 #include "diseqc.h"
00025
00026 #define LOC QString("DVBSH(%1): ").arg(_dvb_dev_num)
00027 #define LOC_WARN QString("DVBSH(%1) Warning: ").arg(_dvb_dev_num)
00028 #define LOC_ERR QString("DVBSH(%1) Error: ").arg(_dvb_dev_num)
00029
00030 QMap<uint,bool> DVBStreamHandler::_rec_supports_ts_monitoring;
00031 QMutex DVBStreamHandler::_rec_supports_ts_monitoring_lock;
00032
00033 QMap<uint,DVBStreamHandler*> DVBStreamHandler::_handlers;
00034 QMap<uint,uint> DVBStreamHandler::_handlers_refcnt;
00035 QMutex DVBStreamHandler::_handlers_lock;
00036
00037 DVBStreamHandler *DVBStreamHandler::Get(uint dvb_device_number)
00038 {
00039 QMutexLocker locker(&_handlers_lock);
00040
00041 QMap<uint,DVBStreamHandler*>::iterator it =
00042 _handlers.find(dvb_device_number);
00043
00044 if (it == _handlers.end())
00045 {
00046 _handlers[dvb_device_number] = new DVBStreamHandler(dvb_device_number);
00047 _handlers_refcnt[dvb_device_number] = 1;
00048 }
00049 else
00050 {
00051 _handlers_refcnt[dvb_device_number]++;
00052 }
00053
00054 return _handlers[dvb_device_number];
00055 }
00056
00057 void DVBStreamHandler::Return(DVBStreamHandler * & ref)
00058 {
00059 QMutexLocker locker(&_handlers_lock);
00060
00061 uint dvb_dev_num = ref->_dvb_dev_num;
00062
00063 QMap<uint,uint>::iterator rit = _handlers_refcnt.find(dvb_dev_num);
00064 if (rit == _handlers_refcnt.end())
00065 return;
00066
00067 if (*rit > 1)
00068 {
00069 *rit--;
00070 return;
00071 }
00072
00073 QMap<uint,DVBStreamHandler*>::iterator it = _handlers.find(dvb_dev_num);
00074 if ((it != _handlers.end()) && (*it == ref))
00075 {
00076 ref = NULL;
00077 delete *it;
00078 _handlers.erase(it);
00079 }
00080
00081 _handlers_refcnt.erase(rit);
00082 }
00083
00084 DVBStreamHandler::DVBStreamHandler(uint dvb_device_number) :
00085 _dvb_dev_num(dvb_device_number),
00086 _dvr_dev_path(CardUtil::GetDeviceName(DVB_DEV_DVR, _dvb_dev_num)),
00087 _allow_section_reader(false),
00088 _needs_buffering(false),
00089 _allow_retune(false),
00090
00091 _start_stop_lock(true),
00092 _running(false),
00093 _using_section_reader(false),
00094
00095 _device_read_buffer(NULL),
00096 _sigmon(NULL),
00097 _dvbchannel(NULL),
00098
00099 _pid_lock(true),
00100 _listener_lock(true)
00101 {
00102 }
00103
00104 DVBStreamHandler::~DVBStreamHandler()
00105 {
00106 assert(_stream_data_list.empty());
00107 }
00108
00109 void DVBStreamHandler::AddListener(MPEGStreamData *data,
00110 bool allow_section_reader,
00111 bool needs_buffering)
00112 {
00113 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- begin");
00114 assert(data);
00115
00116 _listener_lock.lock();
00117
00118 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- locked");
00119
00120 if (_stream_data_list.empty())
00121 {
00122 _allow_section_reader = allow_section_reader;
00123 _needs_buffering = needs_buffering;
00124 }
00125 else
00126 {
00127 _allow_section_reader &= allow_section_reader;
00128 _needs_buffering |= needs_buffering;
00129 }
00130
00131 _stream_data_list.push_back(data);
00132
00133 _listener_lock.unlock();
00134
00135 Start();
00136
00137 VERBOSE(VB_RECORD, LOC + "AddListener("<<data<<") -- end");
00138 }
00139
00140 void DVBStreamHandler::RemoveListener(MPEGStreamData *data)
00141 {
00142 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- begin");
00143 assert(data);
00144
00145 _listener_lock.lock();
00146
00147 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- locked");
00148
00149 vector<MPEGStreamData*>::iterator it =
00150 find(_stream_data_list.begin(), _stream_data_list.end(), data);
00151
00152 if (it != _stream_data_list.end())
00153 _stream_data_list.erase(it);
00154
00155 if (_stream_data_list.empty())
00156 {
00157 _allow_section_reader = false;
00158
00159 _listener_lock.unlock();
00160 Stop();
00161 }
00162 else
00163 {
00164 _listener_lock.unlock();
00165 }
00166
00167 VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- end");
00168 }
00169
00170 void *run_dvb_stream_handler_thunk(void *param)
00171 {
00172 DVBStreamHandler *mon = (DVBStreamHandler*) param;
00173 mon->Run();
00174 return NULL;
00175 }
00176
00177 void DVBStreamHandler::Start(void)
00178 {
00179 QMutexLocker locker(&_start_stop_lock);
00180
00181 _eit_pids.clear();
00182
00183 if (IsRunning() && _using_section_reader && !_allow_section_reader)
00184 Stop();
00185
00186 if (IsRunning() && _needs_buffering && !_device_read_buffer)
00187 Stop();
00188
00189 if (!IsRunning())
00190 {
00191 pthread_create(&_reader_thread, NULL,
00192 run_dvb_stream_handler_thunk, this);
00193
00194 while (!IsRunning())
00195 _running_state_changed.wait(100);
00196 }
00197 }
00198
00199 void DVBStreamHandler::Stop(void)
00200 {
00201 QMutexLocker locker(&_start_stop_lock);
00202
00203 if (IsRunning())
00204 {
00205 if (_device_read_buffer)
00206 _device_read_buffer->Stop();
00207 SetRunning(false);
00208 pthread_join(_reader_thread, NULL);
00209 }
00210 }
00211
00212 void DVBStreamHandler::Run(void)
00213 {
00214 SetRunning(true);
00215
00216 _using_section_reader = !SupportsTSMonitoring() && _allow_section_reader;
00217
00218 if (_using_section_reader)
00219 RunSR();
00220 else
00221 RunTS();
00222 }
00223
00234 void DVBStreamHandler::RunTS(void)
00235 {
00236 if (_needs_buffering)
00237 _device_read_buffer = new DeviceReadBuffer(this);
00238
00239 int remainder = 0;
00240 int buffer_size = TSPacket::SIZE * 15000;
00241 unsigned char *buffer = new unsigned char[buffer_size];
00242 if (!buffer)
00243 return;
00244 bzero(buffer, buffer_size);
00245
00246 int dvr_fd = open(_dvr_dev_path.ascii(), O_RDONLY | O_NONBLOCK);
00247 if (dvr_fd < 0)
00248 {
00249 VERBOSE(VB_IMPORTANT, LOC +
00250 QString("Failed to open DVR device %1 : %2")
00251 .arg(_dvr_dev_path).arg(strerror(errno)));
00252 delete[] buffer;
00253 return;
00254 }
00255
00256 bool _error = false;
00257 if (_device_read_buffer)
00258 {
00259 bool ok = _device_read_buffer->Setup(
00260 QString::number(_dvb_dev_num), dvr_fd);
00261
00262 if (!ok)
00263 {
00264 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate DRB buffer");
00265 _error = true;
00266 return;
00267 }
00268
00269 _device_read_buffer->Start();
00270 }
00271
00272 VERBOSE(VB_RECORD, LOC + "RunTS(): begin");
00273
00274 fd_set fd_select_set;
00275 FD_ZERO( &fd_select_set);
00276 FD_SET (dvr_fd, &fd_select_set);
00277 while (IsRunning() && !_error)
00278 {
00279 RetuneMonitor();
00280 UpdateFiltersFromStreamData();
00281
00282 ssize_t len = 0;
00283
00284 if (_device_read_buffer)
00285 {
00286 len = _device_read_buffer->Read(
00287 &(buffer[remainder]), buffer_size - remainder);
00288
00289
00290 if (_device_read_buffer->IsErrored())
00291 {
00292 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device error detected");
00293 _error = true;
00294 }
00295
00296 if (_device_read_buffer->IsEOF())
00297 {
00298 VERBOSE(VB_IMPORTANT, LOC_ERR + "Device EOF detected");
00299 _error = true;
00300 }
00301 }
00302 else
00303 {
00304
00305 struct timeval timeout = { 0, 50 * 1000 };
00306 select(dvr_fd+1, &fd_select_set, NULL, NULL, &timeout);
00307 len = read(dvr_fd, &(buffer[remainder]), buffer_size - remainder);
00308 }
00309
00310 if ((0 == len) || (-1 == len))
00311 {
00312 usleep(100);
00313 continue;
00314 }
00315
00316 len += remainder;
00317
00318 if (len < 10)
00319 {
00320 remainder = len;
00321 continue;
00322 }
00323
00324 _listener_lock.lock();
00325
00326 if (_stream_data_list.empty())
00327 {
00328 _listener_lock.unlock();
00329 continue;
00330 }
00331
00332 for (uint i = 0; i < _stream_data_list.size(); i++)
00333 {
00334 remainder = _stream_data_list[i]->ProcessData(buffer, len);
00335 }
00336
00337 _listener_lock.unlock();
00338
00339 if (remainder > 0 && (len > remainder))
00340 memmove(buffer, &(buffer[len - remainder]), remainder);
00341 }
00342 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "shutdown");
00343
00344 RemoveAllPIDFilters();
00345
00346 if (_device_read_buffer)
00347 {
00348 if (_device_read_buffer->IsRunning())
00349 _device_read_buffer->Stop();
00350
00351 delete _device_read_buffer;
00352 _device_read_buffer = NULL;
00353 }
00354
00355 close(dvr_fd);
00356 delete[] buffer;
00357
00358 VERBOSE(VB_RECORD, LOC + "RunTS(): " + "end");
00359
00360 SetRunning(false);
00361 }
00362
00369 void DVBStreamHandler::RunSR(void)
00370 {
00371 int buffer_size = 4192;
00372 unsigned char *buffer = new unsigned char[buffer_size];
00373 if (!buffer)
00374 return;
00375
00376 VERBOSE(VB_RECORD, LOC + "RunSR(): begin");
00377
00378 while (IsRunning())
00379 {
00380 RetuneMonitor();
00381 UpdateFiltersFromStreamData();
00382
00383 QMutexLocker read_locker(&_pid_lock);
00384
00385 bool readSomething = false;
00386 PIDInfoMap::const_iterator fit = _pid_info.begin();
00387 for (; fit != _pid_info.end(); ++fit)
00388 {
00389 int len = read((*fit)->filter_fd, buffer, buffer_size);
00390 if (len <= 0)
00391 continue;
00392
00393 readSomething = true;
00394
00395 const PESPacket pes = PESPacket::ViewData(buffer);
00396 const PSIPTable psip(pes);
00397
00398 if (psip.SectionSyntaxIndicator())
00399 {
00400 _listener_lock.lock();
00401 for (uint i = 0; i < _stream_data_list.size(); i++)
00402 {
00403 _stream_data_list[i]->HandleTables(
00404 fit.key() , psip);
00405 }
00406 _listener_lock.unlock();
00407 }
00408 }
00409
00410 if (!readSomething)
00411 usleep(3000);
00412 }
00413 VERBOSE(VB_RECORD, LOC + "RunSR(): " + "shutdown");
00414
00415 RemoveAllPIDFilters();
00416
00417 delete[] buffer;
00418
00419 VERBOSE(VB_RECORD, LOC + "RunSR(): " + "end");
00420 }
00421
00422 bool DVBStreamHandler::AddPIDFilter(PIDInfo *info)
00423 {
00424 VERBOSE(VB_RECORD, LOC + QString("AddPIDFilter(0x%1) priority %2")
00425 .arg(info->_pid, 0, 16).arg(GetPIDPriority(info->_pid)));
00426
00427 QMutexLocker writing_locker(&_pid_lock);
00428 _pid_info[info->_pid] = info;
00429
00430 CycleFiltersByPriority();
00431
00432 return true;
00433 }
00434
00435 typedef vector<uint> pid_list_t;
00436
00437 static pid_list_t::iterator find(
00438 const PIDInfoMap &map,
00439 pid_list_t &list,
00440 pid_list_t::iterator begin,
00441 pid_list_t::iterator end, bool find_open)
00442 {
00443 pid_list_t::iterator it;
00444 for (it = begin; it != end; it++)
00445 {
00446 PIDInfoMap::const_iterator mit = map.find(*it);
00447 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
00448 return it;
00449 }
00450
00451 for (it = list.begin(); it != begin; it++)
00452 {
00453 PIDInfoMap::const_iterator mit = map.find(*it);
00454 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
00455 return it;
00456 }
00457
00458 return list.end();
00459 }
00460
00461 void DVBStreamHandler::CycleFiltersByPriority(void)
00462 {
00463 QMutexLocker writing_locker(&_pid_lock);
00464 QMap<PIDPriority, pid_list_t> priority_queue;
00465 QMap<PIDPriority, uint> priority_open_cnt;
00466
00467 PIDInfoMap::const_iterator cit = _pid_info.begin();
00468 for (; cit != _pid_info.end(); ++cit)
00469 {
00470 PIDPriority priority = GetPIDPriority((*cit)->_pid);
00471 priority_queue[priority].push_back(cit.key());
00472 if ((*cit)->IsOpen())
00473 priority_open_cnt[priority]++;
00474 }
00475
00476 QMap<PIDPriority, pid_list_t>::iterator it = priority_queue.begin();
00477 for (; it != priority_queue.end(); ++it)
00478 sort((*it).begin(), (*it).end());
00479
00480 for (PIDPriority i = kPIDPriorityHigh; i > kPIDPriorityNone;
00481 i = (PIDPriority)((int)i-1))
00482 {
00483 while (priority_open_cnt[i] < priority_queue[i].size())
00484 {
00485
00486
00487
00488 pid_list_t::iterator open = find(
00489 _pid_info, priority_queue[i],
00490 priority_queue[i].begin(), priority_queue[i].end(), true);
00491 if (open == priority_queue[i].end())
00492 open = priority_queue[i].begin();
00493
00494 pid_list_t::iterator closed = find(
00495 _pid_info, priority_queue[i],
00496 open, priority_queue[i].end(), false);
00497
00498 if (closed == priority_queue[i].end())
00499 break;
00500
00501 if (_pid_info[*closed]->Open(_dvb_dev_num, _using_section_reader))
00502 {
00503 _open_pid_filters++;
00504 priority_open_cnt[i]++;
00505 continue;
00506 }
00507
00508
00509 bool freed = false;
00510 for (PIDPriority j = (PIDPriority)((int)i - 1);
00511 (j > kPIDPriorityNone) && !freed;
00512 j = (PIDPriority)((int)j-1))
00513 {
00514 if (!priority_open_cnt[j])
00515 continue;
00516
00517 for (uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
00518 {
00519 PIDInfo *info = _pid_info[priority_queue[j][k]];
00520 if (!info->IsOpen())
00521 continue;
00522
00523 if (info->Close(_dvb_dev_num))
00524 freed = true;
00525
00526 _open_pid_filters--;
00527 priority_open_cnt[j]--;
00528 }
00529 }
00530
00531 if (freed)
00532 {
00533
00534 if (_pid_info[*closed]->Open(
00535 _dvb_dev_num, _using_section_reader))
00536 {
00537 _open_pid_filters++;
00538 priority_open_cnt[i]++;
00539 continue;
00540 }
00541 }
00542
00543
00544
00545 if (_cycle_timer.elapsed() < 1000)
00546 break;
00547
00548 if (!_pid_info[*open]->IsOpen())
00549 break;
00550
00551
00552 bool ok = _pid_info[*open]->Close(_dvb_dev_num);
00553 _open_pid_filters--;
00554 priority_open_cnt[i]--;
00555
00556
00557 if (ok && _pid_info[*closed]->
00558 Open(_dvb_dev_num, _using_section_reader))
00559 {
00560 _open_pid_filters++;
00561 priority_open_cnt[i]++;
00562 }
00563
00564 break;
00565 }
00566 }
00567
00568 _cycle_timer.start();
00569 }
00570
00571 bool DVBStreamHandler::RemovePIDFilter(uint pid)
00572 {
00573 VERBOSE(VB_RECORD, LOC +
00574 QString("RemovePIDFilter(0x%1)").arg(pid, 0, 16));
00575
00576 QMutexLocker write_locker(&_pid_lock);
00577
00578 PIDInfoMap::iterator it = _pid_info.find(pid);
00579 if (it == _pid_info.end())
00580 return false;
00581
00582 PIDInfo *tmp = *it;
00583 _pid_info.erase(it);
00584
00585 bool ok = true;
00586 if (tmp->IsOpen())
00587 {
00588 ok = tmp->Close(_dvb_dev_num);
00589 _open_pid_filters--;
00590
00591 CycleFiltersByPriority();
00592 }
00593
00594 delete tmp;
00595
00596 return ok;
00597 }
00598
00599 bool DVBStreamHandler::RemoveAllPIDFilters(void)
00600 {
00601 QMutexLocker write_locker(&_pid_lock);
00602
00603 vector<int> del_pids;
00604 PIDInfoMap::iterator it = _pid_info.begin();
00605 for (; it != _pid_info.end(); ++it)
00606 del_pids.push_back(it.key());
00607
00608 bool ok = true;
00609 vector<int>::iterator dit = del_pids.begin();
00610 for (; dit != del_pids.end(); ++dit)
00611 ok &= RemovePIDFilter(*dit);
00612
00613 return ok;
00614 }
00615
00616 void DVBStreamHandler::UpdateListeningForEIT(void)
00617 {
00618 vector<uint> add_eit, del_eit;
00619
00620 QMutexLocker read_locker(&_listener_lock);
00621
00622 for (uint i = 0; i < _stream_data_list.size(); i++)
00623 {
00624 MPEGStreamData *sd = _stream_data_list[i];
00625 if (sd->HasEITPIDChanges(_eit_pids) &&
00626 sd->GetEITPIDChanges(_eit_pids, add_eit, del_eit))
00627 {
00628 for (uint i = 0; i < del_eit.size(); i++)
00629 {
00630 uint_vec_t::iterator it;
00631 it = find(_eit_pids.begin(), _eit_pids.end(), del_eit[i]);
00632 if (it != _eit_pids.end())
00633 _eit_pids.erase(it);
00634 sd->RemoveListeningPID(del_eit[i]);
00635 }
00636
00637 for (uint i = 0; i < add_eit.size(); i++)
00638 {
00639 _eit_pids.push_back(add_eit[i]);
00640 sd->AddListeningPID(add_eit[i]);
00641 }
00642 }
00643 }
00644 }
00645
00646 bool DVBStreamHandler::UpdateFiltersFromStreamData(void)
00647 {
00648 UpdateListeningForEIT();
00649
00650 pid_map_t pids;
00651
00652 {
00653 QMutexLocker read_locker(&_listener_lock);
00654
00655 for (uint i = 0; i < _stream_data_list.size(); i++)
00656 _stream_data_list[i]->GetPIDs(pids);
00657 }
00658
00659 QMap<uint, PIDInfo*> add_pids;
00660 vector<uint> del_pids;
00661
00662 {
00663 QMutexLocker read_locker(&_pid_lock);
00664
00665
00666 pid_map_t::const_iterator lit = pids.constBegin();
00667 for (; lit != pids.constEnd(); ++lit)
00668 {
00669 if (lit.data() && (_pid_info.find(lit.key()) == _pid_info.end()))
00670 {
00671 add_pids[lit.key()] = new PIDInfo(
00672 lit.key(), StreamID::PrivSec, DMX_PES_OTHER);
00673 }
00674 }
00675
00676
00677 PIDInfoMap::const_iterator fit = _pid_info.begin();
00678 for (; fit != _pid_info.end(); ++fit)
00679 {
00680 bool in_pids = pids.find(fit.key()) != pids.end();
00681 if (!in_pids)
00682 del_pids.push_back(fit.key());
00683 }
00684 }
00685
00686
00687 bool ok = true;
00688 vector<uint>::iterator dit = del_pids.begin();
00689 for (; dit != del_pids.end(); ++dit)
00690 ok &= RemovePIDFilter(*dit);
00691
00692
00693 QMap<uint, PIDInfo*>::iterator ait = add_pids.begin();
00694 for (; ait != add_pids.end(); ++ait)
00695 ok &= AddPIDFilter(*ait);
00696
00697
00698 if (_cycle_timer.elapsed() > 1000)
00699 CycleFiltersByPriority();
00700
00701 return ok;
00702 }
00703
00704 void DVBStreamHandler::SetRetuneAllowed(
00705 bool allow,
00706 DTVSignalMonitor *sigmon,
00707 DVBChannel *dvbchan)
00708 {
00709 if (allow && sigmon && dvbchan)
00710 {
00711 _allow_retune = true;
00712 _sigmon = sigmon;
00713 _dvbchannel = dvbchan;
00714 }
00715 else
00716 {
00717 _allow_retune = false;
00718 _sigmon = NULL;
00719 _dvbchannel = NULL;
00720 }
00721 }
00722
00723 void DVBStreamHandler::RetuneMonitor(void)
00724 {
00725 if (!_allow_retune)
00726 return;
00727
00728
00729 if (_sigmon->HasFlags(SignalMonitor::kDVBSigMon_WaitForPos))
00730 {
00731 const DiSEqCDevRotor *rotor = _dvbchannel->GetRotor();
00732 if (rotor)
00733 {
00734 bool was_moving, is_moving;
00735 _sigmon->GetRotorStatus(was_moving, is_moving);
00736
00737
00738 if (was_moving && !is_moving)
00739 {
00740 VERBOSE(VB_CHANNEL, LOC + "Retuning for rotor completion");
00741 _dvbchannel->Retune();
00742
00743
00744
00745 }
00746 }
00747 else
00748 {
00749
00750 _sigmon->SetRotorValue(100);
00751 }
00752 }
00753 }
00754
00763 bool DVBStreamHandler::SupportsTSMonitoring(void)
00764 {
00765 const uint pat_pid = 0x0;
00766
00767 {
00768 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00769 QMap<uint,bool>::const_iterator it;
00770 it = _rec_supports_ts_monitoring.find(_dvb_dev_num);
00771 if (it != _rec_supports_ts_monitoring.end())
00772 return *it;
00773 }
00774
00775 int dvr_fd = open(_dvr_dev_path.ascii(), O_RDONLY | O_NONBLOCK);
00776 if (dvr_fd < 0)
00777 {
00778 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00779 _rec_supports_ts_monitoring[_dvb_dev_num] = false;
00780 return false;
00781 }
00782
00783 bool supports_ts = false;
00784 if (AddPIDFilter(new PIDInfo(pat_pid)))
00785 {
00786 supports_ts = true;
00787 RemovePIDFilter(pat_pid);
00788 }
00789
00790 close(dvr_fd);
00791
00792 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00793 _rec_supports_ts_monitoring[_dvb_dev_num] = supports_ts;
00794
00795 return supports_ts;
00796 }
00797
00798 #undef LOC
00799 #undef LOC_WARN
00800 #undef LOC_ERR
00801
00802 #define LOC QString("PIDInfo(%1): ").arg(dvb_dev_num)
00803 #define LOC_WARN QString("PIDInfo(%1) Warning: ").arg(dvb_dev_num)
00804 #define LOC_ERR QString("PIDInfo(%1) Error: ").arg(dvb_dev_num)
00805
00806 bool PIDInfo::Open(uint dvb_dev_num, bool use_section_reader)
00807 {
00808 if (filter_fd >= 0)
00809 {
00810 close(filter_fd);
00811 filter_fd = -1;
00812 }
00813
00814 QString demux_fn = CardUtil::GetDeviceName(DVB_DEV_DEMUX, dvb_dev_num);
00815
00816 VERBOSE(VB_RECORD, LOC + QString("Opening filter for pid 0x%1")
00817 .arg(_pid, 0, 16));
00818
00819 int mux_fd = open(demux_fn.ascii(), O_RDWR | O_NONBLOCK);
00820 if (mux_fd == -1)
00821 {
00822 VERBOSE(VB_IMPORTANT, LOC +
00823 QString("Failed to open demux device %1 "
00824 "for filter on pid 0x%2")
00825 .arg(demux_fn).arg(_pid, 0, 16));
00826 return false;
00827 }
00828
00829 if (!use_section_reader)
00830 {
00831 struct dmx_pes_filter_params pesFilterParams;
00832 bzero(&pesFilterParams, sizeof(struct dmx_pes_filter_params));
00833 pesFilterParams.pid = (__u16) _pid;
00834 pesFilterParams.input = DMX_IN_FRONTEND;
00835 pesFilterParams.output = DMX_OUT_TS_TAP;
00836 pesFilterParams.flags = DMX_IMMEDIATE_START;
00837 pesFilterParams.pes_type = DMX_PES_OTHER;
00838
00839 if (ioctl(mux_fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
00840 {
00841 VERBOSE(VB_IMPORTANT, LOC_ERR +
00842 QString("Failed to set TS filter (pid 0x%1)")
00843 .arg(_pid, 0, 16));
00844
00845 close(mux_fd);
00846 return false;
00847 }
00848 }
00849 else
00850 {
00851 struct dmx_sct_filter_params sctFilterParams;
00852 bzero(&sctFilterParams, sizeof(struct dmx_sct_filter_params));
00853 switch ( (__u16) _pid )
00854 {
00855 case 0x0:
00856 sctFilterParams.filter.filter[0] = 0;
00857 sctFilterParams.filter.mask[0] = 0xff;
00858 break;
00859 case 0x0010:
00860
00861
00862
00863
00864
00865 sctFilterParams.filter.filter[0] = 0x00;
00866 sctFilterParams.filter.mask[0] = 0xbc;
00867 break;
00868 case 0x0011:
00869
00870
00871
00872
00873
00874 sctFilterParams.filter.filter[0] = 0x02;
00875 sctFilterParams.filter.mask[0] = 0xbb;
00876 break;
00877 case 0x1ffb:
00878
00879
00880 sctFilterParams.filter.filter[0] = 0x80;
00881 sctFilterParams.filter.mask[0] = 0xa0;
00882 break;
00883 default:
00884
00885 sctFilterParams.filter.filter[0] = 0x00;
00886 sctFilterParams.filter.mask[0] = 0x00;
00887 break;
00888 }
00889 sctFilterParams.pid = (__u16) _pid;
00890 sctFilterParams.timeout = 0;
00891 sctFilterParams.flags = DMX_IMMEDIATE_START;
00892
00893 if (ioctl(mux_fd, DMX_SET_FILTER, &sctFilterParams) < 0)
00894 {
00895 VERBOSE(VB_IMPORTANT, LOC_ERR +
00896 "Failed to set \"section\" filter " +
00897 QString("(pid 0x%1) (filter %2)").arg(_pid, 0, 16)
00898 .arg(sctFilterParams.filter.filter[0]));
00899 close(mux_fd);
00900 return false;
00901 }
00902 }
00903
00904 filter_fd = mux_fd;
00905
00906 return true;
00907 }
00908
00909 bool PIDInfo::Close(uint dvb_dev_num)
00910 {
00911 VERBOSE(VB_RECORD, LOC +
00912 QString("Closing filter for pid 0x%1").arg(_pid, 0, 16));
00913
00914 if (!IsOpen())
00915 return false;
00916
00917 int tmp = filter_fd;
00918 filter_fd = -1;
00919
00920 int err = close(tmp);
00921 if (err < 0)
00922 {
00923 VERBOSE(VB_IMPORTANT, LOC + QString("Failed to close mux (pid 0x%1)")
00924 .arg(_pid, 0, 16) + ENO);
00925
00926 return false;
00927 }
00928
00929 return true;
00930 }
00931
00932 void DVBStreamHandler::SetRunning(bool is_running)
00933 {
00934 _running = is_running;
00935 _running_state_changed.wakeAll();
00936 }
00937
00938 PIDPriority DVBStreamHandler::GetPIDPriority(uint pid) const
00939 {
00940 QMutexLocker reading_locker(&_listener_lock);
00941
00942 PIDPriority tmp = kPIDPriorityNone;
00943
00944 for (uint i = 0; i < _stream_data_list.size(); i++)
00945 tmp = max(tmp, _stream_data_list[i]->GetPIDPriority(pid));
00946
00947 return tmp;
00948 }
00949
00950 #if 0
00951
00952
00953
00954 int DVBRecorder::OpenFilterFd(uint pid, int pes_type, uint stream_type)
00955 {
00956 if (_open_pid_filters >= _max_pid_filters)
00957 return -1;
00958
00959
00960 uint bpms = (StreamID::IsVideo(stream_type)) ? 19200 : 500;
00961
00962 uint msec_of_buffering = max(POLL_WARNING_TIMEOUT + 50, 1500);
00963
00964 uint pid_buffer_size = ((bpms*msec_of_buffering + 7) / 8);
00965
00966 pid_buffer_size = ((pid_buffer_size + 4095) / 4096) * 4096;
00967
00968 VERBOSE(VB_RECORD, LOC + QString("Adding pid 0x%1 size(%2)")
00969 .arg(pid,0,16).arg(pid_buffer_size));
00970
00971
00972 QString dvbdev = CardUtil::GetDeviceName(
00973 DVB_DEV_DEMUX, _card_number_option);
00974
00975 int fd_tmp = open(dvbdev.ascii(), O_RDWR);
00976 if (fd_tmp < 0)
00977 {
00978 VERBOSE(VB_IMPORTANT, LOC_ERR + "Could not open demux device." + ENO);
00979 _max_pid_filters = _open_pid_filters;
00980 return -1;
00981 }
00982
00983
00984
00985 uint sz = pid_buffer_size;
00986 uint usecs = msec_of_buffering * 1000;
00987 while (ioctl(fd_tmp, DMX_SET_BUFFER_SIZE, sz) < 0 && sz > 1024*8)
00988 {
00989 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set demux buffer size for "+
00990 QString("pid 0x%1 to %2").arg(pid,0,16).arg(sz) + ENO);
00991
00992 sz /= 2;
00993 sz = ((sz+4095)/4096)*4096;
00994 usecs /= 2;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003 struct dmx_pes_filter_params params;
01004 bzero(¶ms, sizeof(params));
01005 params.input = DMX_IN_FRONTEND;
01006 params.output = DMX_OUT_TS_TAP;
01007 params.flags = DMX_IMMEDIATE_START;
01008 params.pid = pid;
01009 params.pes_type = (dmx_pes_type_t) pes_type;
01010 if (ioctl(fd_tmp, DMX_SET_PES_FILTER, ¶ms) < 0)
01011 {
01012 close(fd_tmp);
01013
01014 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set demux filter." + ENO);
01015 _max_pid_filters = _open_pid_filters;
01016 return -1;
01017 }
01018
01019 _open_pid_filters++;
01020 return fd_tmp;
01021 }
01022 #endif
01023