mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +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>
|
||||
|
||||
* ext/dvdnav/README:
|
||||
|
|
|
@ -460,6 +460,10 @@ theora_dec_event (GstTheoraDec * dec, GstEvent * 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
|
||||
theora_dec_chain (GstPad * pad, GstData * data)
|
||||
{
|
||||
|
@ -545,9 +549,19 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
|||
par_den = dec->info.aspect_denominator;
|
||||
if (par_num == 0 && par_den == 0) {
|
||||
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);
|
||||
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 */
|
||||
theora_decode_init (&dec->state, &dec->info);
|
||||
|
@ -556,8 +570,8 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
|||
"framerate", G_TYPE_DOUBLE,
|
||||
((gdouble) dec->info.fps_numerator) / dec->info.fps_denominator,
|
||||
"pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
|
||||
"width", G_TYPE_INT, dec->info.width, "height", G_TYPE_INT,
|
||||
dec->info.height, NULL);
|
||||
"width", G_TYPE_INT, dec->info.frame_width, "height", G_TYPE_INT,
|
||||
dec->info.frame_height, NULL);
|
||||
gst_pad_set_explicit_caps (dec->srcpad, caps);
|
||||
gst_caps_free (caps);
|
||||
}
|
||||
|
@ -565,9 +579,12 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
|||
/* normal data packet */
|
||||
yuv_buffer yuv;
|
||||
GstBuffer *out;
|
||||
guint8 *y, *v, *u;
|
||||
guint i;
|
||||
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
|
||||
* for keyframes */
|
||||
|
@ -591,20 +608,70 @@ theora_dec_chain (GstPad * pad, GstData * data)
|
|||
gst_data_unref (data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_fail (yuv.y_width == dec->info.width);
|
||||
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);
|
||||
y = GST_BUFFER_DATA (out);
|
||||
u = y + yuv.y_width * yuv.y_height;
|
||||
v = u + yuv.y_width * yuv.y_height / 4;
|
||||
for (i = 0; i < yuv.y_height; i++) {
|
||||
memcpy (y + i * yuv.y_width, yuv.y + i * yuv.y_stride, yuv.y_width);
|
||||
|
||||
width = dec->info.frame_width;
|
||||
height = dec->info.frame_height;
|
||||
|
||||
/* should get the stride from the caps, for now we round up to the nearest
|
||||
* multiple of 4 because some element needs it. chroma needs special
|
||||
* 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);
|
||||
memcpy (v + i * yuv.uv_width, yuv.v + i * yuv.uv_stride, yuv.uv_width);
|
||||
|
||||
src_u =
|
||||
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_END (out) = dec->packetno - 3;
|
||||
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");
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
theora_info_init (&enc->info);
|
||||
enc->info.width = enc->width;
|
||||
|
|
Loading…
Reference in a new issue