From ed78d3899404f5258bf51e138b0c0c18765afb37 Mon Sep 17 00:00:00 2001
From: Seven Du <dujinfang@gmail.com>
Date: Wed, 24 Feb 2016 18:34:35 +0800
Subject: [PATCH] FS-8867: create conversion function stubs in the core so
 modules do not need to use libyuv directly

---
 src/include/switch_core_video.h           |  25 ++++-
 src/include/switch_vpx.h                  |  30 ++++-
 src/mod/applications/mod_cv/mod_cv.cpp    |  14 +--
 src/mod/formats/mod_imagick/mod_imagick.c |   9 +-
 src/mod/formats/mod_vlc/mod_vlc.c         |   3 +-
 src/switch_core_video.c                   | 128 +++++++++++++++++++---
 6 files changed, 165 insertions(+), 44 deletions(-)

diff --git a/src/include/switch_core_video.h b/src/include/switch_core_video.h
index 33413cd6f4..0e9ebdd320 100644
--- a/src/include/switch_core_video.h
+++ b/src/include/switch_core_video.h
@@ -339,7 +339,30 @@ SWITCH_DECLARE(switch_status_t) switch_img_fit(switch_image_t **srcP, int width,
 SWITCH_DECLARE(switch_img_position_t) parse_img_position(const char *name);
 SWITCH_DECLARE(switch_img_fit_t) parse_img_fit(const char *name);
 SWITCH_DECLARE(void) switch_img_find_position(switch_img_position_t pos, int sw, int sh, int iw, int ih, int *xP, int *yP);
-SWITCH_DECLARE(switch_status_t) switch_img_convert(switch_image_t *src, switch_convert_fmt_t fmt, void *dest, switch_size_t *size);
+
+/*!\brief convert img to raw format
+*
+* dest should be pre-allocated and big enough for the target fmt
+*
+* \param[in]    src       The image descriptor
+* \param[in]    dest      The target memory address
+* \param[in]    size      The size of target memory address used for bounds check
+* \param[in]    fmt       The target format
+*/
+SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, switch_size_t size, switch_img_fmt_t fmt);
+/*!\brief convert raw memory to switch_img_t
+*
+* if dest is NULL then a new img is created, user should destroy it later,
+* otherwize it will re-used the dest img, and the dest img size must match the src width and height,
+* width and height can be 0 in the latter case and it will figure out according to the dest img
+*
+* \param[in]    dest      The image descriptor
+* \param[in]    src       The raw data memory address
+* \param[in]    fmt       The raw data format
+* \param[in]    width     The raw data width
+* \param[in]    height    The raw data height
+*/
+SWITCH_DECLARE(switch_status_t) switch_img_from_raw(switch_image_t *dest, void *src, switch_img_fmt_t fmt, int width, int height);
 SWITCH_DECLARE(switch_image_t *) switch_img_write_text_img(int w, int h, switch_bool_t full, const char *text);
 
 SWITCH_DECLARE(switch_image_t *) switch_img_read_file(const char* file_name);
diff --git a/src/include/switch_vpx.h b/src/include/switch_vpx.h
index a975775a7a..f2791678f7 100644
--- a/src/include/switch_vpx.h
+++ b/src/include/switch_vpx.h
@@ -59,9 +59,33 @@ SWITCH_BEGIN_EXTERN_C
 #define VPX_IMG_FMT_HIGH         0x800  /**< Image uses 16bit framebuffer */
 #endif
 
