]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7506 FS-7513: refactor switch color and implement draw_text in mod_conference
authorSeven Du <dujinfang@gmail.com>
Tue, 10 Feb 2015 03:30:31 +0000 (11:30 +0800)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:46:59 +0000 (12:46 -0500)
src/include/switch_core_video.h
src/mod/applications/mod_conference/mod_conference.c
src/switch_core_video.c

index 880af749e5e9672e3ce7639064fd61627edd0313..aba9b5c7a3cf00dabf53e9c91d0ee86eee22a66e 100644 (file)
@@ -61,6 +61,13 @@ SWITCH_BEGIN_EXTERN_C
 #define SWITCH_IMG_FMT_HIGH      VPX_IMG_FMT_HIGH
 #define SWITCH_IMG_FMT_I420         VPX_IMG_FMT_I420
 
+typedef struct switch_yuv_color_s {
+       uint8_t y;
+       uint8_t u;
+       uint8_t v;
+} switch_yuv_color_t;
+
+
 typedef vpx_img_fmt_t switch_img_fmt_t;
 
 typedef vpx_image_t switch_image_t;
@@ -176,8 +183,16 @@ SWITCH_DECLARE(void) switch_img_flip(switch_image_t *img);
 */
 SWITCH_DECLARE(void) switch_img_free(switch_image_t **img);
 
+SWITCH_DECLARE(void) switch_img_draw_text(switch_image_t *IMG, int x, int y, char *text);
+
 SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char *s);
 
+SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h);
+
+SWITCH_DECLARE(void) switch_image_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t color);
+
+SWITCH_DECLARE(void) switch_color_set(switch_yuv_color_t *color, char *color_str);
+
 /** @} */
 
 SWITCH_END_EXTERN_C
index 484683cb9a7f5ab7d50825083dcbdd5a91e04b99..222b2268bf71798e3cb2bccbbf7906fcf24a0a14 100644 (file)
@@ -362,13 +362,6 @@ typedef struct mcu_layer_s {
        switch_image_t *cur_img;
 } mcu_layer_t;
 
