Commit 57f7b952 authored by jehan's avatar jehan

fix msvideo downscaling function for x86

parent 6bdf8b4e
......@@ -624,17 +624,16 @@ void ms_video_set_scaler_impl(MSScalerDesc *desc){
}
/* Can rotate Y, U or V plane; use step=2 for interleaved UV planes otherwise step=1*/
static void rotate_plane(int wDest, int hDest, int full_width, const uint8_t* src, uint8_t* dst, int step, bool_t clockWise) {
int hSrc = wDest;
int wSrc = hDest;
int src_stride = full_width * step;
static void rotate_plane_down_scale_by_2(int wDest, int hDest, int full_width, const uint8_t* src, uint8_t* dst, int step, bool_t clockWise,bool_t downscale) {
int factor = downscale?2:1;
int hSrc = wDest*factor;
int wSrc = hDest*factor;
int src_stride = full_width*step*factor;
int signed_dst_stride;
int incr;
int y,x;
if (clockWise) {
/* ms_warning("start writing destination buffer from top right");*/
dst += wDest - 1;
......@@ -646,9 +645,9 @@ static void rotate_plane(int wDest, int hDest, int full_width, const uint8_t* sr
incr = -1;
signed_dst_stride = -wDest;
}
for (y=0; y<hSrc; y++) {
for (y=0; y<hSrc; y+=factor) {
uint8_t* dst2 = dst;
for (x=0; x<step*wSrc; x+=step) {
for (x=0; x<step*wSrc; x+=step*factor) {
/* Copy a line in source buffer (left to right)
Clockwise: Store a column in destination buffer (top to bottom)
Not clockwise: Store a column in destination buffer (bottom to top)
......@@ -661,7 +660,6 @@ static void rotate_plane(int wDest, int hDest, int full_width, const uint8_t* sr
}
}
#ifdef ANDROID
#include "cpu-features.h"
static int hasNeon = -1;
......@@ -674,17 +672,14 @@ static int hasNeon = 0;
/* Destination and source images may have their dimensions inverted.*/
mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBufAllocator *allocator, const uint8_t* y, const uint8_t * cbcr, int rotation, int w, int h, int y_byte_per_row,int cbcr_byte_per_row, bool_t uFirstvSecond, bool_t down_scale) {
MSPicture pict;
int uv_w;
int uv_h;
const uint8_t* ysrc;
uint8_t* ydst;
const uint8_t* uvsrc;
int uv_w=w/2;
int uv_h=h/2;
const uint8_t* srcu;
uint8_t* dstu;
const uint8_t* srcv;
uint8_t* dstv;
mblk_t *yuv_block = ms_yuv_buf_allocator_get(allocator, &pict, w, h);
int factor = down_scale?2:1;
mblk_t * yuv_block;
#ifdef ANDROID
if (hasNeon == -1) {
......@@ -694,14 +689,8 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
#endif
}
#endif
#if MS_HAS_ARM
if (down_scale && !hasNeon) {
ms_error("down scaling by two requires NEON, returning empty block");
return yuv_block;
}
#endif
yuv_block = ms_yuv_buf_allocator_get(allocator, &pict, w, h);
if (!uFirstvSecond) {
unsigned char* tmp = pict.planes[1];
......@@ -709,9 +698,6 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
pict.planes[2] = tmp;
}
uv_w = w/2;
uv_h = h/2;
if (rotation % 180 == 0) {
int i,j;
uint8_t* u_dest=pict.planes[1], *v_dest=pict.planes[2];
......@@ -725,13 +711,19 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
{
// plain copy
for(i=0; i<h; i++) {
memcpy(&pict.planes[0][i*w], &y[i*y_byte_per_row], w);
if (down_scale) {
for(j=0 ; j<w;j++) {
pict.planes[0][i*w+j] = y[i*2*y_byte_per_row+j*2];
}
} else {
memcpy(&pict.planes[0][i*w], &y[i*y_byte_per_row], w);
}
}
// de-interlace u/v
for (i=0; i<uv_h; i++) {
for(j=0; j<uv_w; j++) {
*u_dest++ = cbcr[cbcr_byte_per_row*i + 2*j];
*v_dest++ = cbcr[cbcr_byte_per_row*i + 2*j + 1];
*u_dest++ = cbcr[cbcr_byte_per_row*i*factor + 2*j*factor];
*v_dest++ = cbcr[cbcr_byte_per_row*i*factor + 2*j*factor + 1];
}
}
}
......@@ -741,18 +733,19 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
deinterlace_down_scale_and_rotate_180_neon(y, cbcr, pict.planes[0], u_dest, v_dest, w, h, y_byte_per_row, cbcr_byte_per_row,down_scale);
} else
#endif
{
{
// 180° y rotation
ysrc=y;
ydst=&pict.planes[0][h*w-1];
for(i=0; i<h*w; i++) {
*ydst-- = *ysrc++;
for(i=0; i<h; i++) {
for(j=0 ; j<w;j++) {
pict.planes[0][i*w+j] = y[(h-1-i)*y_byte_per_row*factor+(w-1-j)*factor];
}
}
// 180° rotation + de-interlace u/v
uvsrc=&cbcr[uv_h*uv_w*2-2];
for (i=0; i<uv_h*uv_w; i++) {
*u_dest++ = *uvsrc--;
*v_dest++ = *uvsrc--;
for (i=0; i<uv_h; i++) {
for(j=0; j<uv_w; j++) {
*u_dest++ = cbcr[cbcr_byte_per_row*(uv_h-1-i)*factor + 2*(uv_w-1-j)*factor];
*v_dest++ = cbcr[cbcr_byte_per_row*(uv_h-1-i)*factor + 2*(uv_w-1-j)*factor + 1];
}
}
}
}
......@@ -771,7 +764,7 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
{
uint8_t* dsty = pict.planes[0];
uint8_t* srcy = (uint8_t*) y;
rotate_plane(w,h,y_byte_per_row,srcy,dsty,1, clockwise);
rotate_plane_down_scale_by_2(w,h,y_byte_per_row,srcy,dsty,1, clockwise, down_scale);
}
#if defined(__arm__)
......@@ -783,11 +776,11 @@ mblk_t *copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(MSYuvBu
// Copying U
srcu = cbcr;
dstu = pict.planes[1];
rotate_plane(uv_w,uv_h,cbcr_byte_per_row/2,srcu,dstu, 2, clockwise);
rotate_plane_down_scale_by_2(uv_w,uv_h,cbcr_byte_per_row/2,srcu,dstu, 2, clockwise, down_scale);
// Copying V
srcv = srcu + 1;
dstv = pict.planes[2];
rotate_plane(uv_w,uv_h,cbcr_byte_per_row/2,srcv,dstv, 2, clockwise);
rotate_plane_down_scale_by_2(uv_w,uv_h,cbcr_byte_per_row/2,srcv,dstv, 2, clockwise,down_scale);
}
}
......
......@@ -61,9 +61,10 @@ static void filter_register_tester(void) {
}
#ifdef VIDEO_ENABLED
static void test_video_processing (void) {
static void test_video_processing_base (bool_t downscaling,bool_t rotate_clock_wise,bool_t flip) {
MSVideoSize src_size = { MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H };
MSVideoSize src_dest = { MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H };
MSVideoSize dest_size = src_size;
mblk_t * yuv_block2;
YuvBuf yuv;
int y_bytes_per_row = src_size.width + src_size.width%32 ;
......@@ -72,7 +73,21 @@ static void test_video_processing (void) {
uint8_t* cbcr = (uint8_t*)ms_malloc(crcb_bytes_per_row*src_size.height);
int i,j;
MSYuvBufAllocator *yba = ms_yuv_buf_allocator_new();
int factor=downscaling?2:1;
int rotation = 0;
if (rotate_clock_wise && flip) {
ms_fatal("fix you test");
}
if (rotate_clock_wise) {
rotation = 90;
dest_size.height=src_size.width;
dest_size.width=src_size.height;
} else if (flip) {
rotation = 180;
}
dest_size.height = dest_size.height/factor;
dest_size.width=dest_size.width/factor;
for (i=0;i<src_size.height*src_size.width;i++) {
y[i]=i%256;
}
......@@ -82,46 +97,101 @@ static void test_video_processing (void) {
yuv_block2 = copy_ycbcrbiplanar_to_true_yuv_with_rotation_and_down_scale_by_2(yba, y
,cbcr
,0
, src_size.width
, src_size.height
,rotation
, dest_size.width
, dest_size.height
, y_bytes_per_row
, crcb_bytes_per_row
, 1
, 0);
, downscaling);
BC_ASSERT_FALSE(ms_yuv_buf_init_from_mblk(&yuv, yuv_block2));
BC_ASSERT_EQUAL(dest_size.width,yuv.w, int, "%d");
BC_ASSERT_EQUAL(dest_size.height,yuv.h, int, "%d");
BC_ASSERT_EQUAL(src_dest.width,yuv.w, int, "%d");
BC_ASSERT_EQUAL(src_dest.height,yuv.h, int, "%d");
/*check y*/
for (i=0;i<yuv.h;i++) {
for (j=0;j<yuv.w;j++)
if (yuv.planes[0][i*yuv.strides[0]+j] != y[i*y_bytes_per_row+j]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[0][i*yuv.strides[0]+j],i*yuv.strides[0]+j,y[i*y_bytes_per_row+j]);
BC_FAIL("bad y value");
break;
if (rotate_clock_wise) {
/*check y*/
for (i=0;i<yuv.h;i++) {
for (j=0;j<yuv.w;j++)
if (yuv.planes[0][i*yuv.strides[0]+j] != y[(yuv.w-1-j)*factor*y_bytes_per_row+i*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[0][i*yuv.strides[0]+j],i*yuv.strides[0]+j,y[(yuv.w-1-j)*factor*y_bytes_per_row+i*factor]);
BC_FAIL("bad y value");
break;
}
}
}
/*check cb*/
for (i=0;i<yuv.h/2;i++) {
for (j=0;j<yuv.w/2;j++)
if (yuv.planes[1][i*yuv.strides[1]+j] != cbcr[i*crcb_bytes_per_row+2*j]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[1][i*yuv.strides[1]+j],i*yuv.strides[1]+j,y[i*crcb_bytes_per_row+2*j]);
BC_FAIL("bad cb value");
break;
/*check cb*/
for (i=0;i<yuv.h/2;i++) {
for (j=0;j<yuv.w/2;j++) {
if (yuv.planes[1][i*yuv.strides[1]+j] != cbcr[(yuv.w/2-1-j)*factor*crcb_bytes_per_row+2*i*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[1][i*yuv.strides[1]+j],i*yuv.strides[1]+j,cbcr[(yuv.w/2-1-j)*factor*crcb_bytes_per_row+2*i*factor]);
BC_FAIL("bad cb value");
break;
}
if (yuv.planes[2][i*yuv.strides[2]+j] != cbcr[(yuv.w/2-1-j)*factor*crcb_bytes_per_row+2*i*factor+1]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[2][i*yuv.strides[2]+j],i*yuv.strides[2]+j,cbcr[(yuv.w/2-1-j)*factor*crcb_bytes_per_row+2*i*factor+1]);
BC_FAIL("bad cr value");
break;
}
}
}
} else if (flip) {
/*check y*/
for (i=0;i<yuv.h;i++) {
for (j=0;j<yuv.w;j++)
if (yuv.planes[0][i*yuv.strides[0]+j] != y[(yuv.h-1-i)*factor*y_bytes_per_row+(yuv.w-1-j)*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[0][i*yuv.strides[0]+j],i*yuv.strides[0]+j,y[(yuv.h-1-i)*factor*y_bytes_per_row+(yuv.w-1-j)*factor]);
BC_FAIL("bad y value");
break;
}
}
for (i=0;i<yuv.h/2;i++) {
for (j=0;j<yuv.w/2;j++) {
/*check cb*/
if (yuv.planes[1][i*yuv.strides[1]+j] != cbcr[(yuv.h/2-1-i)*factor*crcb_bytes_per_row+2*(yuv.w/2-1-j)*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[1][i*yuv.strides[1]+j],i*yuv.strides[1]+j,cbcr[(yuv.h/2-1-i)*factor*crcb_bytes_per_row+2*(yuv.w/2-1-j)*factor]);
BC_FAIL("bad cb value");
break;
}
/*check cr*/
if (yuv.planes[2][i*yuv.strides[2]+j] != cbcr[(yuv.h/2-1-i)*factor*crcb_bytes_per_row+2*(yuv.w/2-1-j)*factor+1]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[2][i*yuv.strides[2]+j],i*yuv.strides[2]+j,cbcr[(yuv.h/2-1-i)*factor*crcb_bytes_per_row+2*(yuv.w/2-1-j)*factor+1]);
BC_FAIL("bad cr value");
break;
}
}
}
}
else {
/*check y*/
for (i=0;i<yuv.h;i++) {
for (j=0;j<yuv.w;j++)
if (yuv.planes[0][i*yuv.strides[0]+j] != y[i*factor*y_bytes_per_row+j*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[0][i*yuv.strides[0]+j],i*yuv.strides[0]+j,y[i*factor*y_bytes_per_row+j*factor]);
BC_FAIL("bad y value");
break;
}
}
for (i=0;i<yuv.h/2;i++) {
for (j=0;j<yuv.w/2;j++) {
/*check cb*/
if (yuv.planes[1][i*yuv.strides[1]+j] != cbcr[i*factor*crcb_bytes_per_row+2*j*factor]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[1][i*yuv.strides[1]+j],i*yuv.strides[1]+j,cbcr[i*factor*crcb_bytes_per_row+2*j*factor]);
BC_FAIL("bad cb value");
break;
}
/*check cr*/
if (yuv.planes[2][i*yuv.strides[2]+j] != cbcr[i*factor*crcb_bytes_per_row+2*j*factor+1]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[2][i*yuv.strides[2]+j],i*yuv.strides[2]+j,cbcr[i*factor*crcb_bytes_per_row+2*j*factor+1]);
BC_FAIL("bad cr value");
break;
}
/*check cr*/
for (i=0;i<yuv.h/2;i++) {
for (j=0;j<yuv.w/2;j++)
if (yuv.planes[2][i*yuv.strides[2]+j] != cbcr[i*crcb_bytes_per_row+2*j+1]) {
ms_error("Wrong value [%i] at ofset [%i], should be [%i]",yuv.planes[2][i*yuv.strides[2]+j],i*yuv.strides[2]+j,y[i*crcb_bytes_per_row+2*j+1]);
BC_FAIL("bad cr value");
break;
}
}
}
freemsg(yuv_block2);
......@@ -130,6 +200,30 @@ static void test_video_processing (void) {
ms_yuv_buf_allocator_free(yba);
}
static void test_video_processing () {
test_video_processing_base(FALSE,FALSE,FALSE);
}
static void test_copy_ycbcrbiplanar_to_true_yuv_with_downscaling () {
test_video_processing_base(TRUE,FALSE,FALSE);
}
static void test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_clock_wise() {
test_video_processing_base(FALSE,TRUE,FALSE);
}
static void test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_clock_wise_with_downscaling() {
test_video_processing_base(TRUE,TRUE,FALSE);
}
static void test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_180() {
test_video_processing_base(FALSE,FALSE,TRUE);
}
static void test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_180_with_downscaling() {
test_video_processing_base(TRUE,FALSE,TRUE);
}
#endif
static void test_is_multicast(void) {
......@@ -185,7 +279,12 @@ static test_t tests[] = {
{ "Is multicast", test_is_multicast},
{ "FilterDesc enabling/disabling", test_filterdesc_enable_disable},
#ifdef VIDEO_ENABLED
{ "Video processing function", test_video_processing}
{ "Video processing function", test_video_processing},
{ "Copy ycbcrbiplanar to true yuv with downscaling", test_copy_ycbcrbiplanar_to_true_yuv_with_downscaling},
{ "Copy ycbcrbiplanar to true yuv with rotation clock wise",test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_clock_wise},
{ "Copy ycbcrbiplanar to true yuv with rotation clock wise with downscaling",test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_clock_wise_with_downscaling},
{ "Copy ycbcrbiplanar to true yuv with rotation 180", test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_180},
{ "Copy ycbcrbiplanar to true yuv with rotation 180 with downscaling", test_copy_ycbcrbiplanar_to_true_yuv_with_rotation_180_with_downscaling}
#endif
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment