[FFmpeg-devel] [PATCH] vf_ass: add yuv overlay
Jean First
jeanfirst at gmail.com
Wed Mar 14 14:14:27 CET 2012
---
libavfilter/vf_ass.c | 73 +++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/libavfilter/vf_ass.c b/libavfilter/vf_ass.c
index 7ef78f1..a3c4798 100644
--- a/libavfilter/vf_ass.c
+++ b/libavfilter/vf_ass.c
@@ -29,6 +29,7 @@
#include <ass/ass.h>
#include "libavutil/avstring.h"
+#include "libavutil/colorspace.h"
#include "libavutil/imgutils.h"
#include "libavutil/pixdesc.h"
#include "drawutils.h"
@@ -39,6 +40,7 @@ typedef struct {
ASS_Renderer *renderer;
ASS_Track *track;
int hsub, vsub;
+ int is_packed_rgb;
char *filename;
uint8_t rgba_map[4];
int pix_step[4]; ///< steps per pixel for each plane of the main output
@@ -120,6 +122,11 @@ static int query_formats(AVFilterContext *ctx)
PIX_FMT_ARGB, PIX_FMT_RGBA,
PIX_FMT_ABGR, PIX_FMT_BGRA,
PIX_FMT_RGB24, PIX_FMT_BGR24,
+ PIX_FMT_YUV444P, PIX_FMT_YUV422P, PIX_FMT_YUV420P,
+ PIX_FMT_YUV411P, PIX_FMT_YUV410P, PIX_FMT_YUV440P,
+ PIX_FMT_YUVA420P,
+ PIX_FMT_YUVJ444P, PIX_FMT_YUVJ422P, PIX_FMT_YUVJ420P,
+ PIX_FMT_YUVJ440P,
PIX_FMT_NONE
};
@@ -137,7 +144,7 @@ static int config_input(AVFilterLink *inlink)
double dar = inlink->w / inlink->h * sar;
av_image_fill_max_pixsteps(ass->pix_step, NULL, pix_desc);
- ff_fill_rgba_map(ass->rgba_map, inlink->format);
+ ass->is_packed_rgb = ff_fill_rgba_map(ass->rgba_map, inlink->format) >= 0;
ass->hsub = pix_desc->log2_chroma_w;
ass->vsub = pix_desc->log2_chroma_h;
@@ -150,6 +157,54 @@ static int config_input(AVFilterLink *inlink)
static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
+/* libass stores an RGBA color in the format RRGGBBTT, where TT is the transparency level */
+#define AR(c) ( (c)>>24)
+#define AG(c) (((c)>>16)&0xFF)
+#define AB(c) (((c)>>8) &0xFF)
+#define AA(c) ((0xFF-c) &0xFF)
+
+#define Y 0
+#define U 1
+#define V 2
+#define A 3
+
+#define SET_PIXEL_YUV(picref, yuva_color, val, x, y, hsub, vsub) { \
+ luma_pos = ((x) ) + ((y) ) * picref->linesize[0]; \
+ alpha = yuva_color[A] * (val) * 129; \
+ picref->data[0][luma_pos] = (alpha * yuva_color[Y] + (255*255*129 - alpha) * picref->data[0][luma_pos] ) >> 23; \
+ if (((x) & ((1<<(hsub)) - 1)) == 0 && ((y) & ((1<<(vsub)) - 1)) == 0) {\
+ chroma_pos1 = ((x) >> (hsub)) + ((y) >> (vsub)) * picref->linesize[1]; \
+ chroma_pos2 = ((x) >> (hsub)) + ((y) >> (vsub)) * picref->linesize[2]; \
+ picref->data[1][chroma_pos1] = (alpha * yuva_color[U] + (255*255*129 - alpha) * picref->data[1][chroma_pos1]) >> 23; \
+ picref->data[2][chroma_pos2] = (alpha * yuva_color[V] + (255*255*129 - alpha) * picref->data[2][chroma_pos2]) >> 23; \
+ }\
+}
+
+static void overlay_ass_image_yuv(AVFilterBufferRef *picref, const int hsub,
+ const int vsub, const ASS_Image *image)
+{
+ int i, j, alpha;
+ unsigned int luma_pos, chroma_pos1, chroma_pos2;
+
+ for (; image; image = image->next) {
+ unsigned char *row = image->bitmap;
+ uint8_t yuva_color[4];
+ yuva_color[Y] = RGB_TO_Y_CCIR(AR(image->color), AG(image->color), AB(image->color));
+ yuva_color[U] = RGB_TO_U_CCIR(AR(image->color), AG(image->color), AB(image->color), 0);
+ yuva_color[V] = RGB_TO_V_CCIR(AR(image->color), AG(image->color), AB(image->color), 0);
+ yuva_color[A] = AA(image->color);
+
+ for (i = 0; i < image->h; i++) {
+ for (j = 0; j < image->w; j++) {
+ if (row[j]) {
+ SET_PIXEL_YUV(picref, yuva_color, row[j], image->dst_x + j, image->dst_y + i, hsub, vsub);
+ }
+ }
+ row += image->stride;
+ }
+ }
+}
+
#define R 0
#define G 1
#define B 2
@@ -163,14 +218,8 @@ static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
*(p+b_off) = (alpha * rgba_color[B] + (255*255*129 - alpha) * *(p+b_off)) >> 23; \
}
-/* libass stores an RGBA color in the format RRGGBBTT, where TT is the transparency level */
-#define AR(c) ( (c)>>24)
-#define AG(c) (((c)>>16)&0xFF)
-#define AB(c) (((c)>>8) &0xFF)
-#define AA(c) ((0xFF-c) &0xFF)
-
-static void overlay_ass_image(AVFilterBufferRef *picref, const uint8_t *rgba_map, const int pix_step,
- const ASS_Image *image)
+static void overlay_ass_image_rgb(AVFilterBufferRef *picref, const uint8_t *rgba_map, const int pix_step,
+ const ASS_Image *image)
{
int i, j;
int alpha;
@@ -208,7 +257,11 @@ static void end_frame(AVFilterLink *inlink)
if (detect_change)
av_log(ctx, AV_LOG_DEBUG, "Change happened at time ms:%f\n", time_ms);
- overlay_ass_image(picref, ass->rgba_map, ass->pix_step[0], image);
+ if (ass->is_packed_rgb) {
+ overlay_ass_image_rgb(picref, ass->rgba_map, ass->pix_step[0], image);
+ } else {
+ overlay_ass_image_yuv(picref, ass->hsub, ass->vsub, image);
+ }
avfilter_draw_slice(outlink, 0, picref->video->h, 1);
avfilter_end_frame(outlink);
--
1.7.9.1
More information about the ffmpeg-devel
mailing list