+ conn = new eConnection(this, read.connect(r));
+ return 0;
+}
+
+class eDVBRecordFileThread: public eFilePushThread
+{
+public:
+ eDVBRecordFileThread();
+ void setTimingPID(int pid);
+
+ void saveTimingInformation(const std::string &filename);
+protected:
+ void filterRecordData(const unsigned char *data, int len);
+private:
+ eMPEGStreamParserTS m_ts_parser;
+ eMPEGStreamInformation m_stream_info;
+ off_t m_current_offset;
+ int m_pid;
+};
+
+eDVBRecordFileThread::eDVBRecordFileThread()
+ : m_ts_parser(m_stream_info)
+{
+ m_current_offset = 0;
+}
+
+void eDVBRecordFileThread::setTimingPID(int pid)
+{
+ m_ts_parser.setPid(pid);
+}
+
+void eDVBRecordFileThread::saveTimingInformation(const std::string &filename)
+{
+ m_stream_info.save(filename.c_str());
+}
+
+void eDVBRecordFileThread::filterRecordData(const unsigned char *data, int len)
+{
+ m_ts_parser.parseData(m_current_offset, data, len);
+
+ m_current_offset += len;
+}
+
+DEFINE_REF(eDVBTSRecorder);
+
+eDVBTSRecorder::eDVBTSRecorder(eDVBDemux *demux): m_demux(demux)
+{
+ m_running = 0;
+ m_target_fd = -1;
+ m_thread = new eDVBRecordFileThread();
+ m_demux->m_dvr_busy = 1;
+}
+
+eDVBTSRecorder::~eDVBTSRecorder()
+{
+ stop();
+ delete m_thread;
+ m_demux->m_dvr_busy = 0;
+}
+
+RESULT eDVBTSRecorder::start()
+{
+ if (m_running)
+ return -1;
+
+ if (m_target_fd == -1)
+ return -2;
+
+ char filename[128];
+#if HAVE_DVB_API_VERSION < 3
+ snprintf(filename, 128, "/dev/dvb/card%d/dvr%d", m_demux->adapter, m_demux->demux);
+#else
+ snprintf(filename, 128, "/dev/dvb/adapter%d/dvr%d", m_demux->adapter, m_demux->demux);
+#endif
+ m_source_fd = ::open(filename, O_RDONLY);
+
+ if (m_source_fd < 0)
+ {
+ eDebug("FAILED to open dvr (%s) in ts recoder (%m)", filename);
+ return -3;
+ }
+
+ m_thread->start(m_source_fd, m_target_fd);
+ m_running = 1;
+
+ for (std::map<int,int>::iterator i(m_pids.begin()); i != m_pids.end(); ++i)
+ startPID(i->first);
+