Screens/LocationBox.py: Get rid of "from Directories import *"
[openblackhole/openblackhole-enigma2.git] / lib / service / servicem2ts.cpp
index a86642c..9900919 100644 (file)
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <lib/base/init_num.h>
 #include <lib/base/init.h>
 #include <lib/dvb/metaparser.h>
@@ -5,24 +7,24 @@
 
 DEFINE_REF(eServiceFactoryM2TS)
 
-class eM2TSFile: public iDataSource
+class eM2TSFile: public iTsSource
 {
        DECLARE_REF(eM2TSFile);
        eSingleLock m_lock;
 public:
-       eM2TSFile(const char *filename, bool cached=false);
+       eM2TSFile(const char *filename);
        ~eM2TSFile();
 
-       // iDataSource
-       off_t lseek(off_t offset, int whence);
+       // iTsSource
        ssize_t read(off_t offset, void *buf, size_t count);
        off_t length();
+       off_t offset();
        int valid();
 private:
-       int m_fd;     /* for uncached */
-       FILE *m_file; /* for cached */
-       off_t m_current_offset, m_length;
-       bool m_cached;
+       int m_sync_offset;
+       int m_fd;
+       off_t m_current_offset;
+       off_t m_length;
        off_t lseek_internal(off_t offset, int whence);
 };
 
@@ -36,10 +38,10 @@ public:
        RESULT getName(const eServiceReference &ref, std::string &name);
        int getLength(const eServiceReference &ref);
        RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
-       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
+       int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
        int getInfo(const eServiceReference &ref, int w);
        std::string getInfoString(const eServiceReference &ref,int w);
-       PyObject *getInfoObject(const eServiceReference &r, int what);
+       long long getFileSize(const eServiceReference &ref);
 };
 
 DEFINE_REF(eStaticServiceM2TSInformation);
