dd815641d94ddaf6485d3213783e70ac7018895c
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 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <string.h>
25 #include <inttypes.h>
27 #include "gstmpeg2dec.h"
29 /* mpeg2dec changed a struct name after 0.3.1, here's a workaround */
30 /* mpeg2dec also only defined MPEG2_RELEASE after 0.3.1
31 #if MPEG2_RELEASE < MPEG2_VERSION(0,3,2)
32 */
33 #ifndef MPEG2_RELEASE
34 typedef picture_t mpeg2_picture_t;
35 typedef gint mpeg2_state_t;
36 #define STATE_BUFFER 0
37 #endif
39 GST_DEBUG_CATEGORY_EXTERN (GST_CAT_SEEK);
41 /* elementfactory information */
42 static GstElementDetails gst_mpeg2dec_details = {
43 "mpeg1 and mpeg2 video decoder",
44 "Codec/Decoder/Video",
45 "Uses libmpeg2 to decode MPEG video streams",
46 "Wim Taymans <wim.taymans@chello.be>",
47 };
49 /* Mpeg2dec signals and args */
50 enum {
51 /* FILL ME */
52 LAST_SIGNAL
53 };
55 enum {
56 ARG_0,
57 ARG_STREAMINFO,
58 /* FILL ME */
59 };
61 GST_PAD_TEMPLATE_FACTORY (src_template_factory,
62 "src",
63 GST_PAD_SRC,
64 GST_PAD_ALWAYS,
65 GST_CAPS_NEW (
66 "mpeg2dec_src",
67 "video/x-raw-yuv",
68 "format", GST_PROPS_LIST (
69 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('Y','V','1','2')),
70 GST_PROPS_FOURCC (GST_MAKE_FOURCC ('I','4','2','0'))
71 ),
72 "width", GST_PROPS_INT_RANGE (16, 4096),
73 "height", GST_PROPS_INT_RANGE (16, 4096),
74 "pixel_width", GST_PROPS_INT_RANGE (1, 255),
75 "pixel_height", GST_PROPS_INT_RANGE (1, 255),
76 "framerate", GST_PROPS_LIST (
77 GST_PROPS_FLOAT (24/1.001),
78 GST_PROPS_FLOAT (24.),
79 GST_PROPS_FLOAT (25.),
80 GST_PROPS_FLOAT (30/1.001),
81 GST_PROPS_FLOAT (30.),
82 GST_PROPS_FLOAT (50.),
83 GST_PROPS_FLOAT (60/1.001),
84 GST_PROPS_FLOAT (60.)
85 )
86 )
87 );
89 GST_PAD_TEMPLATE_FACTORY (user_data_template_factory,
90 "user_data",
91 GST_PAD_SRC,
92 GST_PAD_ALWAYS,
93 GST_CAPS_NEW (
94 "mpeg2dec_user_data",
95 "application/octet-stream",
96 NULL
97 )
98 );
100 GST_PAD_TEMPLATE_FACTORY (sink_template_factory,
101 "sink",
102 GST_PAD_SINK,
103 GST_PAD_ALWAYS,
104 GST_CAPS_NEW (
105 "mpeg2dec_sink",
106 "video/mpeg",
107 /* width/height/framerate not needed */
108 "mpegversion", GST_PROPS_INT_RANGE (1, 2),
109 "systemstream", GST_PROPS_BOOLEAN (FALSE)
110 )
111 );
113 static void gst_mpeg2dec_base_init (gpointer g_class);
114 static void gst_mpeg2dec_class_init (GstMpeg2decClass *klass);
115 static void gst_mpeg2dec_init (GstMpeg2dec *mpeg2dec);
117 static void gst_mpeg2dec_dispose (GObject *object);
119 static void gst_mpeg2dec_set_property (GObject *object, guint prop_id,
120 const GValue *value, GParamSpec *pspec);
121 static void gst_mpeg2dec_get_property (GObject *object, guint prop_id,
122 GValue *value, GParamSpec *pspec);
123 static void gst_mpeg2dec_set_index (GstElement *element, GstIndex *index);
124 static GstIndex* gst_mpeg2dec_get_index (GstElement *element);
126 static const GstFormat*
127 gst_mpeg2dec_get_src_formats (GstPad *pad);
128 static const GstEventMask*
129 gst_mpeg2dec_get_src_event_masks (GstPad *pad);
130 static gboolean gst_mpeg2dec_src_event (GstPad *pad, GstEvent *event);
131 static const GstQueryType*
132 gst_mpeg2dec_get_src_query_types (GstPad *pad);
133 static gboolean gst_mpeg2dec_src_query (GstPad *pad, GstQueryType type,
134 GstFormat *format, gint64 *value);
136 static const GstFormat*
137 gst_mpeg2dec_get_sink_formats (GstPad *pad);
138 static gboolean gst_mpeg2dec_convert_sink (GstPad *pad, GstFormat src_format, gint64 src_value,
139 GstFormat *dest_format, gint64 *dest_value);
140 static gboolean gst_mpeg2dec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
141 GstFormat *dest_format, gint64 *dest_value);
143 static GstElementStateReturn
144 gst_mpeg2dec_change_state (GstElement *element);
146 static void gst_mpeg2dec_chain (GstPad *pad, GstData *_data);
148 static GstElementClass *parent_class = NULL;
149 /*static guint gst_mpeg2dec_signals[LAST_SIGNAL] = { 0 };*/
151 GType
152 gst_mpeg2dec_get_type (void)
153 {
154 static GType mpeg2dec_type = 0;
156 if (!mpeg2dec_type) {
157 static const GTypeInfo mpeg2dec_info = {
158 sizeof(GstMpeg2decClass),
159 gst_mpeg2dec_base_init,
160 NULL,
161 (GClassInitFunc)gst_mpeg2dec_class_init,
162 NULL,
163 NULL,
164 sizeof(GstMpeg2dec),
165 0,
166 (GInstanceInitFunc)gst_mpeg2dec_init,
167 };
168 mpeg2dec_type = g_type_register_static(GST_TYPE_ELEMENT, "GstMpeg2dec", &mpeg2dec_info, 0);
169 }
170 return mpeg2dec_type;
171 }
173 static void
174 gst_mpeg2dec_base_init (gpointer g_class)
175 {
176 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
178 gst_element_class_add_pad_template (element_class, GST_PAD_TEMPLATE_GET (src_template_factory));
179 gst_element_class_add_pad_template (element_class, GST_PAD_TEMPLATE_GET (sink_template_factory));
180 gst_element_class_add_pad_template (element_class, GST_PAD_TEMPLATE_GET (user_data_template_factory));
182 gst_element_class_set_details (element_class, &gst_mpeg2dec_details);
183 }
185 static void
186 gst_mpeg2dec_class_init(GstMpeg2decClass *klass)
187 {
188 GObjectClass *gobject_class;
189 GstElementClass *gstelement_class;
191 gobject_class = (GObjectClass*)klass;
192 gstelement_class = (GstElementClass*)klass;
194 parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
196 g_object_class_install_property (gobject_class, ARG_STREAMINFO,
197 g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
198 GST_TYPE_CAPS, G_PARAM_READABLE));
200 gobject_class->set_property = gst_mpeg2dec_set_property;
201 gobject_class->get_property = gst_mpeg2dec_get_property;
202 gobject_class->dispose = gst_mpeg2dec_dispose;
204 gstelement_class->change_state = gst_mpeg2dec_change_state;
205 gstelement_class->set_index = gst_mpeg2dec_set_index;
206 gstelement_class->get_index = gst_mpeg2dec_get_index;
207 }
209 static void
210 gst_mpeg2dec_init (GstMpeg2dec *mpeg2dec)
211 {
212 /* create the sink and src pads */
213 mpeg2dec->sinkpad = gst_pad_new_from_template (
214 GST_PAD_TEMPLATE_GET (sink_template_factory), "sink");
215 gst_element_add_pad (GST_ELEMENT (mpeg2dec), mpeg2dec->sinkpad);
216 gst_pad_set_chain_function (mpeg2dec->sinkpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_chain));
217 gst_pad_set_formats_function (mpeg2dec->sinkpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_get_sink_formats));
218 gst_pad_set_convert_function (mpeg2dec->sinkpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_convert_sink));
220 mpeg2dec->srcpad = gst_pad_new_from_template (
221 GST_PAD_TEMPLATE_GET (src_template_factory), "src");
222 gst_element_add_pad (GST_ELEMENT (mpeg2dec), mpeg2dec->srcpad);
223 gst_pad_set_formats_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_get_src_formats));
224 gst_pad_set_event_mask_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_get_src_event_masks));
225 gst_pad_set_event_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_src_event));
226 gst_pad_set_query_type_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_get_src_query_types));
227 gst_pad_set_query_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_src_query));
228 gst_pad_set_convert_function (mpeg2dec->srcpad, GST_DEBUG_FUNCPTR (gst_mpeg2dec_convert_src));
230 mpeg2dec->userdatapad = gst_pad_new_from_template (
231 GST_PAD_TEMPLATE_GET (user_data_template_factory), "user_data");
232 gst_element_add_pad (GST_ELEMENT (mpeg2dec), mpeg2dec->userdatapad);
234 /* initialize the mpeg2dec acceleration */
235 mpeg2_accel (MPEG2_ACCEL_DETECT);
236 mpeg2dec->closed = TRUE;
237 mpeg2dec->have_fbuf = FALSE;
239 GST_FLAG_SET (GST_ELEMENT (mpeg2dec), GST_ELEMENT_EVENT_AWARE);
240 }
242 static void
243 gst_mpeg2dec_close_decoder (GstMpeg2dec *mpeg2dec)
244 {
245 if (!mpeg2dec->closed) {
246 mpeg2_close (mpeg2dec->decoder);
247 mpeg2dec->closed = TRUE;
248 mpeg2dec->decoder = NULL;
249 }
250 }
252 static void
253 gst_mpeg2dec_open_decoder (GstMpeg2dec *mpeg2dec)
254 {
255 gst_mpeg2dec_close_decoder (mpeg2dec);
256 mpeg2dec->decoder = mpeg2_init ();
257 mpeg2dec->closed = FALSE;
258 mpeg2dec->have_fbuf = FALSE;
259 }
261 static void
262 gst_mpeg2dec_dispose (GObject *object)
263 {
264 GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (object);
266 gst_mpeg2dec_close_decoder (mpeg2dec);
268 G_OBJECT_CLASS (parent_class)->dispose (object);
269 }
271 static void
272 gst_mpeg2dec_set_index (GstElement *element, GstIndex *index)
273 {
274 GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (element);
276 mpeg2dec->index = index;
278 gst_index_get_writer_id (index, GST_OBJECT (element), &mpeg2dec->index_id);
279 }
281 static GstIndex*
282 gst_mpeg2dec_get_index (GstElement *element)
283 {
284 GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (element);
286 return mpeg2dec->index;
287 }
289 static GstBuffer*
290 gst_mpeg2dec_alloc_buffer (GstMpeg2dec *mpeg2dec, const mpeg2_info_t *info, gint64 offset)
291 {
292 GstBuffer *outbuf = NULL;
293 gint size = mpeg2dec->width * mpeg2dec->height;
294 guint8 *buf[3], *out;
295 const mpeg2_picture_t *picture;
297 if (mpeg2dec->peerpool) {
298 outbuf = gst_buffer_new_from_pool (mpeg2dec->peerpool, 0, 0);
299 }
300 if (!outbuf) {
301 outbuf = gst_buffer_new_and_alloc ((size * 3) / 2);
302 }
304 out = GST_BUFFER_DATA (outbuf);
306 buf[0] = out;
307 if (mpeg2dec->format == MPEG2DEC_FORMAT_I420) {
308 buf[1] = buf[0] + size;
309 buf[2] = buf[1] + size/4;
310 }
311 else {
312 buf[2] = buf[0] + size;
313 buf[1] = buf[2] + size/4;
314 }
316 gst_buffer_ref (outbuf);
317 mpeg2_set_buf (mpeg2dec->decoder, buf, outbuf);
319 picture = info->current_picture;
321 if (picture && (picture->flags & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I) {
322 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_KEY_UNIT);
323 }
324 else {
325 GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_KEY_UNIT);
326 }
327 /* we store the original byteoffset of this picture in the stream here
328 * because we need it for indexing */
329 GST_BUFFER_OFFSET (outbuf) = offset;
331 return outbuf;
332 }
334 static gboolean
335 gst_mpeg2dec_negotiate_format (GstMpeg2dec *mpeg2dec)
336 {
337 GstCaps *allowed;
338 GstCaps *intersect, *trylist, *head, *to_intersect;
340 if (!GST_PAD_IS_LINKED (mpeg2dec->srcpad)) {
341 mpeg2dec->format = MPEG2DEC_FORMAT_I420;
342 return TRUE;
343 }
345 /* we what we are allowed to do */
346 allowed = gst_pad_get_allowed_caps (mpeg2dec->srcpad);
347 /* we could not get allowed caps */
348 if (!allowed) {
349 allowed = GST_CAPS_NEW (
350 "mpeg2dec_negotiate",
351 "video/x-raw-yuv",
352 "format", GST_PROPS_FOURCC (GST_STR_FOURCC ("I420"))
353 );
354 }
356 to_intersect = GST_CAPS_NEW (
357 "mpeg2dec_negotiate",
358 "video/x-raw-yuv",
359 "width", GST_PROPS_INT (mpeg2dec->width),
360 "height", GST_PROPS_INT (mpeg2dec->height),
361 "pixel_width", GST_PROPS_INT (mpeg2dec->pixel_width),
362 "pixel_height", GST_PROPS_INT (mpeg2dec->pixel_height),
363 "framerate", GST_PROPS_FLOAT (1. * GST_SECOND / mpeg2dec->frame_period)
364 );
366 /* try to fix our height */
367 intersect = gst_caps_intersect (allowed, to_intersect);
368 gst_caps_unref (allowed);
369 gst_caps_unref (to_intersect);
371 /* prepare for looping */
372 head = trylist = gst_caps_normalize (intersect);
373 gst_caps_unref (intersect);
375 while (trylist) {
376 GstCaps *to_try = gst_caps_copy_1 (trylist);
378 /* try each format */
379 if (gst_pad_try_set_caps (mpeg2dec->srcpad, to_try) > 0) {
380 guint32 fourcc;
382 /* it worked, try to find what it was again */
383 gst_caps_get_fourcc_int (to_try, "format", &fourcc);
385 if (fourcc == GST_STR_FOURCC ("I420")) {
386 mpeg2dec->format = MPEG2DEC_FORMAT_I420;
387 }
388 else {
389 mpeg2dec->format = MPEG2DEC_FORMAT_YV12;
390 }
391 break;
392 }
394 trylist = trylist->next;
395 }
396 gst_caps_unref (head);
398 /* oops list exhausted and nothing was found... */
399 if (!trylist) {
400 return FALSE;
401 }
402 return TRUE;
403 }
405 static void
406 update_streaminfo (GstMpeg2dec *mpeg2dec)
407 {
408 GstCaps *caps;
409 GstProps *props;
410 GstPropsEntry *entry;
411 const mpeg2_info_t *info;
413 info = mpeg2_info (mpeg2dec->decoder);
415 props = gst_props_empty_new ();
417 entry = gst_props_entry_new ("framerate", GST_PROPS_FLOAT (GST_SECOND/(float)mpeg2dec->frame_period));
418 gst_props_add_entry (props, entry);
419 entry = gst_props_entry_new ("bitrate", GST_PROPS_INT (info->sequence->byte_rate * 8));
420 gst_props_add_entry (props, entry);
422 caps = gst_caps_new ("mpeg2dec_streaminfo",
423 "application/x-gst-streaminfo",
424 props);
426 gst_caps_replace_sink (&mpeg2dec->streaminfo, caps);
427 g_object_notify (G_OBJECT (mpeg2dec), "streaminfo");
428 }
430 static void
431 gst_mpeg2dec_flush_decoder (GstMpeg2dec *mpeg2dec)
432 {
433 mpeg2_state_t state;
435 if (mpeg2dec->decoder) {
436 const mpeg2_info_t *info = mpeg2_info (mpeg2dec->decoder);
438 do {
439 state = mpeg2_parse (mpeg2dec->decoder);
440 if (state == STATE_END) {
441 if (info->discard_fbuf && info->discard_fbuf->id) {
442 gst_buffer_unref ((GstBuffer *)info->discard_fbuf->id);
443 }
444 }
445 }
446 while (state != STATE_BUFFER && state != -1);
447 }
448 }
450 static void
451 gst_mpeg2dec_chain (GstPad *pad, GstData *_data)
452 {
453 GstBuffer *buf = GST_BUFFER (_data);
454 GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
455 guint32 size;
456 guint8 *data, *end;
457 gint64 pts;
458 const mpeg2_info_t *info;
459 mpeg2_state_t state;
460 gboolean done = FALSE;
462 if (GST_IS_EVENT (buf)) {
463 GstEvent *event = GST_EVENT (buf);
465 switch (GST_EVENT_TYPE (event)) {
466 case GST_EVENT_DISCONTINUOUS:
467 {
468 GST_DEBUG ("discont");
469 mpeg2dec->next_time = 0;
470 mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
471 gst_mpeg2dec_flush_decoder (mpeg2dec);
472 gst_pad_event_default (pad, event);
473 return;
474 }
475 case GST_EVENT_EOS:
476 if (mpeg2dec->index && mpeg2dec->closed) {
477 gst_index_commit (mpeg2dec->index, mpeg2dec->index_id);
478 }
479 default:
480 gst_pad_event_default (pad, event);
481 return;
482 }
483 }
485 size = GST_BUFFER_SIZE (buf);
486 data = GST_BUFFER_DATA (buf);
487 pts = GST_BUFFER_TIMESTAMP (buf);
489 info = mpeg2_info (mpeg2dec->decoder);
490 end = data + size;
492 if (pts != -1) {
493 gint64 mpeg_pts = GSTTIME_TO_MPEGTIME (pts);
495 GST_DEBUG ("have pts: %" G_GINT64_FORMAT " (%" G_GINT64_FORMAT ")",
496 mpeg_pts, MPEGTIME_TO_GSTTIME (mpeg_pts));
498 mpeg2_pts (mpeg2dec->decoder, mpeg_pts);
499 }
500 else {
501 GST_DEBUG ("no pts");
502 }
504 GST_DEBUG ("calling _buffer");
505 mpeg2_buffer (mpeg2dec->decoder, data, end);
506 GST_DEBUG ("calling _buffer done");
508 while (!done) {
509 gboolean slice = FALSE;
511 GST_DEBUG ("calling parse");
512 state = mpeg2_parse (mpeg2dec->decoder);
513 GST_DEBUG ("parse state %d", state);
514 switch (state) {
515 case STATE_SEQUENCE:
516 {
517 mpeg2dec->width = info->sequence->width;
518 mpeg2dec->height = info->sequence->height;
519 mpeg2dec->pixel_width = info->sequence->pixel_width;
520 mpeg2dec->pixel_height = info->sequence->pixel_height;
521 mpeg2dec->total_frames = 0;
522 mpeg2dec->frame_period = info->sequence->frame_period * GST_USECOND / 27;
524 GST_DEBUG ("sequence flags: %d, frame period: %d",
525 info->sequence->flags, info->sequence->frame_period);
526 GST_DEBUG ("profile: %02x, colour_primaries: %d",
527 info->sequence->profile_level_id, info->sequence->colour_primaries);
528 GST_DEBUG ("transfer chars: %d, matrix coef: %d",
529 info->sequence->transfer_characteristics, info->sequence->matrix_coefficients);
531 if (!gst_mpeg2dec_negotiate_format (mpeg2dec)) {
532 gst_element_error (GST_ELEMENT (mpeg2dec), "could not negotiate format");
533 goto exit;
534 }
536 /* now that we've negotiated, try to get a bufferpool */
537 mpeg2dec->peerpool = gst_pad_get_bufferpool (mpeg2dec->srcpad);
538 if (mpeg2dec->peerpool)
539 GST_INFO ( "got pool %p", mpeg2dec->peerpool);
541 update_streaminfo (mpeg2dec);
543 if (!mpeg2dec->have_fbuf) {
544 /* alloc 3 buffers */
545 gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
546 gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
547 gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
548 mpeg2dec->have_fbuf = TRUE;
549 }
551 mpeg2dec->need_sequence = FALSE;
552 if (mpeg2dec->pending_event) {
553 done = GST_EVENT_SEEK_FLAGS (mpeg2dec->pending_event) & GST_SEEK_FLAG_FLUSH;
555 gst_mpeg2dec_src_event (mpeg2dec->srcpad, mpeg2dec->pending_event);
556 mpeg2dec->pending_event = NULL;
557 }
558 break;
559 }
560 case STATE_SEQUENCE_REPEATED:
561 GST_DEBUG ("sequence repeated");
562 case STATE_GOP:
563 break;
564 case STATE_PICTURE:
565 {
566 gboolean key_frame = FALSE;
567 GstBuffer *outbuf;
569 if (info->current_picture) {
570 key_frame = (info->current_picture->flags & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I;
571 }
572 outbuf = gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
574 GST_DEBUG ("picture %d, %p, %" G_GINT64_FORMAT ", %" G_GINT64_FORMAT,
575 key_frame, outbuf, GST_BUFFER_OFFSET (outbuf), pts);
577 if (mpeg2dec->discont_state == MPEG2DEC_DISC_NEW_PICTURE && key_frame)
578 mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_KEYFRAME;
580 if (!GST_PAD_IS_USABLE (mpeg2dec->srcpad))
581 mpeg2_skip (mpeg2dec->decoder, 1);
582 else
583 mpeg2_skip (mpeg2dec->decoder, 0);
585 break;
586 }
587 case STATE_SLICE_1ST:
588 GST_DEBUG ("slice 1st");
589 break;
590 case STATE_PICTURE_2ND:
591 GST_DEBUG ("picture second");
592 break;
593 case STATE_SLICE:
594 slice = TRUE;
595 case STATE_END:
596 {
597 GstBuffer *outbuf = NULL;
598 gboolean skip = FALSE;
600 if (!slice) {
601 mpeg2dec->need_sequence = TRUE;
602 }
603 GST_DEBUG ("picture end %p %p %p %p", info->display_fbuf, info->display_picture, info->current_picture,
604 (info->display_fbuf ? info->display_fbuf->id : NULL));
606 if (info->display_fbuf && info->display_fbuf->id) {
607 const mpeg2_picture_t *picture;
608 gboolean key_frame = FALSE;
610 outbuf = (GstBuffer *) info->display_fbuf->id;
611 picture = info->display_picture;
613 key_frame = (picture->flags & PIC_MASK_CODING_TYPE) == PIC_FLAG_CODING_TYPE_I;
614 GST_DEBUG ("picture keyfame %d", key_frame);
616 if (key_frame) {
617 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_KEY_UNIT);
618 }
619 if (mpeg2dec->discont_state == MPEG2DEC_DISC_NEW_KEYFRAME && key_frame)
620 mpeg2dec->discont_state = MPEG2DEC_DISC_NONE;
622 if (picture->flags & PIC_FLAG_PTS) {
623 GstClockTime time = MPEGTIME_TO_GSTTIME (picture->pts);
625 GST_DEBUG ("picture had pts %" G_GINT64_FORMAT, time);
626 GST_BUFFER_TIMESTAMP (outbuf) = time;
628 mpeg2dec->next_time = time;
629 }
630 else {
631 GST_DEBUG ("picture didn't have pts using %" G_GINT64_FORMAT, mpeg2dec->next_time);
632 GST_BUFFER_TIMESTAMP (outbuf) = mpeg2dec->next_time;
633 }
634 mpeg2dec->next_time += (mpeg2dec->frame_period * picture->nb_fields) >> 1;
637 GST_DEBUG ("picture: %s %s fields:%d off:%" G_GINT64_FORMAT " ts:%" G_GINT64_FORMAT,
638 (picture->flags & PIC_FLAG_TOP_FIELD_FIRST ? "tff " : " "),
639 (picture->flags & PIC_FLAG_PROGRESSIVE_FRAME ? "prog" : " "),
640 picture->nb_fields,
641 GST_BUFFER_OFFSET (outbuf),
642 GST_BUFFER_TIMESTAMP (outbuf));
644 if (mpeg2dec->index) {
645 gst_index_add_association (mpeg2dec->index, mpeg2dec->index_id,
646 (key_frame ? GST_ASSOCIATION_FLAG_KEY_UNIT : 0),
647 GST_FORMAT_BYTES, GST_BUFFER_OFFSET (outbuf),
648 GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (outbuf), 0);
649 }
652 if (picture->flags & PIC_FLAG_SKIP ||
653 !GST_PAD_IS_USABLE (mpeg2dec->srcpad) ||
654 mpeg2dec->discont_state != MPEG2DEC_DISC_NONE ||
655 mpeg2dec->next_time < mpeg2dec->segment_start ||
656 skip)
657 {
658 gst_buffer_unref (outbuf);
659 }
660 else {
661 /* TODO set correct offset here based on frame number */
662 GST_BUFFER_DURATION (outbuf) = mpeg2dec->frame_period;
663 gst_pad_push (mpeg2dec->srcpad, GST_DATA (outbuf));
664 }
665 }
666 if (info->discard_fbuf && info->discard_fbuf->id) {
667 gst_buffer_unref ((GstBuffer *)info->discard_fbuf->id);
668 }
669 break;
670 }
671 /* need more data */
672 case STATE_BUFFER:
673 case -1:
674 done = TRUE;
675 break;
676 /* error */
677 case STATE_INVALID:
678 g_warning ("mpeg2dec: decoding error");
679 /* it looks like setting a new frame in libmpeg2 avoids a crash */
680 /* FIXME figure out how this screws up sync and buffer leakage */
681 gst_mpeg2dec_alloc_buffer (mpeg2dec, info, GST_BUFFER_OFFSET (buf));
682 break;
683 default:
684 g_warning ("%s: unhandled state %d, FIXME",
685 gst_element_get_name (GST_ELEMENT (mpeg2dec)),
686 state);
687 break;
688 }
690 /*
691 * FIXME: should pass more information such as state the user data is from
692 */
693 if (info->user_data_len > 0) {
694 if (GST_PAD_IS_USABLE (mpeg2dec->userdatapad)) {
695 GstBuffer *udbuf = gst_buffer_new_and_alloc (info->user_data_len);
697 memcpy (GST_BUFFER_DATA (udbuf), info->user_data, info->user_data_len);
699 gst_pad_push (mpeg2dec->userdatapad, GST_DATA (udbuf));
700 }
701 }
702 }
703 exit:
704 gst_buffer_unref(buf);
705 }
707 static const GstFormat*
708 gst_mpeg2dec_get_sink_formats (GstPad *pad)
709 {
710 static const GstFormat formats[] = {
711 GST_FORMAT_BYTES,
712 GST_FORMAT_TIME,
713 0
714 };
715 return formats;
716 }
718 static gboolean
719 gst_mpeg2dec_convert_sink (GstPad *pad, GstFormat src_format, gint64 src_value,
720 GstFormat *dest_format, gint64 *dest_value)
721 {
722 gboolean res = TRUE;
723 GstMpeg2dec *mpeg2dec;
724 const mpeg2_info_t *info;
726 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
728 if (mpeg2dec->decoder == NULL)
729 return FALSE;
731 info = mpeg2_info (mpeg2dec->decoder);
733 switch (src_format) {
734 case GST_FORMAT_BYTES:
735 switch (*dest_format) {
736 case GST_FORMAT_TIME:
737 if (info->sequence && info->sequence->byte_rate) {
738 *dest_value = GST_SECOND * src_value / info->sequence->byte_rate;
739 break;
740 }
741 default:
742 res = FALSE;
743 }
744 break;
745 case GST_FORMAT_TIME:
746 switch (*dest_format) {
747 case GST_FORMAT_BYTES:
748 if (info->sequence && info->sequence->byte_rate) {
749 *dest_value = src_value * info->sequence->byte_rate / GST_SECOND;
750 break;
751 }
752 default:
753 res = FALSE;
754 }
755 break;
756 default:
757 res = FALSE;
758 }
759 return res;
760 }
762 static const GstFormat*
763 gst_mpeg2dec_get_src_formats (GstPad *pad)
764 {
765 static const GstFormat formats[] = {
766 GST_FORMAT_BYTES,
767 GST_FORMAT_TIME,
768 GST_FORMAT_DEFAULT,
769 0
770 };
771 return formats;
772 }
774 static gboolean
775 gst_mpeg2dec_convert_src (GstPad *pad, GstFormat src_format, gint64 src_value,
776 GstFormat *dest_format, gint64 *dest_value)
777 {
778 gboolean res = TRUE;
779 GstMpeg2dec *mpeg2dec;
780 const mpeg2_info_t *info;
781 guint64 scale = 1;
783 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
785 if (mpeg2dec->decoder == NULL)
786 return FALSE;
788 info = mpeg2_info (mpeg2dec->decoder);
790 switch (src_format) {
791 case GST_FORMAT_BYTES:
792 switch (*dest_format) {
793 case GST_FORMAT_TIME:
794 default:
795 res = FALSE;
796 }
797 break;
798 case GST_FORMAT_TIME:
799 switch (*dest_format) {
800 case GST_FORMAT_BYTES:
801 scale = 6 * (mpeg2dec->width * mpeg2dec->height >> 2);
802 case GST_FORMAT_DEFAULT:
803 if (info->sequence && mpeg2dec->frame_period) {
804 *dest_value = src_value * scale / mpeg2dec->frame_period;
805 break;
806 }
807 default:
808 res = FALSE;
809 }
810 break;
811 case GST_FORMAT_DEFAULT:
812 switch (*dest_format) {
813 case GST_FORMAT_TIME:
814 *dest_value = src_value * mpeg2dec->frame_period;
815 break;
816 case GST_FORMAT_BYTES:
817 *dest_value = src_value * 6 * ((mpeg2dec->width * mpeg2dec->height) >> 2);
818 break;
819 default:
820 res = FALSE;
821 }
822 break;
823 default:
824 res = FALSE;
825 }
826 return res;
827 }
829 static const GstQueryType*
830 gst_mpeg2dec_get_src_query_types (GstPad *pad)
831 {
832 static const GstQueryType types[] = {
833 GST_QUERY_TOTAL,
834 GST_QUERY_POSITION,
835 0
836 };
837 return types;
838 }
840 static gboolean
841 gst_mpeg2dec_src_query (GstPad *pad, GstQueryType type,
842 GstFormat *format, gint64 *value)
843 {
844 gboolean res = TRUE;
845 GstMpeg2dec *mpeg2dec;
846 static const GstFormat *formats;
848 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
850 switch (type) {
851 case GST_QUERY_TOTAL:
852 {
853 switch (*format) {
854 case GST_FORMAT_TIME:
855 case GST_FORMAT_BYTES:
856 case GST_FORMAT_DEFAULT:
857 {
858 res = FALSE;
860 /* get our peer formats */
861 formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
863 /* while we did not exhaust our seek formats without result */
864 while (formats && *formats) {
865 GstFormat peer_format;
866 gint64 peer_value;
868 peer_format = *formats;
870 /* do the probe */
871 if (gst_pad_query (GST_PAD_PEER (mpeg2dec->sinkpad), GST_QUERY_TOTAL,
872 &peer_format, &peer_value))
873 {
874 GstFormat conv_format;
876 /* convert to TIME */
877 conv_format = GST_FORMAT_TIME;
878 res = gst_pad_convert (mpeg2dec->sinkpad,
879 peer_format, peer_value,
880 &conv_format, value);
881 /* and to final format */
882 res &= gst_pad_convert (pad,
883 GST_FORMAT_TIME, *value,
884 format, value);
885 }
886 formats++;
887 }
888 break;
889 }
890 default:
891 res = FALSE;
892 break;
893 }
894 break;
895 }
896 case GST_QUERY_POSITION:
897 {
898 switch (*format) {
899 default:
900 res = gst_pad_convert (pad,
901 GST_FORMAT_TIME, mpeg2dec->next_time,
902 format, value);
903 break;
904 }
905 break;
906 }
907 default:
908 res = FALSE;
909 break;
910 }
912 return res;
913 }
916 static const GstEventMask*
917 gst_mpeg2dec_get_src_event_masks (GstPad *pad)
918 {
919 static const GstEventMask masks[] = {
920 { GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH },
921 { 0, }
922 };
923 return masks;
924 }
926 static gboolean
927 index_seek (GstPad *pad, GstEvent *event)
928 {
929 GstIndexEntry *entry;
930 GstMpeg2dec *mpeg2dec;
932 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
934 entry = gst_index_get_assoc_entry (mpeg2dec->index, mpeg2dec->index_id,
935 GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
936 GST_EVENT_SEEK_FORMAT (event),
937 GST_EVENT_SEEK_OFFSET (event));
939 if (entry) {
940 const GstFormat *peer_formats, *try_formats;
941 /* since we know the exaxt byteoffset of the frame, make sure to seek on bytes first */
942 const GstFormat try_all_formats[] =
943 {
944 GST_FORMAT_BYTES,
945 GST_FORMAT_TIME,
946 0
947 };
949 try_formats = try_all_formats;
950 peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
952 while (gst_formats_contains (peer_formats, *try_formats)) {
953 gint64 value;
955 if (gst_index_entry_assoc_map (entry, *try_formats, &value)) {
956 GstEvent *seek_event;
958 GST_CAT_DEBUG (GST_CAT_SEEK, "index %s %" G_GINT64_FORMAT
959 " -> %s %" G_GINT64_FORMAT,
960 gst_format_get_details (GST_EVENT_SEEK_FORMAT (event))->nick,
961 GST_EVENT_SEEK_OFFSET (event),
962 gst_format_get_details (*try_formats)->nick,
963 value);
965 /* lookup succeeded, create the seek */
966 seek_event = gst_event_new_seek (*try_formats | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, value);
967 /* do the seekk */
968 if (gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), seek_event)) {
969 /* seek worked, we're done, loop will exit */
970 gst_mpeg2dec_flush_decoder (mpeg2dec);
971 mpeg2dec->segment_start = GST_EVENT_SEEK_OFFSET (event);
972 return TRUE;
973 }
974 }
975 try_formats++;
976 }
977 }
978 return FALSE;
979 }
982 static gboolean
983 normal_seek (GstPad *pad, GstEvent *event)
984 {
985 gint64 src_offset;
986 gboolean flush;
987 GstFormat format;
988 const GstFormat *peer_formats;
989 gboolean res = FALSE;
990 GstMpeg2dec *mpeg2dec;
992 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
994 format = GST_FORMAT_TIME;
996 /* first bring the src_format to TIME */
997 if (!gst_pad_convert (pad,
998 GST_EVENT_SEEK_FORMAT (event), GST_EVENT_SEEK_OFFSET (event),
999 &format, &src_offset))
1000 {
1001 /* didn't work, probably unsupported seek format then */
1002 return res;
1003 }
1005 /* shave off the flush flag, we'll need it later */
1006 flush = GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH;
1008 /* get our peer formats */
1009 peer_formats = gst_pad_get_formats (GST_PAD_PEER (mpeg2dec->sinkpad));
1011 /* while we did not exhaust our seek formats without result */
1012 while (peer_formats && *peer_formats) {
1013 gint64 desired_offset;
1015 format = *peer_formats;
1017 /* try to convert requested format to one we can seek with on the sinkpad */
1018 if (gst_pad_convert (mpeg2dec->sinkpad, GST_FORMAT_TIME, src_offset, &format, &desired_offset))
1019 {
1020 GstEvent *seek_event;
1022 /* conversion succeeded, create the seek */
1023 seek_event = gst_event_new_seek (format | GST_SEEK_METHOD_SET | flush, desired_offset);
1024 /* do the seekk */
1025 if (gst_pad_send_event (GST_PAD_PEER (mpeg2dec->sinkpad), seek_event)) {
1026 /* seek worked, we're done, loop will exit */
1027 mpeg2dec->segment_start = GST_EVENT_SEEK_OFFSET (event);
1028 res = TRUE;
1029 break;
1030 }
1031 }
1032 peer_formats++;
1033 }
1034 /* at this point, either the seek worked and res = TRUE or res == FALSE and the seek
1035 * failed */
1036 if (res && flush) {
1037 /* if we need to flush, iterate until the buffer is empty */
1038 gst_mpeg2dec_flush_decoder (mpeg2dec);
1039 }
1041 return res;
1042 }
1043 static gboolean
1044 gst_mpeg2dec_src_event (GstPad *pad, GstEvent *event)
1045 {
1046 gboolean res = TRUE;
1047 GstMpeg2dec *mpeg2dec;
1049 mpeg2dec = GST_MPEG2DEC (gst_pad_get_parent (pad));
1051 if (mpeg2dec->decoder == NULL)
1052 return FALSE;
1054 switch (GST_EVENT_TYPE (event)) {
1055 /* the all-formats seek logic */
1056 case GST_EVENT_SEEK:
1057 if (mpeg2dec->need_sequence) {
1058 mpeg2dec->pending_event = event;
1059 return TRUE;
1060 }
1061 else {
1062 if (mpeg2dec->index)
1063 res = index_seek (pad, event);
1064 else
1065 res = normal_seek (pad, event);
1067 if (res)
1068 mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
1069 }
1070 break;
1071 default:
1072 res = FALSE;
1073 break;
1074 }
1075 gst_event_unref (event);
1076 return res;
1077 }
1079 static GstElementStateReturn
1080 gst_mpeg2dec_change_state (GstElement *element)
1081 {
1082 GstMpeg2dec *mpeg2dec = GST_MPEG2DEC (element);
1084 switch (GST_STATE_TRANSITION (element)) {
1085 case GST_STATE_NULL_TO_READY:
1086 break;
1087 case GST_STATE_READY_TO_PAUSED:
1088 {
1089 mpeg2dec->next_time = 0;
1090 mpeg2dec->peerpool = NULL;
1092 /* reset the initial video state */
1093 mpeg2dec->format = MPEG2DEC_FORMAT_NONE;
1094 mpeg2dec->width = -1;
1095 mpeg2dec->height = -1;
1096 mpeg2dec->segment_start = 0;
1097 mpeg2dec->segment_end = -1;
1098 mpeg2dec->discont_state = MPEG2DEC_DISC_NEW_PICTURE;
1099 mpeg2dec->frame_period = 0;
1100 mpeg2dec->streaminfo = NULL;
1101 gst_mpeg2dec_open_decoder (mpeg2dec);
1102 mpeg2dec->need_sequence = TRUE;
1103 break;
1104 }
1105 case GST_STATE_PAUSED_TO_PLAYING:
1106 /* if we've negotiated caps, try to get a bufferpool */
1107 if (mpeg2dec->peerpool == NULL && mpeg2dec->width > 0) {
1108 mpeg2dec->peerpool = gst_pad_get_bufferpool (mpeg2dec->srcpad);
1109 if (mpeg2dec->peerpool)
1110 GST_INFO ( "got pool %p", mpeg2dec->peerpool);
1111 }
1112 break;
1113 case GST_STATE_PLAYING_TO_PAUSED:
1114 /* need to clear things we get from other plugins, since we could be reconnected */
1115 if (mpeg2dec->peerpool) {
1116 gst_buffer_pool_unref (mpeg2dec->peerpool);
1117 mpeg2dec->peerpool = NULL;
1118 }
1119 break;
1120 case GST_STATE_PAUSED_TO_READY:
1121 gst_mpeg2dec_close_decoder (mpeg2dec);
1122 gst_caps_replace (&mpeg2dec->streaminfo, NULL);
1123 break;
1124 case GST_STATE_READY_TO_NULL:
1125 break;
1126 default:
1127 break;
1128 }
1130 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
1131 }
1133 static void
1134 gst_mpeg2dec_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
1135 {
1136 GstMpeg2dec *src;
1138 /* it's not null if we got it, but it might not be ours */
1139 g_return_if_fail (GST_IS_MPEG2DEC (object));
1140 src = GST_MPEG2DEC (object);
1142 switch (prop_id) {
1143 default:
1144 break;
1145 }
1146 }
1148 static void
1149 gst_mpeg2dec_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1150 {
1151 GstMpeg2dec *mpeg2dec;
1153 /* it's not null if we got it, but it might not be ours */
1154 g_return_if_fail (GST_IS_MPEG2DEC (object));
1155 mpeg2dec = GST_MPEG2DEC (object);
1157 switch (prop_id) {
1158 case ARG_STREAMINFO:
1159 g_value_set_boxed (value, mpeg2dec->streaminfo);
1160 break;
1161 default:
1162 break;
1163 }
1164 }
1166 static gboolean
1167 plugin_init (GstPlugin *plugin)
1168 {
1169 if (!gst_element_register (plugin, "mpeg2dec", GST_RANK_PRIMARY, GST_TYPE_MPEG2DEC))
1170 return FALSE;
1172 return TRUE;
1173 }
1175 GST_PLUGIN_DEFINE (
1176 GST_VERSION_MAJOR,
1177 GST_VERSION_MINOR,
1178 "mpeg2dec",
1179 "LibMpeg2 decoder",
1180 plugin_init,
1181 VERSION,
1182 "GPL",
1183 GST_COPYRIGHT,
1184 GST_PACKAGE,
1185 GST_ORIGIN)