-#define SWITCH_IMG_FMT_HIGH      VPX_IMG_FMT_HIGH
-#define SWITCH_IMG_FMT_I420	     VPX_IMG_FMT_I420
-#define SWITCH_IMG_FMT_ARGB	     VPX_IMG_FMT_ARGB
+#define SWITCH_IMG_FMT_NONE      VPX_IMG_FMT_NONE
+#define SWITCH_IMG_FMT_RGB24     VPX_IMG_FMT_RGB24
+#define SWITCH_IMG_FMT_RGB32     VPX_IMG_FMT_RGB32
+#define SWITCH_IMG_FMT_RGB565    VPX_IMG_FMT_RGB565
+#define SWITCH_IMG_FMT_RGB555    VPX_IMG_FMT_RGB555
+#define SWITCH_IMG_FMT_UYVY      VPX_IMG_FMT_UYVY
+#define SWITCH_IMG_FMT_YUY2      VPX_IMG_FMT_YUY2
+#define SWITCH_IMG_FMT_YVYU      VPX_IMG_FMT_YVYU
+#define SWITCH_IMG_FMT_BGR24     VPX_IMG_FMT_BGR24
+#define SWITCH_IMG_FMT_RGB32_LE  VPX_IMG_FMT_RGB32_LE
+#define SWITCH_IMG_FMT_ARGB      VPX_IMG_FMT_ARGB
+#define SWITCH_IMG_FMT_ARGB_LE   VPX_IMG_FMT_ARGB_LE
+#define SWITCH_IMG_FMT_RGB565_LE VPX_IMG_FMT_RGB565_LE
+#define SWITCH_IMG_FMT_RGB555_LE VPX_IMG_FMT_RGB555_LE
+#define SWITCH_IMG_FMT_YV12      VPX_IMG_FMT_YV12
+#define SWITCH_IMG_FMT_I420      VPX_IMG_FMT_I420
+#define SWITCH_IMG_FMT_VPXYV12   VPX_IMG_FMT_VPXYV12
+#define SWITCH_IMG_FMT_VPXI420   VPX_IMG_FMT_VPXI420
+#define SWITCH_IMG_FMT_I422      VPX_IMG_FMT_I422
+#define SWITCH_IMG_FMT_I444      VPX_IMG_FMT_I444
+#define SWITCH_IMG_FMT_I440      VPX_IMG_FMT_I440
+#define SWITCH_IMG_FMT_444A      VPX_IMG_FMT_444A
+#define SWITCH_IMG_FMT_I42016    VPX_IMG_FMT_I42016
+#define SWITCH_IMG_FMT_I42216    VPX_IMG_FMT_I42216
+#define SWITCH_IMG_FMT_I44416    VPX_IMG_FMT_I44416
+#define SWITCH_IMG_FMT_I44016    VPX_IMG_FMT_I44016
+/* experimental */
 #define SWITCH_IMG_FMT_GD	     VPX_IMG_FMT_NONE
 
 typedef vpx_img_fmt_t switch_img_fmt_t;
diff --git a/src/mod/applications/mod_cv/mod_cv.cpp b/src/mod/applications/mod_cv/mod_cv.cpp
index 9f5d95dac0..5183adc40c 100644
--- a/src/mod/applications/mod_cv/mod_cv.cpp
+++ b/src/mod/applications/mod_cv/mod_cv.cpp
@@ -39,7 +39,6 @@ using namespace std;
 using namespace cv;
 
 #include <switch.h>
-#include <libyuv.h>
 
 #include <cv.h>
 #include "cvaux.h"
@@ -724,12 +723,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
             switch_assert(context->rawImage->width * 3 == context->rawImage->widthStep);
         }
 
-        libyuv::I420ToRGB24(frame->img->planes[0], frame->img->stride[0],
-                            frame->img->planes[1], frame->img->stride[1],
-                            frame->img->planes[2], frame->img->stride[2],
-                            (uint8_t *)context->rawImage->imageData, context->rawImage->widthStep,
-                            context->rawImage->width, context->rawImage->height);
-
+        switch_img_to_raw(frame->img, context->rawImage->imageData, context->rawImage->widthStep * context->h, SWITCH_IMG_FMT_RGB24);
         detectAndDraw(context);
 
         if (context->detected.simo_count > 20) {
@@ -824,11 +818,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
     }
 
     if (context->rawImage && (context->debug || !context->overlay_count)) {
-        libyuv::RGB24ToI420((uint8_t *)context->rawImage->imageData, context->w * 3,
-                            frame->img->planes[0], frame->img->stride[0],
-                            frame->img->planes[1], frame->img->stride[1],
-                            frame->img->planes[2], frame->img->stride[2],
-                            context->rawImage->width, context->rawImage->height);
+        switch_img_from_raw(frame->img, (uint8_t *)context->rawImage->imageData, SWITCH_IMG_FMT_RGB24, context->rawImage->width, context->rawImage->height);
     }
 
     int abs = 0;
