]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-10094 Alpha Video support
authorSeven Du <dujinfang@gmail.com>
Mon, 6 Mar 2017 00:43:31 +0000 (08:43 +0800)
committerSeven Du <dujinfang@gmail.com>
Wed, 15 Mar 2017 03:45:58 +0000 (11:45 +0800)
Alpha webm support
RGBA alpha support

src/include/switch_core_video.h
src/mod/applications/mod_av/avformat.c
src/switch_core_video.c

index 11e0558153a7b68d5f503525a2b222c9aba600ea..64c08ddb0dec9749659905a116db8627147fa235 100644 (file)
@@ -440,11 +440,29 @@ SWITCH_DECLARE(switch_status_t) switch_I420_copy2(uint8_t *src_planes[], int src
                                                                                                  uint8_t *dst_planes[], int dst_stride[],
                                                                                                  int width, int height);
 
+/*!\brief I420 to ARGB Convertion*/
+
+SWITCH_DECLARE(switch_status_t) switch_I420ToARGB(const uint8_t *src_y, int src_stride_y,
+                                                                                                       const uint8_t *src_u, int src_stride_u,
+                                                                                                       const uint8_t *src_v, int src_stride_v,
+                                                                                                       uint8_t *dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height);
+
+SWITCH_DECLARE(switch_status_t) switch_RGBAToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height);
+SWITCH_DECLARE(switch_status_t) switch_ABGRToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height);
+SWITCH_DECLARE(switch_status_t) switch_ARGBToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height);
+
 /*!\brief chromakey an img, img must be RGBA and return modified img */
 
 SWITCH_DECLARE(void) switch_img_chromakey(switch_image_t *img, switch_rgb_color_t *mask, int threshold);
 SWITCH_DECLARE(switch_status_t) switch_chromakey_clear_colors(switch_chromakey_t *ck);
-                                                               
+
 SWITCH_DECLARE(switch_status_t) switch_chromakey_autocolor(switch_chromakey_t *ck, switch_shade_t autocolor, uint32_t threshold);
 SWITCH_DECLARE(switch_status_t) switch_chromakey_add_color(switch_chromakey_t *ck, switch_rgb_color_t *color, uint32_t threshold);
 SWITCH_DECLARE(switch_status_t) switch_chromakey_destroy(switch_chromakey_t **ckP);
