theora: Port to 0.11 again with the new base classes

This commit is contained in:
Sebastian Dröge 2012-04-24 21:32:28 +02:00
parent a8c40a658c
commit e120979f17
4 changed files with 122 additions and 254 deletions

View file

@ -47,11 +47,13 @@
#include "gsttheoradec.h"
#include <gst/tag/tag.h>
#include <gst/video/video.h>
#include <gst/video/gstvideometa.h>
#include <gst/video/gstvideopool.h>
#define GST_CAT_DEFAULT theoradec_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
#define THEORA_DEF_CROP TRUE
#define THEORA_DEF_TELEMETRY_MV 0
#define THEORA_DEF_TELEMETRY_MBMODE 0
#define THEORA_DEF_TELEMETRY_QI 0
@ -60,7 +62,6 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
enum
{
PROP_0,
PROP_CROP,
PROP_TELEMETRY_MV,
PROP_TELEMETRY_MBMODE,
PROP_TELEMETRY_QI,
@ -71,8 +72,8 @@ static GstStaticPadTemplate theora_dec_src_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) { I420, Y42B, Y444 }, "
GST_STATIC_CAPS ("video/x-raw, "
"format = (string) { I420, Y42B, Y444 }, "
"framerate = (fraction) [0/1, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
@ -84,8 +85,8 @@ GST_STATIC_PAD_TEMPLATE ("sink",
GST_STATIC_CAPS ("video/x-theora")
);
GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstVideoDecoder,
GST_TYPE_VIDEO_DECODER);
#define gst_theora_dec_parent_class parent_class
G_DEFINE_TYPE (GstTheoraDec, gst_theora_dec, GST_TYPE_VIDEO_DECODER);
static void theora_dec_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
@ -105,22 +106,6 @@ static GstFlowReturn theora_dec_handle_frame (GstVideoDecoder * decoder,
static GstFlowReturn theora_dec_decode_buffer (GstTheoraDec * dec,
GstBuffer * buf, GstVideoCodecFrame * frame);
static void
gst_theora_dec_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_sink_factory));
gst_element_class_set_details_simple (element_class,
"Theora video decoder", "Codec/Decoder/Video",
"decode raw theora streams to raw YUV video",
"Benjamin Otte <otte@gnome.org>, Wim Taymans <wim@fluendo.com>");
}
static gboolean
gst_theora_dec_ctl_is_supported (int req)
{
@ -132,16 +117,12 @@ static void
gst_theora_dec_class_init (GstTheoraDecClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
gobject_class->set_property = theora_dec_set_property;
gobject_class->get_property = theora_dec_get_property;
g_object_class_install_property (gobject_class, PROP_CROP,
g_param_spec_boolean ("crop", "Crop",
"Crop the image to the visible region", THEORA_DEF_CROP,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
if (gst_theora_dec_ctl_is_supported (TH_DECCTL_SET_TELEMETRY_MV)) {
g_object_class_install_property (gobject_class, PROP_TELEMETRY_MV,
g_param_spec_int ("visualize-motion-vectors",
@ -186,6 +167,15 @@ gst_theora_dec_class_init (GstTheoraDecClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_dec_sink_factory));
gst_element_class_set_details_simple (element_class,
"Theora video decoder", "Codec/Decoder/Video",
"decode raw theora streams to raw YUV video",
"Benjamin Otte <otte@gnome.org>, Wim Taymans <wim@fluendo.com>");
video_decoder_class->start = GST_DEBUG_FUNCPTR (theora_dec_start);
video_decoder_class->stop = GST_DEBUG_FUNCPTR (theora_dec_stop);
video_decoder_class->reset = GST_DEBUG_FUNCPTR (theora_dec_reset);
@ -198,9 +188,8 @@ gst_theora_dec_class_init (GstTheoraDecClass * klass)
}
static void
gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class)
gst_theora_dec_init (GstTheoraDec * dec)
{
dec->crop = THEORA_DEF_CROP;
dec->telemetry_mv = THEORA_DEF_TELEMETRY_MV;
dec->telemetry_mbmode = THEORA_DEF_TELEMETRY_MBMODE;
dec->telemetry_qi = THEORA_DEF_TELEMETRY_QI;
@ -269,10 +258,11 @@ theora_dec_parse (GstVideoDecoder * decoder,
av = gst_adapter_available (adapter);
data = gst_adapter_peek (adapter, 1);
data = gst_adapter_map (adapter, 1);
/* check for keyframe; must not be header packet */
if (!(data[0] & 0x80) && (data[0] & 0x40) == 0)
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
gst_adapter_unmap (adapter);
/* and pass along all */
gst_video_decoder_add_to_frame (decoder, av);
@ -295,15 +285,17 @@ theora_dec_set_format (GstVideoDecoder * bdec, GstVideoCodecState * state)
/* FIXME : Interesting, we always accept any kind of caps ? */
if (state->codec_data) {
GstBuffer *buffer;
GstMapInfo minfo;
guint8 *data;
guint size;
guint offset;
buffer = state->codec_data;
gst_buffer_map (buffer, &minfo, GST_MAP_READ);
offset = 0;
size = GST_BUFFER_SIZE (buffer);
data = GST_BUFFER_DATA (buffer);
size = minfo.size;
data = (guint8 *) minfo.data;
while (size > 2) {
guint psize;
@ -318,7 +310,7 @@ theora_dec_set_format (GstVideoDecoder * bdec, GstVideoCodecState * state)
/* make sure we don't read too much */
psize = MIN (psize, size);
buf = gst_buffer_create_sub (buffer, offset, psize);
buf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offset, psize);
/* first buffer is a discont buffer */
if (offset == 2)
@ -333,6 +325,8 @@ theora_dec_set_format (GstVideoDecoder * bdec, GstVideoCodecState * state)
data += psize;
offset += psize;
}
gst_buffer_unmap (buffer, &minfo);
}
GST_DEBUG_OBJECT (dec, "Done");
@ -344,24 +338,17 @@ static GstFlowReturn
theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet)
{
gchar *encoder = NULL;
GstBuffer *buf;
GstTagList *list;
GST_DEBUG_OBJECT (dec, "parsing comment packet");
buf = gst_buffer_new ();
GST_BUFFER_SIZE (buf) = packet->bytes;
GST_BUFFER_DATA (buf) = packet->packet;
list =
gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7,
&encoder);
gst_buffer_unref (buf);
gst_tag_list_from_vorbiscomment (packet->packet, packet->bytes,
(guint8 *) "\201theora", 7, &encoder);
if (!list) {
GST_ERROR_OBJECT (dec, "couldn't decode comments");
list = gst_tag_list_new ();
list = gst_tag_list_new_empty ();
}
if (encoder) {
gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
@ -437,29 +424,13 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
goto unsupported_format;
}
if (dec->crop) {
GST_VIDEO_INFO_WIDTH (info) = dec->info.pic_width;
GST_VIDEO_INFO_HEIGHT (info) = dec->info.pic_height;
dec->offset_x = dec->info.pic_x;
dec->offset_y = dec->info.pic_y;
/* Ensure correct offsets in chroma for formats that need it
* by rounding the offset. libtheora will add proper pixels,
* so no need to handle them ourselves. */
if (dec->offset_x & 1 && dec->info.pixel_fmt != TH_PF_444) {
dec->offset_x--;
GST_VIDEO_INFO_WIDTH (info)++;
}
if (dec->offset_y & 1 && dec->info.pixel_fmt == TH_PF_420) {
dec->offset_y--;
GST_VIDEO_INFO_HEIGHT (info)++;
}
} else {
/* no cropping, use the encoded dimensions */
GST_VIDEO_INFO_WIDTH (info) = dec->info.frame_width;
GST_VIDEO_INFO_HEIGHT (info) = dec->info.frame_height;
dec->offset_x = 0;
dec->offset_y = 0;
}
/* FIXME: Use crop metadata */
/* no cropping, use the encoded dimensions */
GST_VIDEO_INFO_WIDTH (info) = dec->info.frame_width;
GST_VIDEO_INFO_HEIGHT (info) = dec->info.frame_height;
dec->offset_x = 0;
dec->offset_y = 0;
GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
info->width, info->height, dec->offset_x, dec->offset_y);
@ -504,8 +475,8 @@ theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
/* FIXME : Put this on the next outgoing frame */
/* FIXME : */
if (dec->tags) {
gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec),
GST_VIDEO_DECODER_SRC_PAD (dec), dec->tags);
gst_pad_push_event (GST_VIDEO_DECODER (dec)->srcpad,
gst_event_new_tag (dec->tags));
dec->tags = NULL;
}
@ -569,6 +540,7 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
int i, plane;
guint8 *dest, *src;
GstBuffer *out;
GstMapInfo minfo;
result = gst_video_decoder_alloc_output_frame (decoder, frame);
@ -581,13 +553,15 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
out = frame->output_buffer;
info = &dec->output_state->info;
/* FIXME : Use GstVideoInfo */
gst_buffer_map (out, &minfo, GST_MAP_WRITE);
/* FIXME : Use crop metadata */
for (plane = 0; plane < 3; plane++) {
width = GST_VIDEO_INFO_COMP_WIDTH (info, plane);
height = GST_VIDEO_INFO_COMP_HEIGHT (info, plane);
stride = GST_VIDEO_INFO_COMP_STRIDE (info, plane);
dest = GST_BUFFER_DATA (out) + GST_VIDEO_INFO_COMP_OFFSET (info, plane);
dest = minfo.data + GST_VIDEO_INFO_COMP_OFFSET (info, plane);
src = buf[plane].data;
src +=
((height ==
@ -605,6 +579,8 @@ theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
}
}
gst_buffer_unmap (out, &minfo);
return GST_FLOW_OK;
}
@ -700,10 +676,12 @@ theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf,
{
ogg_packet packet;
GstFlowReturn result = GST_FLOW_OK;
GstMapInfo minfo;
/* make ogg_packet out of the buffer */
packet.packet = GST_BUFFER_DATA (buf);
packet.bytes = GST_BUFFER_SIZE (buf);
gst_buffer_map (buf, &minfo, GST_MAP_READ);
packet.packet = minfo.data;
packet.bytes = minfo.size;
packet.granulepos = -1;
packet.packetno = 0; /* we don't really care */
packet.b_o_s = dec->have_header ? 0 : 1;
@ -732,6 +710,8 @@ theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf,
}
done:
gst_buffer_unmap (buf, &minfo);
return result;
}
@ -757,9 +737,6 @@ theora_dec_set_property (GObject * object, guint prop_id,
GstTheoraDec *dec = GST_THEORA_DEC (object);
switch (prop_id) {
case PROP_CROP:
dec->crop = g_value_get_boolean (value);
break;
case PROP_TELEMETRY_MV:
dec->telemetry_mv = g_value_get_int (value);
break;
@ -785,9 +762,6 @@ theora_dec_get_property (GObject * object, guint prop_id,
GstTheoraDec *dec = GST_THEORA_DEC (object);
switch (prop_id) {
case PROP_CROP:
g_value_set_boolean (value, dec->crop);
break;
case PROP_TELEMETRY_MV:
g_value_set_int (value, dec->telemetry_mv);
break;

View file

@ -77,10 +77,7 @@ struct _GstTheoraDec
gint telemetry_qi;
gint telemetry_bits;
gboolean crop;
GstTagList *tags;
};
struct _GstTheoraDecClass

View file

@ -69,25 +69,6 @@
#define GST_CAT_DEFAULT theoraenc_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type())
static GType
gst_border_mode_get_type (void)
{
static GType border_mode_type = 0;
static const GEnumValue border_mode[] = {
{BORDER_NONE, "No Border", "none"},
{BORDER_BLACK, "Black Border", "black"},
{BORDER_MIRROR, "Mirror image in borders", "mirror"},
{0, NULL, NULL},
};
if (!border_mode_type) {
border_mode_type =
g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
}
return border_mode_type;
}
#define GST_TYPE_MULTIPASS_MODE (gst_multipass_mode_get_type())
static GType
gst_multipass_mode_get_type (void)
@ -136,18 +117,11 @@ _ilog (unsigned int v)
enum
{
PROP_0,
PROP_CENTER,
PROP_BORDER,
PROP_BITRATE,
PROP_QUALITY,
PROP_QUICK,
PROP_KEYFRAME_AUTO,
PROP_KEYFRAME_FREQ,
PROP_KEYFRAME_FREQ_FORCE,
PROP_KEYFRAME_THRESHOLD,
PROP_KEYFRAME_MINDISTANCE,
PROP_NOISE_SENSITIVITY,
PROP_SHARPNESS,
PROP_SPEEDLEVEL,
PROP_VP3_COMPATIBLE,
PROP_DROP_FRAMES,
@ -182,8 +156,8 @@ static GstStaticPadTemplate theora_enc_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-raw-yuv, "
"format = (fourcc) { I420, Y42B, Y444 }, "
GST_STATIC_CAPS ("video/x-raw, "
"format = (string) { I420, Y42B, Y444 }, "
"framerate = (fraction) [1/MAX, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
@ -192,11 +166,13 @@ static GstStaticPadTemplate theora_enc_src_factory =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-theora")
GST_STATIC_CAPS ("video/x-theora, "
"framerate = (fraction) [1/MAX, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
);
GST_BOILERPLATE (GstTheoraEnc, gst_theora_enc, GstVideoEncoder,
GST_TYPE_VIDEO_ENCODER);
#define gst_theora_enc_parent_class parent_class
G_DEFINE_TYPE (GstTheoraEnc, gst_theora_enc, GST_TYPE_VIDEO_ENCODER);
static gboolean theora_enc_start (GstVideoEncoder * enc);
static gboolean theora_enc_stop (GstVideoEncoder * enc);
@ -208,7 +184,8 @@ static GstFlowReturn theora_enc_pre_push (GstVideoEncoder * benc,
GstVideoCodecFrame * frame);
static GstFlowReturn theora_enc_finish (GstVideoEncoder * enc);
static GstCaps *theora_enc_sink_getcaps (GstPad * pad);
static GstCaps *theora_enc_getcaps (GstVideoEncoder * encoder,
GstCaps * filter);
static void theora_enc_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void theora_enc_set_property (GObject * object, guint prop_id,
@ -219,9 +196,16 @@ static gboolean theora_enc_write_multipass_cache (GstTheoraEnc * enc,
gboolean begin, gboolean eos);
static void
gst_theora_enc_base_init (gpointer g_class)
gst_theora_enc_class_init (GstTheoraEncClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GObjectClass *gobject_class = (GObjectClass *) klass;
GstElementClass *element_class = (GstElementClass *) klass;
GstVideoEncoderClass *gstvideo_encoder_class =
GST_VIDEO_ENCODER_CLASS (klass);
gobject_class->set_property = theora_enc_set_property;
gobject_class->get_property = theora_enc_get_property;
gobject_class->finalize = theora_enc_finalize;
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&theora_enc_src_factory));
@ -231,18 +215,6 @@ gst_theora_enc_base_init (gpointer g_class)
"Theora video encoder", "Codec/Encoder/Video",
"encode raw YUV video to a theora stream",
"Wim Taymans <wim@fluendo.com>");
}
static void
gst_theora_enc_class_init (GstTheoraEncClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
GstVideoEncoderClass *gstvideo_encoder_class =
GST_VIDEO_ENCODER_CLASS (klass);
gobject_class->set_property = theora_enc_set_property;
gobject_class->get_property = theora_enc_get_property;
gobject_class->finalize = theora_enc_finalize;
gstvideo_encoder_class->start = GST_DEBUG_FUNCPTR (theora_enc_start);
gstvideo_encoder_class->stop = GST_DEBUG_FUNCPTR (theora_enc_stop);
@ -252,16 +224,8 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
GST_DEBUG_FUNCPTR (theora_enc_handle_frame);
gstvideo_encoder_class->pre_push = GST_DEBUG_FUNCPTR (theora_enc_pre_push);
gstvideo_encoder_class->finish = GST_DEBUG_FUNCPTR (theora_enc_finish);
gstvideo_encoder_class->getcaps = GST_DEBUG_FUNCPTR (theora_enc_getcaps);
g_object_class_install_property (gobject_class, PROP_CENTER,
g_param_spec_boolean ("center", "Center",
"ignored and kept for API compat only", TRUE,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_BORDER,
g_param_spec_enum ("border", "Border",
"ignored and kept for API compat only",
GST_TYPE_BORDER_MODE, BORDER_BLACK,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* general encoding stream options */
g_object_class_install_property (gobject_class, PROP_BITRATE,
g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
@ -273,10 +237,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
THEORA_DEF_QUALITY,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
GST_PARAM_MUTABLE_PLAYING));
g_object_class_install_property (gobject_class, PROP_QUICK,
g_param_spec_boolean ("quick", "Quick",
"ignored and kept for API compat only", TRUE,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO,
g_param_spec_boolean ("keyframe-auto", "Keyframe Auto",
"Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO,
@ -290,22 +250,6 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
"Force keyframe every N frames", 1, 32768,
THEORA_DEF_KEYFRAME_FREQ_FORCE,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_KEYFRAME_THRESHOLD,
g_param_spec_int ("keyframe-threshold", "Keyframe threshold",
"ignored and kept for API compat only", 0, 32768, 80,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_KEYFRAME_MINDISTANCE,
g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance",
"ignored and kept for API compat only", 1, 32768, 8,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY,
g_param_spec_int ("noise-sensitivity", "Noise sensitivity",
"ignored and kept for API compat only", 0, 32768, 1,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SHARPNESS,
g_param_spec_int ("sharpness", "Sharpness",
"ignored and kept for API compat only", 0, 2, 0,
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL,
g_param_spec_int ("speed-level", "Speed level",
"Controls the amount of motion vector searching done while "
@ -358,11 +302,8 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
}
static void
gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class)
gst_theora_enc_init (GstTheoraEnc * enc)
{
gst_pad_set_getcaps_function (GST_VIDEO_ENCODER_SINK_PAD (enc),
GST_DEBUG_FUNCPTR (theora_enc_sink_getcaps));
enc->video_bitrate = THEORA_DEF_BITRATE;
enc->video_quality = THEORA_DEF_QUALITY;
enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO;
@ -571,9 +512,9 @@ theora_enc_get_supported_formats (void)
}
static GstCaps *
theora_enc_sink_getcaps (GstPad * pad)
theora_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
{
GstCaps *caps;
GstCaps *caps, *ret;
char *supported_formats, *caps_string;
supported_formats = theora_enc_get_supported_formats ();
@ -582,8 +523,8 @@ theora_enc_sink_getcaps (GstPad * pad)
return gst_caps_new_empty ();
}
caps_string = g_strdup_printf ("video/x-raw-yuv, "
"format = (fourcc) { %s }, "
caps_string = g_strdup_printf ("video/x-raw, "
"format = (string) { %s }, "
"framerate = (fraction) [1/MAX, MAX], "
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]",
supported_formats);
@ -592,7 +533,10 @@ theora_enc_sink_getcaps (GstPad * pad)
g_free (supported_formats);
GST_DEBUG ("Supported caps: %" GST_PTR_FORMAT, caps);
return caps;
ret = gst_video_encoder_proxy_getcaps (encoder, caps, filter);
gst_caps_unref (caps);
return ret;
}
static gboolean
@ -682,14 +626,14 @@ theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet)
benc = GST_VIDEO_ENCODER (enc);
buf = gst_buffer_new_and_alloc (packet->bytes);
buf = gst_buffer_new_allocate (NULL, packet->bytes, NULL);
if (!buf) {
GST_WARNING_OBJECT (enc, "Could not allocate buffer");
ret = GST_FLOW_ERROR;
goto done;
}
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
gst_buffer_fill (buf, 0, packet->packet, packet->bytes);
frame = gst_video_encoder_get_oldest_frame (benc);
frame->output_buffer = buf;
@ -728,7 +672,7 @@ theora_set_header_on_caps (GstCaps * caps, GList * buffers)
buffer = walk->data;
/* mark buffer */
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER);
/* Copy buffer, because we can't use the original -
* it creates a circular refcount with the caps<->buffers */
@ -750,25 +694,11 @@ theora_set_header_on_caps (GstCaps * caps, GList * buffers)
}
static void
theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
theora_enc_init_buffer (th_ycbcr_buffer buf, GstVideoFrame * frame)
{
GstVideoFormat format;
GstVideoInfo vinfo;
guint i;
switch (info->pixel_fmt) {
case TH_PF_444:
format = GST_VIDEO_FORMAT_Y444;
break;
case TH_PF_420:
format = GST_VIDEO_FORMAT_I420;
break;
case TH_PF_422:
format = GST_VIDEO_FORMAT_Y42B;
break;
default:
g_assert_not_reached ();
}
/* According to Theora developer Timothy Terriberry, the Theora
* encoder will not use memory outside of pic_width/height, even when
* the frame size is bigger. The values outside this region will be encoded
@ -776,17 +706,17 @@ theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data)
* Due to this, setting the frame's width/height as the buffer width/height
* is perfectly ok, even though it does not strictly look ok.
*/
for (i = 0; i < 3; i++) {
buf[i].width =
gst_video_format_get_component_width (format, i, info->frame_width);
buf[i].height =
gst_video_format_get_component_height (format, i, info->frame_height);
buf[i].data =
data + gst_video_format_get_component_offset (format, i,
info->pic_width, info->pic_height);
buf[i].stride =
gst_video_format_get_row_stride (format, i, info->pic_width);
gst_video_info_init (&vinfo);
gst_video_info_set_format (&vinfo, GST_VIDEO_FRAME_FORMAT (frame),
GST_ROUND_UP_16 (GST_VIDEO_FRAME_WIDTH (frame)),
GST_ROUND_UP_16 (GST_VIDEO_FRAME_HEIGHT (frame)));
for (i = 0; i < 3; i++) {
buf[i].width = GST_VIDEO_INFO_COMP_WIDTH (&vinfo, i);
buf[i].height = GST_VIDEO_INFO_COMP_HEIGHT (&vinfo, i);
buf[i].data = GST_VIDEO_FRAME_COMP_DATA (frame, i);
buf[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, i);
}
}
@ -795,22 +725,29 @@ theora_enc_read_multipass_cache (GstTheoraEnc * enc)
{
GstBuffer *cache_buf;
const guint8 *cache_data;
gsize bytes_read = 0, bytes_consumed = 0;
gsize bytes_read = 0;
gssize bytes_consumed = 0;
GIOStatus stat = G_IO_STATUS_NORMAL;
gboolean done = FALSE;
while (!done) {
if (gst_adapter_available (enc->multipass_cache_adapter) == 0) {
cache_buf = gst_buffer_new_and_alloc (512);
GstMapInfo minfo;
cache_buf = gst_buffer_new_allocate (NULL, 512, NULL);
gst_buffer_map (cache_buf, &minfo, GST_MAP_WRITE);
stat = g_io_channel_read_chars (enc->multipass_cache_fd,
(gchar *) GST_BUFFER_DATA (cache_buf), GST_BUFFER_SIZE (cache_buf),
&bytes_read, NULL);
(gchar *) minfo.data, minfo.size, &bytes_read, NULL);
if (bytes_read <= 0) {
gst_buffer_unmap (cache_buf, &minfo);
gst_buffer_unref (cache_buf);
break;
} else {
GST_BUFFER_SIZE (cache_buf) = bytes_read;
gst_buffer_unmap (cache_buf, &minfo);
gst_buffer_resize (cache_buf, 0, bytes_read);
gst_adapter_push (enc->multipass_cache_adapter, cache_buf);
}
@ -821,11 +758,13 @@ theora_enc_read_multipass_cache (GstTheoraEnc * enc)
bytes_read =
MIN (gst_adapter_available (enc->multipass_cache_adapter), 512);
cache_data = gst_adapter_peek (enc->multipass_cache_adapter, bytes_read);
cache_data = gst_adapter_map (enc->multipass_cache_adapter, bytes_read);
bytes_consumed =
th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data,
bytes_read);
gst_adapter_unmap (enc->multipass_cache_adapter);
done = bytes_consumed <= 0;
if (bytes_consumed > 0)
gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed);
@ -864,7 +803,7 @@ theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin,
}
if (stat == G_IO_STATUS_ERROR || bytes_read < 0 || bytes_written < 0) {
if (stat == G_IO_STATUS_ERROR || bytes_read < 0) {
if (begin) {
if (eos)
GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL),
@ -900,15 +839,15 @@ theora_enc_buffer_from_header_packet (GstTheoraEnc * enc, ogg_packet * packet)
{
GstBuffer *outbuf;
outbuf = gst_buffer_new_and_alloc (packet->bytes);
memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
outbuf = gst_buffer_new_allocate (NULL, packet->bytes, NULL);
gst_buffer_fill (outbuf, 0, packet->packet, packet->bytes);
GST_BUFFER_OFFSET (outbuf) = 0;
GST_BUFFER_OFFSET_END (outbuf) = 0;
GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
GST_DEBUG ("created header packet buffer, %d bytes",
GST_BUFFER_SIZE (outbuf));
gst_buffer_get_size (outbuf));
return outbuf;
}
@ -996,7 +935,7 @@ theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame)
buffers = g_list_reverse (buffers);
/* mark buffers and put on caps */
caps = gst_caps_new_simple ("video/x-theora", NULL);
caps = gst_caps_new_empty_simple ("video/x-theora");
caps = theora_set_header_on_caps (caps, buffers);
state = gst_video_encoder_set_output_state (benc, caps, enc->input_state);
@ -1012,9 +951,7 @@ theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame)
{
th_ycbcr_buffer ycbcr;
gint res;
theora_enc_init_buffer (ycbcr, &enc->info,
GST_BUFFER_DATA (frame->input_buffer));
GstVideoFrame vframe;
if (force_keyframe) {
theora_enc_reset (enc);
@ -1029,7 +966,13 @@ theora_enc_handle_frame (GstVideoEncoder * benc, GstVideoCodecFrame * frame)
}
}
gst_video_frame_map (&vframe, &enc->input_state->info, frame->input_buffer,
GST_MAP_READ);
theora_enc_init_buffer (ycbcr, &vframe);
res = th_encode_ycbcr_in (enc->encoder, ycbcr);
gst_video_frame_unmap (&vframe);
/* none of the failure cases can happen here */
g_assert (res == 0);
@ -1102,15 +1045,6 @@ theora_enc_set_property (GObject * object, guint prop_id,
GstTheoraEnc *enc = GST_THEORA_ENC (object);
switch (prop_id) {
case PROP_CENTER:
case PROP_BORDER:
case PROP_QUICK:
case PROP_KEYFRAME_THRESHOLD:
case PROP_KEYFRAME_MINDISTANCE:
case PROP_NOISE_SENSITIVITY:
case PROP_SHARPNESS:
/* kept for API compat, but ignored */
break;
case PROP_BITRATE:
GST_OBJECT_LOCK (enc);
enc->video_bitrate = g_value_get_int (value) * 1000;
@ -1176,12 +1110,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
GstTheoraEnc *enc = GST_THEORA_ENC (object);
switch (prop_id) {
case PROP_CENTER:
g_value_set_boolean (value, TRUE);
break;
case PROP_BORDER:
g_value_set_enum (value, BORDER_BLACK);
break;
case PROP_BITRATE:
GST_OBJECT_LOCK (enc);
g_value_set_int (value, enc->video_bitrate / 1000);
@ -1192,9 +1120,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
g_value_set_int (value, enc->video_quality);
GST_OBJECT_UNLOCK (enc);
break;
case PROP_QUICK:
g_value_set_boolean (value, TRUE);
break;
case PROP_KEYFRAME_AUTO:
g_value_set_boolean (value, enc->keyframe_auto);
break;
@ -1204,18 +1129,6 @@ theora_enc_get_property (GObject * object, guint prop_id,
case PROP_KEYFRAME_FREQ_FORCE:
g_value_set_int (value, enc->keyframe_force);
break;
case PROP_KEYFRAME_THRESHOLD:
g_value_set_int (value, 80);
break;
case PROP_KEYFRAME_MINDISTANCE:
g_value_set_int (value, 8);
break;
case PROP_NOISE_SENSITIVITY:
g_value_set_int (value, 1);
break;
case PROP_SHARPNESS:
g_value_set_int (value, 0);
break;
case PROP_SPEEDLEVEL:
g_value_set_int (value, enc->speed_level);
break;

View file

@ -44,22 +44,6 @@ G_BEGIN_DECLS
typedef struct _GstTheoraEnc GstTheoraEnc;
typedef struct _GstTheoraEncClass GstTheoraEncClass;
/**
* GstTheoraEncBorderMode:
* @BORDER_NONE: no border
* @BORDER_BLACK: black border
* @BORDER_MIRROR: Mirror image in border
*
* Border color to add when sizes not multiple of 16.
*/
typedef enum
{
BORDER_NONE,
BORDER_BLACK,
BORDER_MIRROR
}
GstTheoraEncBorderMode;
/**
* GstTheoraEncMultipassMode:
* @MULTIPASS_MODE_SINGLE_PASS: Single pass encoding