This source file includes following definitions.
- get_yuv_base
- format_is_yuv
- is_planar_yuv
- write_yv12_to_yuv
- write_yuv422_to_yuv
- write_yuv444_to_yuv
- write_yvyu_to_yuv
- get_bpp
- rgb_to_24
- rgb_to_555
- rgb_to_565
- rgb_to_32
- dx_copy_pixels
#include <gpac/setup.h>
#include <gpac/constants.h>
#include <gpac/color.h>
static u32 get_yuv_base(u32 in_pf)
{
switch (in_pf) {
case GF_PIXEL_I420:
case GF_PIXEL_IYUV:
case GF_PIXEL_YV12:
return GF_PIXEL_YV12;
case GF_PIXEL_Y422:
case GF_PIXEL_UYNV:
case GF_PIXEL_UYVY:
return GF_PIXEL_UYVY;
case GF_PIXEL_YUNV:
case GF_PIXEL_V422:
case GF_PIXEL_YUY2:
return GF_PIXEL_YUY2;
case GF_PIXEL_YVYU:
return GF_PIXEL_YVYU;
case GF_PIXEL_YV12_10:
return GF_PIXEL_YV12_10;
case GF_PIXEL_YUV444:
return GF_PIXEL_YUV444;
case GF_PIXEL_YUV444_10:
return GF_PIXEL_YUV444_10;
case GF_PIXEL_YUV422_10:
return GF_PIXEL_YUV422_10;
case GF_PIXEL_YUV422:
return GF_PIXEL_YUV422;
default:
return 0;
}
}
static Bool format_is_yuv(u32 in_pf)
{
switch (in_pf) {
case GF_PIXEL_YUY2:
case GF_PIXEL_YVYU:
case GF_PIXEL_UYVY:
case GF_PIXEL_VYUY:
case GF_PIXEL_Y422:
case GF_PIXEL_UYNV:
case GF_PIXEL_YUNV:
case GF_PIXEL_V422:
case GF_PIXEL_YV12:
case GF_PIXEL_IYUV:
case GF_PIXEL_I420:
return GF_TRUE;
case GF_PIXEL_YUVA:
default:
return GF_FALSE;
}
}
static Bool is_planar_yuv(u32 pf)
{
switch (pf) {
case GF_PIXEL_YV12:
case GF_PIXEL_I420:
case GF_PIXEL_IYUV:
return GF_TRUE;
}
return GF_FALSE;
}
static void write_yv12_to_yuv(GF_VideoSurface *vs, unsigned char *pY, u32 src_stride, u32 src_pf,
u32 src_width, u32 src_height, const GF_Window *src_wnd, u8 *pU, u8 *pV)
{
if (!pU) {
pU = pY + src_stride * src_height;
pV = pY + 5*src_stride * src_height/4;
}
pY = pY + src_stride * src_wnd->y + src_wnd->x;
pU = pU + (src_stride * (src_wnd->y / 2) + src_wnd->x) / 2;
pV = pV + (src_stride * (src_wnd->y / 2) + src_wnd->x) / 2;
if (is_planar_yuv(vs->pixel_format)) {
if ( (vs->pitch_y == (s32) src_stride) && (src_wnd->w == src_width) && (src_wnd->h == src_height)) {
assert(!src_wnd->x);
assert(!src_wnd->y);
memcpy(vs->video_buffer, pY, sizeof(unsigned char)*src_width*src_height);
if (vs->pixel_format == GF_PIXEL_YV12) {
memcpy(vs->video_buffer + vs->pitch_y * vs->height, pV, sizeof(unsigned char)*src_width*src_height/4);
memcpy(vs->video_buffer + 5 * vs->pitch_y * vs->height/4, pU, sizeof(unsigned char)*src_width*src_height/4);
} else {
memcpy(vs->video_buffer + vs->pitch_y * vs->height, pU, sizeof(unsigned char)*src_width*src_height/4);
memcpy(vs->video_buffer + 5 * vs->pitch_y * vs->height/4, pV, sizeof(unsigned char)*src_width*src_height/4);
}
} else {
u32 i;
unsigned char *dst, *src, *dst2, *src2, *dst3, *src3;
src = pY;
dst = (unsigned char*)vs->video_buffer;
src2 = (vs->pixel_format != GF_PIXEL_YV12) ? pU : pV;
dst2 = (unsigned char*)vs->video_buffer + vs->pitch_y * vs->height;
src3 = (vs->pixel_format != GF_PIXEL_YV12) ? pV : pU;
dst3 = (unsigned char*)vs->video_buffer + 5*vs->pitch_y * vs->height/4;
for (i=0; i<src_wnd->h; i++) {
memcpy(dst, src, src_wnd->w);
src += src_stride;
dst += vs->pitch_y;
if (i<src_wnd->h/2) {
memcpy(dst2, src2, src_wnd->w/2);
src2 += src_stride/2;
dst2 += vs->pitch_y/2;
memcpy(dst3, src3, src_wnd->w/2);
src3 += src_stride/2;
dst3 += vs->pitch_y/2;
}
}
}
} else if (get_yuv_base(vs->pixel_format)==GF_PIXEL_UYVY) {
u32 i, j;
unsigned char *dst, *y, *u, *v;
for (i=0; i<src_wnd->h; i++) {
y = pY + i*src_stride;
u = pU + (i/2) * src_stride/2;
v = pV + (i/2) * src_stride/2;
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
for (j=0; j<src_wnd->w/2; j++) {
*dst = *u;
dst++;
u++;
*dst = *y;
dst++;
y++;
*dst = *v;
dst++;
v++;
*dst = *y;
dst++;
y++;
}
}
} else if (get_yuv_base(vs->pixel_format)==GF_PIXEL_YUY2) {
u32 i, j;
unsigned char *dst, *y, *u, *v;
for (i=0; i<src_wnd->h; i++) {
y = pY + i*src_stride;
u = pU + (i/2) * src_stride/2;
v = pV + (i/2) * src_stride/2;
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
for (j=0; j<src_wnd->w/2; j++) {
*dst = *y;
dst++;
y++;
*dst = *u;
dst++;
u++;
*dst = *y;
dst++;
y++;
*dst = *v;
dst++;
v++;
}
}
} else if (vs->pixel_format==GF_PIXEL_YVYU) {
u32 i, j;
unsigned char *dst, *y, *u, *v;
for (i=0; i<src_wnd->h; i++) {
y = pY + i*src_stride;
u = pU + (i/2) * src_stride/2;
v = pV + (i/2) * src_stride/2;
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
for (j=0; j<src_wnd->w/2; j++) {
*dst = *y;
dst++;
y++;
*dst = *v;
dst++;
v++;
*dst = *y;
dst++;
y++;
*dst = *u;
dst++;
u++;
}
}
}
}
static void write_yuv422_to_yuv(GF_VideoSurface *vs, unsigned char *pY, u32 src_stride, u32 src_pf,
u32 src_width, u32 src_height, const GF_Window *src_wnd, u8 *pU, u8 *pV)
{
if (!pU) {
pU = pY + src_stride * src_height;
pV = pY + 3 * src_stride * src_height/2;
}
pY = pY + src_stride * src_wnd->y + src_wnd->x;
pU = pU + (src_stride * src_wnd->y + src_wnd->x)/2;
pV = pV + (src_stride *src_wnd->y + src_wnd->x)/2;
if (is_planar_yuv(vs->pixel_format)) {
u32 i;
unsigned char *dst, *src, *dst2, *src2, *dst3, *src3, *_src2, *_src3;
src = pY;
_src2 = (vs->pixel_format != GF_PIXEL_YV12) ? pU : pV;
_src3 = (vs->pixel_format != GF_PIXEL_YV12) ? pV : pU;
dst = (unsigned char*)vs->video_buffer;
dst2 = (unsigned char*)vs->video_buffer + vs->pitch_y * vs->height;
dst3 = (unsigned char*)vs->video_buffer + 5 * vs->pitch_y * vs->height / 4 ;
for (i = 0; i<src_wnd->h; i++) {
memcpy(dst, src, src_wnd->w);
src += src_stride;
dst += vs->pitch_y;
if (i < src_wnd->h / 2)
{
src2 = _src2 + i*src_stride;
src3 = _src3 + i*src_stride;
memcpy(dst2, src2, src_wnd->w / 2);
memcpy(dst3, src3, src_wnd->w / 2);
dst2 += vs->pitch_y / 2;
dst3 += vs->pitch_y / 2;
}
}
}
}
static void write_yuv444_to_yuv(GF_VideoSurface *vs, unsigned char *pY, u32 src_stride, u32 src_pf,
u32 src_width, u32 src_height, const GF_Window *src_wnd, u8 *pU, u8 *pV)
{
if (!pU) {
pU = pY + src_stride * src_height;
pV = pY + 2 * src_stride * src_height ;
}
pY = pY + src_stride * src_wnd->y + src_wnd->x;
pU = pU + src_stride * src_wnd->y + src_wnd->x;
pV = pV + src_stride *src_wnd->y + src_wnd->x;
if (is_planar_yuv(vs->pixel_format)) {
u32 i,j;
unsigned char *dst, *src, *dst2, *src2, *dst3, *src3,*_src2,*_src3;
src = pY;
_src2 = (vs->pixel_format != GF_PIXEL_YV12) ? pU : pV;
_src3 = (vs->pixel_format != GF_PIXEL_YV12) ? pV : pU;
dst = (unsigned char*)vs->video_buffer;
for (i = 0; i<src_wnd->h; i++) {
memcpy(dst, src, src_wnd->w);
src += src_stride;
dst += vs->pitch_y;
}
for (i = 0; i < src_wnd->h / 2; i++) {
src2 = _src2 + 2*i*src_stride ;
dst2 = (unsigned char*)vs->video_buffer + vs->pitch_y * vs->height + i* vs->pitch_y / 2;
src3 = _src3 + 2*i*src_stride;
dst3 = (unsigned char*)vs->video_buffer + 5 * vs->pitch_y * vs->height / 4 + i* vs->pitch_y / 2;
for (j = 0; j<src_wnd->w/2; j++) {
*dst2 = *src2;
dst2++;
src2 += 2;
*dst3 = *src3;
dst3++;
src3 += 2;
}
}
}
}
static void write_yvyu_to_yuv(GF_VideoSurface *vs, unsigned char *src, u32 src_stride, u32 src_pf,
u32 src_width, u32 src_height, const GF_Window *src_wnd)
{
u32 i, j, base_pf;
unsigned char *pY, *pU, *pV;
switch (get_yuv_base(src_pf) ) {
case GF_PIXEL_UYVY:
pU = src + src_stride * src_wnd->y + src_wnd->x;
pY = src + src_stride * src_wnd->y + src_wnd->x + 1;
pV = src + src_stride * src_wnd->y + src_wnd->x + 3;
break;
case GF_PIXEL_YUY2:
pY = src + src_stride * src_wnd->y + src_wnd->x;
pU = src + src_stride * src_wnd->y + src_wnd->x + 1;
pV = src + src_stride * src_wnd->y + src_wnd->x + 3;
break;
case GF_PIXEL_YVYU:
pY = src + src_stride * src_wnd->y + src_wnd->x;
pV = src + src_stride * src_wnd->y + src_wnd->x + 1;
pU = src + src_stride * src_wnd->y + src_wnd->x + 3;
break;
default:
return;
}
if (is_planar_yuv(vs->pixel_format)) {
u32 i, j;
unsigned char *dst_y, *dst_u, *dst_v;
dst_y = (unsigned char*)vs->video_buffer;
if (vs->pixel_format == GF_PIXEL_YV12) {
dst_v = (unsigned char*)vs->video_buffer + vs->pitch_y * vs->height;
dst_u = (unsigned char*)vs->video_buffer + 5*vs->pitch_y * vs->height/4;
} else {
dst_u = (unsigned char*)vs->video_buffer + vs->pitch_y * vs->height;
dst_v = (unsigned char*)vs->video_buffer + 5*vs->pitch_y * vs->height/4;
}
for (i=0; i<src_wnd->h; i++) {
for (j=0; j<src_wnd->w; j+=2) {
*dst_y = * pY;
*(dst_y+1) = * (pY+2);
dst_y += 2;
pY += 4;
if (i%2) continue;
*dst_u = (*pU + *(pU + src_stride)) / 2;
*dst_v = (*pV + *(pV + src_stride)) / 2;
dst_u++;
dst_v++;
pU += 4;
pV += 4;
}
if (i%2) {
pU += src_stride;
pV += src_stride;
}
}
return;
}
if (get_yuv_base(src_pf) == get_yuv_base(vs->pixel_format)) {
u32 i;
for (i=0; i<src_wnd->h; i++) {
char *dst = vs->video_buffer + i*vs->pitch_y;
pY = src + src_stride * (i+src_wnd->y) + src_wnd->x;
memcpy(dst, pY, sizeof(char)*2*src_wnd->w);
}
return;
}
base_pf = get_yuv_base(vs->pixel_format);
for (i=0; i<src_wnd->h; i++) {
char *dst = vs->video_buffer + i*vs->pitch_y;
char *y = (char*)pY + src_stride * i;
char *u = (char*)pU + src_stride * i;
char *v = (char*)pV + src_stride * i;
switch (base_pf) {
case GF_PIXEL_UYVY:
for (j=0; j<src_wnd->w; j+=2) {
dst[0] = *u;
dst[1] = *y;
dst[2] = *v;
dst[3] = *(y+2);
dst += 4;
y+=4;
u+=4;
v+=4;
}
break;
case GF_PIXEL_YVYU:
for (j=0; j<src_wnd->w; j+=2) {
dst[0] = *y;
dst[1] = *v;
dst[2] = *(y+2);
dst[3] = *u;
dst += 4;
y+=4;
u+=4;
v+=4;
}
break;
case GF_PIXEL_YUY2:
for (j=0; j<src_wnd->w; j+=2) {
dst[0] = *y;
dst[1] = *u;
dst[2] = *(y+2);
dst[3] = *v;
dst += 4;
y+=4;
u+=4;
v+=4;
}
break;
}
}
}
u32 get_bpp(u32 pf)
{
switch (pf) {
case GF_PIXEL_RGB_555:
case GF_PIXEL_RGB_565:
return 2;
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
case GF_PIXEL_BGR_24:
return 3;
case GF_PIXEL_RGB_32:
case GF_PIXEL_BGR_32:
case GF_PIXEL_ARGB:
case GF_PIXEL_RGBAS:
case GF_PIXEL_RGBD:
case GF_PIXEL_RGBDS:
return 4;
}
return 0;
}
void rgb_to_24(GF_VideoSurface *vs, unsigned char *src, u32 src_stride, u32 src_w, u32 src_h, u32 src_pf, const GF_Window *src_wnd)
{
u32 i;
u32 BPP = get_bpp(src_pf);
if (!BPP) return;
src += src_stride*src_wnd->y + BPP * src_wnd->x;
if (src_pf==vs->pixel_format) {
for (i=0; i<src_wnd->h; i++) {
memcpy(vs->video_buffer + i*vs->pitch_y, src, sizeof(unsigned char) * BPP * src_wnd->w);
src += src_stride;
}
return;
}
}
void rgb_to_555(GF_VideoSurface *vs, unsigned char *src, u32 src_stride, u32 src_w, u32 src_h, u32 src_pf, const GF_Window *src_wnd)
{
u32 i, j, r, g, b;
u32 BPP = get_bpp(src_pf);
unsigned char *dst, *cur;
if (!BPP) return;
src += src_stride*src_wnd->y + BPP * src_wnd->x;
if (src_pf==vs->pixel_format) {
for (i=0; i<src_wnd->h; i++) {
memcpy(vs->video_buffer + i*vs->pitch_y, src, sizeof(unsigned char) * BPP * src_wnd->w);
}
return;
}
switch (src_pf) {
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
r = *cur++;
g = *cur++;
b = *cur++;
* ((unsigned short *)dst) = GF_COL_555(r, g, b);
dst += 2;
}
}
break;
}
}
void rgb_to_565(GF_VideoSurface *vs, unsigned char *src, u32 src_stride, u32 src_w, u32 src_h, u32 src_pf, const GF_Window *src_wnd)
{
u32 i, j, r, g, b;
u32 BPP = get_bpp(src_pf);
unsigned char *dst, *cur;
if (!BPP) return;
src += src_stride*src_wnd->y + BPP * src_wnd->x;
if (src_pf==vs->pixel_format) {
for (i=0; i<src_wnd->h; i++) {
memcpy(vs->video_buffer + i*vs->pitch_y, src, sizeof(unsigned char) * BPP * src_wnd->w);
}
return;
}
switch (src_pf) {
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
r = *cur++;
g = *cur++;
b = *cur++;
* ((unsigned short *)dst) = GF_COL_565(r, g, b);
dst += 2;
}
}
break;
}
}
void rgb_to_32(GF_VideoSurface *vs, unsigned char *src, u32 src_stride, u32 src_w, u32 src_h, u32 src_pf, const GF_Window *src_wnd)
{
u32 i, j;
Bool isBGR;
u32 BPP = get_bpp(src_pf);
unsigned char *dst, *cur;
if (!BPP) return;
src += src_stride*src_wnd->y + BPP * src_wnd->x;
if (src_pf==vs->pixel_format) {
for (i=0; i<src_wnd->h; i++) {
memcpy(vs->video_buffer + i*vs->pitch_y, src, sizeof(unsigned char) * BPP * src_wnd->w);
}
return;
}
isBGR = (vs->pixel_format==GF_PIXEL_BGR_32) ? GF_TRUE : GF_FALSE;
if (isBGR) {
switch (src_pf) {
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[0] = *cur++;
dst[1] = *cur++;
dst[2] = *cur++;
dst += 4;
}
}
break;
case GF_PIXEL_RGBDS:
case GF_PIXEL_RGBD:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[0] = *cur++;
dst[1] = *cur++;
dst[2] = *cur++;
cur++;
dst += 4;
}
}
break;
case GF_PIXEL_BGR_24:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[2] = *cur++;
dst[1] = *cur++;
dst[0] = *cur++;
dst += 4;
}
}
break;
}
} else {
switch (src_pf) {
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[2] = *cur++;
dst[1] = *cur++;
dst[0] = *cur++;
dst += 4;
}
}
break;
case GF_PIXEL_RGBD:
case GF_PIXEL_RGBDS:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[2] = *cur++;
dst[1] = *cur++;
dst[0] = *cur++;
cur++;
dst += 4;
}
}
break;
case GF_PIXEL_BGR_24:
for (i=0; i<src_wnd->h; i++) {
dst = (unsigned char*)vs->video_buffer + i*vs->pitch_y;
cur = src + i*src_stride;
for (j=0; j<src_wnd->w; j++) {
dst[0] = *cur++;
dst[1] = *cur++;
dst[2] = *cur++;
dst += 4;
}
}
break;
}
}
}
void dx_copy_pixels(GF_VideoSurface *dst_s, const GF_VideoSurface *src_s, const GF_Window *src_wnd)
{
if (get_yuv_base(src_s->pixel_format)==GF_PIXEL_YV12) {
if (format_is_yuv(dst_s->pixel_format)) {
write_yv12_to_yuv(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->pixel_format, src_s->width, src_s->height, src_wnd, src_s->u_ptr, src_s->v_ptr);
return;
}
} else if (get_yuv_base(src_s->pixel_format)==GF_PIXEL_YV12_10) {
if (format_is_yuv(dst_s->pixel_format)) {
gf_color_write_yv12_10_to_yuv(dst_s, src_s->video_buffer, src_s->u_ptr, src_s->v_ptr, src_s->pitch_y, src_s->width, src_s->height, src_wnd, 1);
return;
}
}
else if (get_yuv_base(src_s->pixel_format) == GF_PIXEL_YUV444) {
if (format_is_yuv(dst_s->pixel_format)) {
write_yuv444_to_yuv(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->pixel_format, src_s->width, src_s->height, src_wnd, src_s->u_ptr, src_s->v_ptr);
return;
}
}
else if (get_yuv_base(src_s->pixel_format) == GF_PIXEL_YUV422) {
if (format_is_yuv(dst_s->pixel_format)) {
write_yuv422_to_yuv(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->pixel_format, src_s->width, src_s->height, src_wnd, src_s->u_ptr, src_s->v_ptr);
return;
}
}
else if (get_yuv_base(src_s->pixel_format) == GF_PIXEL_YUV422_10) {
if (format_is_yuv(dst_s->pixel_format)) {
gf_color_write_yuv422_10_to_yuv(dst_s, src_s->video_buffer, src_s->u_ptr, src_s->v_ptr, src_s->pitch_y, src_s->width, src_s->height, src_wnd, 1);
return;
}
}
else if (get_yuv_base(src_s->pixel_format) == GF_PIXEL_YUV444_10) {
if (format_is_yuv(dst_s->pixel_format)) {
gf_color_write_yuv444_10_to_yuv(dst_s, src_s->video_buffer, src_s->u_ptr, src_s->v_ptr, src_s->pitch_y, src_s->width, src_s->height, src_wnd, 1);
return;
}
}
else if (format_is_yuv(src_s->pixel_format)) {
if (format_is_yuv(dst_s->pixel_format)) {
write_yvyu_to_yuv(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->pixel_format, src_s->width, src_s->height, src_wnd);
return;
}
} else {
switch (dst_s->pixel_format) {
case GF_PIXEL_RGB_555:
rgb_to_555(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->width, src_s->height, src_s->pixel_format, src_wnd);
return;
case GF_PIXEL_RGB_565:
rgb_to_565(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->width, src_s->height, src_s->pixel_format, src_wnd);
return;
case GF_PIXEL_RGB_24:
case GF_PIXEL_RGBS:
case GF_PIXEL_BGR_24:
rgb_to_24(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->width, src_s->height, src_s->pixel_format, src_wnd);
return;
case GF_PIXEL_RGB_32:
case GF_PIXEL_RGBD:
case GF_PIXEL_RGBDS:
case GF_PIXEL_BGR_32:
rgb_to_32(dst_s, src_s->video_buffer, src_s->pitch_y, src_s->width, src_s->height, src_s->pixel_format, src_wnd);
return;
}
}
gf_stretch_bits(dst_s, (GF_VideoSurface*) src_s, NULL, (GF_Window *)src_wnd, 0xFF, GF_FALSE, NULL, NULL);
}