index 9a28570da56d470e9781672f2f6b223b92bd155f..88272baa778565063da8f552fafa937400a8d341 100644 (file)
@@ -126,20 +126,61 @@ static void av_unused fill_avframe(AVFrame *pict, switch_image_t *img)
 
 static void av_unused avframe2img(AVFrame *pict, switch_image_t *img)
 {
-       int i;
-       uint8_t *y = pict->data[0];
-       uint8_t *u = pict->data[1];
-       uint8_t *v = pict->data[2];
+       int i, j;
 
-       /* Y */
-       for (i = 0; i < img->d_h; i++) {
-               memcpy(&img->planes[0][i * img->stride[0]], y + i * pict->linesize[0], img->d_w);
-       }
+       if (img->fmt == SWITCH_IMG_FMT_I420) {
+               if (pict->format == AV_PIX_FMT_YUV420P) {
+                       switch_I420_copy2(pict->data, pict->linesize, img->planes, img->stride, img->d_w, img->d_h);
+               } else if (pict->format == AV_PIX_FMT_YUVA420P) {
+                       int linesize[3];
+                       linesize[0] = pict->linesize[0];
+                       linesize[1] = pict->linesize[1];
+                       linesize[2] = pict->linesize[2] + pict->linesize[0];
 
-       /* U/V */
-       for(i = 0; i < pict->height / 2; i++) {
-               memcpy(&img->planes[1][i * img->stride[1]], u + i * pict->linesize[1], img->d_w / 2);
-               memcpy(&img->planes[2][i * img->stride[2]], v + i * pict->linesize[2], img->d_w / 2);
+                       switch_I420_copy2(pict->data, linesize, img->planes, img->stride, img->d_w, img->d_h);
+               }
+
+       } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+               if (pict->format == AV_PIX_FMT_YUV420P) {
+                       switch_rgb_color_t *color = (switch_rgb_color_t *)img->planes[SWITCH_PLANE_PACKED];
+                       uint8_t *alpha = pict->data[3];
+
+                       /*!\brief I420 to ARGB Convertion*/
+                       switch_I420ToARGB(pict->data[0], pict->linesize[0],
+                               pict->data[1], pict->linesize[1],
+                               pict->data[2], pict->linesize[2],
+                               img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                               img->d_w, img->d_h);
+
+
+                       for (j = 0; j < img->d_h; j++) {
+                               for (i = 0; i < img->d_w; i++) {
+                                       color->a = *alpha++;
+                                       color++;
+                               }
+                               color = (switch_rgb_color_t *)(img->planes[SWITCH_PLANE_PACKED] + img->stride[SWITCH_PLANE_PACKED] * j);
+                       }
+               } else if (pict->format == AV_PIX_FMT_RGBA) {
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+                       switch_RGBAToARGB(pict->data[0], pict->linesize[0],
+                               mg->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                               img->d_w, img->d_h);
+#else
+                       switch_ABGRToARGB(pict->data[0], pict->linesize[0],
+                               img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                               img->d_w, img->d_h);
+#endif
+               } else if (pict->format == AV_PIX_FMT_BGRA) {
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+                       switch_BGRAToARGB(pict->data[0], pict->linesize[0],
+                       , img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                       , img->d_w, img->d_h);
+#else
+                       switch_ARGBToARGB(pict->data[0], pict->linesize[0],
+                       img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                       img->d_w, img->d_h);
+#endif
+               }
        }
 }
 
@@ -1289,6 +1330,7 @@ struct av_file_context {
        switch_bool_t read_paused;
        int errs;
        switch_file_handle_t *handle;
+       switch_bool_t alpha_mode;
 };
 
 typedef struct av_file_context av_file_context_t;
@@ -1310,13 +1352,15 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
 {
        AVCodec *audio_codec = NULL;
        AVCodec *video_codec = NULL;
+       AVDictionary *opts = NULL;
        int error;
        int i;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
 
+       // av_dict_set(&opts, "c:v", "libvpx", 0);
+
        /** Open the input file to read from it. */
-       if ((error = avformat_open_input(&context->fc, filename, NULL,
-                                                                        NULL)) < 0) {
+       if ((error = avformat_open_input(&context->fc, filename, NULL, NULL)) < 0) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open input file '%s' (error '%s')\n", filename, get_error_text(error));
                switch_goto_status(SWITCH_STATUS_FALSE, err);
        }
@@ -1325,11 +1369,14 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "file %s is %sseekable\n", filename, handle->seekable ? "" : "not ");
 
        /** Get information on the input file (number of streams etc.). */
-       if ((error = avformat_find_stream_info(context->fc, NULL)) < 0) {
+       if ((error = avformat_find_stream_info(context->fc, opts ? &opts : NULL)) < 0) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open find stream info (error '%s')\n", get_error_text(error));
+               if (opts) av_dict_free(&opts);
                switch_goto_status(SWITCH_STATUS_FALSE, err);
        }
 
