insert cutmark on EIT change
authorFelix Domke <tmbinc@elitedvb.net>
Sun, 11 Jan 2009 23:31:55 +0000 (00:31 +0100)
committerFelix Domke <tmbinc@elitedvb.net>
Sun, 11 Jan 2009 23:31:55 +0000 (00:31 +0100)
lib/dvb/demux.cpp
lib/dvb/demux.h
lib/dvb/idemux.h
lib/dvb/pvrparse.cpp
lib/dvb/pvrparse.h
lib/service/servicedvbrecord.cpp
lib/service/servicedvbrecord.h

index a0f1c326a9522f768afa375a2a92dbb37194ba5b..810b10a5983604b65f6c4940546666ba43d34d0f 100644 (file)
@@ -405,12 +405,14 @@ public:
        void setTimingPID(int pid);
        
        void saveTimingInformation(const std::string &filename);
+       int getLastPTS(pts_t &pts);
 protected:
        int filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining);
 private:
        eMPEGStreamParserTS m_ts_parser;
        eMPEGStreamInformation m_stream_info;
        off_t m_current_offset;
+       pts_t m_last_pcr; /* very approximate.. */
        int m_pid;
 };
 
@@ -430,6 +432,11 @@ void eDVBRecordFileThread::saveTimingInformation(const std::string &filename)
        m_stream_info.save(filename.c_str());
 }
 
+int eDVBRecordFileThread::getLastPTS(pts_t &pts)
+{
+       return m_ts_parser.getLastPTS(pts);
+}
+
 int eDVBRecordFileThread::filterRecordData(const unsigned char *data, int len, size_t &current_span_remaining)
 {
        m_ts_parser.parseData(m_current_offset, data, len);
@@ -589,6 +596,18 @@ RESULT eDVBTSRecorder::stop()
        return 0;
 }
 
+RESULT eDVBTSRecorder::getCurrentPCR(pts_t &pcr)
+{
+       if (!m_running)
+               return 0;
+       if (!m_thread)
+               return 0;
+               /* XXX: we need a lock here */
+
+                       /* we don't filter PCR data, so just use the last received PTS, which is not accurate, but better than nothing */
+       return m_thread->getLastPTS(pcr);
+}
+
 RESULT eDVBTSRecorder::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &conn)
 {
        conn = new eConnection(this, m_event.connect(event));
index 1a7db9791296190350adbb6f1caf9c580eb1e19b..14501b9859b2d2a9a02c41a33d96c2f0dff0e30b 100644 (file)
@@ -101,7 +101,9 @@ public:
        RESULT setBoundary(off_t max);
        
        RESULT stop();
-       
+
+       RESULT getCurrentPCR(pts_t &pcr);
+
        RESULT connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &conn);
 private:
        RESULT startPID(int pid);
index 2b7508820e61998b9d1b29913b151dcfaa486847..9432afb6002491c328d6b63016d8c297c575356b 100644 (file)
@@ -38,6 +38,8 @@ public:
        virtual RESULT setBoundary(off_t max) = 0;
        
        virtual RESULT stop() = 0;
+
+       virtual RESULT getCurrentPCR(pts_t &pcr) = 0;
        
        enum {
                eventWriteError,
index 1b6cb467c8a25c71cf129a95f1cc335b97db37fb..59313669e421749379ccf5e7ed9521a0159ebc86 100644 (file)
@@ -266,7 +266,7 @@ int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, in
        return 0;
 }
 
-eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0)
+eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0), m_last_pts_valid(0)
 {
 }
 
@@ -313,6 +313,9 @@ int eMPEGStreamParserTS::processPacket(const unsigned char *pkt, off_t offset)
                pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
                pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
                ptsvalid = 1;
+               
+               m_last_pts = pts;
+               m_last_pts_valid = 1;
 
 #if 0          
                int sec = pts / 90000;
@@ -503,3 +506,15 @@ void eMPEGStreamParserTS::setPid(int _pid)
        m_pktptr = 0;
        m_pid = _pid;
 }
+
+int eMPEGStreamParserTS::getLastPTS(pts_t &last_pts)
+{
+       if (!m_last_pts_valid)
+       {
+               last_pts = 0;
+               return -1;
+       }
+       last_pts = m_last_pts;
+       return 0;
+}
+
index 69bb992401ac38aa0603585962e09f19edf91304..94f9f67fddc2590cc492cb31f9c38a746cbe2ea9 100644 (file)
@@ -55,6 +55,7 @@ public:
        eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo);
        void parseData(off_t offset, const void *data, unsigned int len);
        void setPid(int pid);
+       int getLastPTS(pts_t &last_pts);
 private:
        eMPEGStreamInformation &m_streaminfo;
        unsigned char m_pkt[188];
@@ -64,6 +65,8 @@ private:
        int m_pid;
        int m_need_next_packet;
        int m_skip;
+       int m_last_pts_valid;
+       pts_t m_last_pts;
 };
 
 #endif
index b92ee2570675e9c9d6d718d356f74fddc91e302e..c2767e8d42b0b29cd8435365b9791535a3ccf1bf 100644 (file)
@@ -3,11 +3,20 @@
 #include <lib/dvb/epgcache.h>
 #include <fcntl.h>
 
