/* veejay - Linux VeeJay * (C) 2002-2004 Niels Elburg * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include /* this routine is the same as frame_YUV422_to_YUV420P , unpack * libdv's 4:2:2-packed into 4:2:0 planar * See http://mjpeg.sourceforge.net/ (MJPEG Tools) (lav-common.c) */ void yuy2toyv12(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input, int width, int height) { int i, j, w2; uint8_t *y, *u, *v; w2 = width / 2; //I420 y = _y; v = _v; u = _u; for (i = 0; i < height; i += 4) { /* top field scanline */ for (j = 0; j < w2; j++) { /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ *(y++) = *(input++); *(u++) = *(input++); *(y++) = *(input++); *(v++) = *(input++); } for (j = 0; j < w2; j++) { *(y++) = *(input++); *(u++) = *(input++); *(y++) = *(input++); *(v++) = *(input++); } /* next two scanlines, one frome each field , interleaved */ for (j = 0; j < w2; j++) { /* skip every second line for U and V */ *(y++) = *(input++); input++; *(y++) = *(input++); input++; } /* bottom field scanline*/ for (j = 0; j < w2; j++) { /* skip every second line for U and V */ *(y++) = *(input++); input++; *(y++) = *(input++); input++; } } } void yuy2toyv16(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input, int width, int height) { int i, j, w2; uint8_t *y, *u, *v; w2 = width / 2; //YV16 y = _y; v = _v; u = _u; for (i = 0; i < height; i ++ ) { for (j = 0; j < w2; j++) { /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ *(y++) = *(input++); *(u++) = *(input++); *(y++) = *(input++); *(v++) = *(input++); } } } /* convert 4:2:0 to yuv 4:2:2 packed */ void yuv422p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width, int height) { unsigned int x, y; for (y = 0; y < height; ++y) { uint8_t *Y = yuv420[0] + y * width; uint8_t *Cb = yuv420[1] + (y / 2) * (width); uint8_t *Cr = yuv420[2] + (y / 2) * (width); for (x = 0; x < width; x +=2) { *(dest + 0) = Y[0]; *(dest + 1) = Cb[0]; *(dest + 2) = Y[1]; *(dest + 3) = Cr[0]; dest += 4; Y += 2; ++Cb; ++Cr; } } } /* convert 4:2:0 to yuv 4:2:2 */ void yuv420p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width, int height) { unsigned int x, y; for (y = 0; y < height; ++y) { uint8_t *Y = yuv420[0] + y * width; uint8_t *Cb = yuv420[1] + (y >> 1) * (width >> 1); uint8_t *Cr = yuv420[2] + (y >> 1) * (width >> 1); for (x = 0; x < width; x += 2) { *(dest + 0) = Y[0]; *(dest + 1) = Cb[0]; *(dest + 2) = Y[1]; *(dest + 3) = Cr[0]; dest += 4; Y += 2; ++Cb; ++Cr; } } } /* convert yuv422 planar to YUYV */ void yuv422_to_yuyv(uint8_t *yuv422[3], uint8_t *pixels, int w, int h) { int x,y; uint8_t *Y = yuv422[0]; uint8_t *U = yuv422[1]; uint8_t *V = yuv422[2]; // U Y V Y for(y = 0; y < h; y ++ ) { Y = yuv422[0] + y * w; U = yuv422[1] + (y>>1) * w; V = yuv422[2] + (y>>1) * w; /* for(x=0; x < w; x+= 2) { *(pixels + 0) = Y[0]; *(pixels + 1) = U[0]; *(pixels + 2) = Y[1]; *(pixels + 3) = V[0]; pixels += 4; Y+=2; ++U; ++V; } */ for( x = 0 ; x < w ; x += 4 ) { *(pixels + 0) = Y[0]; *(pixels + 1) = U[0]; *(pixels + 2) = Y[1]; *(pixels + 3) = V[0]; *(pixels + 4) = Y[2]; *(pixels + 5) = U[1]; *(pixels + 6) = Y[3]; *(pixels + 7) = V[1]; pixels += 8; Y+=4; U+=2; V+=2; } } } /* lav_common - some general utility functionality used by multiple lavtool utilities. */ /* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ /* - added scene change detection code 2001, pHilipp Zabel */ /* - broke some code out to lav_common.h and lav_common.c * July 2001, Shawn Sulma . In doing this, * I replaced the large number of globals with a handful of structs * that are passed into the appropriate methods. Check lav_common.h * for the structs. I'm sure some of what I've done is inefficient, * subtly incorrect or just plain Wrong. Feedback is welcome. */ /*********************** * * Take a random(ish) clipd mean of a frame luma and chroma * Its intended as a rough and ready hash of frame content. * The idea is that changes above a certain threshold are treated as * scene changes. * **********************/ int luminance_mean(uint8_t * frame[], int w, int h) { uint8_t *p; uint8_t *lim; int sum = 0; int count = 0; p = frame[0]; lim = frame[0] + w * (h - 1); while (p < lim) { sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); p += 31; count += 4; } w = w / 2; h = h / 2; p = frame[1]; lim = frame[1] + w * (h - 1); while (p < lim) { sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); p += 31; count += 4; } p = frame[2]; lim = frame[2] + w * (h - 1); while (p < lim) { sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); p += 31; count += 4; } return sum / count; }