I420 Color Space

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

I420 Color Space

Štěpán Rezek
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;
    }
  }
}



-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: I420 Color Space

Dejan Sakelsak
check this patches out:

http://bugzilla.gnome.org/show_bug.cgi?id=526670

regards,
Dejan

On 10/26/08, Rezek Štěpán <[hidden email]> wrote:

> 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;
>     }
>   }
>  }
>
>
>
> -------------------------------------------------------------------------
>  This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
>  Build the coolest Linux based applications with Moblin SDK & win great prizes
>  Grand prize is a trip for two to an Open Source event anywhere in the world
>  http://moblin-contest.org/redirect.php?banner_id=100&url=/
> _______________________________________________
>  gstreamer-devel mailing list
>  [hidden email]
>  https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
>
>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel
Reply | Threaded
Open this post in threaded view
|

Re: I420 Color Space

Štěpán Rezek
Thank you, it helped me a lot. Now I have to think about vector data
transmission (from client app to gstreamer plugin) and then... My plugin
is finished.
    Best regards,
       Stepan

Dejan Sakelsak napsal(a):
> check this patches out:
>
> http://bugzilla.gnome.org/show_bug.cgi?id=526670
>
> regards,
> Dejan
>
>  


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
gstreamer-devel mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/gstreamer-devel