2 #include <lib/dvb/record.h>
9 #include <lib/dvb/dvbservice.h>
10 #include <lib/dvb/servicedvb.h>
11 #include <lib/system/file_eraser.h>
12 #include <lib/system/econfig.h>
15 #ifndef DMX_LOW_BITRATE
16 #define DMX_LOW_BITRATE 0x4000
19 #if HAVE_DVB_API_VERSION < 3
21 #define DVR_DEV "/dev/dvb/card0/dvr1"
22 #define DEMUX1_DEV "/dev/dvb/card0/demux1"
24 #include <linux/dvb/dmx.h>
26 #define DVR_DEV "/dev/dvb/adapter0/dvr0"
27 #define DEMUX1_DEV "/dev/dvb/adapter0/demux0"
29 #define DVR_DEV "/dev/dvb/adapter0/dvr1"
30 #define DEMUX1_DEV "/dev/dvb/adapter0/demux1"
34 extern ePermanentTimeshift permanentTimeshift
;
36 static pthread_mutex_t PMTLock
=
37 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
;
39 inline void lock_pmt()
41 pthread_mutex_lock(&PMTLock
);
44 inline void unlock_pmt(void*)
46 pthread_mutex_unlock(&PMTLock
);
49 static int section_length(const unsigned char *buf
)
51 return ((buf
[1] << 8) | buf
[2]) & 0x0fff;
54 static int ts_header(unsigned char *dest
, int pusi
, int pid
, int scrmbl
, int adap
, unsigned int &cc
)
57 dest
[1] = (!!pusi
<< 6) | (pid
>> 8);
59 dest
[3] = (scrmbl
<< 6) | (adap
<< 4) | (cc
++ & 0x0f);
64 static int section2ts(unsigned char *dest
, const unsigned char *src
, int pid
, unsigned int &ccount
)
66 unsigned char *orig
= dest
;
72 for (len
= section_length(src
) + 3; len
> 0; len
-= cplen
) {
73 dest
+= ts_header(dest
, pusi
, pid
, 0, 1, ccount
);
76 *dest
++ = 0x00; /* pointer_field */
77 cplen
= MIN(len
, 183);
81 cplen
= MIN(len
, 184);
84 memcpy(dest
, src
, cplen
);
89 if ((cplen
= (dest
- orig
) % 188)) {
91 memset(dest
, 0xff, cplen
);
98 int eDVBRecorder::flushBuffer()
103 int towrite
= splitsize
-size
>bufptr
? bufptr
: splitsize
-size
;
105 int retrycount
=5; // 5 write retrys..
108 while( written
< towrite
)
110 int wr
= ::write(outfd
, buf
+written
, towrite
-written
);
111 if ( wr
< towrite
) // to less bytes written?
115 if (errno
== EINTR
) continue;
123 written_since_last_sync
+= wr
;
125 permanentTimeshift
.lock
.lock();
126 if (permanentTimeshift
.IsTimeshifting
)
129 eConfig::getInstance()->getKey("/enigma/timeshift/permanentminutes", minutes
);
130 if (permanentTimeshift
.CheckSlice(minutes
))
132 if ( openFile(permanentTimeshift
.getCurrentRecordingSlice()) )
136 permanentTimeshift
.lock
.unlock();
140 permanentTimeshift
.lock
.unlock();
141 if (size
>= splitsize
)
144 if ( openFile(++splits
) ) // file creation failed?
152 retrycount
=5; // 5 write retrys..
153 while ( written
< bufptr
) // must flush remaining bytes from buffer..
155 towrite
=bufptr
-written
;
156 int wr
= ::write(outfd
, buf
+written
, towrite
);
157 if ( wr
< towrite
) // to less bytes written?
161 if (errno
== EINTR
) continue;
168 written_since_last_sync
+= wr
;
174 if (written_since_last_sync
>= 1024*1024) // 1M
176 int toflush
= written_since_last_sync
> 1024*1024 ? 1024*1024 :
177 written_since_last_sync
& ~4095;
178 off64_t dest_pos
= lseek64(outfd
, 0, SEEK_CUR
);
180 posix_fadvise64(outfd
, dest_pos
, toflush
, POSIX_FADV_DONTNEED
);
181 written_since_last_sync
-= toflush
;
189 permanentTimeshift
.lock
.unlock();
190 eDebug("recording write error, maybe disk full");
192 rmessagepump
.send(eDVBRecorderMessage(eDVBRecorderMessage::rWriteError
));
196 void SAHandler(int ptr
)
198 if ( eDVB::getInstance() && eDVB::getInstance()->recorder
)
199 eDVB::getInstance()->recorder
->setWritePatPmtFlag();
203 #ifndef EBUFFEROVERFLOW
204 #define EBUFFEROVERFLOW 769
207 void eDVBRecorder::thread()
209 signal(SIGALRM
, SAHandler
);
211 while (state
== stateRunning
)
213 int rd
= 524144-bufptr
;
216 int r
= ::read(dvrfd
, buf
+bufptr
, rd
);
219 #if HAVE_DVB_API_VERSION < 3
220 // workaround for driver bug....
221 if (r
== -EBUFFEROVERFLOW
)
231 * any other error will immediately cause the same error
232 * when we would call 'read' again with the same arguments
234 eDebug("recording read error %d", errno
);
236 rmessagepump
.send(eDVBRecorderMessage(eDVBRecorderMessage::rWriteError
));
241 /* note that some dvr devices occasionally return EOF, we should ignore that */
245 if ( writePatPmt
) // is set in SAHandler
250 else if ( bufptr
> 524143 )
254 signal(SIGALRM
, SIG_DFL
);
257 void eDVBRecorder::PMTready(int error
)
259 eDebug("eDVBRecorder PMTready");
262 PMT
*pmt
=tPMT
.ready()?tPMT
.getCurrent():0;
265 eDVBCaPMTClientHandler::distribute_gotPMT(recRef
, pmt
);
266 eDebug("UpdatePIDs");
267 // addNewPID(0); // PAT
268 // addNewPID(pmt->pid); // PMT
269 addNewPID(pmt
->PCR_PID
); // PCR
271 for (ePtrList
<PMTEntry
>::iterator
i(pmt
->streams
); i
!= pmt
->streams
.end(); ++i
)
274 switch (i
->stream_type
)
285 for (ePtrList
<Descriptor
>::iterator
it(i
->ES_info
); it
!= i
->ES_info
.end(); ++it
)
294 #ifdef RECORD_TELETEXT
301 #ifdef RECORD_SUBTITLES
302 case DESCR_SUBTITLING
:
313 addNewPID(i
->elementary_PID
, record
==2?DMX_LOW_BITRATE
:0);
315 for (ePtrList
<Descriptor
>::iterator
it(i
->ES_info
); it
!= i
->ES_info
.end(); ++it
)
317 addNewPID(((CADescriptor
*)*it
)->CA_PID
);
322 pthread_cleanup_push( unlock_pmt
, 0 );
324 if (PmtData
) delete [] PmtData
;
325 PmtData
= pmt
->getRAW();
326 pthread_cleanup_pop(1);
333 void eDVBRecorder::gotBackMessage(const eDVBRecorderMessage
&msg
)
337 case eDVBRecorderMessage::rWriteError
:
338 /* emit */ recMessage(recWriteError
);
345 int eDVBRecorder::openFile(int suffix
)
347 eString tfilename
=filename
;
349 tfilename
+=eString().sprintf(".%03d", suffix
);
352 written_since_last_sync
=0;
358 if ( !stat64(tfilename
.c_str(), &s
) )
360 rename(tfilename
.c_str(), (tfilename
+".$$$").c_str() );
361 if (eBackgroundFileEraser::getInstance())
362 eBackgroundFileEraser::getInstance()->erase((tfilename
+".$$$").c_str());
365 #ifdef HAVE_DREAMBOX_HARDWARE
366 outfd
=::open(tfilename
.c_str(), O_CREAT
|O_WRONLY
|O_TRUNC
|O_LARGEFILE
, 0555);
368 if (access("/var/etc/.no_o_sync", R_OK
) == 0)
369 outfd
=::open(tfilename
.c_str(),O_CREAT
|O_WRONLY
|O_TRUNC
|O_LARGEFILE
, 0555);
371 outfd
=::open(tfilename
.c_str(),O_SYNC
|O_CREAT
|O_WRONLY
|O_TRUNC
|O_LARGEFILE
, 0555);
376 eDebug("failed to open DVR file: %s (%m)", tfilename
.c_str());
380 /* turn off kernel caching strategies */
381 posix_fadvise64(outfd
, 0, 0, POSIX_FADV_RANDOM
);
386 void eDVBRecorder::open(const char *_filename
)
388 eDebug("eDVBRecorder::open(%s)", _filename
);
394 int tmp
=1024*1024; // 1G
395 if (eConfig::getInstance()) eConfig::getInstance()->getKey("/extras/record_splitsize", tmp
);
399 splitsize
/=188; // align to 188 bytes..
407 dvrfd
=::open(DVR_DEV
, O_RDONLY
);
410 eDebug("failed to open "DVR_DEV
" (%m)");
416 rmessagepump
.send(eDVBRecorderMessage(eDVBRecorderMessage::rWriteError
));
419 std::pair
<std::set
<eDVBRecorder::pid_t
>::iterator
,bool> eDVBRecorder::addPID(int pid
, int flags
)
421 eDebugNoNewLine("eDVBRecorder::addPID(0x%x)...", pid
);
424 if ( pids
.find(p
) != pids
.end() )
426 eDebug("we already have this pid... skip!");
427 return std::pair
<std::set
<pid_t
>::iterator
, bool>(pids
.end(),false);
429 p
.fd
=::open(DEMUX1_DEV
, O_RDWR
);
432 eDebug("failed to open demux1");
433 return std::pair
<std::set
<pid_t
>::iterator
, bool>(pids
.end(),false);
435 #if HAVE_DVB_API_VERSION < 3
436 dmxPesFilterParams flt
;
437 flt
.pesType
=DMX_PES_OTHER
;
439 dmx_pes_filter_params flt
;
440 flt
.pes_type
=DMX_PES_OTHER
;
443 flt
.input
=DMX_IN_FRONTEND
;
444 flt
.output
=DMX_OUT_TS_TAP
;
447 eDebug("flags %08x", flags
);
449 if (::ioctl(p
.fd
, DMX_SET_PES_FILTER
, &flt
)<0)
451 eDebug("DMX_SET_PES_FILTER failed (for pid %d)", flt
.pid
);
453 return std::pair
<std::set
<pid_t
>::iterator
, bool>(pids
.end(),false);
456 return pids
.insert(p
);
459 void eDVBRecorder::addNewPID(int pid
, int flags
)
467 void eDVBRecorder::validatePIDs()
469 for (std::set
<pid_t
>::iterator
it(pids
.begin()); it
!= pids
.end();)
471 std::set
<pid_t
>::iterator i
= newpids
.find(*it
);
472 if ( i
== newpids
.end() ) // no more existing pid...
473 removePID((it
++)->pid
);
477 for (std::set
<pid_t
>::iterator
it(newpids
.begin()); it
!= newpids
.end(); ++it
)
479 std::pair
<std::set
<pid_t
>::iterator
,bool> newpid
= addPID(it
->pid
, it
->flags
);
482 if ( state
== stateRunning
)
484 if (newpid
.first
->fd
>= 0)
486 if (::ioctl(newpid
.first
->fd
, DMX_START
, 0)<0)
488 eDebug("DMX_START failed (%m)");
495 eDebug("error during add new pid");
500 void eDVBRecorder::removePID(int pid
)
504 std::set
<pid_t
>::iterator pi
=pids
.find(p
);
505 if (pi
!= pids
.end())
510 eDebug("eDVBRecorder::removePID(0x%x)", pid
);
514 void eDVBRecorder::start()
516 if ( state
== stateRunning
)
519 eDebug("eDVBRecorder::start()");
521 state
= stateRunning
;
523 if ( !thread_running() )
525 eDebug("run thread");
529 for (std::set
<pid_t
>::iterator
i(pids
.begin()); i
!= pids
.end(); ++i
)
531 eDebug("starting pidfilter for pid %d", i
->pid
);
535 if (::ioctl(i
->fd
, DMX_START
, 0)<0)
537 eDebug("DMX_START failed");
545 void eDVBRecorder::stop()
547 if ( state
== stateStopped
)
550 eDebug("eDVBRecorder::stop()");
552 state
= stateStopped
;
555 while ( thread_running() && timeout
)
557 usleep(100000); // 2 sec time for thread shutdown
561 for (std::set
<pid_t
>::iterator
i(pids
.begin()); i
!= pids
.end(); ++i
)
563 ::ioctl(i
->fd
, DMX_STOP
, 0);
568 void eDVBRecorder::close()
570 if (state
!= stateStopped
)
573 eDebug("eDVBRecorder::close()");
575 for (std::set
<pid_t
>::iterator
i(pids
.begin()); i
!= pids
.end(); ++i
)
592 if ( thread_running() )
596 eDVBRecorder::eDVBRecorder(PMT
*pmt
,PAT
*pat
)
597 :state(stateStopped
), rmessagepump(eApp
, 1), dvrfd(-1) ,outfd(-1)
598 ,bufptr(0), PmtData(NULL
), PatData(NULL
)
599 ,PmtCC(0), PatCC(0), writePatPmt(true)
601 CONNECT(rmessagepump
.recv_msg
, eDVBRecorder::gotBackMessage
);
602 rmessagepump
.start();
606 CONNECT( tPMT
.tableReady
, eDVBRecorder::PMTready
);
607 tPMT
.start((PMT
*)pmt
->createNext(), DEMUX1_DEV
);
608 PmtData
=pmt
->getRAW();
613 p
.entries
.setAutoDelete(false);
614 p
.version
=pat
->version
;
615 p
.transport_stream_id
=pat
->transport_stream_id
;
616 for (ePtrList
<PATEntry
>::iterator
it(pat
->entries
);
617 it
!= pat
->entries
.end(); ++it
)
619 if ( it
->program_number
== pmt
->program_number
)
621 p
.entries
.push_back(*it
);
630 eDVBRecorder::~eDVBRecorder()
632 if (PatData
) delete [] PatData
;
633 if (PmtData
) delete [] PmtData
;
634 eDVBServiceController
*sapi
= NULL
;
635 if (eDVB::getInstance()) sapi
= eDVB::getInstance()->getServiceAPI();
639 // workaround for faked service types..
640 eServiceReferenceDVB tmp
= sapi
->service
;
641 tmp
.data
[0] = recRef
.getServiceType();
645 eServiceReferenceDVB ref
=sapi
->service
;
646 eDVBCaPMTClientHandler::distribute_leaveService(recRef
);
652 void eDVBRecorder::writeSection(void *data
, int pid
, unsigned int &cc
)
657 __u8 secbuf
[4300]; // with ts overhead...
659 int len
= section2ts(secbuf
, (__u8
*)data
, pid
, cc
);
663 if ( (bufptr
+len
) > 524143 )
666 memcpy(buf
+bufptr
, secbuf
, len
);
671 void eDVBRecorder::PatPmtWrite()
673 //eDebug("PatPmtWrite");
675 writeSection(PatData
, 0, PatCC
);
677 pthread_cleanup_push( unlock_pmt
, 0 );
680 writeSection(PmtData
, pmtpid
, PmtCC
);
681 pthread_cleanup_pop(1);
685 void eDVBRecorder::SetSlice(int slice
)
688 eString oldfilename
=filename
;
690 oldfilename
+=eString().sprintf(".%03d", splits
);
693 eString newfilename
=filename
;
695 newfilename
+=eString().sprintf(".%03d", slice
);
696 eDebug("rename current recording:%s|%s",oldfilename
.c_str(),newfilename
.c_str());
697 ::rename(oldfilename
.c_str(),newfilename
.c_str());
700 #endif //DISABLE_FILE