I/O priority support with cfq scheduler (needs new kernel patch)
[enigma2.git] / lib / dvb / demux.cpp
index c8e711731323c63f1c524b28f5e064b1601d243e..b0d9b400ac8448e80b0e66a371b08695853c218f 100644 (file)
@@ -25,7 +25,7 @@
 #else
 #include <linux/dvb/dmx.h>
 
-// #define HAVE_ADD_PID
+#define HAVE_ADD_PID
 
 #ifdef HAVE_ADD_PID
 #define DMX_ADD_PID              _IO('o', 51)
@@ -108,6 +108,15 @@ RESULT eDVBDemux::createSectionReader(eMainloop *context, ePtr<iDVBSectionReader
        return res;
 }
 
+RESULT eDVBDemux::createPESReader(eMainloop *context, ePtr<iDVBPESReader> &reader)
+{
+       RESULT res;
+       reader = new eDVBPESReader(this, context, res);
+       if (res)
+               reader = 0;
+       return res;
+}
+
 RESULT eDVBDemux::createTSRecorder(ePtr<iDVBTSRecorder> &recorder)
 {
        if (m_dvr_busy)
@@ -282,6 +291,110 @@ RESULT eDVBSectionReader::connectRead(const Slot1<void,const __u8*> &r, ePtr<eCo
        return 0;
 }
 
+void eDVBPESReader::data(int)
+{
+       while (1)
+       {
+               __u8 buffer[16384];
+               int r;
+               r = ::read(m_fd, buffer, 16384);
+               if (!r)
+                       return;
+               if(r < 0)
+               {
+                       if (errno == EAGAIN) /* ok */
+                               return;
+                       eWarning("ERROR reading PES (fd=%d) - %m", m_fd);
+                       return;
+               }
+
+               if (m_active)
+                       m_read(buffer, r);
+               else
+                       eWarning("PES reader not active");
+       }
+}
+
+eDVBPESReader::eDVBPESReader(eDVBDemux *demux, eMainloop *context, RESULT &res): m_demux(demux)
+{
+       char filename[128];
+       m_fd = m_demux->openDemux();
+       
+       if (m_fd >= 0)
+       {
+               ::ioctl(m_fd, DMX_SET_BUFFER_SIZE, 64*1024);
+               ::fcntl(m_fd, F_SETFL, O_NONBLOCK);
+               m_notifier = new eSocketNotifier(context, m_fd, eSocketNotifier::Read, false);
+               CONNECT(m_notifier->activated, eDVBPESReader::data);
+               res = 0;
+       } else
+       {
+               perror(filename);
+               res = errno;
+       }
+}
+
+DEFINE_REF(eDVBPESReader)
+
+eDVBPESReader::~eDVBPESReader()
+{
+       if (m_notifier)
+               delete m_notifier;
+       if (m_fd >= 0)
+               ::close(m_fd);
+}
+
+RESULT eDVBPESReader::start(int pid)
+{
+       RESULT res;
+       if (m_fd < 0)
+               return -ENODEV;
+
+       m_notifier->start();
+
+#if HAVE_DVB_API_VERSION < 3
+       dmxPesFilterParams flt;
+       
+       flt.pesType = DMX_PES_OTHER;
+#else
+       dmx_pes_filter_params flt;
+       
+       flt.pes_type = DMX_PES_OTHER;
+#endif
+
+       flt.pid     = pid;
+       flt.input   = DMX_IN_FRONTEND;
+       flt.output  = DMX_OUT_TAP;
+       
+       flt.flags   = DMX_IMMEDIATE_START;
+
+       res = ::ioctl(m_fd, DMX_SET_PES_FILTER, &flt);
+       
+       if (res)
+               eWarning("PES filter: DMX_SET_PES_FILTER - %m");
+       if (!res)
+               m_active = 1;
+       return res;
+}
+
+RESULT eDVBPESReader::stop()
+{
+       if (!m_active)
+               return -1;
+
+       m_active=0;
+       ::ioctl(m_fd, DMX_STOP);
+       m_notifier->stop();
+
+       return 0;
+}
+
+RESULT eDVBPESReader::connectRead(const Slot2<void,const __u8*,int> &r, ePtr<eConnection> &conn)
+{
+       conn = new eConnection(this, m_read.connect(r));
+       return 0;
+}
+
 class eDVBRecordFileThread: public eFilePushThread
 {
 public:
@@ -299,7 +412,7 @@ private:
 };
 
 eDVBRecordFileThread::eDVBRecordFileThread()
-       : m_ts_parser(m_stream_info)
+       :eFilePushThread(IOPRIO_CLASS_RT, 7), m_ts_parser(m_stream_info)
 {
        m_current_offset = 0;
 }
@@ -379,7 +492,7 @@ RESULT eDVBTSRecorder::start()
 
        dmx_pes_filter_params flt;
        flt.pes_type = (dmx_pes_type_t)DMX_TAP_TS;
-       flt.pid     = 0x1234; /* FIXME */
+       flt.pid     = (__u16)-1;
        flt.input   = DMX_IN_FRONTEND;
        flt.output  = DMX_OUT_TAP;
        flt.flags   = 0;
@@ -462,6 +575,7 @@ RESULT eDVBTSRecorder::stop()
        m_thread->stop();
        
        close(m_source_fd);
+       m_source_fd = -1;
        
        if (m_target_filename != "")
                m_thread->saveTimingInformation(m_target_filename + ".ap");
@@ -510,10 +624,10 @@ RESULT eDVBTSRecorder::startPID(int pid)
        }
        m_pids[pid] = fd;
 #else
-       eDebug("add pid: %08x", pid);
        if (::ioctl(m_source_fd, DMX_ADD_PID, pid))
                perror("DMX_ADD_PID");
-       eDebug("ok");
+       else
+               m_pids[pid] = 1;
 #endif
        return 0;
 }
@@ -523,9 +637,12 @@ void eDVBTSRecorder::stopPID(int pid)
 #ifndef HAVE_ADD_PID
        if (m_pids[pid] != -1)
                ::close(m_pids[pid]);
-       m_pids[pid] = -1;
 #else
-       if (::ioctl(m_source_fd, DMX_REMOVE_PID, pid))
-               perror("DMX_REMOVE_PID");
+       if (m_pids[pid] != -1)
+       {
+               if (::ioctl(m_source_fd, DMX_REMOVE_PID, pid))
+                       perror("DMX_REMOVE_PID");
+       }
 #endif
+       m_pids[pid] = -1;
 }