00001
00002
00003
00004 #include <fcntl.h>
00005 #include <unistd.h>
00006 #include <sys/select.h>
00007 #include <sys/ioctl.h>
00008
00009
00010 #include <QString>
00011
00012
00013 #include "dvbstreamhandler.h"
00014 #include "dvbchannel.h"
00015 #include "dtvsignalmonitor.h"
00016 #include "streamlisteners.h"
00017 #include "mpegstreamdata.h"
00018 #include "cardutil.h"
00019 #include "dvbtypes.h"
00020 #include "diseqc.h"
00021 #include "mythlogging.h"
00022
00023 #define LOC QString("DVBSH(%1): ").arg(_device)
00024
00025 QMap<QString,bool> DVBStreamHandler::_rec_supports_ts_monitoring;
00026 QMutex DVBStreamHandler::_rec_supports_ts_monitoring_lock;
00027
00028 QMap<QString,DVBStreamHandler*> DVBStreamHandler::_handlers;
00029 QMap<QString,uint> DVBStreamHandler::_handlers_refcnt;
00030 QMutex DVBStreamHandler::_handlers_lock;
00031
00032 DVBStreamHandler *DVBStreamHandler::Get(const QString &devname)
00033 {
00034 QMutexLocker locker(&_handlers_lock);
00035
00036 QMap<QString,DVBStreamHandler*>::iterator it =
00037 _handlers.find(devname);
00038
00039 if (it == _handlers.end())
00040 {
00041 _handlers[devname] = new DVBStreamHandler(devname);
00042 _handlers_refcnt[devname] = 1;
00043 }
00044 else
00045 {
00046 _handlers_refcnt[devname]++;
00047 }
00048
00049 return _handlers[devname];
00050 }
00051
00052 void DVBStreamHandler::Return(DVBStreamHandler * & ref)
00053 {
00054 QMutexLocker locker(&_handlers_lock);
00055
00056 QString devname = ref->_device;
00057
00058 QMap<QString,uint>::iterator rit = _handlers_refcnt.find(devname);
00059 if (rit == _handlers_refcnt.end())
00060 return;
00061
00062 if (*rit > 1)
00063 {
00064 ref = NULL;
00065 (*rit)--;
00066 return;
00067 }
00068
00069 QMap<QString,DVBStreamHandler*>::iterator it = _handlers.find(devname);
00070 if ((it != _handlers.end()) && (*it == ref))
00071 {
00072 delete *it;
00073 _handlers.erase(it);
00074 }
00075 else
00076 {
00077 LOG(VB_GENERAL, LOG_ERR,
00078 QString("DVBSH Error: Couldn't find handler for %1") .arg(devname));
00079 }
00080
00081 _handlers_refcnt.erase(rit);
00082 ref = NULL;
00083 }
00084
00085 DVBStreamHandler::DVBStreamHandler(const QString &dvb_device) :
00086 StreamHandler(dvb_device),
00087 _dvr_dev_path(CardUtil::GetDeviceName(DVB_DEV_DVR, _device)),
00088 _allow_retune(false),
00089
00090 _sigmon(NULL),
00091 _dvbchannel(NULL),
00092 _drb(NULL)
00093 {
00094 setObjectName("DVBRead");
00095 }
00096
00097 void DVBStreamHandler::SetRunningDesired(bool desired)
00098 {
00099 if (_drb && _running_desired && !desired)
00100 _drb->Stop();
00101 StreamHandler::SetRunningDesired(desired);
00102 }
00103
00104 void DVBStreamHandler::run(void)
00105 {
00106 RunProlog();
00107 LOG(VB_RECORD, LOG_INFO, LOC + "run(): begin");
00108
00109 if (!SupportsTSMonitoring() && _allow_section_reader)
00110 RunSR();
00111 else
00112 RunTS();
00113
00114 LOG(VB_RECORD, LOG_INFO, LOC + "run(): end");
00115 RunEpilog();
00116 }
00117
00128 void DVBStreamHandler::RunTS(void)
00129 {
00130 QByteArray dvr_dev_path = _dvr_dev_path.toAscii();
00131 int dvr_fd;
00132 for (int tries = 1; ; ++tries)
00133 {
00134 dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
00135 if (dvr_fd >= 0)
00136 break;
00137
00138 LOG(VB_GENERAL, LOG_WARNING, LOC +
00139 QString("Opening DVR device %1 failed : %2")
00140 .arg(_dvr_dev_path).arg(strerror(errno)));
00141
00142 if (tries >= 20 || (errno != EBUSY && errno != EAGAIN))
00143 {
00144 LOG(VB_GENERAL, LOG_ERR, LOC +
00145 QString("Failed to open DVR device %1 : %2")
00146 .arg(_dvr_dev_path).arg(strerror(errno)));
00147 _error = true;
00148 return;
00149 }
00150 usleep(50000);
00151 }
00152
00153 int remainder = 0;
00154 int buffer_size = TSPacket::kSize * 15000;
00155 unsigned char *buffer = new unsigned char[buffer_size];
00156 if (!buffer)
00157 {
00158 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate memory");
00159 close(dvr_fd);
00160 _error = true;
00161 return;
00162 }
00163 memset(buffer, 0, buffer_size);
00164
00165 DeviceReadBuffer *drb = NULL;
00166 if (_needs_buffering)
00167 {
00168 drb = new DeviceReadBuffer(this, true, false);
00169 if (!drb->Setup(_device, dvr_fd))
00170 {
00171 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to allocate DRB buffer");
00172 delete drb;
00173 delete[] buffer;
00174 close(dvr_fd);
00175 _error = true;
00176 return;
00177 }
00178
00179 drb->Start();
00180 }
00181
00182 SetRunning(true, _needs_buffering, false);
00183 {
00184 QMutexLocker locker(&_start_stop_lock);
00185 _drb = drb;
00186 }
00187
00188 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): begin");
00189
00190 fd_set fd_select_set;
00191 FD_ZERO( &fd_select_set);
00192 FD_SET (dvr_fd, &fd_select_set);
00193 while (_running_desired && !_error)
00194 {
00195 RetuneMonitor();
00196 UpdateFiltersFromStreamData();
00197
00198 ssize_t len = 0;
00199
00200 if (drb)
00201 {
00202 len = drb->Read(
00203 &(buffer[remainder]), buffer_size - remainder);
00204
00205
00206 if (drb->IsErrored())
00207 {
00208 LOG(VB_GENERAL, LOG_ERR, LOC + "Device error detected");
00209 _error = true;
00210 }
00211
00212 if (drb->IsEOF())
00213 {
00214 LOG(VB_GENERAL, LOG_ERR, LOC + "Device EOF detected");
00215 _error = true;
00216 }
00217 }
00218 else
00219 {
00220
00221 struct timeval timeout = { 0, 50 * 1000 };
00222 int ret = select(dvr_fd+1, &fd_select_set, NULL, NULL, &timeout);
00223 if (ret == -1 && errno != EINTR)
00224 {
00225 LOG(VB_GENERAL, LOG_ERR, LOC + "select() failed" + ENO);
00226 }
00227 else
00228 {
00229 len = read(dvr_fd, &(buffer[remainder]),
00230 buffer_size - remainder);
00231 }
00232 }
00233
00234 if ((0 == len) || (-1 == len))
00235 {
00236 usleep(100);
00237 continue;
00238 }
00239
00240 len += remainder;
00241
00242 if (len < 10)
00243 {
00244 remainder = len;
00245 continue;
00246 }
00247
00248 _listener_lock.lock();
00249
00250 if (_stream_data_list.empty())
00251 {
00252 _listener_lock.unlock();
00253 continue;
00254 }
00255
00256 StreamDataList::const_iterator sit = _stream_data_list.begin();
00257 for (; sit != _stream_data_list.end(); ++sit)
00258 remainder = sit.key()->ProcessData(buffer, len);
00259
00260 _listener_lock.unlock();
00261
00262 if (remainder > 0 && (len > remainder))
00263 memmove(buffer, &(buffer[len - remainder]), remainder);
00264 }
00265 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "shutdown");
00266
00267 RemoveAllPIDFilters();
00268
00269 {
00270 QMutexLocker locker(&_start_stop_lock);
00271 _drb = NULL;
00272 }
00273
00274 if (drb)
00275 {
00276 if (drb->IsRunning())
00277 drb->Stop();
00278 delete drb;
00279 }
00280
00281 close(dvr_fd);
00282 delete[] buffer;
00283
00284 LOG(VB_RECORD, LOG_INFO, LOC + "RunTS(): " + "end");
00285
00286 SetRunning(false, _needs_buffering, false);
00287 }
00288
00295 void DVBStreamHandler::RunSR(void)
00296 {
00297 int buffer_size = 4192;
00298 unsigned char *buffer = new unsigned char[buffer_size];
00299 if (!buffer)
00300 {
00301 _error = true;
00302 return;
00303 }
00304
00305 SetRunning(true, _needs_buffering, true);
00306
00307 LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): begin");
00308
00309 while (_running_desired && !_error)
00310 {
00311 RetuneMonitor();
00312 UpdateFiltersFromStreamData();
00313
00314 QMutexLocker read_locker(&_pid_lock);
00315
00316 bool readSomething = false;
00317 PIDInfoMap::const_iterator fit = _pid_info.begin();
00318 for (; fit != _pid_info.end(); ++fit)
00319 {
00320 int len = read((*fit)->filter_fd, buffer, buffer_size);
00321 if (len <= 0)
00322 continue;
00323
00324 readSomething = true;
00325
00326 const PESPacket pes = PESPacket::ViewData(buffer);
00327 const PSIPTable psip(pes);
00328
00329 if (psip.SectionSyntaxIndicator())
00330 {
00331 _listener_lock.lock();
00332 StreamDataList::const_iterator sit = _stream_data_list.begin();
00333 for (; sit != _stream_data_list.end(); ++sit)
00334 sit.key()->HandleTables(fit.key() , psip);
00335 _listener_lock.unlock();
00336 }
00337 }
00338
00339 if (!readSomething)
00340 usleep(3000);
00341 }
00342 LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): " + "shutdown");
00343
00344 RemoveAllPIDFilters();
00345
00346 delete[] buffer;
00347
00348 SetRunning(false, _needs_buffering, true);
00349
00350 LOG(VB_RECORD, LOG_INFO, LOC + "RunSR(): " + "end");
00351 }
00352
00353 typedef vector<uint> pid_list_t;
00354
00355 static pid_list_t::iterator find(
00356 const PIDInfoMap &map,
00357 pid_list_t &list,
00358 pid_list_t::iterator begin,
00359 pid_list_t::iterator end, bool find_open)
00360 {
00361 pid_list_t::iterator it;
00362 for (it = begin; it != end; ++it)
00363 {
00364 PIDInfoMap::const_iterator mit = map.find(*it);
00365 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
00366 return it;
00367 }
00368
00369 for (it = list.begin(); it != begin; ++it)
00370 {
00371 PIDInfoMap::const_iterator mit = map.find(*it);
00372 if ((mit != map.end()) && ((*mit)->IsOpen() == find_open))
00373 return it;
00374 }
00375
00376 return list.end();
00377 }
00378
00379 void DVBStreamHandler::CycleFiltersByPriority(void)
00380 {
00381 QMutexLocker writing_locker(&_pid_lock);
00382 QMap<PIDPriority, pid_list_t> priority_queue;
00383 QMap<PIDPriority, uint> priority_open_cnt;
00384
00385 PIDInfoMap::const_iterator cit = _pid_info.begin();
00386 for (; cit != _pid_info.end(); ++cit)
00387 {
00388 PIDPriority priority = GetPIDPriority((*cit)->_pid);
00389 priority_queue[priority].push_back(cit.key());
00390 if ((*cit)->IsOpen())
00391 priority_open_cnt[priority]++;
00392 }
00393
00394 QMap<PIDPriority, pid_list_t>::iterator it = priority_queue.begin();
00395 for (; it != priority_queue.end(); ++it)
00396 sort((*it).begin(), (*it).end());
00397
00398 for (PIDPriority i = kPIDPriorityHigh; i > kPIDPriorityNone;
00399 i = (PIDPriority)((int)i-1))
00400 {
00401 while (priority_open_cnt[i] < priority_queue[i].size())
00402 {
00403
00404
00405
00406 pid_list_t::iterator open = find(
00407 _pid_info, priority_queue[i],
00408 priority_queue[i].begin(), priority_queue[i].end(), true);
00409 if (open == priority_queue[i].end())
00410 open = priority_queue[i].begin();
00411
00412 pid_list_t::iterator closed = find(
00413 _pid_info, priority_queue[i],
00414 open, priority_queue[i].end(), false);
00415
00416 if (closed == priority_queue[i].end())
00417 break;
00418
00419 if (_pid_info[*closed]->Open(_device, _using_section_reader))
00420 {
00421 _open_pid_filters++;
00422 priority_open_cnt[i]++;
00423 continue;
00424 }
00425
00426
00427 bool freed = false;
00428 for (PIDPriority j = (PIDPriority)((int)i - 1);
00429 (j > kPIDPriorityNone) && !freed;
00430 j = (PIDPriority)((int)j-1))
00431 {
00432 if (!priority_open_cnt[j])
00433 continue;
00434
00435 for (uint k = 0; (k < priority_queue[j].size()) && !freed; k++)
00436 {
00437 PIDInfo *info = _pid_info[priority_queue[j][k]];
00438 if (!info->IsOpen())
00439 continue;
00440
00441 if (info->Close(_device))
00442 freed = true;
00443
00444 _open_pid_filters--;
00445 priority_open_cnt[j]--;
00446 }
00447 }
00448
00449 if (freed)
00450 {
00451
00452 if (_pid_info[*closed]->Open(
00453 _device, _using_section_reader))
00454 {
00455 _open_pid_filters++;
00456 priority_open_cnt[i]++;
00457 continue;
00458 }
00459 }
00460
00461
00462
00463 if (_cycle_timer.elapsed() < 1000)
00464 break;
00465
00466 if (!_pid_info[*open]->IsOpen())
00467 break;
00468
00469
00470 bool ok = _pid_info[*open]->Close(_device);
00471 _open_pid_filters--;
00472 priority_open_cnt[i]--;
00473
00474
00475 if (ok && _pid_info[*closed]->
00476 Open(_device, _using_section_reader))
00477 {
00478 _open_pid_filters++;
00479 priority_open_cnt[i]++;
00480 }
00481
00482 break;
00483 }
00484 }
00485
00486 _cycle_timer.start();
00487 }
00488
00489 void DVBStreamHandler::SetRetuneAllowed(
00490 bool allow,
00491 DTVSignalMonitor *sigmon,
00492 DVBChannel *dvbchan)
00493 {
00494 if (allow && sigmon && dvbchan)
00495 {
00496 _allow_retune = true;
00497 _sigmon = sigmon;
00498 _dvbchannel = dvbchan;
00499 }
00500 else
00501 {
00502 _allow_retune = false;
00503 _sigmon = NULL;
00504 _dvbchannel = NULL;
00505 }
00506 }
00507
00508 void DVBStreamHandler::RetuneMonitor(void)
00509 {
00510 if (!_allow_retune)
00511 return;
00512
00513
00514 if (_sigmon->HasFlags(SignalMonitor::kDVBSigMon_WaitForPos))
00515 {
00516 const DiSEqCDevRotor *rotor = _dvbchannel->GetRotor();
00517 if (rotor)
00518 {
00519 bool was_moving, is_moving;
00520 _sigmon->GetRotorStatus(was_moving, is_moving);
00521
00522
00523 if (was_moving && !is_moving)
00524 {
00525 LOG(VB_CHANNEL, LOG_INFO,
00526 LOC + "Retuning for rotor completion");
00527 _dvbchannel->Retune();
00528
00529
00530
00531 }
00532 }
00533 else
00534 {
00535
00536 _sigmon->SetRotorValue(100);
00537 }
00538 }
00539 }
00540
00549 bool DVBStreamHandler::SupportsTSMonitoring(void)
00550 {
00551 const uint pat_pid = 0x0;
00552
00553 {
00554 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00555 QMap<QString,bool>::const_iterator it;
00556 it = _rec_supports_ts_monitoring.find(_device);
00557 if (it != _rec_supports_ts_monitoring.end())
00558 return *it;
00559 }
00560
00561 QByteArray dvr_dev_path = _dvr_dev_path.toAscii();
00562 int dvr_fd = open(dvr_dev_path.constData(), O_RDONLY | O_NONBLOCK);
00563 if (dvr_fd < 0)
00564 {
00565 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00566 _rec_supports_ts_monitoring[_device] = false;
00567 return false;
00568 }
00569
00570 bool supports_ts = false;
00571 if (AddPIDFilter(new DVBPIDInfo(pat_pid)))
00572 {
00573 supports_ts = true;
00574 RemovePIDFilter(pat_pid);
00575 }
00576
00577 close(dvr_fd);
00578
00579 QMutexLocker locker(&_rec_supports_ts_monitoring_lock);
00580 _rec_supports_ts_monitoring[_device] = supports_ts;
00581
00582 return supports_ts;
00583 }
00584
00585 #undef LOC
00586
00587 #define LOC QString("PIDInfo(%1): ").arg(dvb_dev)
00588
00589 bool DVBPIDInfo::Open(const QString &dvb_dev, bool use_section_reader)
00590 {
00591 if (filter_fd >= 0)
00592 {
00593 close(filter_fd);
00594 filter_fd = -1;
00595 }
00596
00597 QString demux_fn = CardUtil::GetDeviceName(DVB_DEV_DEMUX, dvb_dev);
00598 QByteArray demux_ba = demux_fn.toAscii();
00599
00600 LOG(VB_RECORD, LOG_INFO, LOC + QString("Opening filter for pid 0x%1")
00601 .arg(_pid, 0, 16));
00602
00603 int mux_fd = open(demux_ba.constData(), O_RDWR | O_NONBLOCK);
00604 if (mux_fd == -1)
00605 {
00606 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to open demux device %1 "
00607 "for filter on pid 0x%2")
00608 .arg(demux_fn).arg(_pid, 0, 16));
00609 return false;
00610 }
00611
00612 if (!use_section_reader)
00613 {
00614 struct dmx_pes_filter_params pesFilterParams;
00615 memset(&pesFilterParams, 0, sizeof(struct dmx_pes_filter_params));
00616 pesFilterParams.pid = (__u16) _pid;
00617 pesFilterParams.input = DMX_IN_FRONTEND;
00618 pesFilterParams.output = DMX_OUT_TS_TAP;
00619 pesFilterParams.flags = DMX_IMMEDIATE_START;
00620 pesFilterParams.pes_type = DMX_PES_OTHER;
00621
00622 if (ioctl(mux_fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
00623 {
00624 LOG(VB_GENERAL, LOG_ERR, LOC +
00625 QString("Failed to set TS filter (pid 0x%1)")
00626 .arg(_pid, 0, 16));
00627
00628 close(mux_fd);
00629 return false;
00630 }
00631 }
00632 else
00633 {
00634 struct dmx_sct_filter_params sctFilterParams;
00635 memset(&sctFilterParams, 0, sizeof(struct dmx_sct_filter_params));
00636 switch ( (__u16) _pid )
00637 {
00638 case 0x0:
00639 sctFilterParams.filter.filter[0] = 0;
00640 sctFilterParams.filter.mask[0] = 0xff;
00641 break;
00642 case 0x0010:
00643
00644
00645
00646
00647
00648 sctFilterParams.filter.filter[0] = 0x00;
00649 sctFilterParams.filter.mask[0] = 0xbc;
00650 break;
00651 case 0x0011:
00652
00653
00654
00655
00656
00657 sctFilterParams.filter.filter[0] = 0x02;
00658 sctFilterParams.filter.mask[0] = 0xbb;
00659 break;
00660 case 0x1ffb:
00661
00662
00663 sctFilterParams.filter.filter[0] = 0x80;
00664 sctFilterParams.filter.mask[0] = 0xa0;
00665 break;
00666 default:
00667
00668 sctFilterParams.filter.filter[0] = 0x00;
00669 sctFilterParams.filter.mask[0] = 0x00;
00670 break;
00671 }
00672 sctFilterParams.pid = (__u16) _pid;
00673 sctFilterParams.timeout = 0;
00674 sctFilterParams.flags = DMX_IMMEDIATE_START;
00675
00676 if (ioctl(mux_fd, DMX_SET_FILTER, &sctFilterParams) < 0)
00677 {
00678 LOG(VB_GENERAL, LOG_ERR, LOC +
00679 "Failed to set \"section\" filter " +
00680 QString("(pid 0x%1) (filter %2)").arg(_pid, 0, 16)
00681 .arg(sctFilterParams.filter.filter[0]));
00682 close(mux_fd);
00683 return false;
00684 }
00685 }
00686
00687 filter_fd = mux_fd;
00688
00689 return true;
00690 }
00691
00692 bool DVBPIDInfo::Close(const QString &dvb_dev)
00693 {
00694 LOG(VB_RECORD, LOG_INFO, LOC +
00695 QString("Closing filter for pid 0x%1").arg(_pid, 0, 16));
00696
00697 if (!IsOpen())
00698 return false;
00699
00700 int tmp = filter_fd;
00701 filter_fd = -1;
00702
00703 int err = close(tmp);
00704 if (err < 0)
00705 {
00706 LOG(VB_GENERAL, LOG_ERR,
00707 LOC + QString("Failed to close mux (pid 0x%1)")
00708 .arg(_pid, 0, 16) + ENO);
00709
00710 return false;
00711 }
00712
00713 return true;
00714 }
00715
00716 #if 0
00717
00718
00719
00720 int DVBRecorder::OpenFilterFd(uint pid, int pes_type, uint stream_type)
00721 {
00722 if (_open_pid_filters >= _max_pid_filters)
00723 return -1;
00724
00725
00726 uint bpms = (StreamID::IsVideo(stream_type)) ? 19200 : 500;
00727
00728 uint msec_of_buffering = max(POLL_WARNING_TIMEOUT + 50, 1500);
00729
00730 uint pid_buffer_size = ((bpms*msec_of_buffering + 7) / 8);
00731
00732 pid_buffer_size = ((pid_buffer_size + 4095) / 4096) * 4096;
00733
00734 LOG(VB_RECORD, LOG_INFO, LOC + QString("Adding pid 0x%1 size(%2)")
00735 .arg(pid,0,16).arg(pid_buffer_size));
00736
00737
00738 QString dvbdev = CardUtil::GetDeviceName(
00739 DVB_DEV_DEMUX, _card_number_option);
00740 QByteArray dev = dvbdev.toAscii();
00741
00742 int fd_tmp = open(dev.constData(), O_RDWR);
00743 if (fd_tmp < 0)
00744 {
00745 LOG(VB_GENERAL, LOG_ERR, LOC + "Could not open demux device." + ENO);
00746 _max_pid_filters = _open_pid_filters;
00747 return -1;
00748 }
00749
00750
00751
00752 uint sz = pid_buffer_size;
00753 uint usecs = msec_of_buffering * 1000;
00754 while (ioctl(fd_tmp, DMX_SET_BUFFER_SIZE, sz) < 0 && sz > 1024*8)
00755 {
00756 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set demux buffer size for "+
00757 QString("pid 0x%1 to %2").arg(pid,0,16).arg(sz) + ENO);
00758
00759 sz /= 2;
00760 sz = ((sz+4095)/4096)*4096;
00761 usecs /= 2;
00762 }
00763 #if 0
00764 LOG(VB_RECORD, LOG_DEBUG, LOC + "Set demux buffer size for " +
00765 QString("pid 0x%1 to %2,\n\t\t\twhich gives us a %3 msec buffer.")
00766 .arg(pid,0,16).arg(sz).arg(usecs/1000));
00767 #endif
00768
00769
00770 struct dmx_pes_filter_params params;
00771 memset(¶ms, 0, sizeof(params));
00772 params.input = DMX_IN_FRONTEND;
00773 params.output = DMX_OUT_TS_TAP;
00774 params.flags = DMX_IMMEDIATE_START;
00775 params.pid = pid;
00776 params.pes_type = (dmx_pes_type_t) pes_type;
00777 if (ioctl(fd_tmp, DMX_SET_PES_FILTER, ¶ms) < 0)
00778 {
00779 close(fd_tmp);
00780
00781 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to set demux filter." + ENO);
00782 _max_pid_filters = _open_pid_filters;
00783 return -1;
00784 }
00785
00786 _open_pid_filters++;
00787 return fd_tmp;
00788 }
00789 #endif
00790