# HG changeset patch # User reimar # Date 1346442751 0 # Node ID 848835e1b05306aa05ceb57afd152ebd3d7007ea # Parent 3b57273e1301ef2d99e64620f98e175b9fed34f3 vf_ass: add support for rendering on YUY2 and UYVY images. Patch by Xidorn Quan [quanxunzhen gmail com]. diff -r 3b57273e1301 -r 848835e1b053 libmpcodecs/vf_ass.c --- a/libmpcodecs/vf_ass.c Fri Aug 31 14:28:32 2012 +0000 +++ b/libmpcodecs/vf_ass.c Fri Aug 31 19:52:31 2012 +0000 @@ -36,6 +36,7 @@ #include "vf.h" #include "libvo/fastmemcpy.h" +#include "libavutil/intreadwrite.h" #include "sub/sub.h" #include "m_option.h" #include "m_struct.h" @@ -51,10 +52,14 @@ #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); static const struct vf_priv_s { int outh, outw; + int is_planar; unsigned int outfmt; // 1 = auto-added filter: insert only if chain does not support EOSD already @@ -63,8 +68,15 @@ unsigned char *planes[3]; unsigned char *dirty_rows; + + copy_from_image_func copy_from_image; + copy_to_image_func copy_to_image; } 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 int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, @@ -72,8 +84,23 @@ { struct mp_eosd_settings res = {0}; - if (outfmt == IMGFMT_IF09) + 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; + 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; + break; + default: return 0; + } vf->priv->outfmt = outfmt; vf->priv->outh = height + ass_top_margin + ass_bottom_margin; @@ -84,6 +111,8 @@ 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); @@ -144,6 +173,7 @@ unsigned char *dst; int chroma_rows = (y2 - y1) >> mpi->chroma_y_shift; + if (mpi->flags & MP_IMGFLAG_PLANAR) { dst = mpi->planes[0] + y1 * mpi->stride[0]; for (y = 0; y < y2 - y1; ++y) { memset(dst, color[0], mpi->w); @@ -159,6 +189,27 @@ memset(dst, color[2], mpi->chroma_width); dst += mpi->stride[2]; } + } else { + unsigned char packed_color[4]; + int x; + if (mpi->imgfmt == IMGFMT_UYVY) { + packed_color[0] = color[1]; + packed_color[1] = color[0]; + packed_color[2] = color[2]; + packed_color[3] = color[0]; + } else { + packed_color[0] = color[0]; + packed_color[1] = color[1]; + packed_color[2] = color[0]; + packed_color[3] = color[2]; + } + dst = mpi->planes[0] + y1 * mpi->stride[0]; + for (y = y1; y < y2; ++y) { + for (x = 0; x < mpi->w / 2; ++x) + AV_COPY32(dst + 4 * x, packed_color); + dst += mpi->stride[0]; + } + } } static int prepare_image(struct vf_instance *vf, mp_image_t *mpi) @@ -224,7 +275,7 @@ /** * \brief Copy specified rows from render_context.dmpi to render_context.planes, upsampling to 4:4:4 */ -static void copy_from_image(struct vf_instance *vf, int first_row, +static void copy_from_image_yuv420p(struct vf_instance *vf, int first_row, int last_row) { int pl; @@ -270,7 +321,7 @@ /** * \brief Copy all previously copied rows back to render_context.dmpi */ -static void copy_to_image(struct vf_instance *vf) +static void copy_to_image_yuv420p(struct vf_instance *vf) { int pl; int i, j, k; @@ -300,6 +351,86 @@ } } +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) @@ -311,11 +442,13 @@ 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 = dmpi->planes[0] + dst_x + dst_y * dmpi->stride[0]; + 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) { @@ -329,7 +462,7 @@ dstv[j] = (k * v + (0xFFFFFF - k) * dstv[j] + 0x800000) >> 24; } src += stride; - dsty += dmpi->stride[0]; + dsty += stride_y; dstu += vf->priv->outw; dstv += vf->priv->outw; } @@ -339,6 +472,9 @@ 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; @@ -367,6 +503,8 @@ case IMGFMT_YV12: case IMGFMT_I420: case IMGFMT_IYUV: + case IMGFMT_UYVY: + case IMGFMT_YUY2: return vf_next_query_format(vf, fmt) | VFCAP_EOSD; } return 0; @@ -385,6 +523,8 @@ 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]); free(vf->priv->dirty_rows); @@ -394,6 +534,8 @@ IMGFMT_YV12, IMGFMT_I420, IMGFMT_IYUV, + IMGFMT_UYVY, + IMGFMT_YUY2, 0 };