diff --git a/src/mod/formats/mod_imagick/mod_imagick.c b/src/mod/formats/mod_imagick/mod_imagick.c
index 4c04b91cdf..060889f16a 100644
--- a/src/mod/formats/mod_imagick/mod_imagick.c
+++ b/src/mod/formats/mod_imagick/mod_imagick.c
@@ -34,8 +34,6 @@
 
 
 #include <switch.h>
-#include <libyuv.h>
-
 
 #if defined(__clang__)
 /* the imagemagick header files are very badly broken on clang.  They really should be fixing this, in the mean time, this dirty hack works */
@@ -263,12 +261,7 @@ static switch_status_t read_page(pdf_file_context_t *context)
 			return SWITCH_STATUS_FALSE;
 		}
 
-		RAWToI420(storage, w * 3,
-			context->img->planes[0], context->img->stride[0],
-			context->img->planes[1], context->img->stride[1],
-			context->img->planes[2], context->img->stride[2],
-			context->img->d_w, context->img->d_h);
-
+		switch_img_from_raw(context->img, storage, SWITCH_IMG_FMT_BGR24, w, h);
 		free(storage);
 	} else {
 		switch_image_t *img = switch_img_alloc(NULL, SWITCH_IMG_FMT_ARGB, image->columns, image->rows, 0);
diff --git a/src/mod/formats/mod_vlc/mod_vlc.c b/src/mod/formats/mod_vlc/mod_vlc.c
index 32798099be..e9769fc084 100644
--- a/src/mod/formats/mod_vlc/mod_vlc.c
+++ b/src/mod/formats/mod_vlc/mod_vlc.c
@@ -1642,8 +1642,7 @@ int  vlc_write_video_imem_get_callback(void *data, const char *cookie, int64_t *
 		}
 		
 		*output = context->video_frame_buffer;
-		*size = 0;
-		switch_img_convert(img, SWITCH_CONVERT_FMT_YUYV, *output, size);
+		switch_img_to_raw(img, *output, *size, SWITCH_IMG_FMT_YUY2);
 		switch_img_free(&img);
 		return 0;
 	}
