2 * Copyright (C) 2006 David Schleef <ds@schleef.org>
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.
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.
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.
25 #include <gst/base/gstadapter.h>
26 #include <gst/video/video.h>
27 #include <gst/video/gstbasevideodecoder.h>
29 #include <schroedinger/schro.h>
31 #include "gstschroutils.h"
33 #include <schroedinger/schroparse.h>
35 GST_DEBUG_CATEGORY_EXTERN (schro_debug);
36 #define GST_CAT_DEFAULT schro_debug
38 #define GST_TYPE_SCHRO_DEC \
39 (gst_schro_dec_get_type())
40 #define GST_SCHRO_DEC(obj) \
41 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SCHRO_DEC,GstSchroDec))
42 #define GST_SCHRO_DEC_CLASS(klass) \
43 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SCHRO_DEC,GstSchroDecClass))
44 #define GST_IS_SCHRO_DEC(obj) \
45 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SCHRO_DEC))
46 #define GST_IS_SCHRO_DEC_CLASS(obj) \
47 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHRO_DEC))
49 typedef struct _GstSchroDec GstSchroDec;
50 typedef struct _GstSchroDecClass GstSchroDecClass;
54 GstBaseVideoDecoder base_video_decoder;
56 SchroDecoder *decoder;
58 gboolean seq_header_buffer_seen;
61 struct _GstSchroDecClass
63 GstBaseVideoDecoderClass base_video_decoder_class;
66 GType gst_schro_dec_get_type (void);
69 /* GstSchroDec signals and args */
80 static void gst_schro_dec_finalize (GObject * object);
82 static gboolean gst_schro_dec_sink_query (GstPad * pad, GstQuery * query);
84 static gboolean gst_schro_dec_start (GstBaseVideoDecoder * dec);
85 static gboolean gst_schro_dec_stop (GstBaseVideoDecoder * dec);
86 static gboolean gst_schro_dec_reset (GstBaseVideoDecoder * dec);
87 static GstFlowReturn gst_schro_dec_parse_data (GstBaseVideoDecoder *
88 base_video_decoder, gboolean at_eos);
89 static GstFlowReturn gst_schro_dec_handle_frame (GstBaseVideoDecoder * decoder,
90 GstVideoFrame * frame);
91 static gboolean gst_schro_dec_finish (GstBaseVideoDecoder * base_video_decoder);
92 static void gst_schrodec_send_tags (GstSchroDec * schro_dec);
94 static GstStaticPadTemplate gst_schro_dec_sink_template =
95 GST_STATIC_PAD_TEMPLATE ("sink",
98 GST_STATIC_CAPS ("video/x-dirac")
101 static GstStaticPadTemplate gst_schro_dec_src_template =
102 GST_STATIC_PAD_TEMPLATE ("src",
105 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, AYUV }"))
108 GST_BOILERPLATE (GstSchroDec, gst_schro_dec, GstBaseVideoDecoder,
109 GST_TYPE_BASE_VIDEO_DECODER);
112 gst_schro_dec_base_init (gpointer g_class)
115 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
117 gst_element_class_add_static_pad_template (element_class,
118 &gst_schro_dec_src_template);
119 gst_element_class_add_static_pad_template (element_class,
120 &gst_schro_dec_sink_template);
122 gst_element_class_set_details_simple (element_class, "Dirac Decoder",
123 "Codec/Decoder/Video",
124 "Decode Dirac streams", "David Schleef <ds@schleef.org>");
128 gst_schro_dec_class_init (GstSchroDecClass * klass)
130 GObjectClass *gobject_class;
131 GstBaseVideoDecoderClass *base_video_decoder_class;
133 gobject_class = G_OBJECT_CLASS (klass);
134 base_video_decoder_class = GST_BASE_VIDEO_DECODER_CLASS (klass);
136 gobject_class->finalize = gst_schro_dec_finalize;
138 base_video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_schro_dec_start);
139 base_video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_schro_dec_stop);
140 base_video_decoder_class->reset = GST_DEBUG_FUNCPTR (gst_schro_dec_reset);
141 base_video_decoder_class->parse_data =
142 GST_DEBUG_FUNCPTR (gst_schro_dec_parse_data);
143 base_video_decoder_class->handle_frame =
144 GST_DEBUG_FUNCPTR (gst_schro_dec_handle_frame);
145 base_video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_schro_dec_finish);
147 gst_base_video_decoder_class_set_capture_pattern (base_video_decoder_class,
148 0xffffffff, 0x42424344);
152 gst_schro_dec_init (GstSchroDec * schro_dec, GstSchroDecClass * klass)
154 GST_DEBUG ("gst_schro_dec_init");
156 gst_pad_set_query_function (GST_BASE_VIDEO_CODEC_SINK_PAD (schro_dec),
157 gst_schro_dec_sink_query);
159 schro_dec->decoder = schro_decoder_new ();
162 #define OGG_DIRAC_GRANULE_SHIFT 22
163 #define OGG_DIRAC_GRANULE_LOW_MASK ((1ULL<<OGG_DIRAC_GRANULE_SHIFT)-1)
166 granulepos_to_frame (gint64 granulepos)
170 if (granulepos == -1)
173 pt = ((granulepos >> 22) + (granulepos & OGG_DIRAC_GRANULE_LOW_MASK)) >> 9;
174 /* dist_h = (granulepos >> 22) & 0xff;
175 * dist_l = granulepos & 0xff;
176 * dist = (dist_h << 8) | dist_l;
177 * delay = (granulepos >> 9) & 0x1fff;
178 * dt = pt - delay; */
184 gst_schro_dec_sink_convert (GstPad * pad,
185 GstFormat src_format, gint64 src_value,
186 GstFormat * dest_format, gint64 * dest_value)
190 GstVideoState *state;
192 if (src_format == *dest_format) {
193 *dest_value = src_value;
197 dec = GST_SCHRO_DEC (gst_pad_get_parent (pad));
199 /* FIXME: check if we are in a decoding state */
201 state = gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER (dec));
204 if (src_format == GST_FORMAT_DEFAULT && *dest_format == GST_FORMAT_TIME) {
205 if (state->fps_d != 0) {
206 *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value),
207 state->fps_d * GST_SECOND, state->fps_n);
214 gst_object_unref (dec);
220 gst_schro_dec_sink_query (GstPad * pad, GstQuery * query)
223 gboolean res = FALSE;
225 dec = GST_SCHRO_DEC (gst_pad_get_parent (pad));
227 switch (GST_QUERY_TYPE (query)) {
228 case GST_QUERY_CONVERT:
230 GstFormat src_fmt, dest_fmt;
231 gint64 src_val, dest_val;
233 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
234 res = gst_schro_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt,
238 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
242 res = gst_pad_query_default (pad, query);
246 gst_object_unref (dec);
250 GST_DEBUG_OBJECT (dec, "query failed");
255 gst_schro_dec_start (GstBaseVideoDecoder * dec)
262 gst_schro_dec_stop (GstBaseVideoDecoder * dec)
269 gst_schro_dec_reset (GstBaseVideoDecoder * dec)
271 GstSchroDec *schro_dec;
273 schro_dec = GST_SCHRO_DEC (dec);
277 if (schro_dec->decoder) {
278 schro_decoder_reset (schro_dec->decoder);
285 gst_schro_dec_finalize (GObject * object)
287 GstSchroDec *schro_dec;
289 g_return_if_fail (GST_IS_SCHRO_DEC (object));
290 schro_dec = GST_SCHRO_DEC (object);
292 if (schro_dec->decoder) {
293 schro_decoder_free (schro_dec->decoder);
294 schro_dec->decoder = NULL;
297 G_OBJECT_CLASS (parent_class)->finalize (object);
301 parse_sequence_header (GstSchroDec * schro_dec, guint8 * data, int size)
303 SchroVideoFormat video_format;
305 GstVideoState *state;
307 GST_DEBUG_OBJECT (schro_dec, "parse_sequence_header size=%d", size);
309 state = gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER (schro_dec));
311 schro_dec->seq_header_buffer_seen = TRUE;
313 ret = schro_parse_decode_sequence_header (data + 13, size - 13,
316 if (video_format.chroma_format == SCHRO_CHROMA_444) {
317 state->format = GST_VIDEO_FORMAT_AYUV;
318 } else if (video_format.chroma_format == SCHRO_CHROMA_422) {
319 state->format = GST_VIDEO_FORMAT_YUY2;
320 } else if (video_format.chroma_format == SCHRO_CHROMA_420) {
321 state->format = GST_VIDEO_FORMAT_I420;
323 state->fps_n = video_format.frame_rate_numerator;
324 state->fps_d = video_format.frame_rate_denominator;
325 GST_DEBUG_OBJECT (schro_dec, "Frame rate is %d/%d", state->fps_n,
328 state->width = video_format.width;
329 state->height = video_format.height;
330 GST_DEBUG ("Frame dimensions are %d x %d\n", state->width, state->height);
332 state->clean_width = video_format.clean_width;
333 state->clean_height = video_format.clean_height;
334 state->clean_offset_left = video_format.left_offset;
335 state->clean_offset_top = video_format.top_offset;
337 state->par_n = video_format.aspect_ratio_numerator;
338 state->par_d = video_format.aspect_ratio_denominator;
339 GST_DEBUG ("Pixel aspect ratio is %d/%d", state->par_n, state->par_d);
341 gst_base_video_decoder_set_src_caps (GST_BASE_VIDEO_DECODER (schro_dec));
343 GST_WARNING ("Failed to get frame rate from sequence header");
346 gst_schrodec_send_tags (schro_dec);
351 gst_schro_dec_parse_data (GstBaseVideoDecoder * base_video_decoder,
354 GstSchroDec *schro_decoder;
355 unsigned char header[SCHRO_PARSE_HEADER_SIZE];
360 GST_DEBUG_OBJECT (base_video_decoder, "parse_data");
362 schro_decoder = GST_SCHRO_DEC (base_video_decoder);
364 if (gst_adapter_available (base_video_decoder->input_adapter) <
365 SCHRO_PARSE_HEADER_SIZE) {
366 return GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA;
369 GST_DEBUG ("available %d",
370 gst_adapter_available (base_video_decoder->input_adapter));
372 gst_adapter_copy (base_video_decoder->input_adapter, header, 0,
373 SCHRO_PARSE_HEADER_SIZE);
375 parse_code = header[4];
376 next = GST_READ_UINT32_BE (header + 5);
377 prev = GST_READ_UINT32_BE (header + 9);
379 GST_DEBUG ("%08x %02x %08x %08x",
380 GST_READ_UINT32_BE (header), parse_code, next, prev);
382 if (memcmp (header, "BBCD", 4) != 0 ||
383 (next & 0xf0000000) || (prev & 0xf0000000)) {
384 gst_base_video_decoder_lost_sync (base_video_decoder);
385 return GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA;
388 if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE (parse_code)) {
389 GstVideoFrame *frame;
391 if (next != 0 && next != SCHRO_PARSE_HEADER_SIZE) {
392 GST_WARNING ("next is not 0 or 13 in EOS packet (%d)", next);
395 gst_base_video_decoder_add_to_frame (base_video_decoder,
396 SCHRO_PARSE_HEADER_SIZE);
398 frame = base_video_decoder->current_frame;
399 frame->is_eos = TRUE;
403 return gst_base_video_decoder_have_frame (base_video_decoder);
406 if (gst_adapter_available (base_video_decoder->input_adapter) < next) {
407 return GST_BASE_VIDEO_DECODER_FLOW_NEED_DATA;
410 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER (parse_code)) {
413 data = g_malloc (next);
415 gst_adapter_copy (base_video_decoder->input_adapter, data, 0, next);
416 parse_sequence_header (schro_decoder, data, next);
418 gst_base_video_decoder_set_sync_point (base_video_decoder);
421 if (GST_CLOCK_TIME_IS_VALID (base_video_decoder->last_sink_timestamp)) {
422 base_video_decoder->current_frame->presentation_timestamp =
423 base_video_decoder->last_sink_timestamp;
424 GST_DEBUG ("got timestamp %" G_GINT64_FORMAT,
425 base_video_decoder->last_sink_timestamp);
426 } else if (base_video_decoder->last_sink_offset_end != -1) {
427 GstVideoState *state;
430 /* FIXME perhaps should use this to determine if the granulepos
439 gint64 granulepos = base_video_decoder->last_sink_offset_end;
441 pt = ((granulepos >> 22) +
442 (granulepos & OGG_DIRAC_GRANULE_LOW_MASK)) >> 9;
443 dist_h = (granulepos >> 22) & 0xff;
444 dist_l = granulepos & 0xff;
445 dist = (dist_h << 8) | dist_l;
446 delay = (granulepos >> 9) & 0x1fff;
448 GST_DEBUG ("gp pt %lld dist %d delay %d dt %lld", pt, dist, delay, dt);
451 state = gst_base_video_decoder_get_state (base_video_decoder);
452 base_video_decoder->current_frame->presentation_timestamp =
453 gst_util_uint64_scale (granulepos_to_frame
454 (base_video_decoder->last_sink_offset_end), state->fps_d * GST_SECOND,
457 base_video_decoder->current_frame->presentation_timestamp = -1;
464 if (!schro_decoder->seq_header_buffer_seen) {
465 gst_adapter_flush (base_video_decoder->input_adapter, next);
469 if (SCHRO_PARSE_CODE_IS_PICTURE (parse_code)) {
470 GstVideoFrame *frame;
473 frame = base_video_decoder->current_frame;
475 gst_adapter_copy (base_video_decoder->input_adapter, tmp,
476 SCHRO_PARSE_HEADER_SIZE, 4);
478 frame->presentation_frame_number = GST_READ_UINT32_BE (tmp);
480 gst_base_video_decoder_add_to_frame (base_video_decoder, next);
482 return gst_base_video_decoder_have_frame (base_video_decoder);
484 gst_base_video_decoder_add_to_frame (base_video_decoder, next);
491 gst_schrodec_send_tags (GstSchroDec * schro_dec)
495 list = gst_tag_list_new ();
496 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
497 GST_TAG_VIDEO_CODEC, "Dirac", NULL);
499 gst_element_found_tags_for_pad (GST_ELEMENT_CAST (schro_dec),
500 GST_BASE_VIDEO_CODEC_SRC_PAD (schro_dec), list);
504 gst_schro_dec_process (GstSchroDec * schro_dec, gboolean eos)
514 it = schro_decoder_autoparse_wait (schro_dec->decoder);
517 case SCHRO_DECODER_FIRST_ACCESS_UNIT:
519 case SCHRO_DECODER_NEED_BITS:
520 GST_DEBUG ("need bits");
523 case SCHRO_DECODER_NEED_FRAME:
526 GstVideoState *state;
527 SchroFrame *schro_frame;
529 GST_DEBUG ("need frame");
532 gst_base_video_decoder_get_state (GST_BASE_VIDEO_DECODER
535 gst_base_video_decoder_alloc_src_buffer (GST_BASE_VIDEO_DECODER
538 gst_schro_buffer_wrap (outbuf, state->format, state->width,
540 schro_decoder_add_output_picture (schro_dec->decoder, schro_frame);
543 case SCHRO_DECODER_OK:
545 SchroFrame *schro_frame;
547 GstVideoFrame *frame;
549 GST_DEBUG ("got frame");
551 tag = schro_decoder_get_picture_tag (schro_dec->decoder);
552 schro_frame = schro_decoder_pull (schro_dec->decoder);
556 if (schro_frame->priv) {
557 GstFlowReturn flow_ret;
559 frame->src_buffer = gst_buffer_ref (GST_BUFFER (schro_frame->priv));
562 gst_base_video_decoder_finish_frame (GST_BASE_VIDEO_DECODER
564 if (flow_ret != GST_FLOW_OK) {
565 GST_DEBUG ("finish frame returned %d", flow_ret);
569 GST_DEBUG ("skipped frame");
572 schro_frame_unref (schro_frame);
575 schro_tag_free (tag);
582 case SCHRO_DECODER_EOS:
586 case SCHRO_DECODER_ERROR:
588 GST_DEBUG ("codec error");
589 ret = GST_FLOW_ERROR;
599 gst_schro_dec_handle_frame (GstBaseVideoDecoder * base_video_decoder,
600 GstVideoFrame * frame)
602 GstSchroDec *schro_dec;
603 SchroBuffer *input_buffer;
605 schro_dec = GST_SCHRO_DEC (base_video_decoder);
607 GST_DEBUG ("handle frame");
609 input_buffer = gst_schro_wrap_gst_buffer (frame->sink_buffer);
610 frame->sink_buffer = NULL;
612 input_buffer->tag = schro_tag_new (frame, NULL);
614 schro_decoder_autoparse_push (schro_dec->decoder, input_buffer);
616 return gst_schro_dec_process (schro_dec, FALSE);
620 gst_schro_dec_finish (GstBaseVideoDecoder * base_video_decoder)
622 GstSchroDec *schro_dec;
624 schro_dec = GST_SCHRO_DEC (base_video_decoder);
626 GST_DEBUG ("finish");
628 schro_decoder_autoparse_push_end_of_sequence (schro_dec->decoder);
630 return gst_schro_dec_process (schro_dec, TRUE);