]> git.vomp.tv Git - vompclient.git/blob - demuxerts.cc
Clear some rubbish out of the demuxer.
[vompclient.git] / demuxerts.cc
1 /*
2     Copyright 2006 Mark Calderbank
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "demuxerts.h"
22
23 DemuxerTS::DemuxerTS(int p_vID, int p_aID)
24 {
25   vID = p_vID;
26   aID = p_aID;
27 }
28
29 void DemuxerTS::flush()
30 {
31   partPacket = 0;
32   Demuxer::flush();
33   vPacket.init(0xE0);
34   aPacket.init(0xC0);
35 }
36
37 int DemuxerTS::scan(UCHAR *buf, int len)
38 {
39   return 0xc0;
40 }
41
42 void DemuxerTS::setVID(int p_vID)
43 {
44   vID = p_vID;
45 }
46
47 void DemuxerTS::setAID(int p_aID)
48 {
49   aID = p_aID;
50 }
51
52 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
53 {
54   UINT LoPattern = 0x100 | PESTYPE_VID0,
55        HiPattern = 0x100 | PESTYPE_VIDMAX;
56
57   while (len >= 14)
58   {
59     UINT pattern = *(UINT*)buf;
60     buf++; len--;
61     if (pattern < LoPattern || pattern > HiPattern) continue;
62
63     UINT framelength = ((UINT)buf[3] << 8) | buf[4];
64     buf += 5; len -= 5;
65
66     if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
67     {
68       *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
69               ( (ULLONG)(buf[4])        << 22 ) |
70               ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
71               ( (ULLONG)(buf[6])        <<  7 ) |
72               ( (ULLONG)(buf[7] & 0xFE) >>  1 );
73       return 1;
74     }
75
76     buf += framelength; len -= framelength;
77   }
78   // No PTS found.
79   return 0;
80 }
81
82 int DemuxerTS::put(UCHAR* buf, int len)
83 {
84   int ret = 0;    // return number of bytes consumed
85
86   while (partPacket)
87   {
88     if (len >= TS_SIZE + 1 - partPacket)
89     { // Remainder of partial packet is available, plus one
90       memcpy(store+partPacket, buf, TS_SIZE - partPacket);
91       ret += TS_SIZE - partPacket;
92       buf += TS_SIZE - partPacket;
93       len -= TS_SIZE - partPacket;
94       partPacket = TS_SIZE;
95       if (*buf == TS_SIG)
96       { // Packet is properly terminated
97         int rc = processTS(store);
98         if (rc)
99           partPacket = 0; // Successfully processed
100         else
101           return ret;     // Try again later.
102       }
103       else
104       { // Packet not terminated. Find another candidate, and shift store
105         Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
106         int search = 1;
107         while (search < partPacket && store[search] != TS_SIG)
108           search++;
109         partPacket -= search;
110         if (partPacket) memcpy(store, store+search, partPacket);
111       }
112     }
113     else
114     { // Still don't have complete packet. Consume what we do have.
115       memcpy(store+partPacket, buf, len);
116       partPacket += len;
117       ret += len;
118       return ret;
119     }
120   }
121
122   // Position ourselves at a candidate TS packet
123   while (*buf != TS_SIG && len)
124   {
125     Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
126     buf++; ret++; len--;
127   }
128
129   while (len)
130   {
131     if (len < TS_SIZE + 1)
132     { // Not enough data. Store what we have.
133       memcpy(store, buf, len);
134       partPacket = len;
135       ret += len;
136       return ret;
137     }
138
139     if (buf[TS_SIZE] != TS_SIG)
140     { // Not terminated correctly.
141       while (*buf != TS_SIG && len)
142       {
143         buf++; ret++; len--;
144       }
145     }
146     else
147     {
148       int rc = processTS(buf);
149       if (rc)
150       { // Successfully processed
151         buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
152       }
153       else
154       { // Processing failed.
155         return ret;
156       }
157     }
158   }
159   return ret;
160 }
161
162 int DemuxerTS::processTS(UCHAR* buf)
163 {
164   int datalen = TS_SIZE - 4;
165   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
166   UCHAR payload = buf[1] & 0x40;
167
168   if (buf[3] & 0x20) // Adaptation field is present
169     datalen -= (buf[4] + 1);
170   if (datalen < 0) // Error in stream TODO log this
171     return 1;
172   if (datalen == 0) // Null packet
173     return 1;
174   buf += (TS_SIZE - datalen);
175
176   if (payload)
177   {
178     int rc = 1;
179
180     if (pid == vID) rc = vPacket.submit();
181     if (pid == aID) rc = aPacket.submit();
182     if (rc == 0) return 0;
183
184     if (pid == vID)
185     {
186       vPacket.init(0xE0);
187       buf += 6; datalen -= 6;
188     }
189     if (pid == aID)
190     {
191       aPacket.init(0xC0);
192       buf += 6; datalen -= 6;
193     }
194   }
195
196   PESPacket* packet = NULL;
197   if (pid == vID) packet = &vPacket;
198   if (pid == aID) packet = &aPacket;
199   if (packet != NULL)
200   {
201     if (packet->write(buf, datalen) == 0)
202     { // Writing to packet failed. It has overflowed.
203       if (packet->submit() == 0)
204         return 0;
205       packet->truncate();
206       packet->write((UCHAR*)"\200\000\000", 3);
207       packet->write(buf, datalen);
208     }
209   }
210
211   return 1;
212 }