@@ -68,14 +70,14 @@ RESULT eStaticServiceM2TSInformation::getName(const eServiceReference &ref, std:
 int eStaticServiceM2TSInformation::getLength(const eServiceReference &ref)
 {
        ASSERT(ref == m_ref);
-       
+
        eDVBTSTools tstools;
-       
+
        struct stat s;
        stat(ref.path.c_str(), &s);
 
        eM2TSFile *file = new eM2TSFile(ref.path.c_str());
-       ePtr<iDataSource> source = file;
+       ePtr<iTsSource> source = file;
 
        if (!source->valid())
                return 0;
@@ -135,15 +137,9 @@ std::string eStaticServiceM2TSInformation::getInfoString(const eServiceReference
        }
 }
 
-PyObject *eStaticServiceM2TSInformation::getInfoObject(const eServiceReference &r, int what)
+long long eStaticServiceM2TSInformation::getFileSize(const eServiceReference &ref)
 {
-       switch (what)
-       {
-       case iServiceInformation::sFileSize:
-               return PyLong_FromLongLong(m_parser.m_filesize);
-       default:
-               Py_RETURN_NONE;
-       }
+       return m_parser.m_filesize;
 }
 
 RESULT eStaticServiceM2TSInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
@@ -166,106 +162,101 @@ RESULT eStaticServiceM2TSInformation::getEvent(const eServiceReference &ref, ePt
 
 DEFINE_REF(eM2TSFile);
 
-eM2TSFile::eM2TSFile(const char *filename, bool cached)
-       :m_lock(false), m_fd(-1), m_file(NULL), m_current_offset(0), m_length(0), m_cached(cached)
+eM2TSFile::eM2TSFile(const char *filename):
+       m_lock(),
+       m_sync_offset(0),
+       m_fd(::open(filename, O_RDONLY | O_LARGEFILE | O_CLOEXEC)),
+       m_current_offset(0),
+       m_length(0)
 {
-       if (!m_cached)
-               m_fd = ::open(filename, O_RDONLY | O_LARGEFILE);
-       else
-               m_file = ::fopen64(filename, "rb");
-       if (valid())
+       if (m_fd != -1)
                m_current_offset = m_length = lseek_internal(0, SEEK_END);
 }
 
 eM2TSFile::~eM2TSFile()
 {
-       if (m_cached)
-       {
-               if (m_file)
-               {
-                       ::fclose(m_file);
-                       m_file = 0;
-               }
-       }
-       else
-       {
-               if (m_fd >= 0)
-                       ::close(m_fd);
-               m_fd = -1;
-       }
-}
-
-off_t eM2TSFile::lseek(off_t offset, int whence)
-{
-       eSingleLocker l(m_lock);
-
-       offset = (offset * 192) / 188;
-       ASSERT(!(offset % 192));
-
-       if (offset != m_current_offset)
-               m_current_offset = lseek_internal(offset, whence);
-
-       return m_current_offset;
+       if (m_fd != -1)
+               ::close(m_fd);
 }
 
 off_t eM2TSFile::lseek_internal(off_t offset, int whence)
 {
        off_t ret;
 
-       if (!m_cached)
-               ret = ::lseek(m_fd, offset, whence);
-       else
-       {
-               if (::fseeko(m_file, offset, whence) < 0)
-                       perror("fseeko");
-               ret = ::ftello(m_file);
-       }
-       return ret <= 0 ? ret : (ret*188)/192;
+       ret = ::lseek(m_fd, offset, whence);
+       return ret <= 0 ? ret : (ret % 192) + (ret*188) / 192;
 }
 
 ssize_t eM2TSFile::read(off_t offset, void *b, size_t count)
 {
        eSingleLocker l(m_lock);
-       unsigned char tmp[192];
+       unsigned char tmp[192*3];
        unsigned char *buf = (unsigned char*)b;
-       size_t rd=0;
 
-       offset = (offset * 192) / 188;
-       ASSERT(!(offset % 192));
-       ASSERT(!(count % 188));
+       size_t rd=0;
+       offset = (offset % 188) + (offset * 192) / 188;
 
-       if (offset != m_current_offset)
+sync:
+       if ((offset+m_sync_offset) != m_current_offset)
        {
-               m_current_offset = lseek_internal(offset, SEEK_SET);
+//             eDebug("[eM2TSFile] seekTo %lld", offset+m_sync_offset);
+               m_current_offset = lseek_internal(offset+m_sync_offset, SEEK_SET);
                if (m_current_offset < 0)
                        return m_current_offset;
        }
 
        while (rd < count) {
                size_t ret;
-               if (!m_cached)
-                       ret = ::read(m_fd, tmp, 192);
-               else
-                       ret = ::fread(tmp, 1, 192, m_file);
+               ret = ::read(m_fd, tmp, 192);
                if (ret < 0 || ret < 192)
                        return rd ? rd : ret;
-               memcpy(buf+rd, tmp+4, 188);
 
-               ASSERT(buf[rd] == 0x47);
+               if (tmp[4] != 0x47)
+               {
+                       if (rd > 0) {
+                               eDebug("[eM2TSFile] short read at pos %lld async!!", m_current_offset);
+                               return rd;
+                       }
+                       else {
+                               int x=0;
+                               ret = ::read(m_fd, tmp+192, 384);
+
+#if 0
+                               eDebugNoNewLineStart("[eM2TSFile] m2ts out of sync at pos %lld, real %lld:", offset + m_sync_offset, m_current_offset);
+                               for (; x < 192; ++x)
+                                       eDebugNoNewLine(" %02x", tmp[x]);
+                               eDebugNoNewLine("\n");
+                               x=0;
+#else
+                               eDebug("[eM2TSFile] m2ts out of sync at pos %lld, real %lld", offset + m_sync_offset, m_current_offset);
+#endif
+                               for (; x < 192; ++x)
+                               {
+                                       if (tmp[x] == 0x47 && tmp[x+192] == 0x47)
+                                       {
+                                               int add_offs = (x - 4);
+                                               eDebug("[eM2TSFile] sync found at pos %d, sync_offset is now %d, old was %d", x, add_offs + m_sync_offset, m_sync_offset);
+                                               m_sync_offset += add_offs;
+                                               goto sync;
+                                       }
+                               }
+                       }
+               }
+
+               memcpy(buf+rd, tmp+4, 188);
 
                rd += 188;
                m_current_offset += 188;
        }
 
+       m_sync_offset %= 188;
+
        return rd;
 }
 
 int eM2TSFile::valid()
 {
-       if (!m_cached)
-               return m_fd != -1;
-       else
-               return !!m_file;
+       return m_fd != -1;
 }
 
 off_t eM2TSFile::length()
@@ -273,6 +264,11 @@ off_t eM2TSFile::length()
        return m_length;
 }
 
+off_t eM2TSFile::offset()
+{
+       return m_current_offset;
+}
+
 eServiceFactoryM2TS::eServiceFactoryM2TS()
 {
        ePtr<eServiceCenter> sc;
@@ -289,7 +285,7 @@ eServiceFactoryM2TS::eServiceFactoryM2TS()
 eServiceFactoryM2TS::~eServiceFactoryM2TS()
 {
        ePtr<eServiceCenter> sc;
-       
+
        eServiceCenter::getPrivInstance(sc);
        if (sc)
                sc->removeServiceFactory(eServiceFactoryM2TS::id);
@@ -330,9 +326,9 @@ eServiceM2TS::eServiceM2TS(const eServiceReference &ref)
 {
 }
 
-ePtr<iDataSource> eServiceM2TS::createDataSource(eServiceReferenceDVB &ref)
+ePtr<iTsSource> eServiceM2TS::createTsSource(eServiceReferenceDVB &ref, int packetsize)
 {
-       ePtr<iDataSource> source = new eM2TSFile(ref.path.c_str());
+       ePtr<iTsSource> source = new eM2TSFile(ref.path.c_str());
        return source;
 }