+       if (opts) av_dict_free(&opts);
+
        av_dump_format(context->fc, 0, filename, 0);
 
        for (i = 0; i< context->fc->nb_streams; i++) {
@@ -1534,11 +1581,17 @@ again:
                        //      av_frame_free(&vframe);
                        //      continue;
                        //}
+                       // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got_data=%d, error=%d\n", got_data, error);
 
                        if (got_data && error >= 0) {
-                               // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got picture %dx%d fmt: %d pktpts:%lld pktdts:%lld\n", vframe->width, vframe->height, vframe->format, vframe->pkt_pts, vframe->pkt_dts);
-
-                               if (vframe->format != AV_PIX_FMT_YUV420P) {
+                               switch_img_fmt_t fmt = SWITCH_IMG_FMT_I420;
+                               if (context->alpha_mode && (
+                                               vframe->format == AV_PIX_FMT_YUVA420P ||
+                                               vframe->format == AV_PIX_FMT_RGBA ||
+                                               vframe->format == AV_PIX_FMT_ARGB ||
+                                               vframe->format == AV_PIX_FMT_BGRA )) {
+                                       fmt = SWITCH_IMG_FMT_ARGB;
+                               } else if (vframe->format != AV_PIX_FMT_YUV420P) {
                                        AVFrame *frm = vframe;
                                        int ret;
 
@@ -1580,7 +1633,7 @@ again:
                                        }
                                }
 
-                               img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, vframe->width, vframe->height, 1);
+                               img = switch_img_alloc(NULL, fmt, vframe->width, vframe->height, 1);
 
                                if (img) {
                                        int64_t *pts = malloc(sizeof(int64_t));
@@ -1610,6 +1663,7 @@ again:
                                        }
                                }
                        }
+
                        av_frame_free(&vframe);
 
                        if (eof) {
@@ -1716,8 +1770,12 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
        context->offset = DFT_RECORD_OFFSET;
        context->handle = handle;
 
-       if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
-               context->offset = atoi(tmp);
+       if (handle->params) {
+               if ((tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
+                       context->offset = atoi(tmp);
+               } else if ((tmp = switch_event_get_header(handle->params, "alpha_mode"))) {
+                       context->alpha_mode = switch_true(tmp);
+               }
        }
 
        switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
index fc2f03c7093c2d00d7bfce3fdcd80d065323888e..e5e60abe355c4ecdccca449a7c9d9c20870ea166 100644 (file)
@@ -350,7 +350,7 @@ SWITCH_DECLARE(void) switch_img_attenuate(switch_image_t *img)
 
        img->user_priv = (void *)(intptr_t)1;
 
-       ARGBAttenuate(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED], 
+       ARGBAttenuate(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
                                  img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED], img->d_w, img->d_h);
 }
 
