[encoder] Improved motion estimation.
[schroedinger/research-port.git] / gst / gstschroparse.c
blob552478d22d73487cb8168a5fa1200259854e4e90
1 /* Schrodinger
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.
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <gst/gst.h>
25 #include <gst/base/gstbasetransform.h>
26 #include <gst/base/gstadapter.h>
27 #include <gst/video/video.h>
28 #include <string.h>
29 #include <schroedinger/schro.h>
30 #include <liboil/liboil.h>
31 #include <math.h>
33 #include "gstbasevideoparse.h"
35 #define SCHRO_ENABLE_UNSTABLE_API
36 #include <schroedinger/schroparse.h>
39 GST_DEBUG_CATEGORY_EXTERN (schro_debug);
40 #define GST_CAT_DEFAULT schro_debug
42 #define GST_TYPE_SCHRO_PARSE \
43 (gst_schro_parse_get_type())
44 #define GST_SCHRO_PARSE(obj) \
45 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SCHRO_PARSE,GstSchroParse))
46 #define GST_SCHRO_PARSE_CLASS(klass) \
47 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SCHRO_PARSE,GstSchroParseClass))
48 #define GST_IS_SCHRO_PARSE(obj) \
49 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SCHRO_PARSE))
50 #define GST_IS_SCHRO_PARSE_CLASS(obj) \
51 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHRO_PARSE))
53 typedef struct _GstSchroParse GstSchroParse;
54 typedef struct _GstSchroParseClass GstSchroParseClass;
56 typedef enum {
57 GST_SCHRO_PARSE_OUTPUT_OGG,
58 GST_SCHRO_PARSE_OUTPUT_QUICKTIME,
59 GST_SCHRO_PARSE_OUTPUT_AVI,
60 GST_SCHRO_PARSE_OUTPUT_MPEG_TS
61 } GstSchroParseOutputType;
63 struct _GstSchroParse
65 GstBaseVideoParse base_video_parse;
67 GstPad *sinkpad, *srcpad;
69 GstSchroParseOutputType output_format;
71 GstBuffer *seq_header_buffer;
73 /* state */
76 gboolean have_picture;
77 int buf_picture_number;
78 int seq_hdr_picture_number;
79 int picture_number;
81 guint64 last_granulepos;
83 int bytes_per_picture;
86 struct _GstSchroParseClass
88 GstBaseVideoParseClass base_video_parse_class;
91 /* GstSchroParse signals and args */
92 enum
94 LAST_SIGNAL
97 enum
99 ARG_0
102 static void gst_schro_parse_finalize (GObject *object);
104 static gboolean gst_schro_parse_start (GstBaseVideoParse *base_video_parse);
105 static gboolean gst_schro_parse_stop (GstBaseVideoParse *base_video_parse);
106 static gboolean gst_schro_parse_reset (GstBaseVideoParse *base_video_parse);
107 static int gst_schro_parse_scan_for_sync (GstAdapter *adapter,
108 gboolean at_eos, int offset, int n);
109 static gboolean gst_schro_parse_parse_data (GstBaseVideoParse *base_video_parse,
110 gboolean at_eos);
111 static gboolean gst_schro_parse_shape_output (GstBaseVideoParse *base_video_parse, GstVideoFrame *frame);
112 static GstCaps * gst_schro_parse_get_caps (GstBaseVideoParse *base_video_parse);
116 static GstStaticPadTemplate gst_schro_parse_sink_template =
117 GST_STATIC_PAD_TEMPLATE ("sink",
118 GST_PAD_SINK,
119 GST_PAD_ALWAYS,
120 GST_STATIC_CAPS ("video/x-dirac")
123 static GstStaticPadTemplate gst_schro_parse_src_template =
124 GST_STATIC_PAD_TEMPLATE ("src",
125 GST_PAD_SRC,
126 GST_PAD_ALWAYS,
127 GST_STATIC_CAPS ("video/x-dirac;video/x-qt-part;video/x-avi-part")
130 GST_BOILERPLATE (GstSchroParse, gst_schro_parse, GstBaseVideoParse, GST_TYPE_BASE_VIDEO_PARSE);
132 static void
133 gst_schro_parse_base_init (gpointer g_class)
135 static GstElementDetails compress_details =
136 GST_ELEMENT_DETAILS ("Dirac Parser",
137 "Codec/Parser/Video",
138 "Parse Dirac streams",
139 "David Schleef <ds@schleef.org>");
140 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
142 gst_element_class_add_pad_template (element_class,
143 gst_static_pad_template_get (&gst_schro_parse_src_template));
144 gst_element_class_add_pad_template (element_class,
145 gst_static_pad_template_get (&gst_schro_parse_sink_template));
147 gst_element_class_set_details (element_class, &compress_details);
150 static void
151 gst_schro_parse_class_init (GstSchroParseClass *klass)
153 GObjectClass *gobject_class;
154 GstElementClass *element_class;
155 GstBaseVideoParseClass *base_video_parse_class;
157 gobject_class = G_OBJECT_CLASS (klass);
158 element_class = GST_ELEMENT_CLASS (klass);
159 base_video_parse_class = GST_BASE_VIDEO_PARSE_CLASS (klass);
161 gobject_class->finalize = gst_schro_parse_finalize;
163 base_video_parse_class->start = GST_DEBUG_FUNCPTR(gst_schro_parse_start);
164 base_video_parse_class->stop = GST_DEBUG_FUNCPTR(gst_schro_parse_stop);
165 base_video_parse_class->reset = GST_DEBUG_FUNCPTR(gst_schro_parse_reset);
166 base_video_parse_class->parse_data = GST_DEBUG_FUNCPTR(gst_schro_parse_parse_data);
167 base_video_parse_class->shape_output = GST_DEBUG_FUNCPTR(gst_schro_parse_shape_output);
168 base_video_parse_class->scan_for_sync = GST_DEBUG_FUNCPTR(gst_schro_parse_scan_for_sync);
169 base_video_parse_class->get_caps = GST_DEBUG_FUNCPTR(gst_schro_parse_get_caps);
173 static void
174 gst_schro_parse_init (GstSchroParse *schro_parse, GstSchroParseClass *klass)
176 GstBaseVideoParse *base_video_parse = GST_BASE_VIDEO_PARSE(schro_parse);
178 GST_DEBUG ("gst_schro_parse_init");
180 schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_OGG;
182 base_video_parse->reorder_depth = 2;
185 static gboolean
186 gst_schro_parse_reset (GstBaseVideoParse *base_video_parse)
188 GstSchroParse *schro_parse;
190 schro_parse = GST_SCHRO_PARSE(base_video_parse);
192 GST_DEBUG("reset");
194 return TRUE;
197 static void
198 gst_schro_parse_finalize (GObject *object)
200 GstSchroParse *schro_parse;
202 g_return_if_fail (GST_IS_SCHRO_PARSE (object));
203 schro_parse = GST_SCHRO_PARSE (object);
205 G_OBJECT_CLASS (parent_class)->finalize (object);
208 static gboolean
209 gst_schro_parse_start (GstBaseVideoParse *base_video_parse)
211 GstSchroParse *schro_parse = GST_SCHRO_PARSE(base_video_parse);
212 GstCaps *caps;
213 GstStructure *structure;
215 GST_DEBUG("start");
216 caps = gst_pad_get_allowed_caps (base_video_parse->srcpad);
218 if (gst_caps_is_empty (caps)) {
219 gst_caps_unref (caps);
220 return FALSE;
223 structure = gst_caps_get_structure (caps, 0);
225 if (gst_structure_has_name (structure, "video/x-dirac")) {
226 schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_OGG;
227 } else if (gst_structure_has_name (structure, "video/x-qt-part")) {
228 schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_QUICKTIME;
229 } else if (gst_structure_has_name (structure, "video/x-avi-part")) {
230 schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_AVI;
231 } else if (gst_structure_has_name (structure, "video/x-mpegts-part")) {
232 schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_MPEG_TS;
233 } else {
234 return FALSE;
237 gst_caps_unref (caps);
238 return TRUE;
241 static gboolean
242 gst_schro_parse_stop (GstBaseVideoParse *base_video_parse)
244 return TRUE;
247 static void
248 parse_sequence_header (GstSchroParse *schro_parse, guint8 *data, int size)
250 SchroVideoFormat video_format;
251 int ret;
252 GstVideoState *state;
254 GST_DEBUG("parse_sequence_header size=%d", size);
256 state = gst_base_video_parse_get_state (GST_BASE_VIDEO_PARSE(schro_parse));
258 schro_parse->seq_header_buffer = gst_buffer_new_and_alloc (size);
259 memcpy (GST_BUFFER_DATA (schro_parse->seq_header_buffer), data, size);
261 ret = schro_parse_decode_sequence_header (data + 13, size - 13,
262 &video_format);
263 if (ret) {
264 state->fps_n = video_format.frame_rate_numerator;
265 state->fps_d = video_format.frame_rate_denominator;
266 GST_DEBUG("Frame rate is %d/%d", state->fps_n,
267 state->fps_d);
269 state->width = video_format.width;
270 state->height = video_format.height;
271 GST_DEBUG("Frame dimensions are %d x %d\n", state->width,
272 state->height);
274 state->clean_width = video_format.clean_width;
275 state->clean_height = video_format.clean_height;
276 state->clean_offset_left = video_format.left_offset;
277 state->clean_offset_top = video_format.top_offset;
279 state->par_n = video_format.aspect_ratio_numerator;
280 state->par_d = video_format.aspect_ratio_denominator;
281 GST_DEBUG("Pixel aspect ratio is %d/%d", state->par_n,
282 state->par_d);
284 gst_base_video_parse_set_state (GST_BASE_VIDEO_PARSE (schro_parse),
285 state);
286 } else {
287 GST_WARNING("Failed to get frame rate from sequence header");
292 static int
293 gst_schro_parse_scan_for_sync (GstAdapter *adapter, gboolean at_eos,
294 int offset, int n)
296 int n_available = gst_adapter_available (adapter) - offset;
298 if (n_available < 4) {
299 if (at_eos) {
300 return n_available;
301 } else {
302 return 0;
306 n_available -= 3;
308 return gst_adapter_masked_scan_uint32 (adapter, 0x42424344, 0xffffffff,
309 offset, MIN (n, n_available - 3));
312 #ifdef unused
313 static gboolean
314 gst_schro_parse_get_packet (GstAdapter *adapter, gboolean at_eos,
315 int offset, int *size)
317 int xsize;
318 unsigned char header[SCHRO_PARSE_HEADER_SIZE];
319 int back;
321 if (gst_adapter_available (adapter) - offset < SCHRO_PARSE_HEADER_SIZE) {
322 /* FIXME maybe */
323 return FALSE;
326 gst_adapter_copy_full (adapter, header, offset, SCHRO_PARSE_HEADER_SIZE);
328 if (memcmp (header, "BBCD", 4) != 0) {
329 return FALSE;
332 xsize = GST_READ_UINT32_BE (header + 5);
333 if (xsize & 0xf0000000) {
334 /* unreasonably large size */
335 return FALSE;
338 back = GST_READ_UINT32_BE (header + 9);
339 if (back & 0xf0000000) {
340 /* unreasonably large size */
341 return FALSE;
344 return TRUE;
346 #endif
348 static GstFlowReturn
349 gst_schro_parse_parse_data (GstBaseVideoParse *base_video_parse,
350 gboolean at_eos)
352 GstSchroParse *schro_parse;
353 unsigned char header[SCHRO_PARSE_HEADER_SIZE];
354 int next;
355 int prev;
356 int parse_code;
358 GST_DEBUG("parse_data");
360 schro_parse = GST_SCHRO_PARSE (base_video_parse);
362 if (gst_adapter_available (base_video_parse->input_adapter) < SCHRO_PARSE_HEADER_SIZE) {
363 return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA;
366 GST_DEBUG("available %d", gst_adapter_available (base_video_parse->input_adapter));
368 gst_adapter_copy_full (base_video_parse->input_adapter, header, 0, SCHRO_PARSE_HEADER_SIZE);
370 parse_code = header[4];
371 next = GST_READ_UINT32_BE (header + 5);
372 prev = GST_READ_UINT32_BE (header + 9);
374 GST_DEBUG("%08x %02x %08x %08x",
375 GST_READ_UINT32_BE (header), parse_code, next, prev);
377 if (memcmp (header, "BBCD", 4) != 0 ||
378 (next & 0xf0000000) || (prev & 0xf0000000)) {
379 gst_base_video_parse_lost_sync (base_video_parse);
380 return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA;
383 if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE (parse_code)) {
384 GstVideoFrame *frame;
386 if (next != 0 && next != SCHRO_PARSE_HEADER_SIZE) {
387 GST_WARNING("next is not 0 or 13 in EOS packet (%d)", next);
390 gst_base_video_parse_add_to_frame (base_video_parse,
391 SCHRO_PARSE_HEADER_SIZE);
393 frame = gst_base_video_parse_get_frame (base_video_parse);
394 frame->is_eos = TRUE;
396 SCHRO_DEBUG("eos");
398 return gst_base_video_parse_finish_frame (base_video_parse);
401 if (gst_adapter_available (base_video_parse->input_adapter) < next) {
402 return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA;
405 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code)) {
406 guint8 *data;
408 data = g_malloc (next);
410 gst_adapter_copy_full (base_video_parse->input_adapter, data, 0, next);
411 parse_sequence_header (schro_parse, data, next);
413 gst_base_video_parse_set_sync_point (base_video_parse);
415 g_free (data);
418 if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
419 GstVideoFrame *frame;
420 guint8 tmp[4];
422 frame = gst_base_video_parse_get_frame (base_video_parse);
424 #if 0
425 if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buf))) {
426 frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (buf);
428 #endif
430 gst_adapter_copy_full (base_video_parse->input_adapter, tmp, SCHRO_PARSE_HEADER_SIZE, 4);
432 frame->presentation_frame_number = GST_READ_UINT32_BE (tmp);
434 gst_base_video_parse_add_to_frame (base_video_parse, next);
436 return gst_base_video_parse_finish_frame (base_video_parse);
437 } else {
438 gst_base_video_parse_add_to_frame (base_video_parse, next);
441 return GST_FLOW_OK;
444 static GstFlowReturn
445 gst_schro_parse_shape_output_ogg (GstBaseVideoParse *base_video_parse,
446 GstVideoFrame *frame)
448 GstSchroParse *schro_parse;
449 int dpn;
450 int delay;
451 int dist;
452 int pt;
453 int dt;
454 guint64 granulepos_hi;
455 guint64 granulepos_low;
456 GstBuffer *buf = frame->src_buffer;
458 schro_parse = GST_SCHRO_PARSE (base_video_parse);
460 dpn = frame->decode_frame_number;
462 pt = frame->presentation_frame_number * 2;
463 dt = frame->decode_frame_number * 2;
464 delay = pt - dt;
465 dist = frame->distance_from_sync;
467 GST_DEBUG("sys %d dpn %d pt %d dt %d delay %d dist %d",
468 (int)frame->system_frame_number,
469 (int)frame->decode_frame_number,
470 pt, dt, delay, dist);
472 granulepos_hi = (((guint64)pt - delay)<<9) | ((dist>>8));
473 granulepos_low = (delay << 9) | (dist & 0xff);
474 GST_DEBUG("granulepos %lld:%lld", granulepos_hi, granulepos_low);
476 if (frame->is_eos) {
477 GST_BUFFER_OFFSET_END (buf) = schro_parse->last_granulepos;
478 } else {
479 schro_parse->last_granulepos = (granulepos_hi << 22) | (granulepos_low);
480 GST_BUFFER_OFFSET_END (buf) = schro_parse->last_granulepos;
483 return gst_base_video_parse_push (base_video_parse, buf);
486 static GstFlowReturn
487 gst_schro_parse_shape_output_quicktime (GstBaseVideoParse *base_video_parse,
488 GstVideoFrame *frame)
490 GstBuffer *buf = frame->src_buffer;
491 const GstVideoState *state;
493 state = gst_base_video_parse_get_state (base_video_parse);
495 #if 0
496 GST_BUFFER_TIMESTAMP (buf) = gst_video_state_get_timestamp (state,
497 frame->presentation_frame_number);
498 GST_BUFFER_DURATION (buf) = gst_video_state_get_timestamp (state,
499 frame->presentation_frame_number + 1) - GST_BUFFER_TIMESTAMP (buf);
500 GST_BUFFER_OFFSET_END (buf) = gst_video_state_get_timestamp (state,
501 frame->decode_frame_number);
502 GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
503 #endif
505 if (frame->is_sync_point &&
506 frame->presentation_frame_number == frame->system_frame_number) {
507 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
508 GST_DEBUG("sync point");
509 } else {
510 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
513 return gst_base_video_parse_push (base_video_parse, buf);
516 static GstFlowReturn
517 gst_schro_parse_shape_output_mpeg_ts (GstBaseVideoParse *base_video_parse,
518 GstVideoFrame *frame)
520 GstBuffer *buf = frame->src_buffer;
521 const GstVideoState *state;
523 state = gst_base_video_parse_get_state (base_video_parse);
525 #if 0
526 if (frame->is_sync_point &&
527 frame->presentation_frame_number == frame->system_frame_number) {
528 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
529 GST_DEBUG("sync point");
530 } else {
531 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
533 #endif
535 return gst_base_video_parse_push (base_video_parse, buf);
538 static GstFlowReturn
539 gst_schro_parse_shape_output (GstBaseVideoParse *base_video_parse,
540 GstVideoFrame *frame)
542 GstSchroParse *schro_parse;
544 schro_parse = GST_SCHRO_PARSE (base_video_parse);
546 switch (schro_parse->output_format) {
547 case GST_SCHRO_PARSE_OUTPUT_OGG:
548 return gst_schro_parse_shape_output_ogg (base_video_parse, frame);
549 case GST_SCHRO_PARSE_OUTPUT_QUICKTIME:
550 return gst_schro_parse_shape_output_quicktime (base_video_parse, frame);
551 case GST_SCHRO_PARSE_OUTPUT_MPEG_TS:
552 return gst_schro_parse_shape_output_mpeg_ts (base_video_parse, frame);
553 default:
554 break;
557 return GST_FLOW_ERROR;
560 #if 0
561 static GstFlowReturn
562 gst_schro_parse_handle_packet_ogg (GstSchroParse *schro_parse, GstBuffer *buf)
564 guint8 *data;
565 int parse_code;
566 GstFlowReturn ret = GST_FLOW_OK;
568 data = GST_BUFFER_DATA(buf);
569 parse_code = data[4];
571 if (schro_parse->have_picture) {
572 schro_parse->have_picture = FALSE;
573 if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_code)) {
574 gst_adapter_push (schro_parse->output_adapter, buf);
575 return gst_schro_parse_push_packet_ogg (schro_parse);
576 } else {
577 ret = gst_schro_parse_push_packet_ogg (schro_parse);
581 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code)) {
582 if (!schro_parse->have_seq_header) {
583 handle_sequence_header (schro_parse, data, GST_BUFFER_SIZE(buf));
584 schro_parse->have_seq_header = TRUE;
588 if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
589 schro_parse->have_picture = TRUE;
590 schro_parse->buf_picture_number = GST_READ_UINT32_BE (data+13);
591 if (schro_parse->have_seq_header) {
592 schro_parse->seq_hdr_picture_number = GST_READ_UINT32_BE (data+13);
595 gst_adapter_push (schro_parse->output_adapter, buf);
597 return ret;
600 static GstFlowReturn
601 gst_schro_parse_push_packet_ogg (GstSchroParse *schro_parse)
603 GstBuffer *buf;
605 buf = gst_adapter_take_buffer (schro_parse->output_adapter,
606 gst_adapter_available (schro_parse->output_adapter));
608 if (schro_parse->have_seq_header) {
609 schro_parse->seq_hdr_picture_number = schro_parse->picture_number;
611 #if 0
612 schro_parse->granulepos_hi = schro_parse->seq_hdr_picture_number;
613 schro_parse->granulepos_low = schro_parse->picture_number - schro_parse->granulepos_hi;
614 #else
616 int dpn;
617 int delay;
618 int dist;
619 int sys;
620 int pt;
621 int st;
623 sys = schro_parse->picture_number;
624 dpn = schro_parse->buf_picture_number;
626 pt = schro_parse->buf_picture_number * 2;
627 st = sys * 2;
628 delay = pt - st + 2;
629 dist = schro_parse->picture_number - schro_parse->seq_hdr_picture_number;
631 GST_DEBUG("sys %d dpn %d pt %d delay %d dist %d",
632 sys, dpn, pt, delay, dist);
634 schro_parse->granulepos_hi = (((uint64_t)pt - delay)<<9) | ((dist>>8));
635 schro_parse->granulepos_low = (delay << 9) | (dist & 0xff);
636 GST_DEBUG("granulepos %lld:%lld",
637 schro_parse->granulepos_hi, schro_parse->granulepos_low);
639 #endif
641 GST_BUFFER_OFFSET_END (buf) =
642 (((uint64_t)schro_parse->granulepos_hi)<<OGG_DIRAC_GRANULE_SHIFT) +
643 schro_parse->granulepos_low;
644 if ((int64_t)(GST_BUFFER_OFFSET_END (buf) - schro_parse->last_granulepos) <= 0) {
645 GST_DEBUG("granulepos didn't increase");
647 schro_parse->last_granulepos = GST_BUFFER_OFFSET_END (buf);
649 GST_BUFFER_OFFSET (buf) = gst_schro_parse_get_timestamp (schro_parse,
650 (schro_parse->granulepos_hi + schro_parse->granulepos_low)>>9);
651 GST_BUFFER_TIMESTAMP (buf) = gst_schro_parse_get_timestamp (schro_parse,
652 schro_parse->picture_number);
653 GST_BUFFER_DURATION (buf) = gst_schro_parse_get_timestamp (schro_parse,
654 schro_parse->picture_number + 1) - GST_BUFFER_TIMESTAMP (buf);
656 if (schro_parse->have_seq_header) {
657 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
658 } else {
659 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
661 schro_parse->have_seq_header = FALSE;
663 schro_parse->picture_number++;
665 GST_INFO("size %d offset %lld granulepos %llu:%llu timestamp %lld duration %lld",
666 GST_BUFFER_SIZE (buf),
667 GST_BUFFER_OFFSET (buf),
668 GST_BUFFER_OFFSET_END (buf)>>OGG_DIRAC_GRANULE_SHIFT,
669 GST_BUFFER_OFFSET_END (buf)&OGG_DIRAC_GRANULE_LOW_MASK,
670 GST_BUFFER_TIMESTAMP (buf),
671 GST_BUFFER_DURATION (buf));
673 if (!schro_parse->pushed_seq_header) {
674 GST_BUFFER_OFFSET_END (schro_parse->seq_header_buffer) = -1;
676 gst_pad_push (schro_parse->srcpad,
677 gst_buffer_ref(schro_parse->seq_header_buffer));
678 schro_parse->pushed_seq_header = TRUE;
681 gst_buffer_set_caps (buf, schro_parse->caps);
682 return gst_pad_push (schro_parse->srcpad, buf);
685 static GstFlowReturn
686 gst_schro_parse_handle_packet_qt (GstSchroParse *schro_parse, GstBuffer *buf)
688 guint8 *data;
689 int parse_code;
690 GstFlowReturn ret = GST_FLOW_OK;
692 data = GST_BUFFER_DATA(buf);
693 parse_code = data[4];
695 if (schro_parse->have_picture) {
696 schro_parse->have_picture = FALSE;
697 if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_code)) {
698 gst_adapter_push (schro_parse->output_adapter, buf);
699 return gst_schro_parse_push_packet_qt (schro_parse);
700 } else {
701 ret = gst_schro_parse_push_packet_qt (schro_parse);
705 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code)) {
706 if (!schro_parse->have_seq_header) {
707 handle_sequence_header (schro_parse, data, GST_BUFFER_SIZE(buf));
708 schro_parse->have_seq_header = TRUE;
712 if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
713 schro_parse->have_picture = TRUE;
714 schro_parse->buf_picture_number = GST_READ_UINT32_BE (data+13);
716 gst_adapter_push (schro_parse->output_adapter, buf);
718 return ret;
721 static GstFlowReturn
722 gst_schro_parse_push_packet_qt (GstSchroParse *schro_parse)
724 GstBuffer *buf;
726 buf = gst_adapter_take_buffer (schro_parse->output_adapter,
727 gst_adapter_available (schro_parse->output_adapter));
729 GST_BUFFER_TIMESTAMP (buf) = gst_schro_parse_get_timestamp (schro_parse,
730 schro_parse->buf_picture_number);
731 GST_BUFFER_DURATION (buf) = gst_schro_parse_get_timestamp (schro_parse,
732 schro_parse->buf_picture_number + 1) - GST_BUFFER_TIMESTAMP (buf);
733 GST_BUFFER_OFFSET (buf) = gst_schro_parse_get_timestamp (schro_parse,
734 schro_parse->picture_number - 1);
735 GST_BUFFER_OFFSET_END (buf) = GST_CLOCK_TIME_NONE;
737 if (schro_parse->have_seq_header &&
738 schro_parse->picture_number == schro_parse->buf_picture_number) {
739 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
740 } else {
741 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
743 schro_parse->have_seq_header = FALSE;
745 schro_parse->picture_number++;
747 gst_buffer_set_caps (buf, schro_parse->caps);
749 return gst_pad_push (schro_parse->srcpad, buf);
752 static GstFlowReturn
753 gst_schro_parse_handle_packet_avi (GstSchroParse *schro_parse, GstBuffer *buf)
755 guint8 *data;
756 int parse_code;
757 GstFlowReturn ret = GST_FLOW_OK;
759 data = GST_BUFFER_DATA(buf);
760 parse_code = data[4];
762 while (schro_parse->have_picture) {
763 schro_parse->have_picture = FALSE;
764 if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_code)) {
765 GST_DEBUG("storing");
766 gst_adapter_push (schro_parse->output_adapter, buf);
767 GST_DEBUG("pushing");
768 return gst_schro_parse_push_packet_avi (schro_parse);
769 } else {
770 GST_DEBUG("pushing");
771 if (schro_parse->buf_picture_number == schro_parse->picture_number ||
772 schro_parse->stored_picture_number == schro_parse->picture_number) {
773 ret = gst_schro_parse_push_packet_avi (schro_parse);
774 /* FIXME if we get an error here, we might end up in an
775 * inconsistent state. */
776 } else {
777 schro_parse->stored_picture_number = schro_parse->buf_picture_number;
778 GST_DEBUG("OOO picture %d", schro_parse->stored_picture_number);
779 /* no longer counts as a seek point */
780 schro_parse->have_seq_header = FALSE;
784 GST_DEBUG("stored %d picture %d", schro_parse->stored_picture_number,
785 schro_parse->picture_number);
786 if (schro_parse->stored_picture_number == schro_parse->picture_number) {
787 schro_parse->have_picture = TRUE;
791 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code)) {
792 if (!schro_parse->have_seq_header) {
793 handle_sequence_header (schro_parse, data, GST_BUFFER_SIZE(buf));
794 schro_parse->have_seq_header = TRUE;
798 if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) {
799 schro_parse->have_picture = TRUE;
800 schro_parse->buf_picture_number = GST_READ_UINT32_BE (data+13);
801 GST_DEBUG("picture number %d", schro_parse->buf_picture_number);
803 GST_DEBUG("storing");
804 gst_adapter_push (schro_parse->output_adapter, buf);
806 GST_DEBUG("returning %d", ret);
807 return ret;
810 static GstFlowReturn
811 gst_schro_parse_push_packet_avi (GstSchroParse *schro_parse)
813 GstBuffer *buf;
814 int size;
816 size = gst_adapter_available (schro_parse->output_adapter);
817 GST_DEBUG("size %d", size);
818 if (size > 0) {
819 buf = gst_adapter_take_buffer (schro_parse->output_adapter, size);
820 } else {
821 buf = gst_buffer_new_and_alloc (0);
824 GST_BUFFER_TIMESTAMP (buf) = gst_schro_parse_get_timestamp (schro_parse,
825 schro_parse->buf_picture_number);
826 GST_BUFFER_DURATION (buf) = gst_schro_parse_get_timestamp (schro_parse,
827 schro_parse->buf_picture_number + 1) - GST_BUFFER_TIMESTAMP (buf);
828 GST_BUFFER_OFFSET_END (buf) = gst_schro_parse_get_timestamp (schro_parse,
829 schro_parse->picture_number);
831 GST_DEBUG("buf_pic %d pic %d", schro_parse->buf_picture_number,
832 schro_parse->picture_number);
834 if (schro_parse->have_seq_header &&
835 schro_parse->picture_number == schro_parse->buf_picture_number) {
836 GST_DEBUG("seek point on %d", schro_parse->picture_number);
837 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
838 } else {
839 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
841 schro_parse->have_seq_header = FALSE;
843 schro_parse->picture_number++;
845 gst_buffer_set_caps (buf, schro_parse->caps);
847 return gst_pad_push (schro_parse->srcpad, buf);
849 #endif
851 static GstCaps *
852 gst_schro_parse_get_caps (GstBaseVideoParse *base_video_parse)
854 GstCaps *caps;
855 GstVideoState *state;
856 GstSchroParse *schro_parse;
858 schro_parse = GST_SCHRO_PARSE(base_video_parse);
860 state = gst_base_video_parse_get_state (base_video_parse);
862 if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_OGG) {
863 caps = gst_caps_new_simple ("video/x-dirac",
864 "width", G_TYPE_INT, state->width,
865 "height", G_TYPE_INT, state->height,
866 "framerate", GST_TYPE_FRACTION, state->fps_n,
867 state->fps_d,
868 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
869 state->par_d,
870 NULL);
872 GST_BUFFER_FLAG_SET (schro_parse->seq_header_buffer, GST_BUFFER_FLAG_IN_CAPS);
875 GValue array = { 0 };
876 GValue value = { 0 };
877 GstBuffer *buf;
878 int size;
880 g_value_init (&array, GST_TYPE_ARRAY);
881 g_value_init (&value, GST_TYPE_BUFFER);
882 size = GST_BUFFER_SIZE(schro_parse->seq_header_buffer);
883 buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE);
884 memcpy (GST_BUFFER_DATA(buf),
885 GST_BUFFER_DATA(schro_parse->seq_header_buffer), size);
886 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 0, 0x42424344);
887 GST_WRITE_UINT8 (GST_BUFFER_DATA(buf) + size + 4, SCHRO_PARSE_CODE_END_OF_SEQUENCE);
888 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 5, 0);
889 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 9, size);
890 gst_value_set_buffer (&value, buf);
891 gst_buffer_unref (buf);
892 gst_value_array_append_value (&array, &value);
893 gst_structure_set_value (gst_caps_get_structure(caps,0),
894 "streamheader", &array);
895 g_value_unset (&value);
896 g_value_unset (&array);
898 } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_QUICKTIME) {
899 caps = gst_caps_new_simple ("video/x-qt-part",
900 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
901 "width", G_TYPE_INT, state->width,
902 "height", G_TYPE_INT, state->height,
903 "framerate", GST_TYPE_FRACTION, state->fps_n,
904 state->fps_d,
905 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
906 state->par_d, NULL);
907 } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_AVI) {
908 caps = gst_caps_new_simple ("video/x-avi-part",
909 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
910 "width", G_TYPE_INT, state->width,
911 "height", G_TYPE_INT, state->height,
912 "framerate", GST_TYPE_FRACTION, state->fps_n,
913 state->fps_d,
914 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
915 state->par_d, NULL);
916 } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_MPEG_TS) {
917 caps = gst_caps_new_simple ("video/x-mpegts-part",
918 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
919 "width", G_TYPE_INT, state->width,
920 "height", G_TYPE_INT, state->height,
921 "framerate", GST_TYPE_FRACTION, state->fps_n,
922 state->fps_d,
923 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
924 state->par_d, NULL);
925 } else {
926 g_assert_not_reached ();
929 return caps;