summaryrefslogtreecommitdiff
path: root/command/ts2pkt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'command/ts2pkt.cpp')
-rw-r--r--command/ts2pkt.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/command/ts2pkt.cpp b/command/ts2pkt.cpp
new file mode 100644
index 0000000..0d13df7
--- /dev/null
+++ b/command/ts2pkt.cpp
@@ -0,0 +1,194 @@
+/*
+ * ts2pkt.cpp: A program for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "ts2pkt.h"
+
+cMarkAdTS2Pkt::cMarkAdTS2Pkt(const char *QueueName, int QueueSize)
+{
+ queue=new cMarkAdPaketQueue(QueueName,QueueSize);
+ Reset();
+}
+
+cMarkAdTS2Pkt::~cMarkAdTS2Pkt()
+{
+ if (queue) delete queue;
+}
+
+void cMarkAdTS2Pkt::Reset(int ErrIndex)
+{
+ sync=false;
+ switch (ErrIndex)
+ {
+ case MA_ERR_TSSIZE:
+ dsyslog("inbuf not 188 bytes");
+ break;
+ case MA_ERR_NOSYNC:
+ dsyslog("found no sync");
+ break;
+ case MA_ERR_SEQ:
+ dsyslog("sequence error");
+ break;
+ case MA_ERR_AFC:
+ dsyslog("wrong AFC value");
+ break;
+ case MA_ERR_TOBIG:
+ dsyslog("buflen > 188 bytes");
+ break;
+ case MA_ERR_NEG:
+ dsyslog("buflen negative");
+ break;
+ }
+ counter=-1;
+ if (queue) queue->Clear();
+}
+
+bool cMarkAdTS2Pkt::InjectVideoPES(uchar *PESData, int PESSize)
+{
+ if ((!PESData) || (!PESSize)) return false;
+
+ struct PESHDR *peshdr=(struct PESHDR *) PESData;
+
+ // first check some simple things
+ if ((peshdr->Sync1!=0) && (peshdr->Sync2!=0) && (peshdr->Sync3!=1)) return false;
+ if ((peshdr->StreamID & 0xF0)!=0xE0) return false;
+
+ int Length=(peshdr->LenH<<8)+peshdr->LenL;
+ if (Length) Length+=sizeof(PESHDR);
+ if (Length!=PESSize) return false;
+
+ struct PESHDROPT *peshdropt=(struct PESHDROPT *) &PESData[sizeof(struct PESHDR)];
+
+ uchar *buf;
+ int buflen;
+
+ if (peshdropt->MarkerBits==0x2)
+ {
+ // we have an optional PES header
+ int bpos=sizeof(struct PESHDR)+sizeof(struct PESHDROPT)+
+ peshdropt->Length;
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
+ }
+ else
+ {
+ int bpos=sizeof(struct PESHDR);
+ buf=&PESData[bpos];
+ buflen=PESSize-bpos;
+ }
+ queue->Inject(buf,buflen);
+ return true;
+}
+
+void cMarkAdTS2Pkt::Process(MarkAdPid Pid, uchar *TSData, int TSSize, uchar **PktData, int *PktSize)
+{
+ if ((!PktData) || (!PktSize) || (!queue)) return;
+ *PktData=NULL;
+ *PktSize=0;
+
+ if (TSData)
+ {
+ if (TSSize!=TS_SIZE)
+ {
+ Reset(MA_ERR_TSSIZE);
+ return; // we need a full packet
+ }
+
+ // check TS packet sync
+ if (TSData[0]!=0x47)
+ {
+ Reset(MA_ERR_NOSYNC);
+ return;
+ }
+
+ struct TSHDR *tshdr = (struct TSHDR *) TSData;
+
+ int pid = (tshdr->PidH << 8) | tshdr->PidL;
+ if (Pid.Num!=pid)
+ {
+ return; // not for us
+ }
+
+ if (tshdr->PayloadStart) sync=true;
+ if (!sync)
+ {
+ return; // not synced
+ }
+
+ if ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
+ {
+ if (counter==(int) tshdr->Counter)
+ {
+ // duplicate paket -> just ignore
+ return;
+ }
+ // sequence error
+ Reset(MA_ERR_SEQ);
+ return;
+ }
+ counter=tshdr->Counter;
+
+ if ((tshdr->AFC<=0) || (tshdr->AFC>3))
+ {
+ Reset(MA_ERR_AFC);
+ return;
+ }
+
+ // we just ignore the infos in the adaption field (e.g. OPCR/PCR)
+ if ((tshdr->AFC!=1) && (tshdr->AFC!=3))
+ {
+ return;
+ }
+
+ int buflen=TS_SIZE+1;
+ uchar *buf=NULL;
+
+ if (tshdr->AFC==1)
+ {
+ // payload only
+ buflen=TS_SIZE-sizeof(struct TSHDR);
+ buf=&TSData[sizeof(struct TSHDR)];
+ }
+
+ if (tshdr->AFC==3)
+ {
+ // adaption field + payload
+ struct TSADAPT *tsadapt = (struct TSADAPT *) &TSData[4];
+ int alen=tsadapt->Len+1;
+ buflen=TS_SIZE-(sizeof(struct TSHDR)+alen);
+ buf=&TSData[sizeof(struct TSHDR)+alen];
+ }
+
+ if (buflen>TS_SIZE)
+ {
+ // size to large
+ Reset(MA_ERR_TOBIG);
+ return;
+ }
+ if (buflen<0)
+ {
+ // error in size
+ Reset(MA_ERR_NEG);
+ return;
+ }
+ if (buflen==0)
+ {
+ // no data?
+ return;
+ }
+
+ queue->Put(buf,buflen);
+ }
+ if (Pid.Type==MARKAD_PIDTYPE_VIDEO_H264)
+ {
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_H264);
+ }
+ else
+ {
+ *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
+ }
+ return;
+}