@@ -538,36 +538,56 @@ SWITCH_DECLARE(void) switch_img_patch_rect(switch_image_t *IMG, int X, int Y, sw
 
 SWITCH_DECLARE(void) switch_img_copy(switch_image_t *img, switch_image_t **new_img)
 {
+#ifdef SWITCH_HAVE_YUV
+       switch_img_fmt_t new_fmt = img->fmt;
+
        switch_assert(img);
        switch_assert(new_img);
 
-#ifdef SWITCH_HAVE_YUV
        if (img->fmt != SWITCH_IMG_FMT_I420 && img->fmt != SWITCH_IMG_FMT_ARGB) return;
 
-       if (*new_img != NULL) {
-               if (img->fmt != (*new_img)->fmt || img->d_w != (*new_img)->d_w || img->d_h != (*new_img)->d_w) {
+       if (*new_img) {
+               if ((*new_img)->fmt != SWITCH_IMG_FMT_I420 && (*new_img)->fmt != SWITCH_IMG_FMT_ARGB) return;
+               if (img->d_w != (*new_img)->d_w || img->d_h != (*new_img)->d_w ) {
+                       new_fmt = (*new_img)->fmt;
                        switch_img_free(new_img);
                }
        }
 
        if (*new_img == NULL) {
-               *new_img = switch_img_alloc(NULL, img->fmt, img->d_w, img->d_h, 1);
+               *new_img = switch_img_alloc(NULL, new_fmt, img->d_w, img->d_h, 1);
        }
 
        switch_assert(*new_img);
 
        if (img->fmt == SWITCH_IMG_FMT_I420) {
-               I420Copy(img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
-                                img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
-                                img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
-                                (*new_img)->planes[SWITCH_PLANE_Y], (*new_img)->stride[SWITCH_PLANE_Y],
-                                (*new_img)->planes[SWITCH_PLANE_U], (*new_img)->stride[SWITCH_PLANE_U],
-                                (*new_img)->planes[SWITCH_PLANE_V], (*new_img)->stride[SWITCH_PLANE_V],
-                                img->d_w, img->d_h);
+               if (new_fmt == SWITCH_IMG_FMT_I420) {
+                       I420Copy(img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
+                                        img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
+                                        img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
+                                        (*new_img)->planes[SWITCH_PLANE_Y], (*new_img)->stride[SWITCH_PLANE_Y],
+                                        (*new_img)->planes[SWITCH_PLANE_U], (*new_img)->stride[SWITCH_PLANE_U],
+                                        (*new_img)->planes[SWITCH_PLANE_V], (*new_img)->stride[SWITCH_PLANE_V],
+                                        img->d_w, img->d_h);
+               } else if (new_fmt == SWITCH_IMG_FMT_ARGB) {
+                       I420ToARGB(img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
+                               img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
+                               img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
+                               (*new_img)->planes[SWITCH_PLANE_PACKED], (*new_img)->stride[SWITCH_PLANE_PACKED],
+                               img->d_w, img->d_h);
+               }
        } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
-               ARGBCopy(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+               if (new_fmt == SWITCH_IMG_FMT_ARGB) {
+                       ARGBCopy(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
                                 (*new_img)->planes[SWITCH_PLANE_PACKED], (*new_img)->stride[SWITCH_PLANE_PACKED],
                                 img->d_w, img->d_h);
+               } else if (new_fmt == SWITCH_IMG_FMT_I420) {
+                       ARGBToI420(img->planes[SWITCH_PLANE_PACKED], img->stride[SWITCH_PLANE_PACKED],
+                                         (*new_img)->planes[SWITCH_PLANE_Y], (*new_img)->stride[SWITCH_PLANE_Y],
+                                         (*new_img)->planes[SWITCH_PLANE_U], (*new_img)->stride[SWITCH_PLANE_U],
+                                         (*new_img)->planes[SWITCH_PLANE_V], (*new_img)->stride[SWITCH_PLANE_V],
+                                         img->d_w, img->d_h);
+               }
        }
 #else
        return;
@@ -732,7 +752,7 @@ static inline void switch_core_rgb2hsl(switch_rgb_color_t *rgb, switch_hsl_color
 
 static inline void switch_core_rgb2lab(switch_rgb_color_t *rgb, switch_lab_color_t *lab)
 {
-    double x,y,z;
+       double x,y,z;
        double r = rgb->r;
        double g = rgb->g;
        double b = rgb->b;
@@ -916,7 +936,7 @@ struct switch_chromakey_s {
        uint32_t gg;
        uint32_t bb;
        uint32_t color_count;
-       
+
        switch_rgb_color_t auto_color;
        int no_cache;
        int frames_read;
@@ -979,7 +999,7 @@ SWITCH_DECLARE(switch_status_t) switch_chromakey_autocolor(switch_chromakey_t *c
        return SWITCH_STATUS_SUCCESS;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_chromakey_add_color(switch_chromakey_t *ck, switch_rgb_color_t *color, uint32_t threshold) 
+SWITCH_DECLARE(switch_status_t) switch_chromakey_add_color(switch_chromakey_t *ck, switch_rgb_color_t *color, uint32_t threshold)
 {
        switch_assert(ck);
 
@@ -1054,10 +1074,10 @@ static inline int get_max(switch_rgb_color_t *c1)
 
 static inline int switch_color_dom_cmp(switch_rgb_color_t *c1, switch_rgb_color_t *c2)
 {
-       
+
        int c1_max = get_max(c1);
        int c2_max = get_max(c2);
-       
+
        if (c1_max && c1_max == c2_max) return 1;
 
        return 0;
@@ -1089,7 +1109,7 @@ static inline int switch_color_distance_cheap(switch_rgb_color_t *c1, switch_rgb
 static inline void get_dom(switch_shade_t autocolor, switch_rgb_color_t *color, int *domP, int *aP, int *bP)
 {
        int dom, a, b;
-                               
+
        switch(autocolor) {
        case SWITCH_SHADE_RED:
                dom = color->r;
@@ -1172,7 +1192,7 @@ SWITCH_DECLARE(void) switch_chromakey_process(switch_chromakey_t *ck, switch_ima
 #ifdef DEBUG_CHROMA
                total_pixel++;
 #endif
-               
+
                if (!ck->no_cache && cache_img && cache_pixel) {
                        switch_rgb_color_t *cache_color = (switch_rgb_color_t *)cache_pixel;
                                
@@ -1217,7 +1237,7 @@ SWITCH_DECLARE(void) switch_chromakey_process(switch_chromakey_t *ck, switch_ima
                                        if (dom > a && dom > b && dom > tol) {
                                                if (dom - a > a_tol && dom - b > b_tol) {
                                                        hits = 1;
-                                               } 
+                                               }
                                        }
                                }
                        }
@@ -1231,7 +1251,7 @@ SWITCH_DECLARE(void) switch_chromakey_process(switch_chromakey_t *ck, switch_ima
                        checked++;
 #endif
                }
-               
+
        end:
 
                if (same > 100 && last_color && switch_color_dom_cmp(color, last_color)) {
@@ -2567,17 +2587,26 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char*
        png_bytep buffer = NULL;
        switch_status_t status = SWITCH_STATUS_SUCCESS;
 
-       buffer = malloc(img->d_w * img->d_h * 3);
-       switch_assert(buffer);
+       if (img->fmt == SWITCH_IMG_FMT_I420) {
+               png.format = PNG_FORMAT_RGB;
+               buffer = malloc(img->d_w * img->d_h * 3);
+               switch_assert(buffer);
 
-       I420ToRAW(  img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
+               I420ToRAW(img->planes[SWITCH_PLANE_Y], img->stride[SWITCH_PLANE_Y],
                                img->planes[SWITCH_PLANE_U], img->stride[SWITCH_PLANE_U],
                                img->planes[SWITCH_PLANE_V], img->stride[SWITCH_PLANE_V],
                                buffer, img->d_w * 3,
                                img->d_w, img->d_h);
+       } else if (img->fmt == SWITCH_IMG_FMT_ARGB) {
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+               png.format = PNG_FORMAT_ARGB;
+#else
+               png.format = PNG_FORMAT_BGRA;
+#endif
+               buffer = img->planes[SWITCH_PLANE_PACKED];
+       }
 
        png.version = PNG_IMAGE_VERSION;
-       png.format = PNG_FORMAT_RGB;
        png.width = img->d_w;
        png.height = img->d_h;
 
@@ -2586,7 +2615,10 @@ SWITCH_DECLARE(switch_status_t) switch_img_write_png(switch_image_t *img, char*
                status = SWITCH_STATUS_FALSE;
        }
 
-       switch_safe_free(buffer);
+       if (img->fmt == SWITCH_IMG_FMT_I420) {
+               free(buffer);
+       }
+
        return status;
 }
 
@@ -2879,7 +2911,6 @@ SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *des
        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);
@@ -2889,12 +2920,21 @@ SWITCH_DECLARE(switch_status_t) switch_img_to_raw(switch_image_t *src, void *des
                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, stride,
-                                       src->d_w, src->d_h,
-                                       fourcc);
+       if (src->fmt == SWITCH_IMG_FMT_I420) {
+               ret = ConvertFromI420(src->planes[0], src->stride[0],
+                                               src->planes[1], src->stride[1],
+                                               src->planes[2], src->stride[2],
+                                               dest, stride,
+                                               src->d_w, src->d_h,
+                                               fourcc);
+       } else if (src->fmt == SWITCH_IMG_FMT_ARGB && fmt == src->fmt) {
+               ret = ARGBCopy(src->planes[SWITCH_PLANE_PACKED], src->stride[SWITCH_PLANE_PACKED],
+                                               dest, stride,
+                                               src->d_w, src->d_h);
+       } else {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Convertion not supported %d -> %d\n", src->fmt, fmt);
+               return SWITCH_STATUS_FALSE;
+       }
 
        return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
 #else
@@ -2906,7 +2946,7 @@ SWITCH_DECLARE(switch_status_t) switch_img_from_raw(switch_image_t *dest, void *
 {
 #ifdef SWITCH_HAVE_YUV
        uint32_t fourcc;
-       int ret;
+       int ret = -1;
 
        fourcc = switch_img_fmt2fourcc(fmt);
 
@@ -2937,7 +2977,8 @@ SWITCH_DECLARE(switch_status_t) switch_img_from_raw(switch_image_t *dest, void *
        src_size is only used when FOURCC_MJPG which we don't support so always 0
 */
 
-       ret = ConvertToI420(src, 0,
+       if (dest->fmt == SWITCH_IMG_FMT_I420) {
+               ret = ConvertToI420(src, 0,
                                        dest->planes[0], dest->stride[0],
                                        dest->planes[1], dest->stride[1],
                                        dest->planes[2], dest->stride[2],
@@ -2945,6 +2986,14 @@ SWITCH_DECLARE(switch_status_t) switch_img_from_raw(switch_image_t *dest, void *
                                        width, height,
                                        width, height,
                                        0, fourcc);
+       } else if (dest->fmt == SWITCH_IMG_FMT_ARGB) {
+               ConvertToARGB(src, 0,
+                                       dest->planes[0], width * 4,
+                                       0, 0,
+                                       width, height,
+                                       width, height,
+                                       0, fourcc);
+       }
 
        return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
 #else
@@ -2962,9 +3011,9 @@ SWITCH_DECLARE(switch_status_t) switch_img_scale(switch_image_t *src, switch_ima
                dest = *destP;
        }
 
-       if (!dest) dest = switch_img_alloc(NULL, src->fmt, width, height, 1);
+       if (dest && src->fmt != dest->fmt) switch_img_free(&dest);
 
-       switch_assert(src->fmt == dest->fmt);
+       if (!dest) dest = switch_img_alloc(NULL, src->fmt, width, height, 1);
 
        if (src->fmt == SWITCH_IMG_FMT_I420) {
                ret = I420Scale(src->planes[0], src->stride[0],
@@ -3126,6 +3175,66 @@ SWITCH_DECLARE(switch_status_t) switch_I420_copy2(uint8_t *src_planes[], int src
        return SWITCH_STATUS_FALSE;
 #endif
 }
+
+SWITCH_DECLARE(switch_status_t) switch_I420ToARGB(const uint8_t *src_y, int src_stride_y,
+                                                                                                       const uint8_t *src_u, int src_stride_u,
+                                                                                                       const uint8_t *src_v, int src_stride_v,
+                                                                                                       uint8_t *dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height)
+{
+
+#ifdef SWITCH_HAVE_YUV
+       int ret = I420ToARGB(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
+                                                dst_argb, dst_stride_argb, width, height);
+
+       return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+#else
+       return SWITCH_STATUS_FALSE;
+#endif
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_RGBAToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height)
+{
+#ifdef SWITCH_HAVE_YUV
+       int ret = RGBAToARGB(src_frame, src_stride_frame, dst_argb, dst_stride_argb, width, height);
+
+       return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+#else
+       return SWITCH_STATUS_FALSE;
+#endif
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ABGRToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height)
+{
+#ifdef SWITCH_HAVE_YUV
+       int ret = ABGRToARGB(src_frame, src_stride_frame, dst_argb, dst_stride_argb, width, height);
+
+       return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+#else
+       return SWITCH_STATUS_FALSE;
+#endif
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ARGBToARGB(const uint8_t* src_frame, int src_stride_frame,
+                                                                                                       uint8_t* dst_argb, int dst_stride_argb,
+                                                                                                       int width, int height)
+{
+#ifdef SWITCH_HAVE_YUV
+       int ret = ARGBToARGB(src_frame, src_stride_frame, dst_argb, dst_stride_argb, width, height);
+
+       return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+#else
+       return SWITCH_STATUS_FALSE;
+#endif
+}
+
+
 /* For Emacs:
  * Local Variables:
  * mode:c