enable playback of multifile (split) movies
authorFelix Domke <tmbinc@elitedvb.net>
Fri, 3 Mar 2006 03:13:13 +0000 (03:13 +0000)
committerFelix Domke <tmbinc@elitedvb.net>
Fri, 3 Mar 2006 03:13:13 +0000 (03:13 +0000)
lib/base/Makefile.am
lib/base/filepush.cpp
lib/base/filepush.h
lib/base/rawfile.cpp [new file with mode: 0644]
lib/base/rawfile.h [new file with mode: 0644]
lib/dvb/dvb.cpp
lib/dvb/dvb.h
lib/dvb/tstools.cpp
lib/dvb/tstools.h

index 877de00d6ca2adc8dfeeddac4e9feeba4df5893a..3741df6ebd9dd1bb15a514c165cfa64cb0592350 100644 (file)
@@ -7,4 +7,5 @@ libenigma_base_a_SOURCES = \
        buffer.cpp ebase.cpp eerror.cpp elock.cpp \
        init.cpp message.cpp thread.cpp \
        smartptr.cpp estring.cpp connection.cpp \
-       filepush.cpp encoding.cpp console.cpp
+       filepush.cpp encoding.cpp console.cpp rawfile.cpp
+
index 51b262395633f64954a8f50f2a0bf755a5830504..8d116559aa1f53f5463f4206daf3c06a174a7133 100644 (file)
@@ -40,7 +40,7 @@ void eFilePushThread::thread()
        sigaction(SIGUSR1, &act, 0);
        
        dest_pos = lseek(m_fd_dest, 0, SEEK_CUR);
-       source_pos = lseek(m_fd_source, 0, SEEK_CUR);
+       source_pos = m_raw_source.lseek(0, SEEK_CUR);
        
                /* m_stop must be evaluated after each syscall. */
        while (!m_stop)
@@ -84,7 +84,7 @@ void eFilePushThread::thread()
                        m_sg->getNextSourceSpan(source_pos, bytes_read, current_span_offset, current_span_remaining);
 
                        if (source_pos != current_span_offset)
-                               source_pos = lseek(m_fd_source, current_span_offset, SEEK_SET);
+                               source_pos = m_raw_source.lseek(current_span_offset, SEEK_SET);
                        bytes_read = 0;
                }
                
@@ -98,7 +98,7 @@ void eFilePushThread::thread()
                m_buf_end = 0;
                
                if (maxread)
