diff options
author | zwer <zwer@1f4bef6d-8e0a-0410-8695-e467da8aaccf> | 2006-01-24 12:54:00 +0000 |
---|---|---|
committer | zwer <zwer@1f4bef6d-8e0a-0410-8695-e467da8aaccf> | 2006-01-24 12:54:00 +0000 |
commit | b998c31e7e0f4f84b2f64c50093069c815772808 (patch) | |
tree | 7b65667843ea5db07766d23688f045d20140361c /pes2ts.c | |
download | vdr-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.c | 210 |
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); +} + + |