Files
veejay/veejay-current/libyuv/yuvconv.c
Niels Elburg 9d98c345a9 added dv1394 firewire support
git-svn-id: svn://code.dyne.org/veejay/trunk@197 eb8d1916-c9e9-0310-b8de-cf0c9472ead5
2005-02-21 15:27:00 +00:00

251 lines
5.7 KiB
C

/* veejay - Linux VeeJay
* (C) 2002-2004 Niels Elburg <nelburg@looze.net>
*
*
* 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 <config.h>
#include <stdint.h>
#include <libyuv/yuvconv.h>
/* 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 <lavtools@athos.cx>. 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;
}