diff --git a/src/switch_core_video.c b/src/switch_core_video.c
index 4ea9669d6c..e226b95376 100644
--- a/src/switch_core_video.c
+++ b/src/switch_core_video.c
@@ -1936,29 +1936,121 @@ SWITCH_DECLARE(switch_status_t) switch_img_fit(switch_image_t **srcP, int width,
 	return SWITCH_STATUS_FALSE;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_img_convert(switch_image_t *src, switch_convert_fmt_t fmt, void *dest, switch_size_t *size)
+static inline uint32_t switch_img_fmt2fourcc(switch_img_fmt_t fmt)
 {
 #ifdef SWITCH_HAVE_YUV
-	switch_assert(src->fmt == SWITCH_IMG_FMT_I420);
+	uint32_t fourcc;
 
-	switch (fmt) {
-	case SWITCH_CONVERT_FMT_YUYV:
-		{
-			switch_size_t size_in = *size;
-			ConvertFromI420(src->planes[0], src->stride[0],
-							src->planes[1], src->stride[1],
-							src->planes[2], src->stride[2],
-							dest, size_in,
-							src->d_w, src->d_h,
-							FOURCC_YUY2);  
-			*size = src->d_w * src->d_h * 2;
+	switch(fmt) {
+		case SWITCH_IMG_FMT_NONE:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_RGB24:     fourcc = FOURCC_24BG; break;
+		case SWITCH_IMG_FMT_RGB32:     fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_RGB565:    fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_RGB555:    fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_UYVY:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_YUY2:      fourcc = FOURCC_YUY2; break;
+		case SWITCH_IMG_FMT_YVYU:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_BGR24:     fourcc = FOURCC_RAW ; break;
+		case SWITCH_IMG_FMT_RGB32_LE:  fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_ARGB:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_ARGB_LE:   fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_RGB565_LE: fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_RGB555_LE: fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_YV12:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I420:      fourcc = FOURCC_I420; break;
+		case SWITCH_IMG_FMT_VPXYV12:   fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_VPXI420:   fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I422:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I444:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I440:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_444A:      fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I42016:    fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I42216:    fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I44416:    fourcc = FOURCC_ANY ; break;
+		case SWITCH_IMG_FMT_I44016:    fourcc = FOURCC_ANY ; break;
+		default: fourcc = FOURCC_ANY;
+    }
 
-			return SWITCH_STATUS_SUCCESS;
-		}
-	default:
-		abort();
-		break;
+    return fourcc;
+#else
+    return 0xFFFFFFFF;
+#endif
+}
+
+SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *dest, switch_size_t size, switch_img_fmt_t fmt)
+{
+#ifdef SWITCH_HAVE_YUV
+	uint32_t fourcc;
+	int ret;
+
+	switch_assert(src->fmt == SWITCH_IMG_FMT_I420); // todo: support other formats
+	switch_assert(dest);
+
+	fourcc = switch_img_fmt2fourcc(fmt);
+
+	if (fourcc == FOURCC_ANY) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unsupported format: %d\n", fmt);
+		return SWITCH_STATUS_FALSE;
 	}
+
+	ret = ConvertFromI420(src->planes[0], src->stride[0],
+					src->planes[1], src->stride[1],
+					src->planes[2], src->stride[2],
+					dest, size,
+					src->d_w, src->d_h,
+					fourcc);
+
+	return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+#else
+	return SWITCH_STATUS_FALSE;
+#endif
+}
+
+SWITCH_DECLARE(switch_status_t) switch_img_from_raw(switch_image_t *dest, void *src, switch_img_fmt_t fmt, int width, int height)
+{
+#ifdef SWITCH_HAVE_YUV
+	uint32_t fourcc;
+	int ret;
+
+	fourcc = switch_img_fmt2fourcc(fmt);
+
+	if (fourcc == FOURCC_ANY) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unsupported format: %d\n", fmt);
+		return SWITCH_STATUS_FALSE;
+	}
+
+	if (!dest && width > 0 && height > 0) dest = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, height, 1);
+	if (!dest) return SWITCH_STATUS_FALSE;
+
+	if (width == 0 || height == 0) {
+		width = dest->d_w;
+		height = dest->d_h;
+	}
+
+/*
+	int ConvertToI420(const uint8* src_frame, size_t src_size,
+                  uint8* dst_y, int dst_stride_y,
+                  uint8* dst_u, int dst_stride_u,
+                  uint8* dst_v, int dst_stride_v,
+                  int crop_x, int crop_y,
+                  int src_width, int src_height,
+                  int crop_width, int crop_height,
+                  enum RotationMode rotation,
+                  uint32 format);
+
+	src_size is only used when FOURCC_MJPG which we don't support so always 0
+*/
+
+	ret = ConvertToI420(src, 0,
+					dest->planes[0], dest->stride[0],
+					dest->planes[1], dest->stride[1],
+					dest->planes[2], dest->stride[2],
+					0, 0,
+					width, height,
+					width, height,
+					0, fourcc);
+
+	return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
 #else
 	return SWITCH_STATUS_FALSE;
 #endif