mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
ext/theora/: Added first attempt at cropping of the image as required by the theora spec. We need more properties in ...
Original commit message from CVS: * ext/theora/theoradec.c: (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): * ext/theora/theoraenc.c: (theora_enc_sink_link): Added first attempt at cropping of the image as required by the theora spec. We need more properties in the caps (offset_x, offset_y,stride) to implement this correctly. Added some debug info in the encoder. Note :the encoder is not updated with the offset code.
This commit is contained in:
parent
8aafec7515
commit
69934d5915
3 changed files with 97 additions and 16 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2004-07-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* ext/theora/theoradec.c: (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):
|
||||||
|
* ext/theora/theoraenc.c: (theora_enc_sink_link):
|
||||||
|
Added first attempt at cropping of the image as required by the
|
||||||
|
theora spec. We need more properties in the caps (offset_x,
|
||||||
|
offset_y,stride) to implement this correctly.
|
||||||
|
|
||||||
2004-07-28 Jan Schmidt <thaytan@mad.scientist.com>
|
2004-07-28 Jan Schmidt <thaytan@mad.scientist.com>
|
||||||
|
|
||||||
* ext/dvdnav/README:
|
* ext/dvdnav/README:
|
||||||
|
|
|
@ -460,6 +460,10 @@ theora_dec_event (GstTheoraDec * dec, GstEvent * event)
|
||||||
gst_pad_event_default (dec->sinkpad, event);
|
gst_pad_event_default (dec->sinkpad, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ROUND_UP_2(x) (((x) + 1) & ~1)
|
||||||
|
#define ROUND_UP_4(x) (((x) + 3) & ~3)
|
||||||
|
#define ROUND_UP_8(x) (((x) + 7) & ~7)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
theora_dec_chain (GstPad * pad, GstData * data)
|
theora_dec_chain (GstPad * pad, GstData * data)
|
||||||
{
|
{
|
||||||
|
@ -545,9 +549,19 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
||||||
par_den = dec->info.aspect_denominator;
|
par_den = dec->info.aspect_denominator;
|
||||||
if (par_num == 0 && par_den == 0) {
|
if (par_num == 0 && par_den == 0) {
|
||||||
par_num = par_den = 1;
|
par_num = par_den = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
GST_DEBUG_OBJECT (dec, "video %dx%d, PAR %d/%d", dec->info.width,
|
/* theora has:
|
||||||
|
*
|
||||||
|
* width/height : dimension of the encoded frame
|
||||||
|
* frame_width/frame_height : dimension of the visible part
|
||||||
|
* offset_x/offset_y : offset in encoded frame where visible part starts
|
||||||
|
*/
|
||||||
|
GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
|
||||||
dec->info.height, par_num, par_den);
|
dec->info.height, par_num, par_den);
|
||||||
|
GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
|
||||||
|
dec->info.frame_width, dec->info.frame_height,
|
||||||
|
dec->info.offset_x, dec->info.offset_y);
|
||||||
|
|
||||||
/* done */
|
/* done */
|
||||||
theora_decode_init (&dec->state, &dec->info);
|
theora_decode_init (&dec->state, &dec->info);
|
||||||
|
@ -556,8 +570,8 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
||||||
"framerate", G_TYPE_DOUBLE,
|
"framerate", G_TYPE_DOUBLE,
|
||||||
((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator,
|
((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator,
|
||||||
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
|
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
|
||||||
"width", G_TYPE_INT, dec->info.width, "height", G_TYPE_INT,
|
"width", G_TYPE_INT, dec->info.frame_width, "height", G_TYPE_INT,
|
||||||
dec->info.height, NULL);
|
dec->info.frame_height, NULL);
|
||||||
gst_pad_set_explicit_caps (dec->srcpad, caps);
|
gst_pad_set_explicit_caps (dec->srcpad, caps);
|
||||||
gst_caps_free (caps);
|
gst_caps_free (caps);
|
||||||
}
|
}
|
||||||
|
@ -565,9 +579,12 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
||||||
/* normal data packet */
|
/* normal data packet */
|
||||||
yuv_buffer yuv;
|
yuv_buffer yuv;
|
||||||
GstBuffer *out;
|
GstBuffer *out;
|
||||||
guint8 *y, *v, *u;
|
|
||||||
guint i;
|
guint i;
|
||||||
gboolean keyframe;
|
gboolean keyframe;
|
||||||
|
gint out_size;
|
||||||
|
gint stride_y, stride_uv;
|
||||||
|
gint width, height;
|
||||||
|
gint cwidth, cheight;
|
||||||
|
|
||||||
/* the second most significant bit of the first data byte is cleared
|
/* the second most significant bit of the first data byte is cleared
|
||||||
* for keyframes */
|
* for keyframes */
|
||||||
|
@ -591,20 +608,70 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
||||||
gst_data_unref (data);
|
gst_data_unref (data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_if_fail (yuv.y_width == dec->info.width);
|
g_return_if_fail (yuv.y_width == dec->info.width);
|
||||||
g_return_if_fail (yuv.y_height == dec->info.height);
|
g_return_if_fail (yuv.y_height == dec->info.height);
|
||||||
out = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE,
|
|
||||||
yuv.y_width * yuv.y_height * 3 / 2);
|
width = dec->info.frame_width;
|
||||||
y = GST_BUFFER_DATA (out);
|
height = dec->info.frame_height;
|
||||||
u = y + yuv.y_width * yuv.y_height;
|
|
||||||
v = u + yuv.y_width * yuv.y_height / 4;
|
/* should get the stride from the caps, for now we round up to the nearest
|
||||||
for (i = 0; i < yuv.y_height; i++) {
|
* multiple of 4 because some element needs it. chroma needs special
|
||||||
memcpy (y + i * yuv.y_width, yuv.y + i * yuv.y_stride, yuv.y_width);
|
* treatment, see videotestsrc. */
|
||||||
|
stride_y = ROUND_UP_4 (width);
|
||||||
|
stride_uv = ROUND_UP_8 (width) / 2;
|
||||||
|
|
||||||
|
/* for odd offsets we need to copy one extra line/column of chroma samples */
|
||||||
|
cwidth = width / 2 + (dec->info.offset_x & 1);
|
||||||
|
cheight = height / 2 + (dec->info.offset_y & 1);
|
||||||
|
|
||||||
|
out_size = stride_y * height + stride_uv * cheight * 2;
|
||||||
|
|
||||||
|
/* now copy over the area contained in offset_x,offset_y,
|
||||||
|
* frame_width, frame_height */
|
||||||
|
out = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, out_size);
|
||||||
|
|
||||||
|
/* copy the visible region to the destination. This is actually pretty
|
||||||
|
* complicated and gstreamer doesn't support all the needed caps to do this
|
||||||
|
* correctly. For example, when we have an odd offset, we should only combine
|
||||||
|
* 1 row/column of luma samples with on chroma sample in colorspace conversion.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
guint8 *dest_y, *src_y;
|
||||||
|
guint8 *dest_u, *src_u;
|
||||||
|
guint8 *dest_v, *src_v;
|
||||||
|
|
||||||
|
dest_y = GST_BUFFER_DATA (out);
|
||||||
|
dest_u = dest_y + stride_y * height;
|
||||||
|
dest_v = dest_u + stride_uv * height / 2;
|
||||||
|
|
||||||
|
src_y = yuv.y + dec->info.offset_x + dec->info.offset_y * yuv.y_stride;
|
||||||
|
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
memcpy (dest_y, src_y, width);
|
||||||
|
|
||||||
|
dest_y += stride_y;
|
||||||
|
src_y += yuv.y_stride;
|
||||||
}
|
}
|
||||||
for (i = 0; i < yuv.y_height / 2; i++) {
|
|
||||||
memcpy (u + i * yuv.uv_width, yuv.u + i * yuv.uv_stride, yuv.uv_width);
|
src_u =
|
||||||
memcpy (v + i * yuv.uv_width, yuv.v + i * yuv.uv_stride, yuv.uv_width);
|
yuv.u + dec->info.offset_x / 2 +
|
||||||
|
dec->info.offset_y / 2 * yuv.uv_stride;
|
||||||
|
src_v =
|
||||||
|
yuv.v + dec->info.offset_x / 2 +
|
||||||
|
dec->info.offset_y / 2 * yuv.uv_stride;
|
||||||
|
|
||||||
|
for (i = 0; i < cheight; i++) {
|
||||||
|
memcpy (dest_u, src_u, cwidth);
|
||||||
|
memcpy (dest_v, src_v, cwidth);
|
||||||
|
|
||||||
|
dest_u += stride_uv;
|
||||||
|
src_u += yuv.uv_stride;
|
||||||
|
dest_v += stride_uv;
|
||||||
|
src_v += yuv.uv_stride;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GST_BUFFER_OFFSET (out) = dec->packetno - 4;
|
GST_BUFFER_OFFSET (out) = dec->packetno - 4;
|
||||||
GST_BUFFER_OFFSET_END (out) = dec->packetno - 3;
|
GST_BUFFER_OFFSET_END (out) = dec->packetno - 3;
|
||||||
GST_BUFFER_DURATION (out) =
|
GST_BUFFER_DURATION (out) =
|
||||||
|
|
|
@ -245,8 +245,11 @@ theora_enc_sink_link (GstPad * pad, const GstCaps * caps)
|
||||||
par = gst_structure_get_value (structure, "pixel-aspect-ratio");
|
par = gst_structure_get_value (structure, "pixel-aspect-ratio");
|
||||||
|
|
||||||
/* Theora has a divisible-by-sixteen restriction for the encoded video size */
|
/* Theora has a divisible-by-sixteen restriction for the encoded video size */
|
||||||
if ((enc->width & 0x0f) != 0 || (enc->height & 0x0f) != 0)
|
if ((enc->width & 0x0f) != 0 || (enc->height & 0x0f) != 0) {
|
||||||
|
GST_DEBUG ("width and height not a multiple of 16 in caps %" GST_PTR_FORMAT,
|
||||||
|
caps);
|
||||||
return GST_PAD_LINK_REFUSED;
|
return GST_PAD_LINK_REFUSED;
|
||||||
|
}
|
||||||
|
|
||||||
theora_info_init (&enc->info);
|
theora_info_init (&enc->info);
|
||||||
enc->info.width = enc->width;
|
enc->info.width = enc->width;
|
||||||
|
|
Loading…
Reference in a new issue