summaryrefslogtreecommitdiffstats
path: root/video/mp_image.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-12-19 12:04:32 +0100
committerwm4 <wm4@nowhere>2013-01-13 20:04:10 +0100
commitab94c64ed2d8b90bd7b0c348e79c2d8b8d055ee6 (patch)
treec58bbce7185bd003daad53472a8c49fafb4d769a /video/mp_image.c
parent00653a3eb0520e9d2409929cd217a5c299be2f5c (diff)
downloadmpv-ab94c64ed2d8b90bd7b0c348e79c2d8b8d055ee6.tar.bz2
mpv-ab94c64ed2d8b90bd7b0c348e79c2d8b8d055ee6.tar.xz
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.)
Diffstat (limited to 'video/mp_image.c')
-rw-r--r--video/mp_image.c127
1 files changed, 42 insertions, 85 deletions
diff --git a/video/mp_image.c b/video/mp_image.c
index 7479c98c62..7bcf3b1771 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -95,65 +95,31 @@ static bool m_refcount_is_unique(struct m_refcount *ref)
return true;
}
+static void mp_image_alloc_planes(struct mp_image *mpi)
+{
+ assert(!mpi->planes[0]);
-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;
+ 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];
}
- } 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;
-}
+ plane_size[1] = MP_PALETTE_SIZE;
-void mp_image_copy(struct mp_image *dmpi, 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]);
- }
+ 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)