-                       m_buf_end = read(m_fd_source, m_buffer, maxread);
+                       m_buf_end = m_raw_source.read(m_buffer, maxread);
 
                if (m_buf_end < 0)
                {
@@ -128,7 +128,7 @@ void eFilePushThread::thread()
                        sendEvent(evtEOF);
 #if 0
                        eDebug("FILEPUSH: end-of-file! (currently unhandled)");
-                       if (!lseek(m_fd_source, 0, SEEK_SET))
+                       if (!m_raw_source.lseek(0, SEEK_SET))
                        {
                                eDebug("(looping)");
                                continue;
@@ -151,11 +151,20 @@ void eFilePushThread::thread()
 
 void eFilePushThread::start(int fd_source, int fd_dest)
 {
-       m_fd_source = fd_source;
+       m_raw_source.setfd(fd_source);
        m_fd_dest = fd_dest;
        resume();
 }
 
+int eFilePushThread::start(const char *filename, int fd_dest)
+{
+       if (m_raw_source.open(filename) < 0)
+               return -1;
+       m_fd_dest = fd_dest;
+       resume();
+       return 0;
+}
+
 void eFilePushThread::stop()
 {
        if (!thread_running()) /* FIXME: races */
@@ -172,7 +181,7 @@ void eFilePushThread::pause()
 
 void eFilePushThread::seek(int whence, off_t where)
 {
-       ::lseek(m_fd_source, where, whence);
+       m_raw_source.lseek(where, whence);
 }
 
 void eFilePushThread::resume()
index 75037f6660ff95c35531dc8fcee4503ec6494cfa..25257880d4056c28c00f3b59ffcbda2f87f92b35 100644 (file)
@@ -5,6 +5,7 @@
 #include <libsig_comp.h>
 #include <lib/base/message.h>
 #include <sys/types.h>
+#include <lib/base/rawfile.h>
 
 class iFilePushScatterGather
 {
@@ -20,6 +21,7 @@ public:
        void thread();
        void stop();
        void start(int sourcefd, int destfd);
+       int start(const char *filename, int destfd);
        
        void pause();
        void seek(int whence, off_t where);
@@ -43,9 +45,11 @@ private:
        int m_stop;
        unsigned char m_buffer[65536];
        int m_buf_start, m_buf_end;
-       int m_fd_source, m_fd_dest;
+       int m_fd_dest;
        int m_send_pvr_commit;
        
+       eRawFile m_raw_source;
+       
        eFixedMessagePump<int> m_messagepump;
        
        void recvEvent(const int &evt);
diff --git a/lib/base/rawfile.cpp b/lib/base/rawfile.cpp
new file mode 100644 (file)
index 0000000..f5fb91e
--- /dev/null
@@ -0,0 +1,132 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <lib/base/rawfile.h>
+#include <lib/base/eerror.h>
+
+eRawFile::eRawFile()
+{
+       m_fd = -1;
+       m_splitsize = 0;
+       m_totallength = 0;
+       m_current_offset = 0;
+       m_base_offset = 0;
+       m_nrfiles = 0;
+       m_current_file = 0;
+}
+
+eRawFile::~eRawFile()
+{
+       close();
+}
+
+int eRawFile::open(const char *filename)
+{
+       close();
+       m_basename = filename;
+       scan();
+       m_current_offset = 0;
+       m_fd = ::open(filename, O_RDONLY | O_LARGEFILE);
+       return m_fd;
+}
+
+void eRawFile::setfd(int fd)
+{
+       close();
+       m_nrfiles = 1;
+       m_fd = fd;
+}
+
+off_t eRawFile::lseek(off_t offset, int whence)
+{
+               /* if there is only one file, use the native lseek - the file could be growing! */
+       if (!m_nrfiles)
+               return ::lseek(m_fd, offset, whence);
+       switch (whence)
+       {
+       case SEEK_SET:
+               m_current_offset = offset;
+               break;
+       case SEEK_CUR:
+               m_current_offset += offset;
+               break;
+       case SEEK_END:
+               m_current_offset = m_totallength + offset;
+               break;
+       }
+       if (m_current_offset < 0)
+               m_current_offset = 0;
+       return m_current_offset;
+}
+
+int eRawFile::close()
+{
+       int ret = ::close(m_fd);
+       m_fd = -1;
+       return ret;
+}
+
+ssize_t eRawFile::read(void *buf, size_t count)
+{
+       switchOffset(m_current_offset);
+       int ret = ::read(m_fd, buf, count);
+       if (ret > 0)
+               m_current_offset += ret;
+       return ret;
+}
+
+int eRawFile::valid()
+{
+       return m_fd != -1;
+}
+
+void eRawFile::scan()
+{
+       m_nrfiles = 0;
+       m_totallength = 0;
+       while (m_nrfiles < 1000) /* .999 is the last possible */
+       {
+               int f = openFile(m_nrfiles);
+               if (f < 0)
+                       break;
+               if (!m_nrfiles)
+                       m_splitsize = ::lseek(f, 0, SEEK_END);
+               m_totallength += ::lseek(f, 0, SEEK_END);
+               ::close(f);
+               
+               ++m_nrfiles;
+       }
+       eDebug("found %d files, splitsize: %llx, totallength: %llx", m_nrfiles, m_splitsize, m_totallength);
+}
+
+int eRawFile::switchOffset(off_t off)
+{
+       if (m_splitsize)
+       {
+               int filenr = off / m_splitsize;
+               if (filenr >= m_nrfiles)
+                       filenr = m_nrfiles - 1;
+
+               if (filenr != m_current_file)
+               {
+                       close();
+                       setfd(openFile(filenr));
+                       m_base_offset = m_splitsize * filenr;
+                       eDebug("switched to file %d", filenr);
+               }
+       } else
+               m_base_offset = 0;
+       
+       return ::lseek(m_fd, off - m_base_offset, SEEK_SET) + m_base_offset;
+}
+
+int eRawFile::openFile(int nr)
+{
+       std::string filename = m_basename;
+       if (m_nrfiles)
+       {
+               char suffix[5];
+               snprintf(suffix, 5, ".%03d", nr);
+               filename += suffix;
+       }
+       return ::open(filename.c_str(), O_RDONLY);
+}
diff --git a/lib/base/rawfile.h b/lib/base/rawfile.h
new file mode 100644 (file)
index 0000000..5d15e85
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __lib_base_rawfile_h
+#define __lib_base_rawfile_h
+
+#include <string>
+
+class eRawFile
+{
+public:
+       eRawFile();
+       ~eRawFile();
+       
+       int open(const char *filename);
+       void setfd(int fd);
+       off_t lseek(off_t offset, int whence);
+       int close();
+       ssize_t read(void *buf, size_t count); /* NOTE: you must be able to handle short reads! */
+       off_t length();
+       int valid();
+private:
+       int m_fd;
+       std::string m_basename;
+       off_t m_splitsize, m_totallength, m_current_offset, m_base_offset;
+       int m_nrfiles;
+       void scan();
+       int m_current_file;
+       int switchOffset(off_t off);
+       int openFile(int nr);
+};
+
+#endif
index 3bceebb017c00d605579d02bf91863b8e2c8b302..f8f9527694498e37b77b15a8f8d10cc585bdce5f 100644 (file)
@@ -1008,14 +1008,6 @@ RESULT eDVBChannel::playFile(const char *file)
                return -ENODEV;
        }
        
-       m_pvr_fd_src = open(file, O_RDONLY|O_LARGEFILE);
-       if (m_pvr_fd_src < 0)
-       {
-               eDebug("can't open PVR m_pvr_fd_src file %s (%m)", file);
-               close(m_pvr_fd_dst);
-               return -ENOENT;
-       }
-       
        m_state = state_ok;
        m_stateChanged(this);
        
@@ -1023,7 +1015,13 @@ RESULT eDVBChannel::playFile(const char *file)
        m_pvr_thread->enablePVRCommit(1);
        m_pvr_thread->setScatterGather(this);
 
-       m_pvr_thread->start(m_pvr_fd_src, m_pvr_fd_dst);
+       if (m_pvr_thread->start(file, m_pvr_fd_dst))
+       {
+               delete m_pvr_thread;
+               m_pvr_thread = 0;
+               eDebug("can't open PVR file %s (%m)", file);
+               return -ENOENT;
+       }
        CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
 
        return 0;
@@ -1034,7 +1032,6 @@ void eDVBChannel::stopFile()
        if (m_pvr_thread)
        {
                m_pvr_thread->stop();
-               ::close(m_pvr_fd_src);
                ::close(m_pvr_fd_dst);
                delete m_pvr_thread;
                m_pvr_thread = 0;
index 8b0a3595fd7545d2d1eddb6e213cccaff9383b73..6209f281a2c0ecf217847815ee580c052115756c 100644 (file)
@@ -250,7 +250,7 @@ private:
        eFilePushThread *m_pvr_thread;
        void pvrEvent(int event);
        
-       int m_pvr_fd_src, m_pvr_fd_dst;
+       int m_pvr_fd_dst;
        eDVBTSTools m_tstools;
        
        ePtr<eCueSheet> m_cue;
index b6792c65c48c9e243a370d5bcc019f435b6559b2..5c99ea60c50027d03244d0d6c91b9516bc3d77a3 100644 (file)
@@ -7,7 +7,6 @@
 
 eDVBTSTools::eDVBTSTools()
 {
-       m_fd = -1;
        m_pid = -1;
        m_maxrange = 256*1024;
        
@@ -36,16 +35,14 @@ int eDVBTSTools::openFile(const char *filename)
                m_use_streaminfo = 0;
        }
 
-       m_fd = ::open(filename, O_RDONLY);
-       if (m_fd < 0)
+       if (m_file.open(filename) < 0)
                return -1;
        return 0;
 }
 
 void eDVBTSTools::closeFile()
 {
-       if (m_fd >= 0)
-               ::close(m_fd);
+       m_file.close();
 }
 
 void eDVBTSTools::setSyncPID(int pid)
@@ -64,13 +61,12 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed)
        if (m_use_streaminfo)
                return m_streaminfo.getPTS(offset, pts);
        
-       if (m_fd < 0)
+       if (!m_file.valid() < 0)
                return -1;
 
        offset -= offset % 188;
        
-               // TODO: multiple files!        
-       if (lseek(m_fd, offset, SEEK_SET) < 0)
+       if (m_file.lseek(offset, SEEK_SET) < 0)
                return -1;
 
        int left = m_maxrange;
@@ -78,7 +74,7 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed)
        while (left >= 188)
        {
                unsigned char block[188];
-               if (read(m_fd, block, 188) != 188)
+               if (m_file.read(block, 188) != 188)
                {
                        eDebug("read error");
                        break;
@@ -95,7 +91,7 @@ int eDVBTSTools::getPTS(off_t &offset, pts_t &pts, int fixed)
                                        break;
                                ++i;
                        }
-                       offset = lseek(m_fd, i - 188, SEEK_CUR);
+                       offset = m_file.lseek(i - 188, SEEK_CUR);
                        continue;
                }
                
@@ -204,7 +200,7 @@ int eDVBTSTools::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction
 
 void eDVBTSTools::calcBegin()
 {
-       if (m_fd < 0)   
+       if (!m_file.valid())
                return;
 
        if (!m_begin_valid)
@@ -217,10 +213,10 @@ void eDVBTSTools::calcBegin()
 
 void eDVBTSTools::calcEnd()
 {
-       if (m_fd < 0)   
+       if (!m_file.valid())
                return;
        
-       off_t end = lseek(m_fd, 0, SEEK_END);
+       off_t end = m_file.lseek(0, SEEK_END);
        
        if (abs(end - m_offset_end) > 1*1024*1024)
        {
index 76128071dcca786ecd7749b813535c13dfe2b95d..b6a275dcce108798800b4b960fb183b8bed7874b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <sys/types.h>
 #include <lib/dvb/pvrparse.h>
+#include <lib/base/rawfile.h>
 
 /*
  * Note: we're interested in PTS values, not STC values.
@@ -51,9 +52,11 @@ public:
        int calcBitrate(); /* in bits/sec */
        
 private:
-       int m_fd, m_pid;
+       int m_pid;
        int m_maxrange;
        
+       eRawFile m_file;
+       
        int m_begin_valid, m_end_valid;
        pts_t m_pts_begin, m_pts_end;
        off_t m_offset_begin, m_offset_end;