summaryrefslogtreecommitdiff
path: root/pes2ts.c
diff options
context:
space:
mode:
authorzwer <zwer@1f4bef6d-8e0a-0410-8695-e467da8aaccf>2006-01-24 12:54:00 +0000
committerzwer <zwer@1f4bef6d-8e0a-0410-8695-e467da8aaccf>2006-01-24 12:54:00 +0000
commitb998c31e7e0f4f84b2f64c50093069c815772808 (patch)
tree7b65667843ea5db07766d23688f045d20140361c /pes2ts.c
downloadvdr-plugin-ffnetdev-b998c31e7e0f4f84b2f64c50093069c815772808.tar.gz
vdr-plugin-ffnetdev-b998c31e7e0f4f84b2f64c50093069c815772808.tar.bz2
FFNetDev-Plugin
git-svn-id: svn://svn.berlios.de/ffnetdev/trunk@1 1f4bef6d-8e0a-0410-8695-e467da8aaccf
Diffstat (limited to 'pes2ts.c')
-rw-r--r--pes2ts.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/pes2ts.c b/pes2ts.c
new file mode 100644
index 0000000..506abd9
--- /dev/null
+++ b/pes2ts.c
@@ -0,0 +1,210 @@
+/*
+ * pes2ts.c: PES2TS remux
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+#include <vdr/tools.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "tsworker.h"
+
+#include "pes2ts.h"
+
+cPES2TSRemux::cPES2TSRemux(int VPid, int APid):
+ cThread("[ffnetdev] PES2TS remux"),
+ m_OutputBuffer(new cRingBufferLinear(OUTPUTBUFSIZE, TS_SIZE * 2)),
+ m_InputBuffer(new cRingBufferLinear(INPUTBUFSIZE, IPACKS)),
+ m_Active(false),
+ m_PlayModeChanged(false)
+{
+ vpid = VPid;
+ apid = APid;
+ m_InputBuffer->SetTimeouts(0, 1000); // IMPORTANT to avoid busy wait in threads main loop and thus a high CPU load
+ Start();
+ OutputLocked = false;
+}
+
+cPES2TSRemux::~cPES2TSRemux()
+{
+ m_Active = false;
+ delete m_InputBuffer;
+ delete m_OutputBuffer;
+
+}
+
+void cPES2TSRemux::Action(void)
+{
+ unsigned int i;
+ uchar acc=0; // continutiy counter for audio packets
+ uchar vcc=0; // continutiy counter for video packets
+ uchar *cc; // either cc=&vcc; or cc=&acc;
+ unsigned short pid=0;
+ unsigned int packetlen;
+ uchar ts[188];
+ uchar pes[IPACKS];
+
+ unsigned int minNeededPacketlen = 10; // needed for read packet len: 6 Should be enought ... but makes no sense
+
+
+ m_Active = true;
+ while (m_Active) {
+ int count=0;
+// fprintf(stderr, "[ffnetdev] Remuxer: Inputbuffersize: %d, Outputbuffersize: %d\n",
+// m_InputBuffer->Available(), m_OutputBuffer->Available());
+
+ if (m_PlayModeChanged)
+ {
+ cCondWait::SleepMs(1500);
+ m_PlayModeChanged = false;
+ }
+
+ if (m_InputBuffer->Available() < (int)IPACKS*10) {
+ cCondWait::SleepMs(5);
+ continue;
+ }
+
+ if (!cTSWorker::HaveStreamClient()) {
+ ClearOutput();
+ cCondWait::SleepMs(10);
+ continue;
+ }
+
+
+ InputMutex.Lock();
+ uchar *data = m_InputBuffer->Get(count);
+ if (data==NULL) {
+ InputMutex.Unlock();
+ cCondWait::SleepMs(3);
+ continue;
+ }
+
+// fprintf(stderr, "[ffnetdev] count: %07d Free: %07d AvailO %07d AvailI: %07d\n", count, m_InputBuffer->Free(),
+// m_OutputBuffer->Available(), m_InputBuffer->Available());
+
+ if ( count < (int)minNeededPacketlen ) {
+ fprintf(stderr, "[ffnetdev] Remuxer: not enought bytes for PacketLen-Analysis, have only: %d\n", count);
+ InputMutex.Unlock();
+ cCondWait::SleepMs(2);
+ continue;
+ }
+
+ //DEBUG
+ //fprintf(stderr, "Data ready to read: %d\n", count);
+ //for (i=0; i<20; i++)
+ // fprintf(stderr, "%02X ", data[i]);
+ // END DEBUG
+
+
+ // check for valid PES signature in PES header
+ if ( (data[0]==0x00) && (data[1]==0x00) && (data[2]==0x01) ) {
+
+ packetlen = ((data[4]<<8) | data[5]) + 6 ;
+
+ if ( packetlen>IPACKS) {
+ fprintf(stderr, "[ffnetdev] Remuxer: IPACKS changed? packet length was %d, maximum: %d\n"
+ "This should not happen! Please report!\n", packetlen, IPACKS);
+ }
+
+ if ( count < (int)packetlen) {
+ fprintf(stderr, "[ffnetdev] Remuxer: not enought bytes for whole packet, have only: %d but LenShoud be %d\n", count, packetlen);
+ InputMutex.Unlock();
+ cCondWait::SleepMs(1);
+ continue;
+ }
+
+
+ // check for valid stream id type: is it video or audio or unknown?
+ if ( (data[3]>=0xC0) && (data[3]<=0xDF) ) {
+ pid=apid;
+ cc=&acc;
+ }
+ else {
+ if ( (data[3]>=0xE0) && (data[3]<=0xEF) ) {
+ pid=vpid;
+ cc=&vcc;
+ }
+ else {
+ fprintf(stderr, "[ffnetdev] Remuxer: Unknown stream id: neither video nor audio type.\n");
+ // throw away whole PES packet
+ m_InputBuffer->Del(packetlen);
+ InputMutex.Unlock();
+ continue;
+ }
+ }
+
+ memcpy( pes, data, packetlen);
+ // we are now finished with the PES packet, delete it from ring buffer
+ m_InputBuffer->Del(packetlen);
+
+ InputMutex.Unlock();
+ }
+ else {
+ // no valid PES signature was found, so delete this stuff from ring buffer
+ // normally we should always receive a whole PES packet, since VDR always gives us a whole packet and not less or more
+ // with each call in streamdevice.c (PlayVideo, PlayAudio)
+ fprintf(stderr, "[ffnetdev] Remuxer: No valid PES signature found. This should not happen.\n");
+
+ m_InputBuffer->Del(1); // Probably it is better to delete 1 byte only to get in sync again!?
+ InputMutex.Unlock();
+ continue;
+ }
+
+ int tspacketlen = ((int)packetlen/184) * 188 + ((packetlen % 184 > 0) ? 188 : 0);
+ while (m_OutputBuffer->Free() < tspacketlen) {
+ if (!m_Active)
+ continue;
+ cCondWait::SleepMs(10);
+ //fprintf(stderr, "[ffnetdev] Remuxer: sleep %d %d\n", m_OutputBuffer->Free(), tspacketlen);
+ }
+
+ LockOutput();
+ bool first = true;
+ //--------------------------------------divide PES packet into small TS packets-----------------------
+ for (i=0; i< packetlen/184; i++) {
+ ts[0] = 0x47; //SYNC Byte
+ if (first) ts[1] = 0x40; // Set PUSI or
+ else ts[1] = 0x00; // clear PUSI, TODO: PID (high) is missing
+ ts[2] = pid & 0xFF; // PID (low)
+ ts[3] = 0x10 | ((*cc)&0x0F); // No adaptation field, payload only, continuity counter
+ memcpy(ts + 4, pes + i * 184, 184);
+ ++(*cc);
+ m_OutputBuffer->Put(ts, 188);
+ first = false;
+ }
+ uchar rest = packetlen % 184;
+ if (rest>0) {
+ ts[0] = 0x47; //SYNC Byte
+ if (first) ts[1] = 0x40; // Set PUSI or
+ else ts[1] = 0x00; // clear PUSI, TODO: PID (high) is missing
+ ts[2] = pid & 0xFF; // PID (low)
+ ts[3] = 0x30 | ((*cc)&0x0F); // adaptation field, payload, continuity counter
+ ++(*cc);
+ ts[4] = 183-rest;
+ if (ts[4]>0) {
+ ts[5] = 0x00;
+ memset(ts + 6, 0xFF, ts[4] - 1);
+ }
+ memcpy(ts + 5 + ts[4], pes + i * 184, rest);
+ m_OutputBuffer->Put(ts, 188);
+ first = false;
+ }
+
+ UnlockOutput();
+
+ }
+ m_Active = false;
+}
+
+
+int cPES2TSRemux::Put(const uchar *Data, int Count)
+{
+ InputMutex.Lock();
+ int result = m_InputBuffer->Put(Data, Count);
+ InputMutex.Unlock();
+ return ( result);
+}
+
+