[gst-devel] I420 Color Space
Rezek Štěpán
stepan1117 at atlas.cz
Sun Oct 26 20:41:59 CET 2008
Dear gstreamer developers,
I have got a question regarding I420 color space or, maybe better said, color spaces in gstreamer in general.
I am trying to write a plugin, which will allow to draw anything on video stream using cairo functions. I successfully derived the existing cairotextoverlay plugin and I am changing it to draw anything on cairo surface.
One of the problems I am currently challenging is the I420 color space. The existing cairotextoverlay works in a way that it takes cairo
overlay in ARGB32 color space, translates it into the I420 color space and than blits in to the current video_frame. This is done in function
gst_vector_overlay_push_frame. Everything works fine with one small, but important problem: it translates everything into greyscale, but what I need is to draw colored things on the frame as well.
Is there any obvious solution to this problem, or do I have to learn more about color spaces and program that "translation" myself?
Thank you in advance
The functions (from plugins-good/ext/cairo/gsttextoverlay.c) are:
********************* code ***************************************
static GstFlowReturn gst_vector_overlay_push_frame
(GstCairoVectorOverlay * overlay, GstBuffer * video_frame)
{
guchar *y, *u, *v;
...
video_frame = gst_buffer_make_writable (video_frame);
...
y = GST_BUFFER_DATA (video_frame);
u = y + I420_U_OFFSET (overlay->width, overlay->height);
v = y + I420_V_OFFSET (overlay->width, overlay->height);
...
/* blit text on video image */
gst_vector_overlay_blit_1 (overlay,
y + (ypos / 1) * I420_Y_ROWSTRIDE (overlay->width),
overlay->text_fill_image, 255, I420_Y_ROWSTRIDE (overlay->width));
gst_vector_overlay_blit_sub2x2 (overlay,
u + (ypos / 2) * I420_U_ROWSTRIDE (overlay->width),
overlay->text_fill_image, 128, I420_U_ROWSTRIDE (overlay->width));
gst_vector_overlay_blit_sub2x2 (overlay,
v + (ypos / 2) * I420_V_ROWSTRIDE (overlay->width),
overlay->text_fill_image, 128, I420_V_ROWSTRIDE (overlay->width));
return gst_pad_push (overlay->srcpad, video_frame);
}
***************************** code ends ***********************
where blit functions are
****************************** code ************************
/* These macros are adapted from videotestsrc.c */
#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
#define I420_V_ROWSTRIDE(width)
((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
#define I420_Y_OFFSET(w,h) (0)
#define I420_U_OFFSET(w,h)
(I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
#define I420_V_OFFSET(w,h)
(I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
#define I420_SIZE(w,h)
(I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
static inline void gst_vector_overlay_blit_1 (GstCairoVectorOverlay *
overlay, guchar * dest,
guchar * text_image, gint val, guint dest_stride)
{
gint i, j;
gint x, a, y;
gint y0 = 0;
y = val;
for (i = 0; i < overlay->font_height; i++) {
for (j = 0; j < overlay->width; j++) {
x = dest[(i + y0) * dest_stride + j];
a = text_image[4 * (i * overlay->width + j) + 1];
dest[(i + y0) * dest_stride + j] = (y * a + x * (255 - a)) / 255;
}
}
}
static inline void gst_vector_overlay_blit_sub2x2 (GstCairoVectorOverlay
* overlay, guchar * dest,
guchar * text_image, gint val, guint dest_stride)
{
gint i, j;
gint x, a, y;
gint y0 = 0;
y = val;
for (i = 0; i < overlay->font_height; i += 2) {
for (j = 0; j < overlay->width; j += 2) {
x = dest[(i / 2 + y0) * dest_stride + j / 2];
a = (text_image[4 * (i * overlay->width + j) + 1] +
text_image[4 * (i * overlay->width + j + 1) + 1] +
text_image[4 * ((i + 1) * overlay->width + j) + 1] +
text_image[4 * ((i + 1) * overlay->width + j + 1) + 1] + 2) / 4;
dest[(i / 2 + y0) * dest_stride + j / 2] = (y * a + x * (255 - a))
/ 255;
}
}
}
More information about the gstreamer-devel
mailing list