[encoder] Added 1/8th pel MV refinement
[schroedinger/research-port.git] / gst / gstschroenc.c
blobb6b348a9209871571b2285eede34f6fad548ce5a
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/video/video.h>
26 #include <string.h>
28 #define SCHRO_ENABLE_UNSTABLE_API
30 #include <schroedinger/schro.h>
31 #include <schroedinger/schrobitstream.h>
32 #include <schroedinger/schrovirtframe.h>
33 #include <math.h>
34 #include "gstbasevideoencoder.h"
35 #include "gstschroutils.h"
37 GST_DEBUG_CATEGORY_EXTERN (schro_debug);
38 #define GST_CAT_DEFAULT schro_debug
40 #define GST_TYPE_SCHRO_ENC \
41 (gst_schro_enc_get_type())
42 #define GST_SCHRO_ENC(obj) \
43 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SCHRO_ENC,GstSchroEnc))
44 #define GST_SCHRO_ENC_CLASS(klass) \
45 (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SCHRO_ENC,GstSchroEncClass))
46 #define GST_IS_SCHRO_ENC(obj) \
47 (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SCHRO_ENC))
48 #define GST_IS_SCHRO_ENC_CLASS(obj) \
49 (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHRO_ENC))
51 typedef struct _GstSchroEnc GstSchroEnc;
52 typedef struct _GstSchroEncClass GstSchroEncClass;
54 typedef enum {
55 GST_SCHRO_ENC_OUTPUT_OGG,
56 GST_SCHRO_ENC_OUTPUT_QUICKTIME,
57 GST_SCHRO_ENC_OUTPUT_AVI,
58 GST_SCHRO_ENC_OUTPUT_MPEG_TS
59 } GstSchroEncOutputType;
61 struct _GstSchroEnc
63 GstBaseVideoEncoder base_encoder;
65 GstPad *sinkpad;
66 GstPad *srcpad;
68 /* video properties */
69 GstSchroEncOutputType output_format;
71 /* state */
72 SchroEncoder *encoder;
73 SchroVideoFormat *video_format;
74 GstVideoFrame *eos_frame;
75 GstBuffer *seq_header_buffer;
77 guint64 last_granulepos;
80 struct _GstSchroEncClass
82 GstBaseVideoEncoderClass parent_class;
87 enum
89 LAST_SIGNAL
92 enum
94 ARG_0
97 static void gst_schro_enc_set_property (GObject * object, guint prop_id,
98 const GValue * value, GParamSpec * pspec);
99 static void gst_schro_enc_get_property (GObject * object, guint prop_id,
100 GValue * value, GParamSpec * pspec);
102 static GstFlowReturn gst_schro_enc_process (GstSchroEnc *schro_enc);
104 static gboolean gst_schro_enc_set_format (GstBaseVideoEncoder *base_video_encoder,
105 GstVideoState *state);
106 static gboolean gst_schro_enc_start (GstBaseVideoEncoder *base_video_encoder);
107 static gboolean gst_schro_enc_stop (GstBaseVideoEncoder *base_video_encoder);
108 static gboolean gst_schro_enc_finish (GstBaseVideoEncoder *base_video_encoder,
109 GstVideoFrame *frame);
110 static gboolean gst_schro_enc_handle_frame (GstBaseVideoEncoder *base_video_encoder,
111 GstVideoFrame *frame);
112 static GstFlowReturn gst_schro_enc_shape_output (GstBaseVideoEncoder *base_video_encoder,
113 GstVideoFrame *frame);
114 static GstCaps * gst_schro_enc_get_caps (GstBaseVideoEncoder *base_video_encoder);
116 static GstStaticPadTemplate gst_schro_enc_sink_template =
117 GST_STATIC_PAD_TEMPLATE ("sink",
118 GST_PAD_SINK,
119 GST_PAD_ALWAYS,
120 GST_STATIC_CAPS (
121 GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }") ";"
122 GST_VIDEO_CAPS_ARGB)
125 static GstStaticPadTemplate gst_schro_enc_src_template =
126 GST_STATIC_PAD_TEMPLATE ("src",
127 GST_PAD_SRC,
128 GST_PAD_ALWAYS,
129 GST_STATIC_CAPS ("video/x-dirac;video/x-qt-part")
132 GST_BOILERPLATE (GstSchroEnc, gst_schro_enc, GstBaseVideoEncoder,
133 GST_TYPE_BASE_VIDEO_ENCODER);
135 static void
136 gst_schro_enc_base_init (gpointer g_class)
138 static GstElementDetails schro_enc_details =
139 GST_ELEMENT_DETAILS ("Dirac Encoder",
140 "Codec/Encoder/Video",
141 "Encode raw video into Dirac stream",
142 "David Schleef <ds@schleef.org>");
143 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
145 gst_element_class_add_pad_template (element_class,
146 gst_static_pad_template_get (&gst_schro_enc_src_template));
147 gst_element_class_add_pad_template (element_class,
148 gst_static_pad_template_get (&gst_schro_enc_sink_template));
150 gst_element_class_set_details (element_class, &schro_enc_details);
153 static void
154 gst_schro_enc_class_init (GstSchroEncClass * klass)
156 GObjectClass *gobject_class;
157 GstElementClass *gstelement_class;
158 GstBaseVideoEncoderClass *basevideocoder_class;
159 int i;
161 gobject_class = G_OBJECT_CLASS (klass);
162 gstelement_class = GST_ELEMENT_CLASS (klass);
163 basevideocoder_class = GST_BASE_VIDEO_ENCODER_CLASS (klass);
165 gobject_class->set_property = gst_schro_enc_set_property;
166 gobject_class->get_property = gst_schro_enc_get_property;
168 for(i=0;i<schro_encoder_get_n_settings();i++){
169 const SchroEncoderSetting *setting;
171 setting = schro_encoder_get_setting_info (i);
173 switch (setting->type) {
174 case SCHRO_ENCODER_SETTING_TYPE_BOOLEAN:
175 g_object_class_install_property (gobject_class, i + 1,
176 g_param_spec_boolean (setting->name, setting->name, setting->name,
177 setting->default_value, G_PARAM_READWRITE));
178 break;
179 case SCHRO_ENCODER_SETTING_TYPE_INT:
180 g_object_class_install_property (gobject_class, i + 1,
181 g_param_spec_int (setting->name, setting->name, setting->name,
182 setting->min, setting->max, setting->default_value,
183 G_PARAM_READWRITE));
184 break;
185 case SCHRO_ENCODER_SETTING_TYPE_ENUM:
186 g_object_class_install_property (gobject_class, i + 1,
187 g_param_spec_int (setting->name, setting->name, setting->name,
188 setting->min, setting->max, setting->default_value,
189 G_PARAM_READWRITE));
190 break;
191 case SCHRO_ENCODER_SETTING_TYPE_DOUBLE:
192 g_object_class_install_property (gobject_class, i + 1,
193 g_param_spec_double (setting->name, setting->name, setting->name,
194 setting->min, setting->max, setting->default_value,
195 G_PARAM_READWRITE));
196 break;
197 default:
198 break;
202 basevideocoder_class->set_format = GST_DEBUG_FUNCPTR(gst_schro_enc_set_format);
203 basevideocoder_class->start = GST_DEBUG_FUNCPTR(gst_schro_enc_start);
204 basevideocoder_class->stop = GST_DEBUG_FUNCPTR(gst_schro_enc_stop);
205 basevideocoder_class->finish = GST_DEBUG_FUNCPTR(gst_schro_enc_finish);
206 basevideocoder_class->handle_frame = GST_DEBUG_FUNCPTR(gst_schro_enc_handle_frame);
207 basevideocoder_class->shape_output = GST_DEBUG_FUNCPTR(gst_schro_enc_shape_output);
208 basevideocoder_class->get_caps = GST_DEBUG_FUNCPTR(gst_schro_enc_get_caps);
211 static void
212 gst_schro_enc_init (GstSchroEnc *schro_enc, GstSchroEncClass *klass)
214 GST_DEBUG ("gst_schro_enc_init");
216 /* Normally, we'd create the encoder in ->start(), but we use the
217 * encoder to store object properties. So it needs to be created
218 * here. */
219 schro_enc->encoder = schro_encoder_new ();
220 schro_encoder_set_packet_assembly (schro_enc->encoder, TRUE);
221 schro_enc->video_format =
222 schro_encoder_get_video_format (schro_enc->encoder);
227 static gboolean
228 gst_schro_enc_set_format (GstBaseVideoEncoder *base_video_encoder,
229 GstVideoState *state)
231 GstSchroEnc *schro_enc = GST_SCHRO_ENC(base_video_encoder);
233 schro_video_format_set_std_video_format (schro_enc->video_format,
234 SCHRO_VIDEO_FORMAT_CUSTOM);
236 switch (state->format) {
237 case GST_VIDEO_FORMAT_I420:
238 case GST_VIDEO_FORMAT_YV12:
239 schro_enc->video_format->chroma_format = SCHRO_CHROMA_420;
240 break;
241 case GST_VIDEO_FORMAT_YUY2:
242 case GST_VIDEO_FORMAT_UYVY:
243 schro_enc->video_format->chroma_format = SCHRO_CHROMA_422;
244 break;
245 case GST_VIDEO_FORMAT_AYUV:
246 schro_enc->video_format->chroma_format = SCHRO_CHROMA_444;
247 break;
248 case GST_VIDEO_FORMAT_ARGB:
249 schro_enc->video_format->chroma_format = SCHRO_CHROMA_420;
250 break;
251 default:
252 g_assert_not_reached();
255 schro_enc->video_format->frame_rate_numerator = state->fps_n;
256 schro_enc->video_format->frame_rate_denominator = state->fps_d;
258 schro_enc->video_format->width = state->width;
259 schro_enc->video_format->height = state->height;
260 schro_enc->video_format->clean_width = state->clean_width;
261 schro_enc->video_format->clean_height = state->clean_height;
262 schro_enc->video_format->left_offset = state->clean_offset_left;
263 schro_enc->video_format->top_offset = state->clean_offset_top;
265 schro_enc->video_format->aspect_ratio_numerator = state->par_n;
266 schro_enc->video_format->aspect_ratio_denominator = state->par_d;
268 schro_video_format_set_std_signal_range (schro_enc->video_format,
269 SCHRO_SIGNAL_RANGE_8BIT_VIDEO);
270 schro_video_format_set_std_colour_spec (schro_enc->video_format,
271 SCHRO_COLOUR_SPEC_HDTV);
273 schro_encoder_set_video_format (schro_enc->encoder, schro_enc->video_format);
274 schro_encoder_start (schro_enc->encoder);
276 schro_enc->seq_header_buffer = gst_schro_wrap_schro_buffer (
277 schro_encoder_encode_sequence_header (schro_enc->encoder));
279 return TRUE;
282 static void
283 gst_schro_enc_set_property (GObject * object, guint prop_id,
284 const GValue * value, GParamSpec * pspec)
286 GstSchroEnc *src;
288 g_return_if_fail (GST_IS_SCHRO_ENC (object));
289 src = GST_SCHRO_ENC (object);
291 GST_DEBUG ("gst_schro_enc_set_property");
293 if (prop_id >= 1) {
294 const SchroEncoderSetting *setting;
295 setting = schro_encoder_get_setting_info (prop_id - 1);
296 switch(G_VALUE_TYPE(value)) {
297 case G_TYPE_DOUBLE:
298 schro_encoder_setting_set_double (src->encoder, setting->name,
299 g_value_get_double(value));
300 break;
301 case G_TYPE_INT:
302 schro_encoder_setting_set_double (src->encoder, setting->name,
303 g_value_get_int(value));
304 break;
305 case G_TYPE_BOOLEAN:
306 schro_encoder_setting_set_double (src->encoder, setting->name,
307 g_value_get_boolean(value));
308 break;
313 static void
314 gst_schro_enc_get_property (GObject * object, guint prop_id, GValue * value,
315 GParamSpec * pspec)
317 GstSchroEnc *src;
319 g_return_if_fail (GST_IS_SCHRO_ENC (object));
320 src = GST_SCHRO_ENC (object);
322 if (prop_id >= 1) {
323 const SchroEncoderSetting *setting;
324 setting = schro_encoder_get_setting_info (prop_id - 1);
325 switch(G_VALUE_TYPE(value)) {
326 case G_TYPE_DOUBLE:
327 g_value_set_double (value,
328 schro_encoder_setting_get_double (src->encoder, setting->name));
329 break;
330 case G_TYPE_INT:
331 g_value_set_int (value,
332 schro_encoder_setting_get_double (src->encoder, setting->name));
333 break;
334 case G_TYPE_BOOLEAN:
335 g_value_set_boolean (value,
336 schro_encoder_setting_get_double (src->encoder, setting->name));
337 break;
343 * start is called once the input format is known. This function
344 * must decide on an output format and negotiate it.
346 static gboolean
347 gst_schro_enc_start (GstBaseVideoEncoder *base_video_encoder)
349 GstSchroEnc *schro_enc = GST_SCHRO_ENC(base_video_encoder);
350 GstCaps *caps;
351 GstStructure *structure;
353 GST_DEBUG("set_output_caps");
354 caps = gst_pad_get_allowed_caps (base_video_encoder->srcpad);
356 if (gst_caps_is_empty (caps)) {
357 gst_caps_unref (caps);
358 return FALSE;
361 structure = gst_caps_get_structure (caps, 0);
363 if (gst_structure_has_name (structure, "video/x-dirac")) {
364 schro_enc->output_format = GST_SCHRO_ENC_OUTPUT_OGG;
365 } else if (gst_structure_has_name (structure, "video/x-qt-part")) {
366 schro_enc->output_format = GST_SCHRO_ENC_OUTPUT_QUICKTIME;
367 } else if (gst_structure_has_name (structure, "video/x-avi-part")) {
368 schro_enc->output_format = GST_SCHRO_ENC_OUTPUT_AVI;
369 } else {
370 return FALSE;
373 gst_caps_unref (caps);
374 return TRUE;
377 static gboolean
378 gst_schro_enc_stop (GstBaseVideoEncoder *base_video_encoder)
380 GstSchroEnc *schro_enc = GST_SCHRO_ENC(base_video_encoder);
382 if (schro_enc->encoder) {
383 schro_encoder_free (schro_enc->encoder);
384 schro_enc->encoder = NULL;
387 return TRUE;
390 static gboolean
391 gst_schro_enc_finish (GstBaseVideoEncoder *base_video_encoder,
392 GstVideoFrame *frame)
394 GstSchroEnc *schro_enc = GST_SCHRO_ENC(base_video_encoder);
396 GST_DEBUG("finish");
398 schro_enc->eos_frame = frame;
400 schro_encoder_end_of_stream (schro_enc->encoder);
401 gst_schro_enc_process (schro_enc);
403 return TRUE;
406 static gboolean
407 gst_schro_enc_handle_frame (GstBaseVideoEncoder *base_video_encoder,
408 GstVideoFrame *frame)
410 GstSchroEnc *schro_enc = GST_SCHRO_ENC(base_video_encoder);
411 SchroFrame *schro_frame;
412 GstFlowReturn ret;
413 const GstVideoState *state;
415 state = gst_base_video_encoder_get_state (base_video_encoder);
417 schro_frame = gst_schro_buffer_wrap (frame->sink_buffer,
418 state->format, state->width, state->height);
420 GST_DEBUG ("pushing frame %p", frame);
421 schro_encoder_push_frame_full (schro_enc->encoder, schro_frame, frame);
423 ret = gst_schro_enc_process (schro_enc);
425 return ret;
428 #if 0
429 static void
430 gst_caps_add_streamheader (GstCaps *caps, GList *list)
432 GValue array = { 0 };
433 GValue value = { 0 };
434 GstBuffer *buf;
435 GList *g;
437 g_value_init (&array, GST_TYPE_ARRAY);
439 for(g=g_list_first (list); g; g = g_list_next (list)) {
440 g_value_init (&value, GST_TYPE_BUFFER);
441 buf = gst_buffer_copy (GST_BUFFER(g->data));
442 gst_value_set_buffer (&value, buf);
443 gst_buffer_unref (buf);
444 gst_value_array_append_value (&array, &value);
445 g_value_unset (&value);
447 gst_structure_set_value (gst_caps_get_structure(caps,0),
448 "streamheader", &array);
449 g_value_unset (&array);
451 #endif
453 static GstCaps *
454 gst_schro_enc_get_caps (GstBaseVideoEncoder *base_video_encoder)
456 GstCaps *caps;
457 const GstVideoState *state;
458 GstSchroEnc *schro_enc;
460 schro_enc = GST_SCHRO_ENC(base_video_encoder);
462 state = gst_base_video_encoder_get_state (base_video_encoder);
464 if (schro_enc->output_format == GST_SCHRO_ENC_OUTPUT_OGG) {
465 caps = gst_caps_new_simple ("video/x-dirac",
466 "width", G_TYPE_INT, state->width,
467 "height", G_TYPE_INT, state->height,
468 "framerate", GST_TYPE_FRACTION, state->fps_n,
469 state->fps_d,
470 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
471 state->par_d,
472 NULL);
474 GST_BUFFER_FLAG_SET (schro_enc->seq_header_buffer, GST_BUFFER_FLAG_IN_CAPS);
477 GValue array = { 0 };
478 GValue value = { 0 };
479 GstBuffer *buf;
480 int size;
482 g_value_init (&array, GST_TYPE_ARRAY);
483 g_value_init (&value, GST_TYPE_BUFFER);
484 size = GST_BUFFER_SIZE(schro_enc->seq_header_buffer);
485 buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE);
486 memcpy (GST_BUFFER_DATA(buf),
487 GST_BUFFER_DATA(schro_enc->seq_header_buffer), size);
488 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 0, 0x42424344);
489 GST_WRITE_UINT8 (GST_BUFFER_DATA(buf) + size + 4, SCHRO_PARSE_CODE_END_OF_SEQUENCE);
490 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 5, 0);
491 GST_WRITE_UINT32_BE (GST_BUFFER_DATA(buf) + size + 9, size);
492 gst_value_set_buffer (&value, buf);
493 gst_buffer_unref (buf);
494 gst_value_array_append_value (&array, &value);
495 gst_structure_set_value (gst_caps_get_structure(caps,0),
496 "streamheader", &array);
497 g_value_unset (&value);
498 g_value_unset (&array);
500 } else if (schro_enc->output_format == GST_SCHRO_ENC_OUTPUT_QUICKTIME) {
501 caps = gst_caps_new_simple ("video/x-qt-part",
502 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
503 "width", G_TYPE_INT, state->width,
504 "height", G_TYPE_INT, state->height,
505 "framerate", GST_TYPE_FRACTION, state->fps_n,
506 state->fps_d,
507 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
508 state->par_d, NULL);
509 } else if (schro_enc->output_format == GST_SCHRO_ENC_OUTPUT_AVI) {
510 caps = gst_caps_new_simple ("video/x-avi-part",
511 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
512 "width", G_TYPE_INT, state->width,
513 "height", G_TYPE_INT, state->height,
514 "framerate", GST_TYPE_FRACTION, state->fps_n,
515 state->fps_d,
516 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
517 state->par_d, NULL);
518 } else if (schro_enc->output_format == GST_SCHRO_ENC_OUTPUT_MPEG_TS) {
519 caps = gst_caps_new_simple ("video/x-mpegts-part",
520 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('d','r','a','c'),
521 "width", G_TYPE_INT, state->width,
522 "height", G_TYPE_INT, state->height,
523 "framerate", GST_TYPE_FRACTION, state->fps_n,
524 state->fps_d,
525 "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
526 state->par_d, NULL);
527 } else {
528 g_assert_not_reached ();
531 return caps;
537 static GstFlowReturn
538 gst_schro_enc_shape_output_ogg (GstBaseVideoEncoder *base_video_encoder,
539 GstVideoFrame *frame)
541 GstSchroEnc *schro_enc;
542 int dpn;
543 int delay;
544 int dist;
545 int pt;
546 int dt;
547 guint64 granulepos_hi;
548 guint64 granulepos_low;
549 GstBuffer *buf = frame->src_buffer;
551 schro_enc = GST_SCHRO_ENC (base_video_encoder);
553 dpn = frame->decode_frame_number;
555 pt = frame->presentation_frame_number * 2;
556 dt = frame->decode_frame_number * 2;
557 delay = pt - dt;
558 dist = frame->distance_from_sync;
560 GST_DEBUG("sys %d dpn %d pt %d dt %d delay %d dist %d",
561 (int)frame->system_frame_number,
562 (int)frame->decode_frame_number,
563 pt, dt, delay, dist);
565 granulepos_hi = (((uint64_t)pt - delay)<<9) | ((dist>>8));
566 granulepos_low = (delay << 9) | (dist & 0xff);
567 GST_DEBUG("granulepos %lld:%lld", granulepos_hi, granulepos_low);
569 if (frame->is_eos) {
570 GST_BUFFER_OFFSET_END (buf) = schro_enc->last_granulepos;
571 } else {
572 schro_enc->last_granulepos = (granulepos_hi << 22) | (granulepos_low);
573 GST_BUFFER_OFFSET_END (buf) = schro_enc->last_granulepos;
576 gst_buffer_set_caps (buf, base_video_encoder->caps);
578 return gst_pad_push (base_video_encoder->srcpad, buf);
581 static GstFlowReturn
582 gst_schro_enc_shape_output_quicktime (GstBaseVideoEncoder *base_video_encoder,
583 GstVideoFrame *frame)
585 GstBuffer *buf = frame->src_buffer;
586 const GstVideoState *state;
588 state = gst_base_video_encoder_get_state (base_video_encoder);
590 GST_BUFFER_TIMESTAMP (buf) = gst_video_state_get_timestamp (state,
591 frame->presentation_frame_number);
592 GST_BUFFER_DURATION (buf) = gst_video_state_get_timestamp (state,
593 frame->presentation_frame_number + 1) - GST_BUFFER_TIMESTAMP (buf);
594 GST_BUFFER_OFFSET_END (buf) = gst_video_state_get_timestamp (state,
595 frame->decode_frame_number);
596 GST_BUFFER_OFFSET (buf) = GST_CLOCK_TIME_NONE;
598 if (frame->is_sync_point &&
599 frame->presentation_frame_number == frame->system_frame_number) {
600 GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
601 GST_ERROR("sync point");
602 } else {
603 GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
606 gst_buffer_set_caps (buf, base_video_encoder->caps);
608 return gst_pad_push (base_video_encoder->srcpad, buf);
611 static GstFlowReturn
612 gst_schro_enc_shape_output (GstBaseVideoEncoder *base_video_encoder,
613 GstVideoFrame *frame)
615 GstSchroEnc *schro_enc;
617 schro_enc = GST_SCHRO_ENC (base_video_encoder);
619 switch (schro_enc->output_format) {
620 case GST_SCHRO_ENC_OUTPUT_OGG:
621 return gst_schro_enc_shape_output_ogg (base_video_encoder, frame);
622 break;
623 case GST_SCHRO_ENC_OUTPUT_QUICKTIME:
624 return gst_schro_enc_shape_output_quicktime (base_video_encoder, frame);
625 break;
626 default:
627 g_assert_not_reached ();
628 break;
631 return GST_FLOW_ERROR;
634 static GstFlowReturn
635 gst_schro_enc_process (GstSchroEnc *schro_enc)
637 SchroBuffer *encoded_buffer;
638 GstVideoFrame *frame;
639 GstFlowReturn ret;
640 int presentation_frame;
641 void *voidptr;
642 GstBaseVideoEncoder *base_video_encoder = GST_BASE_VIDEO_ENCODER(schro_enc);
644 GST_DEBUG("process");
646 while (1) {
647 switch (schro_encoder_wait (schro_enc->encoder)) {
648 case SCHRO_STATE_NEED_FRAME:
649 return GST_FLOW_OK;
650 case SCHRO_STATE_END_OF_STREAM:
651 GST_DEBUG("EOS");
652 return GST_FLOW_OK;
653 case SCHRO_STATE_HAVE_BUFFER:
654 voidptr = NULL;
655 encoded_buffer = schro_encoder_pull_full (schro_enc->encoder,
656 &presentation_frame, &voidptr);
657 frame = voidptr;
658 if (encoded_buffer == NULL) {
659 GST_DEBUG("encoder_pull returned NULL");
660 /* FIXME This shouldn't happen */
661 return GST_FLOW_ERROR;
664 if (voidptr == NULL) {
665 GST_DEBUG("got eos");
666 frame = schro_enc->eos_frame;
669 if (SCHRO_PARSE_CODE_IS_SEQ_HEADER (encoded_buffer->data[4])) {
670 frame->is_sync_point = TRUE;
673 frame->src_buffer = gst_schro_wrap_schro_buffer (encoded_buffer);
675 ret = gst_base_video_encoder_finish_frame (base_video_encoder, frame);
677 if (ret != GST_FLOW_OK) {
678 GST_DEBUG("pad_push returned %d", ret);
679 return ret;
681 break;
682 case SCHRO_STATE_AGAIN:
683 break;
686 return GST_FLOW_OK;