+       /* for cutlist */
+#include <byteswap.h>
+#include <netinet/in.h>
+
+#ifndef BYTE_ORDER
+#error no byte order defined!
+#endif
+
 DEFINE_REF(eDVBServiceRecord);
 
 eDVBServiceRecord::eDVBServiceRecord(const eServiceReferenceDVB &ref): m_ref(ref)
 {
        CONNECT(m_service_handler.serviceEvent, eDVBServiceRecord::serviceEvent);
+       CONNECT(m_event_handler.m_eit_changed, eDVBServiceRecord::gotNewEvent);
        m_state = stateIdle;
        m_want_record = 0;
        m_tuned = 0;
@@ -15,6 +24,7 @@ eDVBServiceRecord::eDVBServiceRecord(const eServiceReferenceDVB &ref): m_ref(ref
        m_error = 0;
        m_streaming = 0;
        m_simulate = false;
+       m_last_event_id = -1;
 }
 
 void eDVBServiceRecord::serviceEvent(int event)
@@ -26,6 +36,22 @@ void eDVBServiceRecord::serviceEvent(int event)
        {
                eDebug("tuned..");
                m_tuned = 1;
+
+                       /* start feeding EIT updates */
+               ePtr<iDVBDemux> m_demux;
+               if (!m_service_handler.getDataDemux(m_demux))
+               {
+                       eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_ref;
+                       int sid = ref.getParentServiceID().get();
+                       if (!sid)
+                               sid = ref.getServiceID().get();
+                       if ( ref.getParentTransportStreamID().get() &&
+                               ref.getParentTransportStreamID() != ref.getTransportStreamID() )
+                               m_event_handler.startOther(m_demux, sid);
+                       else
+                               m_event_handler.start(m_demux, sid);
+               }
+
                if (m_state == stateRecording && m_want_record)
                        doRecord();
                m_event((iRecordableService*)this, evTunedIn);
@@ -145,6 +171,9 @@ RESULT eDVBServiceRecord::stop()
                        ::close(m_target_fd);
                        m_target_fd = -1;
                }
+               
+               saveCutlist();
+               
                m_state = statePrepared;
        } else if (!m_simulate)
                eDebug("(was not recording)");
@@ -398,3 +427,77 @@ void eDVBServiceRecord::recordEvent(int event)
                eDebug("unhandled record event %d", event);
        }
 }
+
+void eDVBServiceRecord::gotNewEvent()
+{
+       ePtr<eServiceEvent> event_now;
+       m_event_handler.getEvent(event_now, 0);
+
+       if (!event_now)
+               return;
+
+       int event_id = event_now->getEventId();
+
+       pts_t p;
+       
+       if (m_record)
+       {
+               if (m_record->getCurrentPCR(p))
+                       eDebug("getting PCR failed!");
+               else
+               {
+                       static int i;
+                       m_event_timestamps[/* event_id*/ ++i] = p;
+                       eDebug("pcr of eit change: %llx", p);
+               }
+       }
+
+       if (event_id != m_last_event_id)
+               eDebug("[eDVBServiceRecord] now running: %s (%d seconds)", event_now->getEventName().c_str(), event_now->getDuration());
+       
+       m_last_event_id = event_id;
+}
+
+void eDVBServiceRecord::saveCutlist()
+{
+                       /* XXX: dupe of eDVBServicePlay::saveCuesheet, refactor plz */
+       std::string filename = m_filename + ".cuts";
+
+       eDVBTSTools tstools;
+       
+       if (tstools.openFile(m_filename.c_str()))
+       {
+               eDebug("[eDVBServiceRecord] saving cutlist failed because tstools failed");
+               return;
+       }
+       
+       FILE *f = fopen(filename.c_str(), "wb");
+
+       if (f)
+       {
+               unsigned long long where;
+               int what;
+
+               for (std::map<int,pts_t>::iterator i(m_event_timestamps.begin()); i != m_event_timestamps.end(); ++i)
+               {
+                       pts_t p = i->second;
+                       off_t offset = 0; // fixme, we need to note down both
+                       if (tstools.fixupPTS(offset, p))
+                       {
+                               eDebug("[eDVBServiceRecord] fixing up PTS failed, not saving");
+                               continue;
+                       }
+                       eDebug("fixed up %llx to %llx (offset %llx)", i->second, p, offset);
+#if BYTE_ORDER == BIG_ENDIAN
+                       where = p;
+#else
+                       where = bswap_64(p);
+#endif
+                       what = htonl(2); /* mark */
+                       fwrite(&where, sizeof(where), 1, f);
+                       fwrite(&what, sizeof(what), 1, f);
+               }
+               fclose(f);
+       }
+       
+}
index 17de033e190b18629f386538ea589d195fe799f0..856f92b3ce9ec63984fc0f73ee0160b0e4ae4140 100644 (file)
@@ -36,6 +36,8 @@ private:
        friend class eServiceFactoryDVB;
        eDVBServiceRecord(const eServiceReferenceDVB &ref);
        
+       eDVBServiceEITHandler m_event_handler;
+       
        eServiceReferenceDVB m_ref;
        
        ePtr<iDVBTSRecorder> m_record;
@@ -44,8 +46,11 @@ private:
        int m_recording, m_tuned, m_error;
        std::set<int> m_pids_active;
        std::string m_filename;
+
+       std::map<int,pts_t> m_event_timestamps;
        int m_target_fd;
        int m_streaming;
+       int m_last_event_id;
        
        int doPrepare();
        int doRecord();
@@ -56,6 +61,10 @@ private:
        
                        /* recorder events */
        void recordEvent(int event);
+
+                       /* eit updates */
+       void gotNewEvent();
+       void saveCutlist();
 };
 
 #endif