mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
ext/ffmpeg/: Fix strides and plane sizes when dealing with odd sized movies.
Original commit message from CVS: * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_avpicture_get_size), (gst_ffmpeg_avpicture_fill), (gst_ffmpeg_img_convert): * ext/ffmpeg/gstffmpegcodecmap.h: * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain): Fix strides and plane sizes when dealing with odd sized movies.
This commit is contained in:
parent
46d853ba99
commit
8b92efb152
4 changed files with 94 additions and 12 deletions
|
@ -1,3 +1,12 @@
|
|||
2004-11-05 Wim Taymans <wim@fluendo.com>
|
||||
|
||||
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_avpicture_get_size),
|
||||
(gst_ffmpeg_avpicture_fill), (gst_ffmpeg_img_convert):
|
||||
* ext/ffmpeg/gstffmpegcodecmap.h:
|
||||
* ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain):
|
||||
Fix strides and plane sizes when dealing with odd sized
|
||||
movies.
|
||||
|
||||
2004-10-29 Sebastien Cote <sc5@hermes.usherb.ca>
|
||||
|
||||
Reviewed by: Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
|
|
@ -2134,7 +2134,20 @@ static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
|
|||
},
|
||||
};
|
||||
|
||||
#define ROUND_UP_4(x) (((x) + 3) & ~3)
|
||||
int
|
||||
gst_ffmpeg_avpicture_get_size (int pix_fmt, int width, int height)
|
||||
{
|
||||
AVPicture dummy_pict;
|
||||
|
||||
return gst_ffmpeg_avpicture_fill (&dummy_pict, NULL, pix_fmt, width, height);
|
||||
}
|
||||
|
||||
#define GEN_MASK(x) ((1<<(x))-1)
|
||||
#define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
|
||||
#define ROUND_UP_2(x) ROUND_UP_X (x, 1)
|
||||
#define ROUND_UP_4(x) ROUND_UP_X (x, 2)
|
||||
#define ROUND_UP_8(x) ROUND_UP_X (x, 3)
|
||||
#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x))
|
||||
|
||||
int
|
||||
gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
||||
|
@ -2145,8 +2158,6 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
|||
PixFmtInfo *pinfo;
|
||||
|
||||
pinfo = &pix_fmt_info[pix_fmt];
|
||||
stride = ROUND_UP_4 (width);
|
||||
size = stride * height;
|
||||
switch (pix_fmt) {
|
||||
case PIX_FMT_YUV420P:
|
||||
case PIX_FMT_YUV422P:
|
||||
|
@ -2157,10 +2168,11 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
|||
case PIX_FMT_YUVJ422P:
|
||||
case PIX_FMT_YUVJ444P:
|
||||
stride = ROUND_UP_4 (width);
|
||||
size = stride * height;
|
||||
w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
|
||||
h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
|
||||
size = stride * h2;
|
||||
w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
|
||||
stride2 = ROUND_UP_4 (w2);
|
||||
h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
|
||||
h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
|
||||
size2 = stride2 * h2;
|
||||
picture->data[0] = ptr;
|
||||
picture->data[1] = picture->data[0] + size;
|
||||
|
@ -2233,3 +2245,41 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert image 'src' to 'dst'.
|
||||
*
|
||||
* We use this code to copy two pictures between the same
|
||||
* colorspaces, so this function is not realy used to do
|
||||
* colorspace conversion.
|
||||
* The ffmpeg code has a bug in it where odd sized frames were
|
||||
* not copied completely. We adjust the input parameters for
|
||||
* the original ffmpeg img_convert function here so that it
|
||||
* still does the right thing.
|
||||
*/
|
||||
int
|
||||
gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
|
||||
const AVPicture * src, int src_pix_fmt, int src_width, int src_height)
|
||||
{
|
||||
int i;
|
||||
PixFmtInfo *pf = &pix_fmt_info[src_pix_fmt];
|
||||
|
||||
pf = &pix_fmt_info[src_pix_fmt];
|
||||
switch (pf->pixel_type) {
|
||||
case FF_PIXEL_PACKED:
|
||||
/* nothing wrong here */
|
||||
break;
|
||||
case FF_PIXEL_PLANAR:
|
||||
/* patch up, so that img_copy copies all of the pixels */
|
||||
src_width = ROUND_UP_X (src_width, pf->x_chroma_shift);
|
||||
src_height = ROUND_UP_X (src_height, pf->y_chroma_shift);
|
||||
break;
|
||||
case FF_PIXEL_PALETTE:
|
||||
/* nothing wrong here */
|
||||
break;
|
||||
}
|
||||
return img_convert (dst, dst_pix_fmt, src, src_pix_fmt, src_width, src_height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -95,6 +95,12 @@ gst_ffmpeg_formatid_to_caps (const gchar *format_name);
|
|||
G_CONST_RETURN gchar *
|
||||
gst_ffmpeg_get_codecid_longname (enum CodecID codec_id);
|
||||
|
||||
/*
|
||||
*Get the size of an picture
|
||||
*/
|
||||
int
|
||||
gst_ffmpeg_avpicture_get_size (int pix_fmt, int width, int height);
|
||||
|
||||
/*
|
||||
* Fill in pointers in an AVPicture, aligned by 4 (required by X).
|
||||
*/
|
||||
|
@ -106,6 +112,15 @@ gst_ffmpeg_avpicture_fill (AVPicture * picture,
|
|||
int width,
|
||||
int height);
|
||||
|
||||
/*
|
||||
* convert an image, we only use this for copying the image, ie,
|
||||
* convert between the same colorspaces.
|
||||
*/
|
||||
int
|
||||
gst_ffmpeg_img_convert (AVPicture * dst, int dst_pix_fmt,
|
||||
const AVPicture * src, int src_pix_fmt, int src_width, int src_height);
|
||||
|
||||
|
||||
/*
|
||||
* FFMPEG debugging function; maybe move to a different file.
|
||||
*/
|
||||
|
|
|
@ -358,6 +358,9 @@ gst_ffmpegdec_release_buffer (AVCodecContext * context, AVFrame * picture)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define ROUND_UP_2(x) (((x) + 1) & ~1)
|
||||
#define ROUND_UP_4(x) (((x) + 3) & ~3)
|
||||
|
||||
static void
|
||||
gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
|
||||
{
|
||||
|
@ -406,23 +409,28 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
|
|||
ffmpegdec->picture, &have_data, data, size);
|
||||
|
||||
if (len >= 0 && have_data) {
|
||||
#define ROUND_UP_4(x) (((x) + 3) & ~3)
|
||||
/* libavcodec constantly crashes on stupid buffer allocation
|
||||
* errors inside. This drives me crazy, so we let it allocate
|
||||
* it's own buffers and copy to our own buffer afterwards... */
|
||||
AVPicture pic;
|
||||
gint size = avpicture_get_size (ffmpegdec->context->pix_fmt,
|
||||
ROUND_UP_4 (ffmpegdec->context->width),
|
||||
ROUND_UP_4 (ffmpegdec->context->height));
|
||||
gint size = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt,
|
||||
ffmpegdec->context->width, ffmpegdec->context->height);
|
||||
|
||||
outbuf = gst_buffer_new_and_alloc (size);
|
||||
/* original ffmpeg code does not handle odd sizes correctly. This patched
|
||||
* up version does */
|
||||
gst_ffmpeg_avpicture_fill (&pic, GST_BUFFER_DATA (outbuf),
|
||||
ffmpegdec->context->pix_fmt,
|
||||
ffmpegdec->context->width, ffmpegdec->context->height);
|
||||
img_convert (&pic, ffmpegdec->context->pix_fmt,
|
||||
|
||||
/* the original convert function did not do the right thing, this
|
||||
* is a patched up version that adjust widht/height so that the
|
||||
* ffmpeg one works correctly. */
|
||||
gst_ffmpeg_img_convert (&pic, ffmpegdec->context->pix_fmt,
|
||||
(AVPicture *) ffmpegdec->picture,
|
||||
ffmpegdec->context->pix_fmt,
|
||||
ffmpegdec->context->width, ffmpegdec->context->height);
|
||||
ffmpegdec->context->width,
|
||||
ffmpegdec->context->height);
|
||||
|
||||
/* note that ffmpeg sometimes gets the FPS wrong */
|
||||
if (GST_CLOCK_TIME_IS_VALID (expected_ts) &&
|
||||
|
|
Loading…
Reference in a new issue