From 8ef240801bf66e543cdea9df3b32fc09cebcc7e5 Mon Sep 17 00:00:00 2001 From: Felix Domke Date: Fri, 3 Mar 2006 03:13:13 +0000 Subject: [PATCH] enable playback of multifile (split) movies --- lib/base/Makefile.am | 3 +- lib/base/filepush.cpp | 21 +++++-- lib/base/filepush.h | 6 +- lib/base/rawfile.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++ lib/base/rawfile.h | 30 ++++++++++ lib/dvb/dvb.cpp | 17 +++--- lib/dvb/dvb.h | 2 +- lib/dvb/tstools.cpp | 22 +++---- lib/dvb/tstools.h | 5 +- 9 files changed, 205 insertions(+), 33 deletions(-) create mode 100644 lib/base/rawfile.cpp create mode 100644 lib/base/rawfile.h diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am index 877de00d..3741df6e 100644 --- a/lib/base/Makefile.am +++ b/lib/base/Makefile.am @@ -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 + diff --git a/lib/base/filepush.cpp b/lib/base/filepush.cpp index 51b26239..8d116559 100644 --- a/lib/base/filepush.cpp +++ b/lib/base/filepush.cpp @@ -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() diff --git a/lib/base/filepush.h b/lib/base/filepush.h index 75037f66..25257880 100644 --- a/lib/base/filepush.h +++ b/lib/base/filepush.h @@ -5,6 +5,7 @@ #include #include #include +#include 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 m_messagepump; void recvEvent(const int &evt); diff --git a/lib/base/rawfile.cpp b/lib/base/rawfile.cpp new file mode 100644 index 00000000..f5fb91ee --- /dev/null +++ b/lib/base/rawfile.cpp @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +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 index 00000000..5d15e85d --- /dev/null +++ b/lib/base/rawfile.h @@ -0,0 +1,30 @@ +#ifndef __lib_base_rawfile_h +#define __lib_base_rawfile_h + +#include + +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 diff --git a/lib/dvb/dvb.cpp b/lib/dvb/dvb.cpp index 3bceebb0..f8f95276 100644 --- a/lib/dvb/dvb.cpp +++ b/lib/dvb/dvb.cpp @@ -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; diff --git a/lib/dvb/dvb.h b/lib/dvb/dvb.h index 8b0a3595..6209f281 100644 --- a/lib/dvb/dvb.h +++ b/lib/dvb/dvb.h @@ -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 m_cue; diff --git a/lib/dvb/tstools.cpp b/lib/dvb/tstools.cpp index b6792c65..5c99ea60 100644 --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@ -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) { diff --git a/lib/dvb/tstools.h b/lib/dvb/tstools.h index 76128071..b6a275dc 100644 --- a/lib/dvb/tstools.h +++ b/lib/dvb/tstools.h @@ -3,6 +3,7 @@ #include #include +#include /* * 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; -- 2.30.2