[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