mp_image: simplify image allocation

mp_image_alloc_planes() allocated images with minimal stride, even if
the resulting stride was unaligned. It was the responsibility of
vf_get_image() to set an image's width to something larger than
required to get an aligned stride, and then crop it. Always allocate
with aligned strides instead.

Get rid of IMGFMT_IF09 special handling. This format is not used
anymore. (IF09 has 4x4 chroma sub-sampling, and that is what it was
mainly used for - this is still supported.) Get rid of swapped chroma
plane allocation. This is not used anywhere, and VOs like vo_xv,
vo_direct3d and vo_sdl do their own swapping.

Always round chroma width/height up instead of down. Consider 4:2:0 and
an uneven image size. For luma, the size was left uneven, and the chroma
size was rounded down. This doesn't make sense, because chroma would be
missing for the bottom/right border.

Remove mp_image_new_empty() and mp_image_alloc_planes(), they were not
used anymore, except in draw_bmp.c. (It's still allowed to setup
mp_images manually, you just can't allocate image data with them
anymore - this is also done in draw_bmp.c.)
This commit is contained in:
wm4 2012-12-19 12:04:32 +01:00
parent 00653a3eb0
commit ab94c64ed2
4 changed files with 62 additions and 122 deletions

View File

@ -213,23 +213,23 @@ static void unpremultiply_and_split_BGR32(struct mp_image *img,
static void scale_sb_rgba(struct sub_bitmap *sb, struct mp_image *dst_format,
struct mp_image **out_sbi, struct mp_image **out_sba)
{
struct mp_image *sbisrc = new_mp_image(sb->w, sb->h);
mp_image_setfmt(sbisrc, IMGFMT_BGR32);
sbisrc->planes[0] = sb->bitmap;
sbisrc->stride[0] = sb->stride;
struct mp_image *sbisrc2 = alloc_mpi(sb->dw, sb->dh, IMGFMT_BGR32);
mp_image_swscale(sbisrc2, sbisrc, SWS_BILINEAR);
struct mp_image sbisrc = {0};
mp_image_setfmt(&sbisrc, IMGFMT_BGR32);
mp_image_set_size(&sbisrc, sb->w, sb->h);
sbisrc.planes[0] = sb->bitmap;
sbisrc.stride[0] = sb->stride;
struct mp_image *sbisrc2 = mp_image_alloc(IMGFMT_BGR32, sb->dw, sb->dh);
mp_image_swscale(sbisrc2, &sbisrc, SWS_BILINEAR);
struct mp_image *sba = alloc_mpi(sb->dw, sb->dh, IMGFMT_Y8);
struct mp_image *sba = mp_image_alloc(IMGFMT_Y8, sb->dw, sb->dh);
unpremultiply_and_split_BGR32(sbisrc2, sba);
struct mp_image *sbi = alloc_mpi(sb->dw, sb->dh, dst_format->imgfmt);
struct mp_image *sbi = mp_image_alloc(dst_format->imgfmt, sb->dw, sb->dh);
sbi->colorspace = dst_format->colorspace;
sbi->levels = dst_format->levels;
mp_image_swscale(sbi, sbisrc2, SWS_BILINEAR);
free_mp_image(sbisrc);
free_mp_image(sbisrc2);
talloc_free(sbisrc2);
*out_sbi = sbi;
*out_sba = sba;
@ -328,10 +328,9 @@ static void draw_ass(struct mp_draw_sub_cache **cache, struct mp_rect bb,
static void mp_image_crop(struct mp_image *img, struct mp_rect rc)
{
for (int p = 0; p < img->num_planes; ++p) {
int bits = MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(img, p);
img->planes[p] +=
(rc.y0 >> (p ? img->chroma_y_shift : 0)) * img->stride[p] +
(rc.x0 >> (p ? img->chroma_x_shift : 0)) * bits / 8;
(rc.y0 >> img->fmt.ys[p]) * img->stride[p] +
(rc.x0 >> img->fmt.xs[p]) * img->fmt.bpp[p] / 8;
}
mp_image_set_size(img, rc.x1 - rc.x0, rc.y1 - rc.y0);
}
@ -359,7 +358,7 @@ static void get_swscale_alignment(const struct mp_image *img, int *out_xstep,
}
for (int p = 0; p < img->num_planes; ++p) {
int bits = MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(img, p);
int bits = img->fmt.bpp[p];
// the * 2 fixes problems with writing past the destination width
while (((sx >> img->chroma_x_shift) * bits) % (SWS_MIN_BYTE_ALIGN * 8 * 2))
sx *= 2;
@ -594,7 +593,7 @@ static void backup_realloc(struct mp_draw_sub_backup *backup,
static void copy_line(struct mp_image *dst, struct mp_image *src,
int p, int plane_y, int x0, int x1)
{
int bits = MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(dst, p);
int bits = dst->fmt.bpp[p];
int xs = p ? dst->chroma_x_shift : 0;
memcpy(dst->planes[p] + plane_y * dst->stride[p] + (x0 >> xs) * bits / 8,
src->planes[p] + plane_y * src->stride[p] + (x0 >> xs) * bits / 8,

View File

@ -61,8 +61,8 @@ static const vd_info_t info = {
#include "libavcodec/avcodec.h"
#include "lavc.h"
#if AVPALETTE_SIZE > 1024
#error palette too large, adapt libmpcodecs/vf.c:vf_get_image
#if AVPALETTE_SIZE != MP_PALETTE_SIZE
#error palette too large, adapt video/mp_image.h:MP_PALETTE_SIZE
#endif
#include "core/m_option.h"

View File

@ -95,65 +95,31 @@ static bool m_refcount_is_unique(struct m_refcount *ref)
return true;
}
void mp_image_alloc_planes(mp_image_t *mpi) {
assert(!mpi->refcount);
// IF09 - allocate space for 4. plane delta info - unused
if (mpi->imgfmt == IMGFMT_IF09) {
mpi->planes[0]=av_malloc(mpi->bpp*mpi->w*(mpi->h+2)/8+
mpi->chroma_width*mpi->chroma_height);
} else
mpi->planes[0]=av_malloc(mpi->bpp*mpi->w*(mpi->h+2)/8);
if (!mpi->planes[0])
abort(); //out of memory
if (mpi->flags&MP_IMGFLAG_PLANAR) {
// FIXME this code only supports same bpp for all planes, and bpp divisible
// by 8. Currently the case for all planar formats.
int bpp = MP_IMAGE_PLANAR_BITS_PER_PIXEL_ON_PLANE(mpi, 0) / 8;
// YV12/I420/YVU9/IF09. feel free to add other planar formats here...
mpi->stride[0]=mpi->stride[3]=bpp*mpi->w;
if(mpi->num_planes > 2){
mpi->stride[1]=mpi->stride[2]=bpp*mpi->chroma_width;
if(mpi->flags&MP_IMGFLAG_SWAPPED){
// I420/IYUV (Y,U,V)
mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->h;
mpi->planes[2]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
if (mpi->num_planes > 3)
mpi->planes[3]=mpi->planes[2]+mpi->stride[2]*mpi->chroma_height;
} else {
// YV12,YVU9,IF09 (Y,V,U)
mpi->planes[2]=mpi->planes[0]+mpi->stride[0]*mpi->h;
mpi->planes[1]=mpi->planes[2]+mpi->stride[1]*mpi->chroma_height;
if (mpi->num_planes > 3)
mpi->planes[3]=mpi->planes[1]+mpi->stride[1]*mpi->chroma_height;
}
} else {
// NV12/NV21
mpi->stride[1]=mpi->chroma_width;
mpi->planes[1]=mpi->planes[0]+mpi->stride[0]*mpi->h;
}
} else {
mpi->stride[0]=mpi->w*mpi->bpp/8;
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
mpi->planes[1] = av_malloc(1024);
}
mpi->flags|=MP_IMGFLAG_ALLOCATED;
}
void mp_image_copy(struct mp_image *dmpi, struct mp_image *mpi)
static void mp_image_alloc_planes(struct mp_image *mpi)
{
if(mpi->flags&MP_IMGFLAG_PLANAR){
memcpy_pic(dmpi->planes[0],mpi->planes[0], MP_IMAGE_BYTES_PER_ROW_ON_PLANE(mpi, 0), mpi->h,
dmpi->stride[0],mpi->stride[0]);
memcpy_pic(dmpi->planes[1],mpi->planes[1], MP_IMAGE_BYTES_PER_ROW_ON_PLANE(mpi, 1), mpi->chroma_height,
dmpi->stride[1],mpi->stride[1]);
memcpy_pic(dmpi->planes[2], mpi->planes[2], MP_IMAGE_BYTES_PER_ROW_ON_PLANE(mpi, 2), mpi->chroma_height,
dmpi->stride[2],mpi->stride[2]);
} else {
memcpy_pic(dmpi->planes[0],mpi->planes[0],
MP_IMAGE_BYTES_PER_ROW_ON_PLANE(mpi, 0), mpi->h,
dmpi->stride[0],mpi->stride[0]);
}
assert(!mpi->planes[0]);
size_t plane_size[MP_MAX_PLANES];
for (int n = 0; n < MP_MAX_PLANES; n++) {
int line_bytes = (mpi->plane_w[n] * mpi->fmt.bpp[n] + 7) / 8;
mpi->stride[n] = FFALIGN(line_bytes, SWS_MIN_BYTE_ALIGN);
plane_size[n] = mpi->stride[n] * mpi->plane_h[n];
}
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
plane_size[1] = MP_PALETTE_SIZE;
size_t sum = 0;
for (int n = 0; n < MP_MAX_PLANES; n++)
sum += plane_size[n];
uint8_t *data = av_malloc(FFMAX(sum, 1));
if (!data)
abort(); //out of memory
for (int n = 0; n < MP_MAX_PLANES; n++) {
mpi->planes[n] = plane_size[n] ? data : NULL;
data += plane_size[n];
}
}
void mp_image_copy_attributes(struct mp_image *dmpi, struct mp_image *mpi)
@ -178,28 +144,13 @@ void mp_image_setfmt(struct mp_image *mpi, unsigned int out_fmt)
static int mp_image_destructor(void *ptr)
{
mp_image_t *mpi = ptr;
if (mpi->refcount) {
m_refcount_unref(mpi->refcount);
}
if (mpi->flags & MP_IMGFLAG_ALLOCATED) {
/* because we allocate the whole image at once */
av_free(mpi->planes[0]);
if (mpi->flags & MP_IMGFLAG_RGB_PALETTE)
av_free(mpi->planes[1]);
}
m_refcount_unref(mpi->refcount);
return 0;
}
// Image without format or allocated image data
struct mp_image *mp_image_new_empty(int w, int h)
static int mp_chroma_div_up(int size, int shift)
{
struct mp_image *mpi = talloc_zero(NULL, struct mp_image);
talloc_set_destructor(mpi, mp_image_destructor);
mp_image_set_size(mpi, w, h);
return mpi;
return (size + (1 << shift) - 1) >> shift;
}
// Caller has to make sure this doesn't exceed the allocated plane data/strides.
@ -208,8 +159,8 @@ void mp_image_set_size(struct mp_image *mpi, int w, int h)
mpi->w = w;
mpi->h = h;
for (int n = 0; n < mpi->num_planes; n++) {
mpi->plane_w[n] = mpi->w >> mpi->fmt.xs[n];
mpi->plane_h[n] = mpi->h >> mpi->fmt.ys[n];
mpi->plane_w[n] = mp_chroma_div_up(mpi->w, mpi->fmt.xs[n]);
mpi->plane_h[n] = mp_chroma_div_up(mpi->h, mpi->fmt.ys[n]);
}
mpi->chroma_width = mpi->plane_w[1];
mpi->chroma_height = mpi->plane_h[1];
@ -224,15 +175,12 @@ void mp_image_set_display_size(struct mp_image *mpi, int dw, int dh)
struct mp_image *mp_image_alloc(unsigned int imgfmt, int w, int h)
{
struct mp_image *mpi = mp_image_new_empty(w, h);
mpi->w = FFALIGN(w, MP_STRIDE_ALIGNMENT);
struct mp_image *mpi = talloc_zero(NULL, struct mp_image);
talloc_set_destructor(mpi, mp_image_destructor);
mp_image_set_size(mpi, w, h);
mp_image_setfmt(mpi, imgfmt);
mp_image_alloc_planes(mpi);
mpi->w = w;
mp_image_setfmt(mpi, imgfmt); // reset chroma size
mpi->flags &= ~MP_IMGFLAG_ALLOCATED;
mpi->refcount = m_refcount_new();
mpi->refcount->free = av_free;
mpi->refcount->arg = mpi->planes[0];
@ -300,7 +248,6 @@ struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *free_arg,
talloc_set_destructor(new, mp_image_destructor);
*new = *img;
new->flags &= ~MP_IMGFLAG_ALLOCATED;
new->refcount = m_refcount_new();
new->refcount->free = free;
new->refcount->arg = free_arg;
@ -319,7 +266,6 @@ struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
talloc_set_destructor(new, mp_image_destructor);
*new = *img;
new->flags &= ~MP_IMGFLAG_ALLOCATED;
new->refcount = m_refcount_new();
new->refcount->ext_ref = ref;
new->refcount->ext_unref = unref;
@ -330,9 +276,8 @@ struct mp_image *mp_image_new_external_ref(struct mp_image *img, void *arg,
bool mp_image_is_writeable(struct mp_image *img)
{
// if non ref-counted, it's writeable if the caller allocated the image
if (!img->refcount)
return img->flags & MP_IMGFLAG_ALLOCATED;
return true; // not ref-counted => always considered writeable
return m_refcount_is_unique(img->refcount);
}
@ -363,6 +308,18 @@ void mp_image_unrefp(struct mp_image **p_img)
*p_img = NULL;
}
void mp_image_copy(struct mp_image *dst, struct mp_image *src)
{
assert(dst->imgfmt == src->imgfmt);
assert(dst->w == src->w && dst->h == src->h);
assert(mp_image_is_writeable(dst));
for (int n = 0; n < dst->num_planes; n++) {
int line_bytes = (dst->plane_w[n] * dst->fmt.bpp[n] + 7) / 8;
memcpy_pic(dst->planes[n], src->planes[n], line_bytes, dst->plane_h[n],
dst->stride[n], src->stride[n]);
}
}
enum mp_csp mp_image_csp(struct mp_image *img)
{
if (img->colorspace != MP_CSP_AUTO)

View File

@ -28,11 +28,7 @@
#include "csputils.h"
#include "video/img_format.h"
// Minimum stride alignment in pixels
#define MP_STRIDE_ALIGNMENT 32
// set if buffer is allocated (used in destination images):
#define MP_IMGFLAG_ALLOCATED 0x4000
#define MP_PALETTE_SIZE (256 * 4)
#define MP_IMGFIELD_ORDERED 0x01
#define MP_IMGFIELD_TOP_FIRST 0x02
@ -113,9 +109,7 @@ void mp_image_unrefp(struct mp_image **p_img);
void mp_image_set_size(struct mp_image *mpi, int w, int h);
void mp_image_set_display_size(struct mp_image *mpi, int dw, int dh);
struct mp_image *mp_image_new_empty(int w, int h);
void mp_image_setfmt(mp_image_t* mpi,unsigned int out_fmt);
void mp_image_alloc_planes(struct mp_image *mpi);
void mp_image_steal_data(struct mp_image *dst, struct mp_image *src);
struct mp_image *mp_image_new_custom_ref(struct mp_image *img, void *arg,
@ -133,14 +127,4 @@ struct mp_csp_details;
void mp_image_set_colorspace_details(struct mp_image *image,
struct mp_csp_details *csp);
// this macro requires img_format.h to be included too:
#define MP_IMAGE_PLANAR_BITS_PER_PIXEL_ON_PLANE(mpi, p) \
(IMGFMT_IS_YUVP16((mpi)->imgfmt) ? 16 : 8)
#define MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(mpi, p) \
(((mpi)->flags & MP_IMGFLAG_PLANAR) \
? MP_IMAGE_PLANAR_BITS_PER_PIXEL_ON_PLANE(mpi, p) \
: (mpi)->bpp)
#define MP_IMAGE_BYTES_PER_ROW_ON_PLANE(mpi, p) \
((MP_IMAGE_BITS_PER_PIXEL_ON_PLANE(mpi, p) * ((mpi)->w >> (p ? mpi->chroma_x_shift : 0)) + 7) / 8)
#endif /* MPLAYER_MP_IMAGE_H */