]> git.vomp.tv Git - vompclient.git/blob - demuxerts.cc
*** empty log message ***
[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   // Temporarily, just look for the lowest audio stream and return it
42
43   UINT LoPattern = 0x100 | PESTYPE_AUD0,
44        HiPattern = 0x100 | PESTYPE_AUDMAX;
45   int ret = 0;
46
47   while (len >= 4)
48   {
49     UINT pattern = *(UINT*)buf;
50     buf++; len--;
51
52     if (pattern < LoPattern || pattern > HiPattern) continue;
53     ret = pattern & 0xFF;
54     HiPattern = pattern;
55     if (HiPattern == LoPattern) break;
56   }
57   return ret;
58 */
59 }
60
61 void DemuxerTS::setVID(int p_vID)
62 {
63   vID = p_vID;
64 }
65
66 void DemuxerTS::setAID(int p_aID)
67 {
68   aID = p_aID;
69 }
70
71 int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest)
72 {
73   UINT LoPattern = 0x100 | PESTYPE_VID0,
74        HiPattern = 0x100 | PESTYPE_VIDMAX;
75
76   while (len >= 14)
77   {
78     UINT pattern = *(UINT*)buf;
79     buf++; len--;
80     if (pattern < LoPattern || pattern > HiPattern) continue;
81
82     UINT framelength = ((UINT)buf[3] << 8) | buf[4];
83     buf += 5; len -= 5;
84
85     if ( buf[1] & 0x80 ) // PTS_DTS_flags indicate that PTS is present
86     {
87       *dest = ( (ULLONG)(buf[3] & 0x0E) << 29 ) |
88               ( (ULLONG)(buf[4])        << 22 ) |
89               ( (ULLONG)(buf[5] & 0xFE) << 14 ) |
90               ( (ULLONG)(buf[6])        <<  7 ) |
91               ( (ULLONG)(buf[7] & 0xFE) >>  1 );
92       return 1;
93     }
94
95     buf += framelength; len -= framelength;
96   }
97   // No PTS found.
98   return 0;
99 }
100
101 int DemuxerTS::put(UCHAR* buf, int len)
102 {
103   int ret = 0;    // return number of bytes consumed
104
105   while (partPacket)
106   {
107     if (len >= TS_SIZE + 1 - partPacket)
108     { // Remainder of partial packet is available, plus one
109       memcpy(store+partPacket, buf, TS_SIZE - partPacket);
110       ret += TS_SIZE - partPacket;
111       buf += TS_SIZE - partPacket;
112       len -= TS_SIZE - partPacket;
113       partPacket = TS_SIZE;
114       if (*buf == TS_SIG)
115       { // Packet is properly terminated
116         int rc = processTS(store);
117         if (rc)
118           partPacket = 0; // Successfully processed
119         else
120           return ret;     // Try again later.
121       }
122       else
123       { // Packet not terminated. Find another candidate, and shift store
124         Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
125         int search = 1;
126         while (search < partPacket && store[search] != TS_SIG)
127           search++;
128         partPacket -= search;
129         if (partPacket) memcpy(store, store+search, partPacket);
130       }
131     }
132     else
133     { // Still don't have complete packet. Consume what we do have.
134       memcpy(store+partPacket, buf, len);
135       partPacket += len;
136       ret += len;
137       return ret;
138     }
139   }
140
141   // Position ourselves at a candidate TS packet
142   while (*buf != TS_SIG && len)
143   {
144     Log::getInstance()->log("TS Demuxer", Log::ERR, "TS Misaligned!");
145     buf++; ret++; len--;
146   }
147
148   while (len)
149   {
150     if (len < TS_SIZE + 1)
151     { // Not enough data. Store what we have.
152       memcpy(store, buf, len);
153       partPacket = len;
154       ret += len;
155       return ret;
156     }
157
158     if (buf[TS_SIZE] != TS_SIG)
159     { // Not terminated correctly.
160       while (*buf != TS_SIG && len)
161       {
162         buf++; ret++; len--;
163       }
164     }
165     else
166     {
167       int rc = processTS(buf);
168       if (rc)
169       { // Successfully processed
170         buf += TS_SIZE; ret += TS_SIZE; len -= TS_SIZE;
171       }
172       else
173       { // Processing failed.
174         return ret;
175       }
176     }
177   }
178   return ret;
179 }
180
181 int DemuxerTS::processTS(UCHAR* buf)
182 {
183   int datalen = TS_SIZE - 4;
184   int pid = ( (buf[1] & 0x1F) << 8 ) | buf[2];
185   UCHAR payload = buf[1] & 0x40;
186
187   if (buf[3] & 0x20) // Adaptation field is present
188     datalen -= (buf[4] + 1);
189   if (datalen < 0) // Error in stream TODO log this
190     return 1;
191   if (datalen == 0) // Null packet
192     return 1;
193   buf += (TS_SIZE - datalen);
194
195   if (payload)
196   {
197     int rc = 1;
198
199     if (pid == vID) rc = vPacket.submit();
200     if (pid == aID) rc = aPacket.submit();
201     if (rc == 0) return 0;
202
203     if (pid == vID)
204     {
205       vPacket.init(0xE0);
206       buf += 6; datalen -= 6;
207     }
208     if (pid == aID)
209     {
210       aPacket.init(0xC0);
211       buf += 6; datalen -= 6;
212     }
213 //    int pesID = -1;
214 //    if (datalen >= 4) pesID = buf[3];
215 //    switch (pesID)
216 //    {
217 //    case PESTYPE_VID0 ... PESTYPE_VIDMAX:
218 //      if (video_current == -1) video_current = pesID;
219 //      if (video_current == pesID)
220 //      {
221 //        vPID = pid;
222 //        vPacket.init(pesID);
223 //        buf += 6; datalen -= 6;
224 //      }
225 //      break;
226 //    case PESTYPE_AUD0 ... PESTYPE_AUDMAX:
227 //      if (audio_current == -1) audio_current = pesID;
228 //      if (audio_current == pesID)
229 //      {
230 //        aPID = pid;
231 //        aPacket.init(pesID);
232 //        buf += 6; datalen -= 6;
233 //      }
234 //      break;
235 //    }
236   }
237
238   PESPacket* packet = NULL;
239   if (pid == vID) packet = &vPacket;
240   if (pid == aID) packet = &aPacket;
241   if (packet != NULL)
242   {
243     if (packet->write(buf, datalen) == 0)
244     { // Writing to packet failed. It has overflowed.
245       Log::getInstance()->log("TS Demuxer", Log::DEBUG, "Packet overflow, pid %d", pid);
246       if (packet->submit() == 0)
247         return 0;
248       packet->truncate();
249       packet->write((UCHAR*)"\200\000\000", 3);
250       packet->write(buf, datalen);
251     }
252   }
253
254   return 1;
255 }