summaryrefslogtreecommitdiff
path: root/ts2pkt.cpp
blob: ad26ebea19b94b8dcf7ed2eb740fac4285d8015d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * ts2pkt.cpp: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include "ts2pkt.h"

cMarkAdTS2Pkt::cMarkAdTS2Pkt(int RecvNumber, const char *QueueName, int QueueSize)
{
    recvnumber=RecvNumber;
    queue=new cMarkAdPaketQueue(RecvNumber,QueueName,QueueSize);
    Reset();
}

cMarkAdTS2Pkt::~cMarkAdTS2Pkt()
{
    if (queue) delete queue;
}

void cMarkAdTS2Pkt::Reset(int ErrIndex)
{
    switch (ErrIndex)
    {
    case MA_ERR_TOSMALL:
        dsyslog("markad [%i]: input to small",recvnumber);
        break;
    case MA_ERR_NOSYNC:
        dsyslog("markad [%i]: found no sync",recvnumber);
        break;
    case MA_ERR_SEQ:
        dsyslog("markad [%i]: sequence error",recvnumber);
        break;
    case MA_ERR_AFC:
        dsyslog("markad [%i]: wrong AFC value",recvnumber);
        break;
    case MA_ERR_TOBIG:
        dsyslog("markad [%i]: buflen > 188",recvnumber);
        break;
    case MA_ERR_NEG:
        dsyslog("markad [%i]: buflen < 0",recvnumber);
        break;
    }
    counter=-1;
    if (queue) queue->Clear();
}

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_TOSMALL);
            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 ((counter!=-1) && (((counter+1) & 0xF)!=tshdr->Counter))
        {
            if (counter==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);
    }
    *PktData=queue->GetPacket(PktSize,MA_PACKET_PKT);
    return;
}