[MPlayer-dev-eng] [PATCH] new vf_ass implementation
Xidorn Quan
quanxunzhen at gmail.com
Sun Oct 7 18:00:18 CEST 2012
On Sun, Oct 7, 2012 at 2:34 PM, Xidorn Quan <quanxunzhen at gmail.com> wrote:
> Hi,
>
> The patch attached is a new implementation for vf_ass. The core idea
> for it is that since subtitles usually keep unchanged for several
> frames, we can render subtitle images on a buffer with alpha channal
> when subtitles get changed, and then compose it with every frame.
> It can perform better because composing images with alpha channal is
> much faster than rendering subtitle images.
>
> There are also some other optimizations like processing pixels as few
> as possible by using extent dirty_rows, downsampling buffer images
> instead of upsampling frame pictures.
>
> For normal subtitles which is changed not very frequently, it can be
> about 2.2x (for packed YUV) or 1.8x (for planar YUV) faster than
> the current ass filter by itself. For subtitles which is changed
> nearly every frame, it can also be 40% faster than the current one
> for packed YUV, but be slower (by less than 10%) for planar YUV.
>
> Although it is sometimes slower, composing can be easily optimized
> (by using SIMD for example). Then it can be never slower.
>
> Best regards,
> Xidorn Quan
>
I found some problems in this patch, and the new patch is attached.
-------------- next part --------------
Index: libmpcodecs/vf_ass.c
===================================================================
--- libmpcodecs/vf_ass.c (revision 35233)
+++ libmpcodecs/vf_ass.c (working copy)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov at gmail.com>
+ * Copyright (C) 2012 Xidorn Quan <quanxunzhen at gmail.com>
*
* This file is part of MPlayer.
*
@@ -52,9 +53,13 @@
#define rgba2u(c) ( ((-152*_r(c) - 298*_g(c) + 450*_b(c)) >> 10) + 128 )
#define rgba2v(c) ( (( 450*_r(c) - 376*_g(c) - 73*_b(c)) >> 10) + 128 )
-typedef void (*copy_from_image_func)(struct vf_instance *vf,
- int first_row, int last_row);
-typedef void (*copy_to_image_func)(struct vf_instance *vf);
+#define rshr(v, b) (((v) + (1 << ((b) - 1))) >> (b))
+#define rshr8(v) rshr(v, 8)
+#define rshr24(v) rshr(v, 24)
+/* map 0 - 0xFF => 0 - 0x101 */
+#define map_16bit(v) rshr8(0x102 * (v))
+/* map 0 - 0xFF => 0 - 0x10101 */
+#define map_24bit(v) rshr8(0x10203 * (v))
static const struct vf_priv_s {
int outh, outw;
@@ -66,56 +71,298 @@
// 0 = insert always
int auto_insert;
- unsigned char *planes[3];
- unsigned char *dirty_rows;
+ uint8_t *planes[MP_MAX_PLANES];
+ uint8_t *alphas[MP_MAX_PLANES];
+ struct dirty_rows_extent {
+ int xmin, xmax;
+ } *dirty_rows;
- copy_from_image_func copy_from_image;
- copy_to_image_func copy_to_image;
+ // called for every eosd image when subtitle is changed
+ void (*draw_image)(vf_instance_t *, struct mp_eosd_image *);
+ // called for every time subtitle is changed
+ void (*prepare_buffer)(vf_instance_t *);
+ // called for every frame
+ void (*render_frame)(vf_instance_t *);
} vf_priv_dflt;
-static void copy_from_image_yuv420p(struct vf_instance *, int, int);
-static void copy_to_image_yuv420p(struct vf_instance *);
-static void copy_from_image_yuv422(struct vf_instance *, int, int);
-static void copy_to_image_yuv422(struct vf_instance *);
+static void draw_image_yuv(vf_instance_t *vf, struct mp_eosd_image *img)
+{
+ uint32_t color = img->color;
+ uint32_t opacity = 0xFF - _a(color);
+ uint8_t y = rgba2y(color),
+ u = rgba2u(color),
+ v = rgba2v(color);
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ uint8_t *alpha = vf->priv->alphas[0],
+ *dst_y = vf->priv->planes[0],
+ *dst_u = vf->priv->planes[1],
+ *dst_v = vf->priv->planes[2];
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ int src_x = img->dst_x, src_w = img->w,
+ src_y = img->dst_y, src_h = img->h,
+ stride = img->stride;
+ uint8_t *src = img->bitmap;
+ int i, j;
+ opacity = map_24bit(opacity);
+ for (i = 0; i < src_h; i++) {
+ struct dirty_rows_extent *dirty_row = &dirty_rows[src_y + i];
+ dirty_row->xmin = FFMIN(dirty_row->xmin, src_x);
+ dirty_row->xmax = FFMAX(dirty_row->xmax, src_x + src_w);
+
+ for (j = 0; j < src_w; j++) {
+ uint32_t k = src[i * stride + j];
+ if (k) {
+ int p = (src_y + i) * outw + src_x + j;
+ k *= opacity;
+ alpha[p] = rshr24((0xFFFFFF - k) * alpha[p]);
+ dst_y[p] = rshr24((0xFFFFFF - k) * dst_y[p] + k * y);
+ dst_u[p] = rshr24((0xFFFFFF - k) * dst_u[p] + k * u);
+ dst_v[p] = rshr24((0xFFFFFF - k) * dst_v[p] + k * v);
+ }
+ }
+ }
+}
+
+static void prepare_buffer_422(vf_instance_t *vf)
+{
+ uint8_t *dst_u = vf->priv->planes[1],
+ *dst_v = vf->priv->planes[2];
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ int i, j;
+
+ for (i = 0; i < outh; i++) {
+ size_t xmin = dirty_rows[i].xmin,
+ xmax = dirty_rows[i].xmax;
+ xmin -= xmin % 2;
+ for (j = xmin; j < xmax; j += 2) {
+ size_t p = i * outw + j;
+ dst_u[p] = (dst_u[p] + dst_u[p + 1]) / 2;
+ dst_v[p] = (dst_v[p] + dst_v[p + 1]) / 2;
+ }
+ }
+}
+
+static void render_frame_yuv422(vf_instance_t *vf)
+{
+ uint8_t *alpha = vf->priv->alphas[0];
+ uint8_t *src_y = vf->priv->planes[0],
+ *src_u = vf->priv->planes[1],
+ *src_v = vf->priv->planes[2];
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ uint8_t *dest = vf->dmpi->planes[0];
+ int stride = vf->dmpi->stride[0];
+ int is_uyvy = vf->priv->outfmt == IMGFMT_UYVY;
+ int i, j;
+
+ for (i = 0; i < outh; i++) {
+ size_t xmin = dirty_rows[i].xmin,
+ xmax = dirty_rows[i].xmax;
+ xmin -= xmin % 2;
+ for (j = xmin; j < xmax; j += 2) {
+ size_t src = i * outw + j,
+ dst = i * stride + j * 2;
+ uint_fast16_t a0 = alpha[src],
+ a1 = alpha[src + 1];
+ uint8_t y0, y1, u, v;
+
+ if (a0 == 0xFF && a1 == 0xFF)
+ continue;
+
+ y0 = dest[dst + is_uyvy + 0];
+ y1 = dest[dst + is_uyvy + 2];
+ u = dest[dst - is_uyvy + 1];
+ v = dest[dst - is_uyvy + 3];
+
+ a0 = map_16bit(a0);
+ a1 = map_16bit(a1);
+ y0 = ((a0 * y0) >> 8) + src_y[src];
+ y1 = ((a1 * y1) >> 8) + src_y[src + 1];
+
+ a0 = (a0 + a1) / 2;
+ u = ((a0 * u) >> 8) + src_u[src];
+ v = ((a0 * v) >> 8) + src_v[src];
+
+ dest[dst + is_uyvy + 0] = y0;
+ dest[dst + is_uyvy + 2] = y1;
+ dest[dst - is_uyvy + 1] = u;
+ dest[dst - is_uyvy + 3] = v;
+ }
+ }
+}
+
+static void prepare_buffer_420p(vf_instance_t *vf)
+{
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ uint8_t *dst_u = vf->priv->planes[1],
+ *dst_v = vf->priv->planes[2];
+ uint8_t *src_a = vf->priv->alphas[0],
+ *dst_a = vf->priv->alphas[1];
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ int i, j;
+
+ for (i = 0; i < outh; i += 2) {
+ size_t xmin = FFMIN(dirty_rows[i].xmin, dirty_rows[i + 1].xmin),
+ xmax = FFMAX(dirty_rows[i].xmax, dirty_rows[i + 1].xmax);
+ xmin -= xmin % 2;
+ for (j = xmin; j < xmax; j += 2) {
+ size_t p = i * outw / 4 + j / 2,
+ q = i * outw + j;
+ dst_a[p] = (src_a[q] + src_a[q + 1] + 2) / 4;
+ dst_u[p] = (dst_u[q] + dst_u[q + 1] + 2) / 4;
+ dst_v[p] = (dst_v[q] + dst_v[q + 1] + 2) / 4;
+ }
+ for (j = xmin; j < xmax; j += 2) {
+ size_t p = i * outw / 4 + j / 2,
+ q = (i + 1) * outw + j;
+ dst_a[p] += (src_a[q] + src_a[q + 1] + 1) / 4;
+ dst_u[p] += (dst_u[q] + dst_u[q + 1] + 1) / 4;
+ dst_v[p] += (dst_v[q] + dst_v[q + 1] + 1) / 4;
+ }
+ }
+}
+
+static void render_frame_yuv420p(vf_instance_t *vf)
+{
+ uint8_t **planes = vf->priv->planes;
+ uint8_t **dest = vf->dmpi->planes;
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ uint8_t *alpha;
+ uint8_t *src_y = vf->priv->planes[0],
+ *src_u = vf->priv->planes[1],
+ *src_v = vf->priv->planes[2];
+ uint8_t *dst_y = vf->dmpi->planes[0],
+ *dst_u = vf->dmpi->planes[1],
+ *dst_v = vf->dmpi->planes[2];
+ int stride;
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ int i, j;
+
+ // y
+ alpha = vf->priv->alphas[0];
+ stride = vf->dmpi->stride[0];
+ for (i = 0; i < outh; i++) {
+ int xmin = dirty_rows[i].xmin,
+ xmax = dirty_rows[i].xmax;
+ for (j = xmin; j < xmax; j++) {
+ int s = i * outw + j,
+ d = i * stride + j;
+ if (alpha[s] != 0xFF)
+ dst_y[d] = ((map_16bit(alpha[s]) * dst_y[d]) >> 8) + src_y[s];
+ }
+ }
+
+ // u & v
+ alpha = vf->priv->alphas[1];
+ stride = vf->dmpi->stride[1];
+ for (i = 0; i < outh / 2; i++) {
+ int xmin = FFMIN(dirty_rows[i * 2].xmin, dirty_rows[i * 2 + 1].xmin),
+ xmax = FFMAX(dirty_rows[i * 2].xmax, dirty_rows[i * 2 + 1].xmax);
+ for (j = xmin / 2; j < (xmax + 1) / 2; j++) {
+ int s = i * outw / 2 + j,
+ d = i * stride + j;
+ if (alpha[s] != 0xFF) {
+ uint_fast16_t a = map_16bit(alpha[s]);
+ dst_u[d] = ((a * dst_u[d]) >> 8) + src_u[s];
+ dst_v[d] = ((a * dst_v[d]) >> 8) + src_v[s];
+ }
+ }
+ }
+}
+
+static void clean_buffer(vf_instance_t *vf)
+{
+ int outw = vf->priv->outw,
+ outh = vf->priv->outh;
+ struct dirty_rows_extent *dirty_rows = vf->priv->dirty_rows;
+ uint8_t **planes = vf->priv->planes;
+ uint8_t *alpha = vf->priv->alphas[0];
+ int i, j;
+
+ for (i = 0; i < MP_MAX_PLANES; i++) {
+ uint8_t *plane = planes[i];
+ if (!plane)
+ break;
+ for (j = 0; j < outh; j++) {
+ int xmin = dirty_rows[j].xmin;
+ int width = dirty_rows[j].xmax - xmin;
+ if (width > 0)
+ memset(plane + j * outw + xmin, 0, width);
+ }
+ }
+ for (i = 0; i < outh; i++) {
+ int xmin = dirty_rows[i].xmin;
+ int width = dirty_rows[i].xmax - xmin;
+ if (width > 0)
+ memset(alpha + i * outw + xmin, -1, width);
+ }
+ for (i = 0; i < outh; i++) {
+ dirty_rows[i].xmin = outw;
+ dirty_rows[i].xmax = 0;
+ }
+}
+
static int config(struct vf_instance *vf,
int width, int height, int d_width, int d_height,
unsigned int flags, unsigned int outfmt)
{
struct mp_eosd_settings res = {0};
+ struct dirty_rows_extent *dirty_rows;
+ int outw, outh;
+ int planes, alphas;
+ int i;
switch (outfmt) {
case IMGFMT_YV12:
case IMGFMT_I420:
case IMGFMT_IYUV:
vf->priv->is_planar = 1;
- vf->priv->copy_from_image = copy_from_image_yuv420p;
- vf->priv->copy_to_image = copy_to_image_yuv420p;
+ planes = 3;
+ alphas = 2;
+ vf->priv->draw_image = draw_image_yuv;
+ vf->priv->render_frame = render_frame_yuv420p;
+ vf->priv->prepare_buffer = prepare_buffer_420p;
break;
case IMGFMT_UYVY:
case IMGFMT_YUY2:
vf->priv->is_planar = 0;
- vf->priv->copy_from_image = copy_from_image_yuv422;
- vf->priv->copy_to_image = copy_to_image_yuv422;
+ planes = 3;
+ alphas = 1;
+ vf->priv->draw_image = draw_image_yuv;
+ vf->priv->render_frame = render_frame_yuv422;
+ vf->priv->prepare_buffer = prepare_buffer_422;
break;
default:
return 0;
}
vf->priv->outfmt = outfmt;
- vf->priv->outh = height + ass_top_margin + ass_bottom_margin;
- vf->priv->outw = width;
+ vf->priv->outh = outh = height + ass_top_margin + ass_bottom_margin;
+ vf->priv->outw = outw = width;
if (!opt_screen_size_x && !opt_screen_size_y) {
d_width = d_width * vf->priv->outw / width;
d_height = d_height * vf->priv->outh / height;
}
- if (!vf->priv->is_planar)
- vf->priv->planes[0] = malloc(vf->priv->outw * vf->priv->outh);
- vf->priv->planes[1] = malloc(vf->priv->outw * vf->priv->outh);
- vf->priv->planes[2] = malloc(vf->priv->outw * vf->priv->outh);
- vf->priv->dirty_rows = malloc(vf->priv->outh);
+ for (i = 0; i < planes; i++)
+ vf->priv->planes[i] = malloc(outw * outh);
+ for (i = 0; i < alphas; i++)
+ vf->priv->alphas[i] = malloc(outw * outh);
+ dirty_rows = malloc(outh * sizeof(*dirty_rows));
+ for (i = 0; i < outh; i++) {
+ dirty_rows[i].xmin = 0;
+ dirty_rows[i].xmax = outw;
+ }
+ vf->priv->dirty_rows = dirty_rows;
+ clean_buffer(vf);
res.w = vf->priv->outw;
res.h = vf->priv->outh;
@@ -272,228 +519,26 @@
return 0;
}
-/**
- * \brief Copy specified rows from render_context.dmpi to render_context.planes, upsampling to 4:4:4
- */
-static void copy_from_image_yuv420p(struct vf_instance *vf, int first_row,
- int last_row)
+static void prepare_eosd(vf_instance_t *vf, struct mp_eosd_image_list *imgs)
{
- int pl;
- int i, j, k;
- unsigned char val;
- int chroma_rows;
+ struct mp_eosd_image *img = eosd_image_first(imgs);
+ void (*draw_image)(vf_instance_t *, struct mp_eosd_image *);
- first_row -= (first_row % 2);
- last_row += (last_row % 2);
- chroma_rows = (last_row - first_row) / 2;
-
- assert(first_row >= 0);
- assert(first_row <= last_row);
- assert(last_row <= vf->priv->outh);
-
- for (pl = 1; pl < 3; ++pl) {
- int dst_stride = vf->priv->outw;
- int src_stride = vf->dmpi->stride[pl];
-
- unsigned char *src = vf->dmpi->planes[pl] + (first_row / 2) * src_stride;
- unsigned char *dst = vf->priv->planes[pl] + first_row * dst_stride;
- unsigned char *dst_next = dst + dst_stride;
- for (i = 0; i < chroma_rows; ++i) {
- if ((vf->priv->dirty_rows[first_row + i * 2 ] == 0) ||
- (vf->priv->dirty_rows[first_row + i * 2 + 1] == 0)) {
- for (j = 0, k = 0; j < vf->dmpi->chroma_width; ++j, k += 2) {
- val = *(src + j);
- *(dst + k ) = val;
- *(dst + k + 1) = val;
- *(dst_next + k ) = val;
- *(dst_next + k + 1) = val;
- }
- }
- src += src_stride;
- dst = dst_next + dst_stride;
- dst_next = dst + dst_stride;
- }
- }
- for (i = first_row; i < last_row; ++i)
- vf->priv->dirty_rows[i] = 1;
+ clean_buffer(vf);
+ draw_image = vf->priv->draw_image;
+ for (; img; img = eosd_image_next(imgs))
+ draw_image(vf, img);
+ vf->priv->prepare_buffer(vf);
}
-/**
- * \brief Copy all previously copied rows back to render_context.dmpi
- */
-static void copy_to_image_yuv420p(struct vf_instance *vf)
-{
- int pl;
- int i, j, k;
- for (pl = 1; pl < 3; ++pl) {
- int dst_stride = vf->dmpi->stride[pl];
- int src_stride = vf->priv->outw;
-
- unsigned char *dst = vf->dmpi->planes[pl];
- unsigned char *src = vf->priv->planes[pl];
- unsigned char *src_next = vf->priv->planes[pl] + src_stride;
- for (i = 0; i < vf->priv->outh / 2; ++i) {
- if ((vf->priv->dirty_rows[i * 2] == 1)) {
- assert(vf->priv->dirty_rows[i * 2 + 1] == 1);
- for (j = 0, k = 0; j < vf->dmpi->chroma_width; ++j, k += 2) {
- unsigned val = 0;
- val += *(src + k);
- val += *(src + k + 1);
- val += *(src_next + k);
- val += *(src_next + k + 1);
- *(dst + j) = val >> 2;
- }
- }
- dst += dst_stride;
- src = src_next + src_stride;
- src_next = src + src_stride;
- }
- }
-}
-
-static void copy_from_image_yuv422(struct vf_instance *vf,
- int first_row, int last_row)
-{
- unsigned char *dirty_rows = vf->priv->dirty_rows;
- int src_stride = vf->dmpi->stride[0];
- int dst_stride = vf->priv->outw;
- unsigned char *src = vf->dmpi->planes[0] + first_row * src_stride;
- unsigned char **dst = vf->priv->planes;
- int dst_off = first_row * dst_stride;
- int is_uyvy = vf->priv->outfmt == IMGFMT_UYVY;
- int i, j, k;
-
- for (i = first_row; i < last_row; ++i) {
- int next_off = dst_off + dst_stride;
- if (!dirty_rows[i]) {
- if (is_uyvy) {
- for (j = dst_off, k = 0; j < next_off; j += 2, k += 4) {
- dst[0][j ] = src[k + 1];
- dst[0][j + 1] = src[k + 3];
- dst[1][j ] = src[k ];
- dst[1][j + 1] = src[k ];
- dst[2][j ] = src[k + 2];
- dst[2][j + 1] = src[k + 2];
- }
- } else {
- for (j = dst_off, k = 0; j < next_off; j += 2, k += 4) {
- dst[0][j ] = src[k ];
- dst[0][j + 1] = src[k + 2];
- dst[1][j ] = src[k + 1];
- dst[1][j + 1] = src[k + 1];
- dst[2][j ] = src[k + 3];
- dst[2][j + 1] = src[k + 3];
- }
- }
- }
- src += src_stride;
- dst_off = next_off;
- }
- for (i = first_row; i < last_row; ++i)
- dirty_rows[i] = 1;
-}
-
-static void copy_to_image_yuv422(struct vf_instance *vf)
-{
- unsigned char *dirty_rows = vf->priv->dirty_rows;
- int src_stride = vf->priv->outw;
- int dst_stride = vf->dmpi->stride[0];
- int height = vf->priv->outh;
- unsigned char **src = vf->priv->planes;
- unsigned char *dst = vf->dmpi->planes[0];
- int src_off = 0;
- int is_uyvy = vf->priv->outfmt == IMGFMT_UYVY;
- int i, j, k;
-
- for (i = 0; i < height; ++i) {
- int next_off = src_off + src_stride;
- if (*dirty_rows++) {
-#define AVERAGE(a, b) (((unsigned)(a) + (unsigned)(b)) >> 1)
- if (is_uyvy) {
- for (j = src_off, k = 0; j < next_off; j += 2, k += 4) {
- dst[k ] = AVERAGE(src[1][j], src[1][j + 1]);
- dst[k + 1] = src[0][j];
- dst[k + 2] = AVERAGE(src[2][j], src[2][j + 1]);
- dst[k + 3] = src[0][j + 1];
- }
- } else {
- for (j = src_off, k = 0; j < next_off; j += 2, k += 4) {
- dst[k ] = src[0][j];
- dst[k + 1] = AVERAGE(src[1][j], src[1][j + 1]);
- dst[k + 2] = src[0][j + 1];
- dst[k + 3] = AVERAGE(src[2][j], src[2][j + 1]);
- }
- }
-#undef AVERAGE
- }
- src_off = next_off;
- dst += dst_stride;
- }
-}
-
-static void my_draw_bitmap(struct vf_instance *vf, unsigned char *bitmap,
- int bitmap_w, int bitmap_h, int stride,
- int dst_x, int dst_y, unsigned color)
-{
- unsigned char y = rgba2y(color);
- unsigned char u = rgba2u(color);
- unsigned char v = rgba2v(color);
- unsigned opacity = 255 - _a(color);
- unsigned char *src, *dsty, *dstu, *dstv;
- int i, j;
- mp_image_t *dmpi = vf->dmpi;
- int stride_y = vf->priv->is_planar ? dmpi->stride[0] : vf->priv->outw;
-
- opacity = (0x10203 * opacity + 0x80) >> 8; /* 0x10203 = (1<<32)/(255*255) */
- /* 0 <= opacity <= 0x10101 */
- src = bitmap;
- dsty = vf->priv->is_planar ? dmpi->planes[0] : vf->priv->planes[0];
- dsty += dst_x + dst_y * stride_y;
- dstu = vf->priv->planes[1] + dst_x + dst_y * vf->priv->outw;
- dstv = vf->priv->planes[2] + dst_x + dst_y * vf->priv->outw;
- for (i = 0; i < bitmap_h; ++i) {
- for (j = 0; j < bitmap_w; ++j) {
- unsigned k = src[j];
- if (!k)
- continue;
- k *= opacity; /* 0 <= k <= 0xFFFFFF */
- dsty[j] = (k * y + (0xFFFFFF - k) * dsty[j] + 0x800000) >> 24;
- dstu[j] = (k * u + (0xFFFFFF - k) * dstu[j] + 0x800000) >> 24;
- dstv[j] = (k * v + (0xFFFFFF - k) * dstv[j] + 0x800000) >> 24;
- }
- src += stride;
- dsty += stride_y;
- dstu += vf->priv->outw;
- dstv += vf->priv->outw;
- }
-}
-
-static void render_frame(struct vf_instance *vf, mp_image_t *mpi,
- struct mp_eosd_image_list *images)
-{
- struct mp_eosd_image *img;
- copy_from_image_func copy_from_image = vf->priv->copy_from_image;
- copy_to_image_func copy_to_image = vf->priv->copy_to_image;
-
- img = eosd_image_first(images);
- if (!img)
- return;
- memset(vf->priv->dirty_rows, 0, vf->priv->outh); // reset dirty rows
- while (img) {
- copy_from_image(vf, img->dst_y, img->dst_y + img->h);
- my_draw_bitmap(vf, img->bitmap, img->w, img->h, img->stride,
- img->dst_x, img->dst_y, img->color);
- img = eosd_image_next(images);
- }
- copy_to_image(vf);
-}
-
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
struct mp_eosd_image_list images;
eosd_render_frame(pts, &images);
prepare_image(vf, mpi);
- render_frame(vf, mpi, &images);
+ if (images.changed)
+ prepare_eosd(vf, &images);
+ vf->priv->render_frame(vf);
return vf_next_put_image(vf, vf->dmpi, pts);
}
@@ -523,10 +568,13 @@
static void uninit(struct vf_instance *vf)
{
- if (!vf->priv->is_planar)
- free(vf->priv->planes[0]);
- free(vf->priv->planes[1]);
- free(vf->priv->planes[2]);
+ int i;
+ for (i = 0; i < MP_MAX_PLANES; i++)
+ if (vf->priv->planes[i])
+ free(vf->priv->planes[i]);
+ for (i = 0; i < MP_MAX_PLANES; i++)
+ if (vf->priv->alphas[i])
+ free(vf->priv->alphas[i]);
free(vf->priv->dirty_rows);
}
@@ -579,7 +627,7 @@
const vf_info_t vf_info_ass = {
"Render ASS/SSA subtitles",
"ass",
- "Evgeniy Stepanov",
+ "Evgeniy Stepanov, Xidorn Quan",
"",
vf_open,
&vf_opts
More information about the MPlayer-dev-eng
mailing list