mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
ext/theora/: Added cropping option to theora decoder.
Original commit message from CVS: * ext/theora/theoradec.c: (gst_theora_dec_class_init), (gst_theora_dec_init), (theora_get_formats), (theora_dec_src_convert), (theora_dec_sink_convert), (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), (theora_dec_chain), (theora_dec_set_property), (theora_dec_get_property): * ext/theora/theoraenc.c: (gst_border_mode_get_type), (gst_theora_enc_class_init), (gst_theora_enc_init), (theora_enc_sink_link), (theora_enc_chain), (theora_enc_set_property), (theora_enc_get_property): Added cropping option to theora decoder. Added border option to theora encoder.
This commit is contained in:
parent
05584c6b22
commit
fe21b56332
3 changed files with 197 additions and 21 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
2004-07-30 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/theora/theoradec.c: (gst_theora_dec_class_init),
|
||||
(gst_theora_dec_init), (theora_get_formats),
|
||||
(theora_dec_src_convert), (theora_dec_sink_convert),
|
||||
(theora_dec_src_query), (theora_dec_src_event), (theora_dec_event),
|
||||
(theora_dec_chain), (theora_dec_set_property),
|
||||
(theora_dec_get_property):
|
||||
* ext/theora/theoraenc.c: (gst_border_mode_get_type),
|
||||
(gst_theora_enc_class_init), (gst_theora_enc_init),
|
||||
(theora_enc_sink_link), (theora_enc_chain),
|
||||
(theora_enc_set_property), (theora_enc_get_property):
|
||||
Added cropping option to theora decoder.
|
||||
Added border option to theora encoder.
|
||||
|
||||
2004-07-30 Zaheer Abbas Merali <zaheerabbas at merali dot org>
|
||||
|
||||
* ext/libpng/gstpngenc.c: (gst_pngenc_class_init),
|
||||
|
|
|
@ -60,6 +60,8 @@ struct _GstTheoraDec
|
|||
gboolean need_keyframe;
|
||||
gint width, height;
|
||||
gint offset_x, offset_y;
|
||||
|
||||
gboolean crop;
|
||||
};
|
||||
|
||||
struct _GstTheoraDecClass
|
||||
|
@ -67,6 +69,13 @@ struct _GstTheoraDecClass
|
|||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
#define THEORA_DEF_CROP TRUE
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_CROP
|
||||
};
|
||||
|
||||
static GstElementDetails theora_dec_details = {
|
||||
"TheoraDec",
|
||||
"Codec/Decoder/Video",
|
||||
|
@ -94,6 +103,11 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
|||
|
||||
GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT);
|
||||
|
||||
static void theora_dec_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec);
|
||||
static void theora_dec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec);
|
||||
|
||||
static void theora_dec_chain (GstPad * pad, GstData * data);
|
||||
static GstElementStateReturn theora_dec_change_state (GstElement * element);
|
||||
static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event);
|
||||
|
@ -125,8 +139,17 @@ gst_theora_dec_base_init (gpointer g_class)
|
|||
static void
|
||||
gst_theora_dec_class_init (GstTheoraDecClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GstElementClass *gstelement_class = GST_ELEMENT_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, ARG_CROP,
|
||||
g_param_spec_boolean ("crop", "Crop",
|
||||
"Crop the image to the visible region", THEORA_DEF_CROP,
|
||||
(GParamFlags) G_PARAM_READWRITE));
|
||||
|
||||
gstelement_class->change_state = theora_dec_change_state;
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder");
|
||||
|
@ -157,6 +180,8 @@ gst_theora_dec_init (GstTheoraDec * dec)
|
|||
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
|
||||
|
||||
GST_FLAG_SET (dec, GST_ELEMENT_EVENT_AWARE);
|
||||
|
||||
dec->crop = THEORA_DEF_CROP;
|
||||
}
|
||||
|
||||
/* FIXME: copy from libtheora, theora should somehow make this available for seeking */
|
||||
|
@ -565,14 +590,22 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
|||
dec->info.frame_width, dec->info.frame_height,
|
||||
dec->info.offset_x, dec->info.offset_y);
|
||||
|
||||
/* add black borders to make width/height/offsets even. we need this because
|
||||
* we cannot express an offset to the peer plugin. */
|
||||
dec->width =
|
||||
ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
|
||||
dec->height =
|
||||
ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
|
||||
dec->offset_x = dec->info.offset_x & ~1;
|
||||
dec->offset_y = dec->info.offset_y & ~1;
|
||||
if (dec->crop) {
|
||||
/* add black borders to make width/height/offsets even. we need this because
|
||||
* we cannot express an offset to the peer plugin. */
|
||||
dec->width =
|
||||
ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
|
||||
dec->height =
|
||||
ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
|
||||
dec->offset_x = dec->info.offset_x & ~1;
|
||||
dec->offset_y = dec->info.offset_y & ~1;
|
||||
} else {
|
||||
/* no cropping, use the encoded dimensions */
|
||||
dec->width = dec->info.width;
|
||||
dec->height = dec->info.height;
|
||||
dec->offset_x = 0;
|
||||
dec->offset_y = 0;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
|
||||
dec->width, dec->height, dec->offset_x, dec->offset_y);
|
||||
|
@ -726,3 +759,35 @@ theora_dec_change_state (GstElement * element)
|
|||
|
||||
return parent_class->change_state (element);
|
||||
}
|
||||
|
||||
static void
|
||||
theora_dec_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTheoraDec *dec = GST_THEORA_DEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_CROP:
|
||||
dec->crop = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
theora_dec_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTheoraDec *dec = GST_THEORA_DEC (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_CROP:
|
||||
g_value_set_boolean (value, dec->crop);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,33 @@ GST_DEBUG_CATEGORY (theoraenc_debug);
|
|||
typedef struct _GstTheoraEnc GstTheoraEnc;
|
||||
typedef struct _GstTheoraEncClass GstTheoraEncClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BORDER_NONE,
|
||||
BORDER_BLACK,
|
||||
BORDER_MIRROR
|
||||
}
|
||||
GstTheoraEncBorderMode;
|
||||
|
||||
#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 GEnumValue border_mode[] = {
|
||||
{BORDER_NONE, "BORDER_NONE", "No Border"},
|
||||
{BORDER_BLACK, "BORDER_BLACK", "Black Border"},
|
||||
{BORDER_MIRROR, "BORDER_MIRROR", "Mirror image in borders"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
|
||||
if (!border_mode_type) {
|
||||
border_mode_type =
|
||||
g_enum_register_static ("GstTheoraEncBorderMode", border_mode);
|
||||
}
|
||||
return border_mode_type;
|
||||
}
|
||||
|
||||
struct _GstTheoraEnc
|
||||
{
|
||||
GstElement element;
|
||||
|
@ -57,6 +84,7 @@ struct _GstTheoraEnc
|
|||
theora_comment comment;
|
||||
|
||||
gboolean center;
|
||||
GstTheoraEncBorderMode border;
|
||||
|
||||
gint video_bitrate; /* bitrate target for Theora video */
|
||||
gint video_quality; /* Theora quality selector 0 = low, 63 = high */
|
||||
|
@ -88,6 +116,7 @@ struct _GstTheoraEncClass
|
|||
#define ROUND_UP_8(x) (((x) + 7) & ~7)
|
||||
|
||||
#define THEORA_DEF_CENTER TRUE
|
||||
#define THEORA_DEF_BORDER BORDER_BLACK
|
||||
#define THEORA_DEF_BITRATE 0
|
||||
#define THEORA_DEF_QUALITY 16
|
||||
#define THEORA_DEF_QUICK TRUE
|
||||
|
@ -102,6 +131,7 @@ enum
|
|||
{
|
||||
ARG_0,
|
||||
ARG_CENTER,
|
||||
ARG_BORDER,
|
||||
ARG_BITRATE,
|
||||
ARG_QUALITY,
|
||||
ARG_QUICK,
|
||||
|
@ -174,6 +204,11 @@ gst_theora_enc_class_init (GstTheoraEncClass * klass)
|
|||
g_param_spec_boolean ("center", "Center",
|
||||
"Center image when sizes not multiple of 16", THEORA_DEF_CENTER,
|
||||
(GParamFlags) G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_BORDER,
|
||||
g_param_spec_enum ("border", "Border",
|
||||
"Border color to add when sizes not multiple of 16",
|
||||
GST_TYPE_BORDER_MODE, THEORA_DEF_BORDER,
|
||||
(GParamFlags) G_PARAM_READWRITE));
|
||||
/* general encoding stream options */
|
||||
g_object_class_install_property (gobject_class, ARG_BITRATE,
|
||||
g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)",
|
||||
|
@ -229,6 +264,9 @@ gst_theora_enc_init (GstTheoraEnc * enc)
|
|||
gst_pad_use_explicit_caps (enc->srcpad);
|
||||
gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad);
|
||||
|
||||
enc->center = THEORA_DEF_CENTER;
|
||||
enc->border = THEORA_DEF_BORDER;
|
||||
|
||||
enc->video_bitrate = THEORA_DEF_BITRATE;
|
||||
enc->video_quality = THEORA_DEF_QUALITY;
|
||||
enc->quick = THEORA_DEF_QUICK;
|
||||
|
@ -494,6 +532,7 @@ theora_enc_chain (GstPad * pad, GstData * data)
|
|||
gint dst_y_stride, dst_uv_stride;
|
||||
gint width, height;
|
||||
gint cwidth, cheight;
|
||||
gint offset_x, right_x, right_border;
|
||||
|
||||
/* source width/height */
|
||||
width = enc->width;
|
||||
|
@ -513,33 +552,74 @@ theora_enc_chain (GstPad * pad, GstData * data)
|
|||
newbuf = gst_pad_alloc_buffer (enc->srcpad,
|
||||
GST_BUFFER_OFFSET_NONE, y_size * 3 / 2);
|
||||
|
||||
yuv.y = GST_BUFFER_DATA (newbuf);
|
||||
yuv.u = yuv.y + y_size;
|
||||
yuv.v = yuv.u + y_size / 4;
|
||||
|
||||
/* center if needed */
|
||||
dest_y = yuv.y + enc->offset_x + enc->offset_y * dst_y_stride;
|
||||
dest_u =
|
||||
yuv.u + (enc->offset_x / 2) + (enc->offset_y / 2) * dst_uv_stride;
|
||||
dest_v =
|
||||
yuv.v + (enc->offset_x / 2) + (enc->offset_y / 2) * dst_uv_stride;
|
||||
dest_y = yuv.y = GST_BUFFER_DATA (newbuf);
|
||||
dest_u = yuv.u = yuv.y + y_size;
|
||||
dest_v = yuv.v = yuv.u + y_size / 4;
|
||||
|
||||
src_y = GST_BUFFER_DATA (buf);
|
||||
src_u = src_y + src_y_stride * ROUND_UP_2 (height);
|
||||
src_v = src_u + src_uv_stride * ROUND_UP_2 (height) / 2;
|
||||
|
||||
if (enc->border != BORDER_NONE) {
|
||||
/* fill top border */
|
||||
for (i = 0; i < enc->offset_y; i++) {
|
||||
memset (dest_y, 0, dst_y_stride);
|
||||
dest_y += dst_y_stride;
|
||||
}
|
||||
} else {
|
||||
dest_y += dst_y_stride * enc->offset_y;
|
||||
}
|
||||
|
||||
offset_x = enc->offset_x;
|
||||
right_x = width + enc->offset_x;
|
||||
right_border = dst_y_stride - right_x;
|
||||
|
||||
/* copy Y plane */
|
||||
for (i = 0; i < height; i++) {
|
||||
memcpy (dest_y, src_y, width);
|
||||
memcpy (dest_y + offset_x, src_y, width);
|
||||
if (enc->border != BORDER_NONE) {
|
||||
memset (dest_y, 0, offset_x);
|
||||
memset (dest_y + right_x, 0, right_border);
|
||||
}
|
||||
|
||||
dest_y += dst_y_stride;
|
||||
src_y += src_y_stride;
|
||||
}
|
||||
|
||||
if (enc->border != BORDER_NONE) {
|
||||
/* fill bottom border */
|
||||
for (i = height + enc->offset_y; i < enc->info.height; i++) {
|
||||
memset (dest_y, 0, dst_y_stride);
|
||||
dest_y += dst_y_stride;
|
||||
}
|
||||
|
||||
/* fill top border chroma */
|
||||
for (i = 0; i < enc->offset_y / 2; i++) {
|
||||
memset (dest_u, 128, dst_uv_stride);
|
||||
memset (dest_v, 128, dst_uv_stride);
|
||||
dest_u += dst_uv_stride;
|
||||
dest_v += dst_uv_stride;
|
||||
}
|
||||
} else {
|
||||
dest_u += dst_uv_stride * enc->offset_y / 2;
|
||||
dest_v += dst_uv_stride * enc->offset_y / 2;
|
||||
}
|
||||
|
||||
offset_x = enc->offset_x / 2;
|
||||
right_x = cwidth + offset_x;
|
||||
right_border = dst_uv_stride - right_x;
|
||||
|
||||
/* copy UV planes */
|
||||
for (i = 0; i < cheight; i++) {
|
||||
memcpy (dest_u, src_u, cwidth);
|
||||
memcpy (dest_v, src_v, cwidth);
|
||||
memcpy (dest_v + offset_x, src_v, cwidth);
|
||||
memcpy (dest_u + offset_x, src_u, cwidth);
|
||||
|
||||
if (enc->border != BORDER_NONE) {
|
||||
memset (dest_u, 128, offset_x);
|
||||
memset (dest_u + right_x, 128, right_border);
|
||||
memset (dest_v, 128, offset_x);
|
||||
memset (dest_v + right_x, 128, right_border);
|
||||
}
|
||||
|
||||
dest_u += dst_uv_stride;
|
||||
dest_v += dst_uv_stride;
|
||||
|
@ -547,6 +627,16 @@ theora_enc_chain (GstPad * pad, GstData * data)
|
|||
src_v += src_uv_stride;
|
||||
}
|
||||
|
||||
if (enc->border != BORDER_NONE) {
|
||||
/* fill bottom border */
|
||||
for (i = cheight + enc->offset_y / 2; i < enc->info_height / 2; i++) {
|
||||
memset (dest_u, 128, dst_uv_stride);
|
||||
memset (dest_v, 128, dst_uv_stride);
|
||||
dest_u += dst_uv_stride;
|
||||
dest_v += dst_uv_stride;
|
||||
}
|
||||
}
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
@ -604,6 +694,9 @@ theora_enc_set_property (GObject * object, guint prop_id,
|
|||
case ARG_CENTER:
|
||||
enc->center = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_BORDER:
|
||||
enc->border = g_value_get_enum (value);
|
||||
break;
|
||||
case ARG_BITRATE:
|
||||
enc->video_bitrate = g_value_get_int (value) * 1000;
|
||||
enc->video_quality = 0;
|
||||
|
@ -649,6 +742,9 @@ theora_enc_get_property (GObject * object, guint prop_id,
|
|||
case ARG_CENTER:
|
||||
g_value_set_boolean (value, enc->center);
|
||||
break;
|
||||
case ARG_BORDER:
|
||||
g_value_set_enum (value, enc->border);
|
||||
break;
|
||||
case ARG_BITRATE:
|
||||
g_value_set_int (value, enc->video_bitrate / 1000);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue