more mergeback from the latest release
[glsdk/gst-plugins-ugly0-10.git] / gst / mpegstream / gstmpegdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
21 /*#define GST_DEBUG_ENABLED*/
22 #include <gstmpegdemux.h>
24 /* elementfactory information */
25 static GstElementDetails mpeg_demux_details = {
26   "MPEG System Parser",
27   "Filter/Parser/System",
28   "Demultiplexes MPEG1 and MPEG2 System Streams",
29   VERSION,
30   "Erik Walthinsen <omega@cse.ogi.edu>\n"
31   "Wim Taymans <wim.taymans@chello.be>",
32   "(C) 1999",
33 };
35 /* MPEG2Demux signals and args */
36 enum {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
41 enum {
42   ARG_0,
43   ARG_BIT_RATE,
44   ARG_MPEG2,
45   /* FILL ME */
46 };
48 GST_PAD_TEMPLATE_FACTORY (sink_factory,
49   "sink",
50   GST_PAD_SINK,
51   GST_PAD_ALWAYS,
52   GST_CAPS_NEW (
53     "mpeg_demux_sink",
54     "video/mpeg",
55       "mpegversion",  GST_PROPS_INT_RANGE (1, 2),
56       "systemstream", GST_PROPS_BOOLEAN (TRUE)
57   )
58 );
60 GST_PAD_TEMPLATE_FACTORY (audio_factory,
61   "audio_%02d",
62   GST_PAD_SRC,
63   GST_PAD_SOMETIMES,
64   GST_CAPS_NEW (
65     "mpeg_demux_audio",
66     "audio/mp3",
67     NULL
68   )
69 );
71 GST_PAD_TEMPLATE_FACTORY (video_mpeg1_factory,
72   "video_%02d",
73   GST_PAD_SRC,
74   GST_PAD_SOMETIMES,
75   GST_CAPS_NEW (
76     "mpeg_demux_video_mpeg1",
77     "video/mpeg",
78       "mpegversion",  GST_PROPS_INT (1),
79       "systemstream",  GST_PROPS_BOOLEAN (FALSE)
80   )
81 );
83 GST_PAD_TEMPLATE_FACTORY (video_mpeg2_factory,
84   "video_%02d",
85   GST_PAD_SRC,
86   GST_PAD_SOMETIMES,
87   GST_CAPS_NEW (
88     "mpeg_demux_video_mpeg2",
89     "video/mpeg",
90       "mpegversion",  GST_PROPS_INT (2),
91       "systemstream",  GST_PROPS_BOOLEAN (FALSE)
92   )
93 );
96 GST_PAD_TEMPLATE_FACTORY (private1_factory,
97   "private_stream_1_%02d",
98   GST_PAD_SRC,
99   GST_PAD_SOMETIMES,
100   GST_CAPS_NEW (
101     "mpeg_demux_private1",
102     "audio/a52",
103     NULL
104   )
105 );
107 GST_PAD_TEMPLATE_FACTORY (private2_factory,
108   "private_stream_2",
109   GST_PAD_SRC,
110   GST_PAD_SOMETIMES,
111   GST_CAPS_NEW (
112     "mpeg_demux_private2",
113     "unknown/unknown",
114     NULL
115   )
116 );
118 GST_PAD_TEMPLATE_FACTORY (subtitle_factory,
119   "subtitle_stream_%d",
120   GST_PAD_SRC,
121   GST_PAD_SOMETIMES,
122   GST_CAPS_NEW (
123     "mpeg_demux_subtitle",
124     "video/mpeg",
125     NULL
126   )
127 );
129 static void     gst_mpeg_demux_class_init       (GstMPEGDemuxClass *klass);
130 static void     gst_mpeg_demux_init             (GstMPEGDemux *mpeg_demux);
132 static gboolean gst_mpeg_demux_parse_packhead   (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
133 static gboolean gst_mpeg_demux_parse_syshead    (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
134 static gboolean gst_mpeg_demux_parse_packet     (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
135 static gboolean gst_mpeg_demux_parse_pes        (GstMPEGParse *mpeg_parse, GstBuffer *buffer);
136 static void     gst_mpeg_demux_send_data        (GstMPEGParse *mpeg_parse, GstData *data);
138 static GstElementStateReturn
139                 gst_mpeg_demux_change_state     (GstElement *element);
141 static GstMPEGParseClass *parent_class = NULL;
142 /*static guint gst_mpeg_demux_signals[LAST_SIGNAL] = { 0 };*/
144 GType
145 mpeg_demux_get_type (void)
147   static GType mpeg_demux_type = 0;
149   if (!mpeg_demux_type) {
150     static const GTypeInfo mpeg_demux_info = {
151       sizeof(GstMPEGDemuxClass),      
152       NULL,
153       NULL,
154       (GClassInitFunc)gst_mpeg_demux_class_init,
155       NULL,
156       NULL,
157       sizeof(GstMPEGDemux),
158       0,
159       (GInstanceInitFunc)gst_mpeg_demux_init,
160     };
161     mpeg_demux_type = g_type_register_static(GST_TYPE_MPEG_PARSE, "GstMPEGDemux", &mpeg_demux_info, 0);
162   }
163   return mpeg_demux_type;
166 static void
167 gst_mpeg_demux_class_init (GstMPEGDemuxClass *klass) 
169   GstMPEGParseClass *mpeg_parse_class;
170   GstElementClass *gstelement_class;
172   parent_class = g_type_class_ref (GST_TYPE_MPEG_PARSE);
174   mpeg_parse_class = (GstMPEGParseClass *) klass;
175   gstelement_class = (GstElementClass *) klass;
177   gstelement_class->change_state = gst_mpeg_demux_change_state;
179   mpeg_parse_class->parse_packhead      = gst_mpeg_demux_parse_packhead;
180   mpeg_parse_class->parse_syshead       = gst_mpeg_demux_parse_syshead;
181   mpeg_parse_class->parse_packet        = gst_mpeg_demux_parse_packet;
182   mpeg_parse_class->parse_pes           = gst_mpeg_demux_parse_pes;
183   mpeg_parse_class->send_data           = gst_mpeg_demux_send_data;
187 static void
188 gst_mpeg_demux_init (GstMPEGDemux *mpeg_demux)
190   gint i;
191   GstMPEGParse *mpeg_parse = GST_MPEG_PARSE (mpeg_demux);
193   gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
194   mpeg_parse->sinkpad = gst_pad_new_from_template(
195                   GST_PAD_TEMPLATE_GET (sink_factory), "sink");
196   gst_element_add_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->sinkpad);
197   gst_element_remove_pad (GST_ELEMENT (mpeg_parse), mpeg_parse->srcpad);
199   /* i think everything is already zero'd, but oh well*/
200   for (i=0;i<NUM_PRIVATE_1_PADS;i++) {
201     mpeg_demux->private_1_pad[i] = NULL;
202     mpeg_demux->private_1_offset[i] = 0;
203   }
204   for (i=0;i<NUM_SUBTITLE_PADS;i++) {
205     mpeg_demux->subtitle_pad[i] = NULL;
206     mpeg_demux->subtitle_offset[i] = 0;
207   }
208   mpeg_demux->private_2_pad = NULL;
209   mpeg_demux->private_2_offset = 0;
210   for (i=0;i<NUM_VIDEO_PADS;i++) {
211     mpeg_demux->video_pad[i] = NULL;
212     mpeg_demux->video_offset[i] = 0;
213     mpeg_demux->video_PTS[i] = 0;
214   }
215   for (i=0;i<NUM_AUDIO_PADS;i++) {
216     mpeg_demux->audio_pad[i] = NULL;
217     mpeg_demux->audio_offset[i] = 0;
218     mpeg_demux->audio_PTS[i] = 0;
219   }
221   GST_FLAG_SET (mpeg_demux, GST_ELEMENT_EVENT_AWARE);
224 static void
225 gst_mpeg_demux_send_data (GstMPEGParse *mpeg_parse, GstData *data)
227   if (GST_IS_BUFFER (data)) {
228     gst_buffer_unref (GST_BUFFER (data));
229   }
230   else {
231     GstEvent *event = GST_EVENT (data);
233     gst_pad_event_default (mpeg_parse->sinkpad, event);
234   }
237 static gboolean
238 gst_mpeg_demux_parse_packhead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
240   guint8 *buf;
242   parent_class->parse_packhead (mpeg_parse, buffer);
244   GST_DEBUG (0, "mpeg_demux: in parse_packhead");
246   buf = GST_BUFFER_DATA (buffer);
247   /* do something usefull here */
249   return TRUE;
252 static gboolean
253 gst_mpeg_demux_parse_syshead (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
255   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
256   guint16 header_length;
257   guchar *buf;
259   GST_DEBUG (0, "mpeg_demux: in parse_syshead");
261   buf = GST_BUFFER_DATA (buffer);
262   buf += 4;
264   header_length = GUINT16_FROM_BE (*(guint16 *) buf);
265   GST_DEBUG (0, "mpeg_demux: header_length %d", header_length);
266   buf += 2;
268   /* marker:1==1 ! rate_bound:22 | marker:1==1*/
269   buf += 3;
271   /* audio_bound:6==1 ! fixed:1 | constrained:1*/
272   buf += 1;
274   /* audio_lock:1 | video_lock:1 | marker:1==1 | video_bound:5 */
275   buf += 1;
277   /* apacket_rate_restriction:1 | reserved:7==0x7F */
278   buf += 1;
280   if (!GST_MPEG_PARSE_IS_MPEG2 (mpeg_demux)) {
281     gint stream_count = (header_length - 6) / 3;
282     gint i, j=0;
284     GST_DEBUG (0, "mpeg_demux::parse_syshead: number of streams=%d ",
285                stream_count);
287     for (i = 0; i < stream_count; i++) {
288       gint stream_num;
289       guint8 stream_id;
290       gboolean STD_buffer_bound_scale;
291       guint16 STD_buffer_size_bound;
292       guint32 buf_byte_size_bound;
293       gchar *name = NULL;
294       GstPad **outpad = NULL;
295       GstPadTemplate *newtemp = NULL;
297       stream_id = *buf++;
298       if (!(stream_id & 0x80)) {
299         GST_DEBUG (0, "mpeg_demux::parse_syshead: error in system header length");
300         return FALSE;
301       }
303       /* check marker bits */
304       if ((*buf & 0xC0) != 0xC0) {
305         GST_DEBUG (0,
306                    "mpeg_demux::parse_syshead: expecting placeholder bit values '11' after stream id\n");
307         return FALSE;
308       }
310       STD_buffer_bound_scale = *buf & 0x20;
311       STD_buffer_size_bound = (*buf++ & 0x1F) << 8;
312       STD_buffer_size_bound |= *buf++;
314       if (STD_buffer_bound_scale == 0) {
315         buf_byte_size_bound = STD_buffer_size_bound * 128;
316       }
317       else {
318         buf_byte_size_bound = STD_buffer_size_bound * 1024;
319       }
321       /* private_stream_1 */
322       if (stream_id == 0xBD) {
323         name = NULL;
324         outpad = NULL;
325       }
326       /* private_stream_2 */
327       else if (stream_id == 0xBF) {
328         name = g_strdup_printf ("private_stream_2");
329         stream_num = 0;
330         outpad = &mpeg_demux->private_2_pad;
331         newtemp = GST_PAD_TEMPLATE_GET (private2_factory);
332       }
333       /* Audio */
334       else if ((stream_id >= 0xC0) && (stream_id <= 0xDF)) {
335         name = g_strdup_printf ("audio_%02d", stream_id & 0x1F);
336         stream_num = stream_id & 0x1F;
337         outpad = &mpeg_demux->audio_pad[stream_num];
338         newtemp = GST_PAD_TEMPLATE_GET (audio_factory);
339       }
340       /* Video */
341       else if ((stream_id >= 0xE0) && (stream_id <= 0xEF)) {
342         name = g_strdup_printf ("video_%02d", stream_id & 0x0F);
343         stream_num = stream_id & 0x0F;
344         outpad = &mpeg_demux->video_pad[stream_num];
345         if (!GST_MPEG_PARSE_IS_MPEG2 (mpeg_demux)) {
346           newtemp = GST_PAD_TEMPLATE_GET (video_mpeg1_factory);
347         }
348         else {
349           newtemp = GST_PAD_TEMPLATE_GET (video_mpeg2_factory);
350         }
351       }
353       GST_DEBUG (0, "mpeg_demux::parse_syshead: stream ID 0x%02X (%s)", stream_id, name);
354       GST_DEBUG (0, "mpeg_demux::parse_syshead: STD_buffer_bound_scale %d", STD_buffer_bound_scale);
355       GST_DEBUG (0, "mpeg_demux::parse_syshead: STD_buffer_size_bound %d or %d bytes",
356                  STD_buffer_size_bound, buf_byte_size_bound);
358       /* create the pad and add it to self if it does not yet exist
359        * this should trigger the NEW_PAD signal, which should be caught by
360        * the app and used to attach to desired streams.
361        */
362       if (outpad && *outpad == NULL) {
363         *outpad = gst_pad_new_from_template (newtemp, name);
364         gst_pad_try_set_caps (*outpad, gst_pad_get_pad_template_caps (*outpad));
365         gst_element_add_pad (GST_ELEMENT (mpeg_demux), (*outpad));
366       }
367       else {
368         /* we won't be needing this. */
369         if (name)
370           g_free (name);
371       }
373       mpeg_demux->STD_buffer_info[j].stream_id = stream_id;
374       mpeg_demux->STD_buffer_info[j].STD_buffer_bound_scale =
375         STD_buffer_bound_scale;
376       mpeg_demux->STD_buffer_info[j].STD_buffer_size_bound =
377         STD_buffer_size_bound;
379       j++;
380     }
381   }
383   return TRUE;
386 static gboolean
387 gst_mpeg_demux_parse_packet (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
389   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
390   guint8 id;
391   guint16 headerlen;
393   guint16 packet_length;
394   gboolean STD_buffer_bound_scale;
395   guint16 STD_buffer_size_bound;
396   guint64 dts;
397   guint8 ps_id_code;
398   gint64 pts = -1;
400   guint16 datalen;
401   gulong outoffset = 0;   /* wrong XXX FIXME */
403   GstPad **outpad = NULL;
404   GstBuffer *outbuf;
405   guint8 *buf, *basebuf;
407   GST_DEBUG (0,"mpeg_demux::parse_packet: in parse_packet");
409   basebuf = buf = GST_BUFFER_DATA (buffer);
410   id = *(buf+3);
411   buf += 4;
413   /* start parsing */
414   packet_length = GUINT16_FROM_BE (*((guint16 *)buf));
416   GST_DEBUG (0,"mpeg_demux: got packet_length %d", packet_length);
417   headerlen = 2;
418   buf += 2;
420   /* loop through looping for stuffing bits, STD, PTS, DTS, etc */
421   do {
422     guint8 bits = *buf++;
424     /* stuffing bytes */
425     switch (bits & 0xC0) {
426       case 0xC0:
427         if (bits == 0xff) {
428           GST_DEBUG (0,"mpeg_demux::parse_packet: have stuffing byte");
429         } else {
430           GST_DEBUG (0,"mpeg_demux::parse_packet: expected stuffing byte");
431         }
432         headerlen++;
433         break;
434       case 0x40:
435         GST_DEBUG (0,"mpeg_demux::parse_packet: have STD");
437         STD_buffer_bound_scale =  bits & 0x20;
438         STD_buffer_size_bound  = (bits & 0x1F) << 8;
439         STD_buffer_size_bound |=  *buf++;
441         headerlen += 2;
442         break;
443       case 0x00:
444         switch (bits & 0x30) {
445           case 0x20:
446             /* pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
447             pts  = (bits & 0x0E)   << 29;
448             pts |=  *buf++         << 22;
449             pts |= (*buf++ & 0xFE) << 14;
450             pts |=  *buf++         <<  7;
451             pts |= (*buf++ & 0xFE) >>  1;
453             GST_DEBUG (0,"mpeg_demux::parse_packet: PTS = %llu", pts);
454             headerlen += 5;
455             goto done;
456           case 0x30:
457             /* pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
458             pts  = (bits & 0x0E)   << 29;
459             pts |=  *buf++         << 22;
460             pts |= (*buf++ & 0xFE) << 14;
461             pts |=  *buf++         <<  7;
462             pts |= (*buf++ & 0xFE) >>  1;
464             /* sync:4 ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
465             dts  = (*buf++ & 0x0E) << 29;
466             dts |=  *buf++         << 22;
467             dts |= (*buf++ & 0xFE) << 14;
468             dts |=  *buf++         <<  7;
469             dts |= (*buf++ & 0xFE) >>  1;
471             GST_DEBUG (0,"mpeg_demux::parse_packet: PTS = %llu, DTS = %llu", pts, dts);
472             headerlen += 10;
473             goto done;
474           case 0x00:
475             GST_DEBUG (0,"mpeg_demux::parse_packet: have no pts/dts");
476             GST_DEBUG (0,"mpeg_demux::parse_packet: got trailer bits %x", (bits & 0x0f));
477             if ((bits & 0x0f) != 0xf) {
478               GST_DEBUG (0,"mpeg_demux::parse_packet: not a valid packet time sequence");
479               return FALSE;
480             }
481             headerlen++;
482           default:
483             goto done;
484         }
485       default:
486         goto done;
487     } 
488   } while (1);
489   GST_DEBUG (0,"mpeg_demux::parse_packet: done with header loop");
491 done:
492   /* calculate the amount of real data in this packet */
493   datalen = packet_length - headerlen+2;
494   GST_DEBUG (0,"mpeg_demux::parse_packet: headerlen is %d, datalen is %d",
495         headerlen,datalen);
497   /* private_stream_1 */
498   if (id == 0xBD) {
499     /* first find the track code */
500     ps_id_code = *(basebuf + headerlen);
501     /* make sure it's valid */
502     if ((ps_id_code >= 0x80) && (ps_id_code <= 0x87)) {
503       GST_DEBUG (0,"mpeg_demux::parse_packet: 0x%02X: we have a private_stream_1 (AC3) packet, track %d",
504             id, ps_id_code - 0x80);
505       outpad = &mpeg_demux->private_1_pad[ps_id_code - 0x80];
506       /* scrap first 4 bytes (so-called "mystery AC3 tag") */
507       headerlen += 4;
508       datalen -= 4;
509     }
510   /* private_stream_1 */
511   } else if (id == 0xBF) {
512     GST_DEBUG (0,"mpeg_demux::parse_packet: 0x%02X: we have a private_stream_2 packet", id);
513     outpad = &mpeg_demux->private_2_pad;
514   /* audio */
515   } else if ((id >= 0xC0) && (id <= 0xDF)) {
516     GST_DEBUG (0,"mpeg_demux::parse_packet: 0x%02X: we have an audio packet", id);
517     outpad = &mpeg_demux->audio_pad[id & 0x1F];
518     outoffset = mpeg_demux->audio_offset[id & 0x1F];
519     mpeg_demux->audio_offset[id & 0x1F] += datalen;
520   /* video */
521   } else if ((id >= 0xE0) && (id <= 0xEF)) {
522     GST_DEBUG (0,"mpeg_demux::parse_packet: 0x%02X: we have a video packet", id);
523     outpad = &mpeg_demux->video_pad[id & 0x0F];
524     outoffset = mpeg_demux->video_offset[id & 0x1F];
525     mpeg_demux->video_offset[id & 0x1F] += datalen;
526     if (pts == -1) 
527       pts = mpeg_demux->video_PTS[id & 0x1F];
528     else 
529       mpeg_demux->video_PTS[id & 0x1F] = pts;
530   }
532   /* if we don't know what it is, bail */
533   if (outpad == NULL) {
534     GST_DEBUG (0,"mpeg_demux::parse_packet: unknown packet id 0x%02X !!", id);
535     /* return total number of bytes */
536     return FALSE;
537   }
539   /* FIXME, this should be done in parse_syshead */
540   if ((*outpad) == NULL) {
541     GST_DEBUG (0,"mpeg_demux::parse_packet: unexpected packet id 0x%02X!!", id);
542     /* return total number of bytes */
543     return FALSE;
544   }
546   /* create the buffer and send it off to the Other Side */
547   if (GST_PAD_IS_CONNECTED(*outpad) && datalen > 0) {
548     /* if this is part of the buffer, create a subbuffer */
549     GST_DEBUG (0,"mpeg_demux::parse_packet: creating subbuffer len %d", datalen);
551     outbuf = gst_buffer_create_sub (buffer, headerlen+4, datalen);
553     GST_BUFFER_OFFSET (outbuf) = outoffset;
554     if (pts != -1) {
555       GST_BUFFER_TIMESTAMP (outbuf) = (pts * 100LL)/9LL;
556     }
557     else {
558       GST_BUFFER_TIMESTAMP (outbuf) = -1LL;
559     }
560     GST_DEBUG (0,"mpeg_demux::parse_packet: pushing buffer of len %d id %d, ts %lld", 
561                     datalen, id, GST_BUFFER_TIMESTAMP (outbuf));
562     gst_pad_push ((*outpad), outbuf);
563   }
565   return TRUE;
568 static gboolean
569 gst_mpeg_demux_parse_pes (GstMPEGParse *mpeg_parse, GstBuffer *buffer)
571   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (mpeg_parse);
572   guint8 id;
573   gint64 pts = -1;
575   guint16 packet_length;
576   guint8 header_data_length = 0;
578   guint16 datalen;
579   gulong outoffset = 0;   /* wrong XXX FIXME  */
580   guint16 headerlen;
581   guint8 ps_id_code = 0x80;
583   GstPad **outpad = NULL;
584   GstBuffer *outbuf;
585   GstPadTemplate *newtemp = NULL;
586   guint8 *buf, *basebuf;
588   GST_DEBUG (0,"mpeg_demux: in parse_pes");
590   basebuf = buf = GST_BUFFER_DATA (buffer);
591   id = *(buf+3);
592   buf += 4;
594   /* start parsing */
595   packet_length = GUINT16_FROM_BE (*((guint16 *)buf));
597   GST_DEBUG (0,"mpeg_demux: got packet_length %d", packet_length);
598   buf += 2;
600   /* we don't operate on: program_stream_map, padding_stream, */
601   /* private_stream_2, ECM, EMM, or program_stream_directory  */
602   if ((id != 0xBC) && (id != 0xBE) && (id != 0xBF) && (id != 0xF0) &&
603       (id != 0xF1) && (id != 0xFF)) 
604   {
605     guchar flags1 = *buf++;
606     guchar flags2 = *buf++;
608     if ((flags1 & 0xC0) != 0x80) {
609       return FALSE;
610     }
612     header_data_length = *buf++;
614     GST_DEBUG (0,"mpeg_demux: header_data_length is %d",header_data_length);
616     /* check for PTS */
617     if ((flags2 & 0x80)) {
618     /*if ((flags2 & 0x80) && id == 0xe0) { */
619       pts  = (*buf++ & 0x0E) << 29;
620       pts |=  *buf++         << 22;
621       pts |= (*buf++ & 0xFE) << 14;
622       pts |=  *buf++         <<  7;
623       pts |= (*buf++ & 0xFE) >>  1;
624       GST_DEBUG (0, "mpeg_demux::parse_packet: %x PTS = %llu", id, (pts*1000000LL)/90000LL);
625     }
626     if ((flags2 & 0x40)) {
627       GST_DEBUG (0, "mpeg_demux::parse_packet: %x DTS foundu", id);
628       buf += 5;
629     }
630     if ((flags2 & 0x20)) {
631       GST_DEBUG (0, "mpeg_demux::parse_packet: %x ESCR foundu", id);
632       buf += 6;
633     }
634     if ((flags2 & 0x10)) {
635       guint32 es_rate;
637       es_rate  = (*buf++ & 0x07) << 14;
638       es_rate |= (*buf++       ) << 7;
639       es_rate |= (*buf++ & 0xFE) >> 1;
640       GST_DEBUG (0, "mpeg_demux::parse_packet: %x ES Rate foundu", id);
641     }
642     /* FIXME: lots of PES parsing missing here... */
644   }
646   /* calculate the amount of real data in this PES packet */
647   /* constant is 2 bytes packet_length, 2 bytes of bits, 1 byte header len */
648   headerlen = 5 + header_data_length;
649   /* constant is 2 bytes of bits, 1 byte header len */
650   datalen = packet_length - (3 + header_data_length);
651   GST_DEBUG (0,"mpeg_demux: headerlen is %d, datalen is %d",
652         headerlen, datalen);
654   /* private_stream_1 */
655   if (id == 0xBD) {
656     /* first find the track code */
657     ps_id_code = *(basebuf + headerlen + 4);
658     /* make sure it's valid */
659     if ((ps_id_code >= 0x80) && (ps_id_code <= 0x87)) {
660       GST_DEBUG (0,"mpeg_demux: we have a private_stream_1 (AC3) packet, track %d",
661             ps_id_code - 0x80);
662       outpad = &mpeg_demux->private_1_pad[ps_id_code - 0x80];
663       /* scrap first 4 bytes (so-called "mystery AC3 tag") */
664       headerlen += 4;
665       datalen -= 4;
666       outoffset = mpeg_demux->private_1_offset[ps_id_code - 0x80];
667       mpeg_demux->private_1_offset[ps_id_code - 0x80] += datalen;
668     }
669     else if ((ps_id_code >= 0x20) && (ps_id_code <= 0x2f)) {
670       GST_DEBUG (0,"mpeg_demux: we have a subtitle_stream packet, track %d",
671             ps_id_code - 0x20);
672       outpad = &mpeg_demux->subtitle_pad[ps_id_code - 0x20];
673       headerlen += 1;
674       datalen -= 1;
675       outoffset = mpeg_demux->subtitle_offset[ps_id_code - 0x20];
676       mpeg_demux->subtitle_offset[ps_id_code - 0x20] += datalen;
677     }
678   /* private_stream_1 */
679   } else if (id == 0xBF) {
680     GST_DEBUG (0,"mpeg_demux: we have a private_stream_2 packet");
681     outpad = &mpeg_demux->private_2_pad;
682     outoffset = mpeg_demux->private_2_offset;
683     mpeg_demux->private_2_offset += datalen;
684   /* audio */
685   } else if ((id >= 0xC0) && (id <= 0xDF)) {
686     GST_DEBUG (0,"mpeg_demux: we have an audio packet");
687     outpad = &mpeg_demux->audio_pad[id - 0xC0];
688     outoffset = mpeg_demux->audio_offset[id & 0x1F];
689     mpeg_demux->audio_offset[id & 0x1F] += datalen;
690     if (pts == -1) 
691       pts = mpeg_demux->audio_PTS[id & 0x1F];
692     else 
693       mpeg_demux->audio_PTS[id & 0x1F] = pts;
694   /* video */
695   } else if ((id >= 0xE0) && (id <= 0xEF)) {
696     GST_DEBUG (0,"mpeg_demux: we have a video packet");
697     outpad = &mpeg_demux->video_pad[id - 0xE0];
698     outoffset = mpeg_demux->video_offset[id & 0x0F];
699     mpeg_demux->video_offset[id & 0x0F] += datalen;
700     if (pts == -1) 
701       pts = mpeg_demux->video_PTS[id & 0x1F];
702     else 
703       mpeg_demux->video_PTS[id & 0x1F] = pts;
704   }
706   /* if we don't know what it is, bail */
707   if (outpad == NULL)
708     return TRUE;
710   /* create the pad and add it if we don't already have one.            */
711   /* this should trigger the NEW_PAD signal, which should be caught by  */
712   /* the app and used to attach to desired streams.                     */
713   if ((*outpad) == NULL) {
714     gchar *name = NULL;
716     /* we have to name the stream approriately */
717     if (id == 0xBD) {
718       if (ps_id_code >= 0x80 && ps_id_code <= 0x87) {
719         name = g_strdup_printf("private_stream_1.%d",ps_id_code - 0x80);
720         newtemp = GST_PAD_TEMPLATE_GET (private1_factory);
721       }
722       else if (ps_id_code >= 0x20 && ps_id_code <= 0x2f) {
723         name = g_strdup_printf("subtitle_stream_%d",ps_id_code - 0x20);
724         newtemp = GST_PAD_TEMPLATE_GET (subtitle_factory);
725       }
726       else {
727         name = g_strdup_printf("unknown_stream_%d",ps_id_code);
728       }
729     }
730     else if (id == 0xBF) {
731       name = g_strdup ("private_stream_2");
732       newtemp = GST_PAD_TEMPLATE_GET (private2_factory);
733     }
734     else if ((id >= 0xC0) && (id <= 0xDF)) {
735       name = g_strdup_printf("audio_%02d",id - 0xC0);
736       newtemp = GST_PAD_TEMPLATE_GET (audio_factory);
737     }
738     else if ((id >= 0xE0) && (id <= 0xEF)) {
739       name = g_strdup_printf("video_%02d",id - 0xE0);
740       newtemp = GST_PAD_TEMPLATE_GET (video_mpeg2_factory);
741     }
742     else {
743       name = g_strdup_printf("unknown");
744     }
746     if (newtemp) {
747       /* create the pad and add it to self */
748       (*outpad) = gst_pad_new_from_template (newtemp, name);
749       gst_pad_try_set_caps ((*outpad), gst_pad_get_pad_template_caps (*outpad));
750       gst_element_add_pad(GST_ELEMENT(mpeg_demux),(*outpad));
751     }
752     else {
753       g_warning ("mpeg_demux: cannot create pad %s, no template for %02x", name, id);
754     }
755     if (name)
756       g_free (name);
757   }
759   /* create the buffer and send it off to the Other Side */
760   if (GST_PAD_IS_CONNECTED(*outpad)) {
761     /* if this is part of the buffer, create a subbuffer */
762     GST_DEBUG (0,"mpeg_demux: creating subbuffer len %d", datalen);
764     outbuf = gst_buffer_create_sub (buffer, headerlen+4, datalen);
765     GST_BUFFER_OFFSET(outbuf) = outoffset;
766     GST_BUFFER_TIMESTAMP(outbuf) = (pts*100LL)/9LL;
768     gst_pad_push((*outpad),outbuf);
769   }
771   /* return total number of bytes */
772   return TRUE;
775 static GstElementStateReturn
776 gst_mpeg_demux_change_state (GstElement *element)
777
778   GstMPEGDemux *mpeg_demux = GST_MPEG_DEMUX (element);
779   gint i;
780             
781   switch (GST_STATE_TRANSITION (element)) {
782     case GST_STATE_READY_TO_PAUSED:
783       break;
784     case GST_STATE_PAUSED_TO_READY:
785       for (i=0;i<NUM_VIDEO_PADS;i++) {
786         mpeg_demux->video_offset[i] = 0;
787         mpeg_demux->video_PTS[i] = 0;
788       }
789       for (i=0;i<NUM_AUDIO_PADS;i++) {
790         mpeg_demux->audio_offset[i] = 0;
791         mpeg_demux->audio_PTS[i] = 0;
792       }
793       break;
794     case GST_STATE_READY_TO_NULL:
795       break;
796     default:
797       break;
798   }
800   return GST_ELEMENT_CLASS (parent_class)->change_state (element);
804 gboolean
805 gst_mpeg_demux_plugin_init (GModule *module, GstPlugin *plugin)
807   GstElementFactory *factory;
809   /* this filter needs the bytestream package */
810   if (!gst_library_load ("gstbytestream")) {
811     gst_info ("mpeg_demux:: could not load support library: 'gstbytestream'\n");
812     return FALSE;
813   }
815   /* create an elementfactory for the mpeg_demux element */
816   factory = gst_element_factory_new ("mpegdemux", GST_TYPE_MPEG_DEMUX,
817                                     &mpeg_demux_details);
818   g_return_val_if_fail (factory != NULL, FALSE);
820   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory));
821   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (video_mpeg1_factory));
822   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (video_mpeg2_factory));
823   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (private1_factory));
824   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (private2_factory));
825   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (subtitle_factory));
826   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (audio_factory));
828   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
830   return TRUE;