-typedef struct bgcolor_yuv_s
-{
-       uint8_t y;
-       uint8_t u;
-       uint8_t v;
-} bgcolor_yuv_t;
-
 typedef struct mcu_canvas_s {
        int width;
        int height;
@@ -377,7 +370,7 @@ typedef struct mcu_canvas_s {
        int total_layers;
        int layers_used;
        int layout_floor_id;
-       bgcolor_yuv_t bgcolor;
+       switch_yuv_color_t bgcolor;
        switch_mutex_t *mutex;
        switch_mutex_t *cond_mutex;
        switch_mutex_t *cond2_mutex;
@@ -708,6 +701,93 @@ typedef struct layout_group_s {
        video_layout_node_t *layouts;
 } layout_group_t;
 
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+
+static void draw_bitmap(switch_image_t *img, FT_Bitmap* bitmap, FT_Int x, FT_Int y, switch_yuv_color_t color)
+{
+       FT_Int  i, j, p, q;
+       FT_Int  x_max = x + bitmap->width;
+       FT_Int  y_max = y + bitmap->rows;
+
+       for ( i = x, p = 0; i < x_max; i++, p++ ) {
+               for ( j = y, q = 0; j < y_max; j++, q++ ) {
+                       if ( i < 0 || j < 0 || i >= img->d_w || j >= img->d_h) continue;
+
+                       if (bitmap->buffer[q * bitmap->width + p]) {
+                               // TODO the value ranges from 1 - 255, maybe we should reset the color based on that
+                               switch_image_draw_pixel(img, i, j, color);
+                       }
+               }
+       }
+}
+
+SWITCH_DECLARE(void) switch_img_draw_text(switch_image_t *img, int x, int y, char *text)
+{
+       FT_Library    library;
+       FT_Face       face;
+       FT_GlyphSlot  slot;
+       FT_Matrix     matrix; /* transformation matrix */
+       FT_Vector     pen;    /* untransformed origin  */
+       FT_Error      error;
+       char*         font_family = "/usr/local/freeswitch/SimHei.ttf";
+       int           font_size = 64;
+       double        angle;
+       int           target_height;
+       int           n, num_chars;
+       switch_yuv_color_t color;
+
+       if (zstr(text)) return;
+       switch_color_set(&color, "#FFFFFF");
+
+       num_chars     = strlen(text);
+       angle         = 0; // (45.0 / 360 ) * 3.14159 * 2;
+       target_height = img->d_h;
+
+       error = FT_Init_FreeType( &library ); /* initialize library */
+       if (error) return;
+
+       error = FT_New_Face(library, font_family, 0, &face); /* create face object */
+       if (error) return;
+
+       /* use 50pt at 100dpi */
+       error = FT_Set_Char_Size(face, 50 * font_size, 0, 100, 0); /* set character size */
+       if (error) return;
+
+       slot = face->glyph;
+
+       /* set up matrix */
+       matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
+       matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
+       matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
+       matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
+
+       /* the pen position in 26.6 cartesian space coordinates; */
+       /* start at (300,200) relative to the upper left corner  */
+       pen.x = x * 64;
+       pen.y = (target_height - y) * 64;
+
+       for(n = 0; n < num_chars; n++) {
+               /* set transformation */
+               FT_Set_Transform(face, &matrix, &pen);
+
+               /* load glyph image into the slot (erase previous one) */
+               error = FT_Load_Char(face, text[n], FT_LOAD_RENDER);
+               if (error) continue;
+
+               /* now, draw to our target surface (convert position) */
+               draw_bitmap(img, &slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top + font_size, color);
+
+               /* increment pen position */
+               pen.x += slot->advance.x;
+               pen.y += slot->advance.y;
+       }
+
+       FT_Done_Face(face);
+       FT_Done_FreeType(library);
+}
+
 static void conference_parse_layouts(conference_obj_t *conference)
 {
        switch_event_t *params;
@@ -890,7 +970,7 @@ static int mcu_canvas_wake(mcu_canvas_t *mcu_canvas)
        return 0;
 }
 
-static void reset_image(switch_image_t *img, bgcolor_yuv_t *color)
+static void reset_image(switch_image_t *img, switch_yuv_color_t *color)
 {
        int i;
 
@@ -904,32 +984,6 @@ static void reset_image(switch_image_t *img, bgcolor_yuv_t *color)
        }
 }
 
-static void set_bgcolor(bgcolor_yuv_t *bgcolor, char *bgcolor_str)
-{
-       uint8_t y = 134;
-       uint8_t u = 128;
-       uint8_t v = 124;
-
-       if (bgcolor_str != NULL && strlen(bgcolor_str) == 7) {
-               uint8_t red, green, blue;
-               char str[7];
-               bgcolor_str ++;
-               strncpy(str, bgcolor_str, 6);
-               red = (str[0] >= 'A' ? (str[0] - 'A' + 10) * 16 : (str[0] - '0') * 16) + (str[1] >= 'A' ? (str[1] - 'A' + 10) : (str[0] - '0'));
-               green = (str[2] >= 'A' ? (str[2] - 'A' + 10) * 16 : (str[2] - '0') * 16) + (str[3] >= 'A' ? (str[3] - 'A' + 10) : (str[0] - '0'));
-               blue = (str[4] >= 'A' ? (str[4] - 'A' + 10) * 16 : (str[4] - '0') * 16) + (str[5] >= 'A' ? (str[5] - 'A' + 10) : (str[0] - '0'));
-
-               y = (uint8_t)(((red * 4897) >> 14) + ((green * 9611) >> 14) + ((blue * 1876) >> 14));
-               u = (uint8_t)(- ((red * 2766) >> 14)  - ((5426 * green) >> 14) + blue / 2 + 128);
-               v = (uint8_t)(red / 2 -((6855 * green) >> 14) - ((blue * 1337) >> 14) + 128);
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "analy_bgcolor, red = %u, green = %u, blue = %u, y = %u, u = %u, v = %u\n", red, green, blue, y, u, v);
-       }
-
-       bgcolor->y = y;
-       bgcolor->u = u;
-       bgcolor->v = v;
-}
-
 #define SCALE_FACTOR 360.0f
 
 static void reset_layer(mcu_canvas_t *canvas, mcu_layer_t *layer)
@@ -1041,7 +1095,7 @@ static void scale_and_patch(conference_obj_t *conference, mcu_layer_t *layer)
 
 static void set_canvas_bgcolor(mcu_canvas_t *canvas, char *color)
 {
-       set_bgcolor(&canvas->bgcolor, color);
+       switch_color_set(&canvas->bgcolor, color);
        reset_image(canvas->img, &canvas->bgcolor);
 }
 
@@ -1480,6 +1534,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread
                        }
                }
 
+               // switch_img_draw_text(conference->canvas->img, 10, 10, "AVA 123 你好 FreeSWITCH");
 
                if (used) {
                        switch_time_t now = switch_micro_time_now();
index bbdc40dddc0fd02d307f0c5b700d057966692d2b..9e0eadbf219af63e6e8feb522e20aa94ee679af9 100644 (file)
@@ -131,6 +131,47 @@ SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_i
 
 }
 
