summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sub/draw_bmp.c31
-rw-r--r--video/decode/vd_lavc.c4
-rw-r--r--video/mp_image.c127
-rw-r--r--video/mp_image.h18
4 files changed, 60 insertions, 120 deletions
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c
index ac347f7374..245d1edd2b 100644
--- a/sub/draw_bmp.c
+++ b/sub/draw_bmp.c
@@ -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 *sba = alloc_mpi(sb->dw, sb->dh, IMGFMT_Y8);
+ 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 = 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,
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 7fd7437a3b..2d47cb9c88 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -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"
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)
diff --git a/video/mp_image.h b/video/mp_image.h
index 3a86dc5fcd..cfc839c1cc 100644
--- a/video/mp_image.h
+++ b/video/mp_image.h
@@ -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 */