]> git.vomp.tv Git - vompclient-marten.git/blob - demuxer.cc
Initial import
[vompclient-marten.git] / demuxer.cc
1 /*
2     Copyright 2005 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 "demuxer.h"
22
23 const int Demuxer::FrameRates[9] = { 0, 23, 24, 25, 29, 30, 50, 59, 60 };
24
25 Demuxer* Demuxer::instance = NULL;
26
27 Demuxer::Demuxer()
28 {
29   if (instance) return;
30   instance = this;
31   initted = 0;
32 }
33
34 Demuxer::~Demuxer()
35 {
36   shutdown();
37   instance = NULL;
38 }
39
40 Demuxer* Demuxer::getInstance()
41 {
42   return instance;
43 }
44
45 int Demuxer::init()
46 {
47   if (!initted)
48   {
49     if ( videostream.init(demuxMemory) ||
50          audiostream.init(demuxMemory) ||
51          !(local_frame = (UCHAR *) malloc(0x10000)))
52     {
53       printf("failed to initialize demuxer\n");
54       shutdown();
55       return 1;
56     }
57   }
58
59   reset();
60   initted = 1;
61   return 0;
62 }
63
64 void Demuxer::reset()
65 {
66   flush();
67   video_current = audio_current = -1;
68   horizontal_size = vertical_size = 0;
69   aspect_ratio = (enum AspectRatio) 0;
70   frame_rate = bit_rate = 0;
71 }
72
73 int Demuxer::shutdown()
74 {
75   videostream.shutdown();
76   audiostream.shutdown();
77   free(local_frame);
78   initted = 0;
79   return 1;
80 }
81
82 void Demuxer::flush()
83 {
84   videostream.flush();
85   audiostream.flush();
86   state_frametype = state_framepos = 0;
87   seek();
88 }
89
90 void Demuxer::flushAudio()
91 {
92   audiostream.flush();
93 }
94
95 void Demuxer::seek()
96 {
97   seeking = 1;
98 }
99
100 void Demuxer::setAudioStream(int id)
101 {
102   audio_current = id;
103 }
104
105 void Demuxer::setVideoStream(int id)
106 {
107   video_current = id;
108 }
109
110 int Demuxer::scan(UCHAR *buf, int len)
111 {
112   // Temporarily, just look for the lowest audio stream and return it
113   int ret = 0;
114   UCHAR byte;
115   int zeros = 0;
116   while (len > 1)
117   {
118     // We are searching for a string of bytes (0,0,1).
119     byte = *(buf++); --len;
120
121     if (byte == 0)
122     {
123       ++zeros; continue;
124     }
125     if (zeros < 2 || byte != 1)
126     {
127       zeros = 0; continue;
128     }
129     zeros = 0;
130     // We have found the pattern (0,0,1).
131     // Check the next byte for the sub-frame type.
132     byte = *(buf++); --len;
133     if (byte >= 0xc0 && byte <= 0xdf) // Audio
134       if (ret == 0 || ret > byte) ret = byte;
135   }
136   return ret;
137 }
138
139 int Demuxer::put(UCHAR* buf, int len)
140 {
141   int ret = 0;    // return number of bytes consumed
142   int parsed = 0; // number of bytes parsed by sub-function
143   int full;       // sub-function sets this to tell us to exit early
144   inbuf = buf;    // Initialize buffer pointer
145
146   while (len)
147   {
148     full = 0;
149     switch (state_frametype)
150     {
151       case 0: // Search for frame
152         parsed = parse_find_frame(len);
153         break;
154       case FRAMETYPE_VID0 ... FRAMETYPE_VIDMAX:
155         parsed = parse_video_frame(len, &full);
156         break;
157       case FRAMETYPE_AUD0 ... FRAMETYPE_AUDMAX:
158         parsed = parse_audio_frame(len, &full);
159         break;
160     }
161     ret += parsed; len -= parsed;
162     if (full) // We have to exit early.
163       break; // out of while loop
164   }
165   Log::getInstance()->log(
166       "Demuxer", Log::DEBUG, "Put %d; took %d", ret + len, ret);
167   return ret;
168 }
169
170 int Demuxer::parse_find_frame(int len)
171 {
172   int ret = 0; // return number of bytes parsed
173   UCHAR byte;
174
175   // In this function, state_framepos represents
176   // the number of fixed header bytes found so far.
177   if (state_framepos > 3 || state_framepos < 0)
178   {
179     // ERROR!
180     state_framepos = 0;
181   }
182
183   while (len)
184   {
185     byte = *inbuf++;
186     ++ret; --len;
187     switch (state_framepos)
188     {
189       case 0:
190       case 1:
191         if (byte == 0)
192           ++state_framepos;
193         else
194           state_framepos = 0;
195         break;
196       case 2:
197         if (byte == 1)
198           ++state_framepos;
199         else if (byte != 0)
200           state_framepos = 0;
201         break;
202       default:
203         state_framepos = 0; // Set initial state for the new frame
204         switch (byte)
205         {
206           case 0:
207             state_framepos = 1; // Count this as a first header byte!
208             break;
209           case FRAMETYPE_VID0 ... FRAMETYPE_VIDMAX:
210           case FRAMETYPE_AUD0 ... FRAMETYPE_AUDMAX:
211             state_frametype = byte;
212             return ret;
213         }
214         // Not a recognised frame type. Go back to Old Kent Road.
215         break;
216     }
217   }
218   return ret;
219 }
220
221 int Demuxer::parse_video_frame(int len, int* full)
222 {
223   int ret = 0; // return number of bytes consumed
224   int stream_sent, bytes_remaining;
225
226   switch(state_framepos)
227   {
228     case 0: // Brand new video frame. Set initial states.
229       state_stream_fill = 0; state_vid_parsed = 0;
230       // Create a local copy of the frame header
231       local_frame[0] = local_frame[1] = 0; local_frame[2] = 1;
232       local_frame[3] = state_frametype;
233       // If no video stream has been set, use this one.
234       if (video_current == -1) video_current = state_frametype;
235       // Get MSB of frame length and copy to local frame.
236       frame_length = *inbuf << 8;
237       local_frame[4] = *inbuf;
238       ++inbuf; ++state_framepos; ++ret; --len;
239       if (len == 0) return ret;
240       // FALL THROUGH TO NEXT BYTE IN STREAM
241     case 1: // Get LSB of frame length and copy to local frame.
242       frame_length += *inbuf;
243       local_frame[5] = *inbuf;
244       ++inbuf; ++state_framepos; ++ret; --len;
245       if (len == 0) return ret;
246       // FALL THROUGH TO NEXT BYTE IN STREAM
247     case 2: // First data byte
248       if (len >= frame_length     // If we have the entire frame
249           && !state_vid_parsed)   // and haven't parsed it yet
250       {
251         if (video_current == state_frametype) // and we're interested
252           parse_video_details(inbuf, frame_length); // then parse it
253         state_vid_parsed = 1;
254       }
255   }
256   // We are in the frame data
257   bytes_remaining = 2 + frame_length - state_framepos;
258   if (video_current != state_frametype)
259   {
260     // We don't want this frame. Throw it away.
261     if (len >= bytes_remaining)
262     {
263       inbuf += bytes_remaining;
264       ret += bytes_remaining;
265       state_frametype = state_framepos = 0;
266       return ret;
267     }
268     else
269     {
270       inbuf += len; ret += len;
271       state_framepos += len;
272       return ret;
273     }
274   } // No fall through here
275
276   if (state_vid_parsed)
277   {
278     // We have already parsed the whole frame
279     if (seeking)   // Still not found a sync point. Throw this frame away.
280     {
281       if (len >= bytes_remaining)
282       {
283         inbuf += bytes_remaining;
284         ret += bytes_remaining;
285         state_frametype = state_framepos = 0;
286         return ret;
287       }
288       else
289       {
290         inbuf += len; ret += len; return ret;
291       }
292     } // No fall through is allowed here
293     // Send frame header to stream
294     if (state_stream_fill < 6)
295     {
296       state_stream_fill += videostream.put(local_frame,
297                                    6 - state_stream_fill);
298       if (state_stream_fill < 6)   // stream is full!
299       {
300         *full = 1; return ret;
301       }
302     }
303     // Send all frame data we have to stream
304     if (len >= bytes_remaining) len = bytes_remaining;
305     stream_sent = videostream.put(inbuf, len);
306     inbuf += stream_sent; ret += stream_sent;
307     state_framepos += stream_sent;
308     state_stream_fill += stream_sent;
309     if (stream_sent != len)   // stream is full!
310     {
311       *full = 1; return ret;
312     }
313     if (state_framepos == frame_length + 2)   // frame done
314     {
315       state_frametype = state_framepos = 0;
316     }
317     return ret;
318   } // No fall through is allowed here
319
320   // We haven't parsed the frame yet. It's arriving in pieces.
321   if (bytes_remaining)   // There is data yet to copy to local_frame
322   {
323     if (len >= bytes_remaining) len = bytes_remaining;
324     memcpy(local_frame + state_framepos + 4, inbuf, len);
325     inbuf += len; ret += len; state_framepos += len;
326     if (len < bytes_remaining)   // Not all arrived yet
327       return ret;
328     parse_video_details(local_frame+6, frame_length);
329     if (seeking) // Still not found a sync point. Ignore this frame.
330       return ret;
331   }
332   // We have the whole frame in local_frame. Send it to the stream.
333   state_stream_fill += videostream.put(local_frame,
334                   6 + frame_length - state_stream_fill);
335   if (state_stream_fill < frame_length + 6)   // stream is full!
336   {
337     *full = 1; return ret;
338   }
339   state_frametype = state_framepos = 0;
340   return ret;
341 }
342
343 int Demuxer::parse_audio_frame(int len, int* full)
344 {
345   int ret = 0; // return number of bytes consumed
346   int stream_sent, bytes_remaining;
347
348   switch(state_framepos)
349   {
350     case 0: // Brand new audio frame. Set initial states.
351       state_stream_fill = 0;
352       // Create a local copy of the frame header
353       local_frame[0] = local_frame[1] = 0; local_frame[2] = 1;
354       local_frame[3] = state_frametype;
355       // If no audio stream has been set, use this one.
356       if (audio_current == -1) audio_current = state_frametype;
357       // Get MSB of frame length and copy to local frame.
358       frame_length = *inbuf << 8;
359       local_frame[4] = *inbuf;
360       ++inbuf; ++state_framepos; ++ret; --len;
361       if (len == 0) return ret;
362       // FALL THROUGH TO NEXT BYTE IN STREAM
363     case 1: // Get LSB of frame length and copy to local frame.
364       frame_length += *inbuf;
365       local_frame[5] = *inbuf;
366       ++inbuf; ++state_framepos; ++ret; --len;
367       if (len == 0) return ret;
368   }
369   // We are in the frame data
370   bytes_remaining = 2 + frame_length - state_framepos;
371   if (audio_current != state_frametype)
372   {
373     // We don't want this frame. Throw it away.
374     if (len >= bytes_remaining)
375     {
376       inbuf += bytes_remaining;
377       ret += bytes_remaining;
378       state_frametype = state_framepos = 0;
379       return ret;
380     }
381     else
382     {
383       inbuf += len; ret += len;
384       state_framepos += len;
385       return ret;
386     }
387   } // No fall through is allowed here
388
389   // Send frame header to stream
390   if (state_stream_fill < 6)
391   {
392     state_stream_fill += audiostream.put(local_frame,
393                                  6 - state_stream_fill);
394     if (state_stream_fill < 6) // stream is full!
395     {
396       *full = 1; return ret;
397     }
398   }
399   // Send all frame data we have to stream
400   if (len >= bytes_remaining) len = bytes_remaining;
401   stream_sent = audiostream.put(inbuf, len);
402   inbuf += stream_sent; ret += stream_sent;
403   state_framepos += stream_sent;
404   state_stream_fill += stream_sent;
405   if (stream_sent != len) // stream is full!
406   {
407     *full = 1; return ret;
408   }
409   if (state_framepos == frame_length + 2) // frame done
410   {
411     state_frametype = state_framepos = 0;
412   }
413   return ret;
414 }
415
416 void Demuxer::parse_video_details(UCHAR* buf, int len)
417 {
418   UCHAR byte;
419   int zeros = 0;
420   while (len >= 8) // 8 is length of a GOP header
421   {
422     // We are searching for a string of bytes (0,0,1).
423     byte = *(buf++); --len;
424
425     if (byte == 0)
426     {
427       ++zeros; continue;
428     }
429     if (zeros < 2 || byte != 1)
430     {
431       zeros = 0; continue;
432     }
433     zeros = 0;
434     // We have found the pattern (0,0,1).
435     // Check the next byte for the sub-frame type.
436     byte = *(buf++); --len;
437     switch (byte)
438     {
439       case 0x00: // Picture header
440                  // 10 bits: temporal reference
441                  //  3 bits: coding type (I/P/B)
442                  //  ...
443         if (len < 2) return;
444         if ( (buf[1] & 0x38) == 0x08 ) // I-frame
445           seeking = 0;
446         buf += 4; // Minimum length of picture header
447         len -= 4;
448         break;
449       case 0xb3: // Sequence header
450                  // 12 bits: Horizontal size
451                  // 12 bits: Vertical size
452                  //  4 bits: Aspect ratio
453                  //  4 bits: Frame rate code
454                  // 18 bits: Bit rate value
455                  // ...
456         if (len < 7) return;
457         horizontal_size = ((int)buf[0] << 4) | ((int)buf[1] >> 4);
458         vertical_size = (((int)buf[1] & 0xf) << 8) | (int)buf[2];
459         aspect_ratio = (enum AspectRatio)(buf[3] >> 4);
460         frame_rate = buf[3] & 0x0f;
461         if (frame_rate >= 1 && frame_rate <= 8)
462           frame_rate = FrameRates[frame_rate];
463         else
464           frame_rate = 0;
465         bit_rate = ((int)buf[4] << 10) |
466                    ((int)buf[5] << 2) |
467                    ((int)buf[6] >> 6);
468         seeking = 0;
469         buf += 8; // Minimum length of sequence header
470         len -= 8;
471         break;
472       case 0xb8: // Group header
473                  // We're not going to bother parsing anything.
474         seeking = 0;
475         buf += 4; // Minimum length of group header
476         len -= 4;
477         break;
478     }
479   }
480 }