+SWITCH_DECLARE(switch_image_t *) switch_img_copy_rect(switch_image_t *img, int x, int y, int w, int h)
+{
+       switch_image_t *new_img = NULL;
+       int i = 0;
+       int len;
+
+       switch_assert(img);
+       switch_assert(x >= 0 && y >= 0 && w >= 0 && h >= 0);
+
+       if (!img->fmt == SWITCH_IMG_FMT_I420) return NULL;
+
+       new_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, w, h, 1);
+       if (new_img == NULL) return NULL;
+
+       len = MIN(img->d_w - x, w);
+       if (len <= 0) return NULL;
+
+       for (i = 0; i < (img->d_h - y) && i < h; i++) {
+               memcpy(new_img->planes[SWITCH_PLANE_Y] + new_img->stride[SWITCH_PLANE_Y] * i, img->planes[SWITCH_PLANE_Y] + img->stride[SWITCH_PLANE_Y] * (y + i) + x, len);
+       }
+
+       len /= 2;
+
+       for (i = 0; i < (img->d_h - y) && i < h; i += 2) {
+               memcpy(new_img->planes[SWITCH_PLANE_U] + new_img->stride[SWITCH_PLANE_U] * i / 2, img->planes[SWITCH_PLANE_U] + img->stride[SWITCH_PLANE_U] * (y + i) / 2 + x / 2, len);
+               memcpy(new_img->planes[SWITCH_PLANE_V] + new_img->stride[SWITCH_PLANE_V] * i / 2, img->planes[SWITCH_PLANE_V] + img->stride[SWITCH_PLANE_V] * (y + i) / 2 + x / 2, len);
+       }
+       return new_img;
+}
+
+SWITCH_DECLARE(void) switch_image_draw_pixel(switch_image_t *img, int x, int y, switch_yuv_color_t color)
+{
+       if (x < 0 || y < 0 || x >= img->d_w || y >= img->d_h) return;
+
+       img->planes[SWITCH_PLANE_Y][y * img->stride[SWITCH_PLANE_Y] + x] = color.y;
+
+       if (((x & 0x1) == 0) && ((y & 0x1) == 0)) {// only draw on even position
+               img->planes[SWITCH_PLANE_U][y / 2 * img->stride[SWITCH_PLANE_U] + x / 2] = color.u;
+               img->planes[SWITCH_PLANE_V][y / 2 * img->stride[SWITCH_PLANE_V] + x / 2] = color.v;
+       }
+}
 
 static uint8_t scv_art[14][16] = {
        {0x00, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x00},
@@ -185,6 +226,31 @@ SWITCH_DECLARE(void) switch_img_add_text(void *buffer, int w, int x, int y, char
        }
 }
 
+SWITCH_DECLARE(void) switch_color_set(switch_yuv_color_t *color, char *color_str)
+{
+       uint8_t y = 134;
+       uint8_t u = 128;
+       uint8_t v = 124;
+
+       if (color_str != NULL && strlen(color_str) == 7) {
+               uint8_t red, green, blue;
+               char str[7];
+               color_str++;
+               strncpy(str, color_str, 6);
+               red = (str[0] >= 'A' ? (str[0] - 'A' + 10) * 16 : (str[0] - '0') * 16) + (str[1] >= 'A' ? (str[1] - 'A' + 10) : (str[0] - '0'));
+               green = (str[2] >= 'A' ? (str[2] - 'A' + 10) * 16 : (str[2] - '0') * 16) + (str[3] >= 'A' ? (str[3] - 'A' + 10) : (str[0] - '0'));
+               blue = (str[4] >= 'A' ? (str[4] - 'A' + 10) * 16 : (str[4] - '0') * 16) + (str[5] >= 'A' ? (str[5] - 'A' + 10) : (str[0] - '0'));
+
+               y = (uint8_t)(((red * 4897) >> 14) + ((green * 9611) >> 14) + ((blue * 1876) >> 14));
+               u = (uint8_t)(- ((red * 2766) >> 14)  - ((5426 * green) >> 14) + blue / 2 + 128);
+               v = (uint8_t)(red / 2 -((6855 * green) >> 14) - ((blue * 1337) >> 14) + 128);
+               // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "set color, red = %u, green = %u, blue = %u, y = %u, u = %u, v = %u\n", red, green, blue, y, u, v);
+       }
+
+       color->y = y;
+       color->u = u;
+       color->v = v;
+}
 
 /* For Emacs:
  * Local Variables: