]> git.vomp.tv Git - vompclient.git/blob - demuxerts.cc
Teletext
[vompclient.git] / demuxerts.cc
1 /*
2     Copyright 2006-2008 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 Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "demuxerts.h"
22 #include "log.h"
23
24 DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID)
25 {
26   vID = p_vID; vActive = false;
27   aID = p_aID; aActive = false;
28   subID = p_subID; subActive = false;
29   atype = 0;
30   subLength = 0;
31   tID = p_tID;
32 }
33
34 void DemuxerTS::flush()
35 {
36   partPacket = 0;
37   parsed = false;
38   Demuxer::flush();
39   vPacket.init(PESTYPE_VID0);
40   switch (atype)
41   {
42   case 1:
43     aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
44     break;
45   default:
46   case 0:
47     aPacket.init(PESTYPE_AUD0);
48     break;
49   }
50   subPacket.init(PESTYPE_PRIVATE_1);
51 tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
52
53   vActive = false;
54   aActive = false;
55   subActive = false;
56   subLength = 0;
57   tActive = false;
58 }
59
60 int DemuxerTS::scan(UCHAR *buf, int len)
61 {
62   switch (atype)
63   {
64   case 1:
65     return PESTYPE_PRIVATE_1;
66   default:
67   case 0:
68     return PESTYPE_AUD0;
69   }
70 }
71
72 void DemuxerTS::setVID(int p_vID)
73 {
74   vID = p_vID;
75   vPacket.init(PESTYPE_VID0);
76   vActive = false;
77 }
78
79 void DemuxerTS::setAID(int p_aID, int type)
80 {
81   aID = p_aID;
82   atype = type;
83   switch (atype)
84   {
85   case 1:
86     aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
87     setAudioStream(PESTYPE_SUBSTREAM_AC30);
88     break;
89   default:
90   case 0:
91     aPacket.init(PESTYPE_AUD0);
92     setAudioStream(PESTYPE_AUD0);
93     break;
94   }
95   aActive = false;
96 }
97
98 void DemuxerTS::setSubID(int p_subID)
99 {
100   subID = p_subID;
101   subPacket.init(PESTYPE_PRIVATE_1);
102   subActive = false;
103   subLength = 0;
104 }
105
106 void DemuxerTS::setTID(int p_tID)
107 {
108   tID = p_tID;
109   tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
110   tActive = false;
111
112 }
113
114 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
115 {
116   UINT LoPattern = 0x100 | PESTYPE_VID0,
117        HiPattern = 0x100 | PESTYPE_VIDMAX;
118
119   while (len >= 14)
120   {
121     UINT pattern = *(UINT*)buf;
122     buf++; len--;
123     if (pattern < LoPattern || pattern > HiPattern) continue;
124
125     UINT framelength = ((UINT)buf[3] << 8) | buf[4];
126     buf += 5; len -= 5;
127
128     if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
129     {
130       *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
131               ( (ULLONG)(buf[4])        << 22 ) |
132               ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
133               ( (ULLONG)(buf[6])        <<  7 ) |
134               ( (ULLONG)(buf[7] & 0xFE) >>  1 );
135       return 1;
136     }
137
138     buf += framelength; len -= framelength;
139   }
140   // No PTS found.
141   return 0;
142 }
143
144 int DemuxerTS::put(UCHAR* buf, int len)
145 {
146   int ret = 0;    // return number of bytes consumed
147
148   while (partPacket)
149   {
150     if (len >= TS_SIZE + 1 - partPacket)
151     { // Remainder of partial packet is available, plus one
152       memcpy(store+partPacket, buf, TS_SIZE - partPacket);
153       ret += TS_SIZE - partPacket;
154       buf += TS_SIZE - partPacket;
155       len -= TS_SIZE - partPacket;
156       partPacket = TS_SIZE;
157       if (*buf == TS_SIG)
158       { // Packet is properly terminated
159         int rc = processTS(store);
160         if (rc)
161           partPacket = 0; // Successfully processed
162         else
163           return ret;     // Try again later.
164       }
165       else
166       { // Packet not terminated. Find another candidate, and shift store
167         Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
168         int search = 1;
169         while (search < partPacket && store[search] != TS_SIG)
170           search++;
171         partPacket -= search;
172         if (partPacket) memcpy(store, store+search, partPacket);
173       }
174     }
175     else
176     { // Still don't have complete packet. Consume what we do have.
177       memcpy(store+partPacket, buf, len);
178       partPacket += len;
179       ret += len;
180       return ret;
181     }
182   }
183
184   // Position ourselves at a candidate TS packet
185   while (len > 0 && *buf != TS_SIG)
186   {
187     Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
188     buf++; ret++; len--;
189   }
190
191   while (len)
192   {
193     if (len < TS_SIZE + 1)
194     { // Not enough data. Store what we have.
195       memcpy(store, buf, len);
196       partPacket = len;
197       ret += len;
198       return ret;
199     }
200
201     if (buf[TS_SIZE] != TS_SIG)
202     { // Not terminated correctly.
203       buf++; ret++; len--;
204       while (len > 0 && *buf != TS_SIG)
205       {
206         buf++; ret++; len--;
207       }
208     }
209     else
210     {
211       int rc = processTS(buf);
212       if (rc)
213       { // Successfully processed
214         buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
215       }
216       else
217       { // Processing failed.
218         return ret;
219       }
220     }
221   }
222   return ret;
223 }
224
225 int DemuxerTS::processTS(UCHAR* buf)
226 {
227   int datalen = TS_SIZE - 4;
228   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
229   UCHAR payload = buf[1] & 0x40;
230
231   if (buf[3] & 0x20) // Adaptation field is present
232     datalen -= (buf[4] + 1);
233   if (datalen < 0) // Error in stream TODO log this
234     return 1;
235   if (datalen == 0) // Null packet
236     return 1;
237   buf += (TS_SIZE - datalen);
238
239   if (payload)
240   {
241     int rc = 1;
242
243     if (pid == vID)
244     {
245       if (vActive)
246       {
247         if (!parsed)
248         {
249           parsePacketDetails(vPacket);
250           parsed = true;
251         }
252         rc = submitPacket(vPacket);
253       }
254       vActive = true;
255     }
256     if (pid == aID)
257     {
258       if (aActive)
259       {
260         if (!parsed)
261         {
262           parsePacketDetails(aPacket);
263           parsed = true;
264         }
265         rc = submitPacket(aPacket);
266       }
267       aActive = true;
268     }
269     if (pid == subID)
270     {
271       if (subActive)
272       {
273         if (!parsed)
274         {
275           parsePacketDetails(subPacket);
276           parsed = true;
277         }
278         rc = submitPacket(subPacket);
279       }
280       subActive = true;
281     }
282     if (isteletextdecoded && pid == tID)
283     {
284       if (tActive)
285       {
286         if (!parsed)
287         {
288           parsePacketDetails(tPacket);
289           parsed = true;
290         }
291       rc = submitPacket(tPacket);
292       }
293       tActive = true;
294     }
295     if (rc == 0) return 0;
296
297     parsed = false;
298     if (pid == vID)
299     {
300       vPacket.init(PESTYPE_VID0);
301       buf += 6; datalen -= 6;
302     }
303     if (pid == aID)
304     {
305       switch (atype)
306       {
307       case 1:
308         aPacket.init(PESTYPE_PRIVATE_1, PESTYPE_SUBSTREAM_AC30);
309         break;
310       default:
311       case 0:
312         aPacket.init(PESTYPE_AUD0);
313         break;
314       }
315       buf += 6; datalen -= 6;
316     }
317     if (pid == subID)
318     {
319       subPacket.init(PESTYPE_PRIVATE_1);
320       subLength = (buf[4] << 8) + buf[5];
321       buf += 6; datalen -= 6;
322     }
323     if (isteletextdecoded && pid == tID)
324     {
325         tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX);
326       buf += 6; datalen -= 6;
327     }
328   }
329
330   if ( (pid == vID && vActive) ||
331        (pid == aID && aActive) ||
332        (pid == tID && tActive) ||
333        (pid == subID && subActive) )
334   {
335     PESPacket* packet = NULL;
336     if (pid == vID) packet = &vPacket;
337     if (pid == aID) packet = &aPacket;
338     if (pid == subID) {
339 #ifdef WIN32
340         MessageBox(0,"sub","usb",0);
341 #endif
342         packet = &subPacket;
343     }
344     if (pid == tID) packet = &tPacket;
345     if (packet != NULL)
346     {
347       if (packet->write(buf, datalen) == 0)
348       { // Writing to packet failed. It has overflowed.
349         if (!parsed)
350         {
351           parsePacketDetails(*packet);
352           parsed = true;
353         }
354         if (submitPacket(*packet) == 0) return 0;
355         parsed = false;
356         packet->truncate();
357         packet->write((UCHAR*)"\200\000\000", 3);
358         packet->write(buf, datalen);
359       }
360     }
361   }
362
363   if (pid == subID && subActive && subPacket.getLength() == subLength)
364   {
365     parsePacketDetails(subPacket);
366 Log::getInstance()->log("DEMUXERTS", Log::DEBUG, "SUBMITTING A SUBTITLE PACKET %d %x", subLength, subPacket.getSubstream());
367     submitPacket(subPacket);
368     subActive = false;
369   }
370
371   return 1;
372 }