diff -Nru vdr-1.3.14-vanilla/Makefile vdr-1.3.14-subtitles/Makefile --- vdr-1.3.14-vanilla/Makefile 2004-10-16 14:58:14.000000000 +0300 +++ vdr-1.3.14-subtitles/Makefile 2004-10-24 18:38:51.218767352 +0300 @@ -40,6 +40,8 @@ skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\ timers.o tools.o transfer.o vdr.o videodir.o +OBJS += osdcontroller.o rcontroller.o dvbsub.o vdrttxtsubshooks.o + FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1 OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1 SMLFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-1 diff -Nru vdr-1.3.14-vanilla/dvbplayer.c vdr-1.3.14-subtitles/dvbplayer.c --- vdr-1.3.14-vanilla/dvbplayer.c 2004-10-23 15:39:35.000000000 +0300 +++ vdr-1.3.14-subtitles/dvbplayer.c 2004-10-24 18:38:51.221766896 +0300 @@ -14,6 +14,9 @@ #include "ringbuffer.h" #include "thread.h" #include "tools.h" +#include "rcontroller.h" +#include "dvbsub.h" +#include "vdrttxtsubshooks.h" // --- cBackTrace ---------------------------------------------------------- @@ -321,6 +324,12 @@ int l = b[i + 4] * 256 + b[i + 5] + 6; switch (c) { case 0xBD: // dolby + if (RecordingPatch::RecordingController.isExtendedPacket( b + i , l ) ) { + break; + } + if (b[i + 8] == 0x24 && b[i + 45] >= 0x10 && b[i + 45] < 0x20) { + break; // run these through the ring buffer to get somewhat correct timing for the subtitles + } if (Except) PlayAudio(&b[i], l); // continue with deleting the data - otherwise it disturbs DVB replay @@ -347,6 +356,35 @@ } } +static void StripExtendedPackets(uchar *b, int Length) +{ + for (int i = 0; i < Length - 6; i++) { + if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) { + uchar c = b[i + 3]; + int l = b[i + 4] * 256 + b[i + 5] + 6; + switch (c) { + case 0xBD: // dolby + { + if (RecordingPatch::RecordingController.isExtendedPacket(b + i , l)) + RecordingPatch::RecordingController.Receive( b + i, l ); + // EBU Teletext data, ETSI EN 300 472 + if (b[i + 8] == 0x24 && b[i + 45] >= 0x10 && b[i + 45] < 0x20) + cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData(&b[i], l); + // continue with deleting the data - otherwise it disturbs DVB replay + int n = l; + for (int j = i; j < Length && n--; j++) + b[j] = 0x00; + } + break; + default: + break; + } + if (l) + i += l - 1; // the loop increments, too! + } + } +} + bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset) { if (FileNumber > 0) @@ -522,6 +560,8 @@ StripAudioPackets(p, pc, AudioTrack); } } + if (p) + StripExtendedPackets(p, pc); if (p) { int w = PlayVideo(p, pc); if (w > 0) { diff -Nru vdr-1.3.14-vanilla/dvbsub.c vdr-1.3.14-subtitles/dvbsub.c --- vdr-1.3.14-vanilla/dvbsub.c 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/dvbsub.c 2004-10-24 18:38:51.260760968 +0300 @@ -0,0 +1,18 @@ +#include "dvbsub.h" + +cDvbSubtitlesRecording DvbSubtitlesRecording; + +cDvbSubtitlesRecording::cDvbSubtitlesRecording(){ + query=0; +} +void cDvbSubtitlesRecording::Subscribe(iPidQuery* listener){ + query = listener ; +} + +int cDvbSubtitlesRecording::GetPidByChannel( int DevNr, const cChannel* Channel, int Language ) +{ + if (query) + return query->GetPidByChannel( DevNr, Channel,Language ); + else + return 0; +} diff -Nru vdr-1.3.14-vanilla/dvbsub.h vdr-1.3.14-subtitles/dvbsub.h --- vdr-1.3.14-vanilla/dvbsub.h 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/dvbsub.h 2004-10-24 18:38:51.262760664 +0300 @@ -0,0 +1,21 @@ +class cChannel; +class cRecordControl; + +class iPidQuery +{ +public: + virtual int GetPidByChannel( int DevNr, const cChannel* Channel, int Language ) = 0; +}; +class cDvbSubtitlesRecording +{ +public: + cDvbSubtitlesRecording(); + void Subscribe(iPidQuery* listener); +private: + friend class cRecordControl; + int GetPidByChannel( int DevNr, const cChannel* Channel, int Language ); + iPidQuery* query; +}; + +extern cDvbSubtitlesRecording DvbSubtitlesRecording; + diff -Nru vdr-1.3.14-vanilla/menu.c vdr-1.3.14-subtitles/menu.c --- vdr-1.3.14-vanilla/menu.c 2004-10-17 13:28:27.000000000 +0300 +++ vdr-1.3.14-subtitles/menu.c 2004-10-24 18:38:51.268759752 +0300 @@ -28,6 +28,8 @@ #include "themes.h" #include "timers.h" #include "transfer.h" +#include "vdrttxtsubshooks.h" +#include "dvbsub.h" #include "videodir.h" #define MENUTIMEOUT 120 // seconds @@ -2771,8 +2773,13 @@ isyslog("record %s", fileName); if (MakeDirs(fileName, true)) { const cChannel *ch = timer->Channel(); - recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2()); + int SubPid1 = DvbSubtitlesRecording.GetPidByChannel( device->DeviceNumber(), ch, 1 ); + int SubPid2 = DvbSubtitlesRecording.GetPidByChannel( device->DeviceNumber(), ch, 2 ); + cTtxtSubsRecorderBase *subsRecorder = cVDRTtxtsubsHookListener::Hook()->NewTtxtSubsRecorder(device, ch); + recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2(), subsRecorder, SubPid1, SubPid2); if (device->AttachReceiver(recorder)) { + if (subsRecorder) + subsRecorder->DeviceAttach(); Recording.WriteSummary(); cStatus::MsgRecording(device, Recording.Name()); if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() diff -Nru vdr-1.3.14-vanilla/osd.c vdr-1.3.14-subtitles/osd.c --- vdr-1.3.14-vanilla/osd.c 2004-10-16 13:31:34.000000000 +0300 +++ vdr-1.3.14-subtitles/osd.c 2004-10-24 18:38:51.271759296 +0300 @@ -15,6 +15,8 @@ #include #include #include "tools.h" +#include "osdcontroller.h" +#include "vdrttxtsubshooks.h" // --- cPalette -------------------------------------------------------------- @@ -574,6 +576,7 @@ // --- cOsd ------------------------------------------------------------------ bool cOsd::isOpen = false; +bool cOsd::niosd = false; cOsd::cOsd(int Left, int Top) { @@ -593,6 +596,9 @@ delete bitmaps[i]; delete savedRegion; isOpen = false; + if (!niosd) + NonInteractiveOsdPatch::OsdController.Show(); + cVDRTtxtsubsHookListener::Hook()->ShowOSD(); } cBitmap *cOsd::GetBitmap(int Area) @@ -714,8 +720,13 @@ osdProvider = NULL; } -cOsd *cOsdProvider::NewOsd(int Left, int Top) +cOsd *cOsdProvider::NewOsd(int Left, int Top, bool dontHide) { + if (!dontHide) + NonInteractiveOsdPatch::OsdController.Hide(); + cOsd::niosd = dontHide; + // OSD_HOOK_2 - Information to Checkpatch.sh + cVDRTtxtsubsHookListener::Hook()->HideOSD(); if (cOsd::IsOpen()) esyslog("ERROR: attempt to open OSD while it is already open - using dummy OSD!"); else if (osdProvider) diff -Nru vdr-1.3.14-vanilla/osd.h vdr-1.3.14-subtitles/osd.h --- vdr-1.3.14-vanilla/osd.h 2004-10-16 13:33:44.000000000 +0300 +++ vdr-1.3.14-subtitles/osd.h 2004-10-24 18:38:51.273758992 +0300 @@ -215,6 +215,8 @@ cBitmap *bitmaps[MAXOSDAREAS]; int numBitmaps; int left, top, width, height; +public: + static bool niosd; protected: cOsd(int Left, int Top); ///< Initializes the OSD with the given coordinates. @@ -327,7 +329,7 @@ cOsdProvider(void); //XXX maybe parameter to make this one "sticky"??? (frame-buffer etc.) virtual ~cOsdProvider(); - static cOsd *NewOsd(int Left, int Top); + static cOsd *NewOsd(int Left, int Top, bool dontHide = false); ///< Returns a pointer to a newly created cOsd object, which will be located ///< at the given coordinates. When the cOsd object is no longer needed, the ///< caller must delete it. If the OSD is already in use, or there is no OSD diff -Nru vdr-1.3.14-vanilla/osdcontroller.c vdr-1.3.14-subtitles/osdcontroller.c --- vdr-1.3.14-vanilla/osdcontroller.c 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/osdcontroller.c 2004-10-24 18:38:51.274758840 +0300 @@ -0,0 +1,132 @@ +#include "osdcontroller.h" +#include "thread.h" + +namespace NonInteractiveOsdPatch +{ + + class cListenerListObject : public cListObject + { + public: + cListenerListObject(int priority, cOsdListener* listener); + bool operator< (const cListObject &ListObject); + + int iPriority; + cOsdListener* iListener; + }; + + cListenerListObject::cListenerListObject(int priority, cOsdListener* listener) + : cListObject(),iPriority(priority), iListener( listener ) + { + } + bool cListenerListObject::operator< (const cListObject &ListObject) + { + + return iPriority > ((cListenerListObject *)&ListObject)->iPriority; + } + + cOsdController OsdController; + + cOsdController::cOsdController() + : iShowing( false ) + { + iMutex = new cMutex(); + iListeners = new cList; + } + + cOsdController::~cOsdController() + { + delete iListeners; + delete iMutex; + } + + bool cOsdController::Subscribe( int priority, cOsdListener* listener ) + { + + cMutexLock( iMutex ); + if ( !listener ) + return false; + + for ( cListenerListObject* llo = iListeners->First(); + llo; llo = iListeners->Next(llo)) + { + // check for duplicates + if ( llo->iListener == listener ) + return false; + } + + cListenerListObject *lo = new cListenerListObject(priority, listener); + iListeners->Add( lo ); + iListeners->Sort(); + + // Give osd to the new listener if it has higher priority + // than the current one + if ( iShowing && !iCurrent ) + { + listener->Show(); + iCurrent = lo; + } + else if ( iShowing && iCurrent && iCurrent->iPriority < priority ) + { + iCurrent->iListener->Hide(); + ShowHighest(); + + } + + return true; + } + + void cOsdController::Unsubscribe( cOsdListener* listener ) + { + cMutexLock( iMutex ); + if ( !listener ) + return; + + for ( cListenerListObject* llo = iListeners->First(); + llo; llo = iListeners->Next(llo)) + { + + if ( llo->iListener == listener ) + { + iListeners->Del( llo, true ); + if ( iShowing && llo == iCurrent ) + { + listener->Hide(); + ShowHighest(); + } + break; + } + } + + } + + void cOsdController::Show() + { + cMutexLock( iMutex ); + iShowing = true; + ShowHighest(); + + } + + void cOsdController::Hide() + { + cMutexLock( iMutex ); + iShowing = false; + if ( iCurrent ) + iCurrent->iListener->Hide(); + iCurrent = NULL; + } + + void cOsdController::ShowHighest() + { + + cListenerListObject* llo = iListeners->First(); + + if ( llo ) + llo->iListener->Show(); + + iCurrent = llo; + + } + + +} diff -Nru vdr-1.3.14-vanilla/osdcontroller.h vdr-1.3.14-subtitles/osdcontroller.h --- vdr-1.3.14-vanilla/osdcontroller.h 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/osdcontroller.h 2004-10-24 18:38:51.275758688 +0300 @@ -0,0 +1,50 @@ +#ifndef __OSDCONTROLLER_H +#define __OSDCONTROLLER_H + +#include "tools.h" + + +#define MAX_OSD_LISTENERS 10 + +class cOsd; +class cMutex; + +namespace NonInteractiveOsdPatch +{ + + class cOsdListener + { + + public: + virtual void Show() = 0; + virtual void Hide() = 0; + + }; + + class cListenerListObject; + + class cOsdController + { + public: + cOsdController(); + ~cOsdController(); + bool Subscribe( int priority, cOsdListener* listener ); + void Unsubscribe( cOsdListener* listner ); + + private: + friend class cOsdProvider; + friend class cOsd; + void Show(); + void Hide(); + void ShowHighest(); + + bool iShowing; + cMutex* iMutex; + cListenerListObject* iCurrent; + cList* iListeners; + + }; + extern cOsdController OsdController; + +} +#endif diff -Nru vdr-1.3.14-vanilla/rcontroller.c vdr-1.3.14-subtitles/rcontroller.c --- vdr-1.3.14-vanilla/rcontroller.c 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/rcontroller.c 2004-10-24 18:38:51.277758384 +0300 @@ -0,0 +1,82 @@ +#include +#include "rcontroller.h" +#include +#define PRIVATE_STREAM_1 0xBD +#define PES_EXTENSION_MASK 0x01 +#define PES_EXTENSION2_MASK 0x81 +namespace RecordingPatch { + + cRecordingController RecordingController; + + // Returns the Data Identifier or 0 if not enough data + unsigned char GetDataIdentifier( unsigned char* Data, int Length ) + { + if ( Length < 9 ) + return 0; + int hlength = Data[8]; + if ( Length < 9 + hlength ) + return 0; + return Data[ 9 + hlength - 1 ]; + } + + cRecordingController::cRecordingController() + { + listeners = (iRecordingPlugin**)malloc( sizeof(iRecordingPlugin*)*256 ); + for (int i=0; i < 256; i++) + listeners[i] = 0; + } + + cRecordingController::~cRecordingController() + { + free (listeners); + } + void cRecordingController::Subscribe(unsigned char DataIdentifier, iRecordingPlugin* plugin) + { + if ( listeners[ DataIdentifier ] == 0 ) + listeners[ DataIdentifier ] = plugin; + } + void cRecordingController::Unsubscribe(unsigned char DataIdentifier, iRecordingPlugin* plugin) + { + + if ( listeners[ DataIdentifier ] != 0 && listeners[ DataIdentifier ] == plugin ) + listeners[ DataIdentifier ] = 0; + + } + + bool cRecordingController::isExtendedPacket(unsigned char* Data, int Length) + { + if ( Length < 9 ) + return false; + if ( Data[0] != 0x00 || Data[1] != 0x00 || Data[2] != 0x01 ) + return false; + if ( Data[3] != PRIVATE_STREAM_1 ) + return false; + + if ( !(Data[7] & PES_EXTENSION_MASK) ) + return false; + + int hlength = Data[8]; + + if ( ( Data[ 9 + hlength - 3 ] & PES_EXTENSION2_MASK ) == 1 + && Data[ 9 + hlength - 2 ] == 0x81) + return true; + + return false; + + } + + + void cRecordingController::Receive(unsigned char* Data, int Length) + { + if ( isExtendedPacket( Data, Length ) ) + { + unsigned char DataIdentifier = GetDataIdentifier( Data, Length ); + if ( listeners[ DataIdentifier ] != 0 ) + listeners[ DataIdentifier ] -> Receive( DataIdentifier, Data, Length ); + } + else + { + } + } + +} // namespace diff -Nru vdr-1.3.14-vanilla/rcontroller.h vdr-1.3.14-subtitles/rcontroller.h --- vdr-1.3.14-vanilla/rcontroller.h 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/rcontroller.h 2004-10-24 18:38:51.278758232 +0300 @@ -0,0 +1,28 @@ +#ifndef __RECORDING_PATCH_OSD_CONTROLLER_H +#define __RECORDING_PATCH_OSD_CONTROLLER_H + +class cDvbPlayer; +namespace RecordingPatch { + + class iRecordingPlugin + { + public: + virtual void Receive(unsigned char DataIdentifier, unsigned char* Data, int Length) = 0; + }; + + class cRecordingController + { + public: + cRecordingController(); + ~cRecordingController(); + void Subscribe(unsigned char DataIdentifier, iRecordingPlugin* plugin); + void Unsubscribe(unsigned char DataIdentifer, iRecordingPlugin* plugin); + bool isExtendedPacket(unsigned char* Data, int Length); + void Receive(unsigned char* Data, int Length); + private: + iRecordingPlugin** listeners; + }; + extern cRecordingController RecordingController; + +} +#endif diff -Nru vdr-1.3.14-vanilla/recorder.c vdr-1.3.14-subtitles/recorder.c --- vdr-1.3.14-vanilla/recorder.c 2004-10-16 12:23:01.000000000 +0300 +++ vdr-1.3.14-subtitles/recorder.c 2004-10-24 18:38:51.280757928 +0300 @@ -10,6 +10,7 @@ #include #include #include +#include #include "recorder.h" #define RECORDERBUFSIZE MEGABYTE(5) @@ -23,6 +24,7 @@ class cFileWriter : public cThread { private: + cTtxtSubsRecorderBase *ttxtSubsRecorder; cRemux *remux; cFileName *fileName; cIndexFile *index; @@ -36,13 +38,14 @@ protected: virtual void Action(void); public: - cFileWriter(const char *FileName, cRemux *Remux); + cFileWriter(const char *FileName, cRemux *Remux, cTtxtSubsRecorderBase *tsr); virtual ~cFileWriter(); }; -cFileWriter::cFileWriter(const char *FileName, cRemux *Remux) +cFileWriter::cFileWriter(const char *FileName, cRemux *Remux, cTtxtSubsRecorderBase *tsr) :cThread("file writer") { + ttxtSubsRecorder = tsr; active = false; fileName = NULL; remux = Remux; @@ -67,6 +70,8 @@ Cancel(3); delete index; delete fileName; + if (ttxtSubsRecorder) + delete ttxtSubsRecorder; } bool cFileWriter::RunningLowOnDiskSpace(void) @@ -113,6 +118,16 @@ } fileSize += Count; remux->Del(Count); + // not sure if the pictureType test is needed, but it seems we can get + // incomplete pes packets from remux if we are not getting pictures? + if (ttxtSubsRecorder && pictureType != NO_PICTURE) { + uint8_t *subsp; + size_t len; + if (ttxtSubsRecorder->GetPacket(&subsp, &len)) { + safe_write(recordFile, subsp, len); + fileSize += len; + } + } } else break; @@ -127,8 +142,8 @@ active = false; } -cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2) -:cReceiver(Ca, Priority, Setup.RecordDolbyDigital ? 5 : 3, VPid, APid1, APid2, DPid1, DPid2) +cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2, cTtxtSubsRecorderBase *tsr, int SubPid1, int SubPid2) +:cReceiver(Ca, Priority, Setup.RecordDolbyDigital ? 7 : 5, VPid, APid1, APid2, SubPid1, SubPid2, DPid1, DPid2) ,cThread("recording") { active = false; @@ -139,8 +154,8 @@ ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder"); ringBuffer->SetTimeouts(0, 100); - remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true); - writer = new cFileWriter(FileName, remux); + remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2, true, SubPid1, SubPid2); + writer = new cFileWriter(FileName, remux, tsr); } cRecorder::~cRecorder() diff -Nru vdr-1.3.14-vanilla/recorder.h vdr-1.3.14-subtitles/recorder.h --- vdr-1.3.14-vanilla/recorder.h 2004-10-10 14:22:38.000000000 +0300 +++ vdr-1.3.14-subtitles/recorder.h 2004-10-24 18:38:51.281757776 +0300 @@ -15,6 +15,7 @@ #include "remux.h" #include "ringbuffer.h" #include "thread.h" +#include "vdrttxtsubshooks.h" class cFileWriter; @@ -29,7 +30,7 @@ virtual void Receive(uchar *Data, int Length); virtual void Action(void); public: - cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2); + cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2, cTtxtSubsRecorderBase *tsr, int SubPid1 = 0, int SubPid2 = 0); // Creates a new recorder that requires conditional access Ca, has // the given Priority and will record the given PIDs into the file FileName. virtual ~cRecorder(); diff -Nru vdr-1.3.14-vanilla/remux.c vdr-1.3.14-subtitles/remux.c --- vdr-1.3.14-vanilla/remux.c 2004-10-24 12:25:33.000000000 +0300 +++ vdr-1.3.14-subtitles/remux.c 2004-10-24 18:38:51.284757320 +0300 @@ -42,6 +42,9 @@ //pts_dts flags #define PTS_ONLY 0x80 +#define PES_EXTENSION 0x01 +#define PES_EXTENSION2 0x01 + #define TS_SIZE 188 #define PID_MASK_HI 0x1F #define CONT_CNT_MASK 0x0F @@ -83,6 +86,8 @@ int tsErrors; int ccErrors; int ccCounter; + uint8_t dataIdentifier; + static uint8_t eHeadr[]; static uint8_t headr[]; void store(uint8_t *Data, int Count); void reset_ipack(void); @@ -90,15 +95,16 @@ void write_ipack(const uint8_t *Data, int Count); void instant_repack(const uint8_t *Buf, int Count); public: - cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00); + cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid = 0x00, uint8_t DataIndentifier = 0x00); ~cTS2PES(); void ts_to_pes(const uint8_t *Buf); // don't need count (=188) void Clear(void); }; +uint8_t cTS2PES::eHeadr[] = { 0x01, 0x81 }; // extension header uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 }; -cTS2PES::cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid) +cTS2PES::cTS2PES(cRingBufferLinear *ResultBuffer, int Size, uint8_t AudioCid, uint8_t DataIdentifier) { resultBuffer = ResultBuffer; size = Size; @@ -107,6 +113,7 @@ tsErrors = 0; ccErrors = 0; ccCounter = -1; + dataIdentifier = DataIdentifier; if (!(buf = MALLOC(uint8_t, size))) esyslog("Not enough memory for ts_transform"); @@ -159,10 +166,21 @@ switch (mpeg) { case 2: + if ( dataIdentifier == 0 ) { buf[6] = 0x80; buf[7] = 0x00; buf[8] = 0x00; count = 9; + } + else { + buf[6] = 0x80; + buf[7] = 0x01; // pes_extension_flag == 1 + buf[8] = 0x03; // pes_header_data_length == 3 + buf[9] = 0x01; // pes_extension_flag_2=1 + buf[10]= 0x81; // marker_bit=1, pes_extension_data_length=1 + buf[11] = dataIdentifier; + count = 12; + } break; case 1: buf[6] = 0x0F; @@ -273,12 +291,21 @@ case 7: if (!done && mpeg == 2) { flag2 = Buf[c++]; + if ( dataIdentifier && (flag2 & PES_EXTENSION) ) { + esyslog("Error: cannot add extension to pes packet. Disabling."); + dataIdentifier = 0; + } + else { + flag2 |= PES_EXTENSION; + } found++; } break; case 8: if (!done && mpeg == 2) { hlength = Buf[c++]; + if ( dataIdentifier ) + hlength += 3; found++; } break; @@ -315,6 +342,20 @@ return; } + // Write header one byte at a time + // Remove from hlength size of our header (3) + if ( dataIdentifier ) { + while (c < Count && (found < (hlength + 9-3)) && found < plength+6) { + write_ipack(Buf + c, 1); + c++; + found++; + } + if (found == (hlength+9-3)) { + write_ipack(eHeadr, 2); + write_ipack(&dataIdentifier, 1); + } + } + while (c < Count && found < plength + 6) { int l = Count - c; if (l + found > plength + 6) @@ -395,13 +436,15 @@ #define RESULTBUFFERSIZE KILOBYTE(256) -cRemux::cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure) +cRemux::cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure, int SubPid1, int SubPid2) { vPid = VPid; aPid1 = APid1; aPid2 = APid2; dPid1 = DPid1; dPid2 = DPid2; + sPid1 = SubPid1; + sPid2 = SubPid2; exitOnFailure = ExitOnFailure; numUPTerrors = 0; synced = false; @@ -415,6 +458,8 @@ dTS2PES1 = dPid1 ? new cTS2PES(resultBuffer, IPACKS) : NULL; //XXX don't yet know how to tell apart primary and secondary DD data... dTS2PES2 = /*XXX dPid2 ? new cTS2PES(resultBuffer, IPACKS) : XXX*/ NULL; + sTS2PES1 = SubPid1 ? new cTS2PES(resultBuffer, IPACKS, 0x00, 0x28) : NULL; + sTS2PES2 = SubPid2 ? new cTS2PES(resultBuffer, IPACKS, 0x00, 0x29) : NULL; } cRemux::~cRemux() @@ -424,6 +469,8 @@ delete aTS2PES2; delete dTS2PES1; delete dTS2PES2; + delete sTS2PES1; + delete sTS2PES2; delete resultBuffer; } @@ -500,6 +547,8 @@ else if (pid == aPid2 && aTS2PES2) aTS2PES2->ts_to_pes(Data + i); else if (pid == dPid1 && dTS2PES1) dTS2PES1->ts_to_pes(Data + i); else if (pid == dPid2 && dTS2PES2) dTS2PES2->ts_to_pes(Data + i); + else if (pid == sPid1 && sTS2PES1) sTS2PES1->ts_to_pes(Data + i); + else if (pid == sPid2 && sTS2PES2) sTS2PES2->ts_to_pes(Data + i); } used += TS_SIZE; } diff -Nru vdr-1.3.14-vanilla/remux.h vdr-1.3.14-subtitles/remux.h --- vdr-1.3.14-vanilla/remux.h 2004-10-15 15:31:16.000000000 +0300 +++ vdr-1.3.14-subtitles/remux.h 2004-10-24 18:38:51.285757168 +0300 @@ -29,15 +29,15 @@ int numUPTerrors; bool synced; int skipped; - int vPid, aPid1, aPid2, dPid1, dPid2; - cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2; + int vPid, aPid1, aPid2, dPid1, dPid2, sPid1, sPid2; + cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2, *dTS2PES1, *dTS2PES2, *sTS2PES1, *sTS2PES2; cRingBufferLinear *resultBuffer; int resultSkipped; int GetPid(const uchar *Data); int GetPacketLength(const uchar *Data, int Count, int Offset); int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType); public: - cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure = false); + cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure = false, int SubPid1 = 0, int SubPid2 = 0); ~cRemux(); int Put(const uchar *Data, int Count); ///< Puts at most Count bytes of Data into the remuxer. diff -Nru vdr-1.3.14-vanilla/vdrttxtsubshooks.c vdr-1.3.14-subtitles/vdrttxtsubshooks.c --- vdr-1.3.14-vanilla/vdrttxtsubshooks.c 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/vdrttxtsubshooks.c 2004-10-24 18:38:51.286757016 +0300 @@ -0,0 +1,44 @@ + +#include +#include +#include + +#include "vdrttxtsubshooks.h" + +// XXX Really should be a list... +static cVDRTtxtsubsHookListener *gListener; + +// ------ class cVDRTtxtsubsHookProxy ------ + +class cVDRTtxtsubsHookProxy : public cVDRTtxtsubsHookListener +{ + public: + virtual void HideOSD(void) { if(gListener) gListener->HideOSD(); }; + virtual void ShowOSD(void) { if(gListener) gListener->ShowOSD(); }; + virtual void PlayerTeletextData(uint8_t *p, int length) + { if(gListener) gListener->PlayerTeletextData(p, length); }; + virtual cTtxtSubsRecorderBase *NewTtxtSubsRecorder(cDevice *dev, const cChannel *ch) + { if(gListener) return gListener->NewTtxtSubsRecorder(dev, ch); else return NULL; }; +}; + + +// ------ class cVDRTtxtsubsHookListener ------ + +cVDRTtxtsubsHookListener::~cVDRTtxtsubsHookListener() +{ + gListener = 0; +} + +void cVDRTtxtsubsHookListener::HookAttach(void) +{ + gListener = this; + //printf("cVDRTtxtsubsHookListener::HookAttach\n"); +} + +static cVDRTtxtsubsHookProxy gProxy; + +cVDRTtxtsubsHookListener *cVDRTtxtsubsHookListener::Hook(void) +{ + return &gProxy; +} + diff -Nru vdr-1.3.14-vanilla/vdrttxtsubshooks.h vdr-1.3.14-subtitles/vdrttxtsubshooks.h --- vdr-1.3.14-vanilla/vdrttxtsubshooks.h 1970-01-01 02:00:00.000000000 +0200 +++ vdr-1.3.14-subtitles/vdrttxtsubshooks.h 2004-10-24 18:38:51.287756864 +0300 @@ -0,0 +1,36 @@ + +#ifndef __VDRTTXTSUBSHOOKS_H +#define __VDRTTXTSUBSHOOKS_H + +class cDevice; +class cChannel; + +#define VDRTTXTSUBSHOOKS + +class cTtxtSubsRecorderBase { + public: + virtual ~cTtxtSubsRecorderBase() {}; + + // returns a PES packet if there is data to add to the recording + virtual uint8_t *GetPacket(uint8_t **buf, size_t *len) { return NULL; }; + virtual void DeviceAttach(void) {}; +}; + +class cVDRTtxtsubsHookListener { + public: + cVDRTtxtsubsHookListener(void) {}; + virtual ~cVDRTtxtsubsHookListener(); + + void HookAttach(void); + + virtual void HideOSD(void) {}; + virtual void ShowOSD(void) {}; + virtual void PlayerTeletextData(uint8_t *p, int length) {}; + virtual cTtxtSubsRecorderBase *NewTtxtSubsRecorder(cDevice *dev, const cChannel *ch) + { return NULL; }; + + // used by VDR to call hook listeners + static cVDRTtxtsubsHookListener *Hook(void); +}; + +#endif