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/gstbasetransform.h>
26 #include <gst/base/gstadapter.h>
27 #include <gst/video/video.h>
29 #include <schroedinger/schro.h>
30 #include <liboil/liboil.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
;
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
;
65 GstBaseVideoParse base_video_parse
;
67 GstPad
*sinkpad
, *srcpad
;
69 GstSchroParseOutputType output_format
;
71 GstBuffer
*seq_header_buffer
;
76 gboolean have_picture
;
77 int buf_picture_number
;
78 int seq_hdr_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 */
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
,
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",
120 GST_STATIC_CAPS ("video/x-dirac")
123 static GstStaticPadTemplate gst_schro_parse_src_template
=
124 GST_STATIC_PAD_TEMPLATE ("src",
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
);
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
);
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
);
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;
186 gst_schro_parse_reset (GstBaseVideoParse
*base_video_parse
)
188 GstSchroParse
*schro_parse
;
190 schro_parse
= GST_SCHRO_PARSE(base_video_parse
);
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
);
209 gst_schro_parse_start (GstBaseVideoParse
*base_video_parse
)
211 GstSchroParse
*schro_parse
= GST_SCHRO_PARSE(base_video_parse
);
213 GstStructure
*structure
;
216 caps
= gst_pad_get_allowed_caps (base_video_parse
->srcpad
);
218 if (gst_caps_is_empty (caps
)) {
219 gst_caps_unref (caps
);
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
;
237 gst_caps_unref (caps
);
242 gst_schro_parse_stop (GstBaseVideoParse
*base_video_parse
)
248 parse_sequence_header (GstSchroParse
*schro_parse
, guint8
*data
, int size
)
250 SchroVideoFormat video_format
;
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,
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
,
269 state
->width
= video_format
.width
;
270 state
->height
= video_format
.height
;
271 GST_DEBUG("Frame dimensions are %d x %d\n", state
->width
,
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
,
284 gst_base_video_parse_set_state (GST_BASE_VIDEO_PARSE (schro_parse
),
287 GST_WARNING("Failed to get frame rate from sequence header");
293 gst_schro_parse_scan_for_sync (GstAdapter
*adapter
, gboolean at_eos
,
296 int n_available
= gst_adapter_available (adapter
) - offset
;
298 if (n_available
< 4) {
308 return gst_adapter_masked_scan_uint32 (adapter
, 0x42424344, 0xffffffff,
309 offset
, MIN (n
, n_available
- 3));
314 gst_schro_parse_get_packet (GstAdapter
*adapter
, gboolean at_eos
,
315 int offset
, int *size
)
318 unsigned char header
[SCHRO_PARSE_HEADER_SIZE
];
321 if (gst_adapter_available (adapter
) - offset
< SCHRO_PARSE_HEADER_SIZE
) {
326 gst_adapter_copy_full (adapter
, header
, offset
, SCHRO_PARSE_HEADER_SIZE
);
328 if (memcmp (header
, "BBCD", 4) != 0) {
332 xsize
= GST_READ_UINT32_BE (header
+ 5);
333 if (xsize
& 0xf0000000) {
334 /* unreasonably large size */
338 back
= GST_READ_UINT32_BE (header
+ 9);
339 if (back
& 0xf0000000) {
340 /* unreasonably large size */
349 gst_schro_parse_parse_data (GstBaseVideoParse
*base_video_parse
,
352 GstSchroParse
*schro_parse
;
353 unsigned char header
[SCHRO_PARSE_HEADER_SIZE
];
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
;
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
)) {
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
);
418 if (SCHRO_PARSE_CODE_IS_PICTURE(parse_code
)) {
419 GstVideoFrame
*frame
;
422 frame
= gst_base_video_parse_get_frame (base_video_parse
);
425 if (GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buf
))) {
426 frame
->presentation_timestamp
= GST_BUFFER_TIMESTAMP (buf
);
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
);
438 gst_base_video_parse_add_to_frame (base_video_parse
, next
);
445 gst_schro_parse_shape_output_ogg (GstBaseVideoParse
*base_video_parse
,
446 GstVideoFrame
*frame
)
448 GstSchroParse
*schro_parse
;
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;
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
);
477 GST_BUFFER_OFFSET_END (buf
) = schro_parse
->last_granulepos
;
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
);
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
);
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
;
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");
510 GST_BUFFER_FLAG_SET (buf
, GST_BUFFER_FLAG_DELTA_UNIT
);
513 return gst_base_video_parse_push (base_video_parse
, buf
);
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
);
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");
531 GST_BUFFER_FLAG_SET (buf
, GST_BUFFER_FLAG_DELTA_UNIT
);
535 return gst_base_video_parse_push (base_video_parse
, buf
);
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
);
557 return GST_FLOW_ERROR
;
562 gst_schro_parse_handle_packet_ogg (GstSchroParse
*schro_parse
, GstBuffer
*buf
)
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
);
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
);
601 gst_schro_parse_push_packet_ogg (GstSchroParse
*schro_parse
)
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
;
612 schro_parse
->granulepos_hi
= schro_parse
->seq_hdr_picture_number
;
613 schro_parse
->granulepos_low
= schro_parse
->picture_number
- schro_parse
->granulepos_hi
;
623 sys
= schro_parse
->picture_number
;
624 dpn
= schro_parse
->buf_picture_number
;
626 pt
= schro_parse
->buf_picture_number
* 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
);
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
);
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
);
686 gst_schro_parse_handle_packet_qt (GstSchroParse
*schro_parse
, GstBuffer
*buf
)
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
);
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
);
722 gst_schro_parse_push_packet_qt (GstSchroParse
*schro_parse
)
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
);
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
);
753 gst_schro_parse_handle_packet_avi (GstSchroParse
*schro_parse
, GstBuffer
*buf
)
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
);
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. */
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
);
811 gst_schro_parse_push_packet_avi (GstSchroParse
*schro_parse
)
816 size
= gst_adapter_available (schro_parse
->output_adapter
);
817 GST_DEBUG("size %d", size
);
819 buf
= gst_adapter_take_buffer (schro_parse
->output_adapter
, size
);
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
);
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
);
852 gst_schro_parse_get_caps (GstBaseVideoParse
*base_video_parse
)
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
,
868 "pixel-aspect-ratio", GST_TYPE_FRACTION
, state
->par_n
,
872 GST_BUFFER_FLAG_SET (schro_parse
->seq_header_buffer
, GST_BUFFER_FLAG_IN_CAPS
);
875 GValue array
= { 0 };
876 GValue value
= { 0 };
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
,
905 "pixel-aspect-ratio", GST_TYPE_FRACTION
, state
->par_n
,
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
,
914 "pixel-aspect-ratio", GST_TYPE_FRACTION
, state
->par_n
,
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
,
923 "pixel-aspect-ratio", GST_TYPE_FRACTION
, state
->par_n
,
926 g_assert_not_reached ();