Group :: Video
RPM: vdr
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: vdr-1.3.14-subtitles-0.3.4-and-ttxtsubs-0.0.5.diff
Download
Download
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 <sys/stat.h>
#include <sys/unistd.h>
#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<cListenerListObject>;
+ }
+
+ 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<cListenerListObject>* 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 <stdlib.h>
+#include "rcontroller.h"
+#include <stdio.h>
+#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 <stdarg.h>
#include <stdio.h>
#include <unistd.h>
+#include <stdint.h>
#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 <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#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