You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
902 lines
28 KiB
902 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1998 Philips B.V. CE - I&C
|
|
|
|
Module Name:
|
|
|
|
mcodec.c
|
|
|
|
Abstract:
|
|
|
|
this module converts the raw USB data to video data.
|
|
|
|
Original Author:
|
|
|
|
Ronald v.d.Meer
|
|
|
|
Environment:
|
|
|
|
Kernel mode only
|
|
|
|
|
|
Revision History:
|
|
|
|
Date Reason
|
|
14-04-1998 Initial version
|
|
--*/
|
|
|
|
#include "wdm.h"
|
|
#include "mcamdrv.h"
|
|
#include "mstreams.h"
|
|
#include "mdecoder.h"
|
|
#include "mcodec.h"
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* START DEFINES
|
|
*
|
|
******************************************************************************/
|
|
|
|
#define NO_BANDS_CIF (CIF_Y / 4) /* Number of YUV bands per frame */
|
|
#define NO_BANDS_SIF (SIF_Y / 4) /* Number of YUV bands per frame */
|
|
#define NO_BANDS_SSIF (SSIF_Y / 4) /* Number of YUV bands per frame */
|
|
#define NO_BANDS_SCIF (SCIF_Y / 4) /* Number of YUV bands per frame */
|
|
|
|
#define NO_LINES_IN_BAND 4
|
|
|
|
/*
|
|
* one line contains "Width * 3/2" bytes (12 bits per pixel)
|
|
* one YYYYCC block is 6 bytes
|
|
* NO_YYYYCC_PER_LINE = (Width * 3/2 / 6) = (Width / 4)
|
|
*/
|
|
#define NO_YYYYCC_PER_LINE(width) (width >> 2)
|
|
|
|
#define QQCIF_DY ((SQCIF_Y - QQCIF_Y) / 2)
|
|
#define QQCIF_DX ((SQCIF_X - QQCIF_X) / 2)
|
|
|
|
#define SQSIF_DY ((SQCIF_Y - SQSIF_Y) / 2)
|
|
#define SQSIF_DX ((SQCIF_X - SQSIF_X) / 2)
|
|
|
|
#define QSIF_DY (( QCIF_Y - QSIF_Y) / 2)
|
|
#define QSIF_DX (( QCIF_X - QSIF_X) / 2)
|
|
|
|
#define SSIF_DY (( CIF_Y - SSIF_Y) / 2)
|
|
#define SSIF_DX (( CIF_X - SSIF_X) / 2)
|
|
|
|
#define SIF_DY (( CIF_Y - SIF_Y) / 2)
|
|
#define SIF_DX (( CIF_X - SIF_X) / 2)
|
|
|
|
#define SCIF_DY (( CIF_Y - SCIF_Y) / 2)
|
|
#define SCIF_DX (( CIF_X - SCIF_X) / 2)
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* START STATIC VARIABLES
|
|
*
|
|
******************************************************************************/
|
|
|
|
static WORD FixGreenbarArray[CIF_Y][4];
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* START STATIC METHODS DECLARATIONS
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
static void TranslateP420ToI420 (PBYTE pInput, PBYTE pOutput, int w, int h,
|
|
DWORD camVersion);
|
|
|
|
extern void TranslatePCFxToI420 (PBYTE pInput, PBYTE pOutput, int width,
|
|
int height, DWORD camVersion);
|
|
|
|
#ifdef PIX12_FIX
|
|
static void FixPix12InI420 (PBYTE p, BOOLEAN Compress, int w, int h,
|
|
DWORD camVersion);
|
|
#endif
|
|
|
|
static void Fix16PixGreenbarInI420 (PBYTE pStart, int w);
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* START EXPORTED METHODS DEFINITIONS
|
|
*
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* This routine is called at selection of a new stream
|
|
*/
|
|
|
|
extern NTSTATUS
|
|
PHILIPSCAM_DecodeUsbData (PPHILIPSCAM_DEVICE_CONTEXT DeviceContext,
|
|
PUCHAR FrameBuffer,
|
|
ULONG FrameLength,
|
|
PUCHAR RawFrameBuffer,
|
|
ULONG RawFrameLength)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
int width;
|
|
int height;
|
|
|
|
switch (DeviceContext->CamStatus.PictureFormat)
|
|
{
|
|
case FORMATCIF :
|
|
width = CIF_X;
|
|
height = CIF_Y;
|
|
break;
|
|
case FORMATQCIF :
|
|
width = QCIF_X;
|
|
height = QCIF_Y;
|
|
break;
|
|
case FORMATSQCIF :
|
|
width = SQCIF_X;
|
|
height = SQCIF_Y;
|
|
break;
|
|
case FORMATSIF :
|
|
width = SIF_X;
|
|
height = SIF_Y;
|
|
break;
|
|
case FORMATQSIF :
|
|
width = QSIF_X;
|
|
height = QSIF_Y;
|
|
break;
|
|
case FORMATSQSIF :
|
|
width = SQSIF_X;
|
|
height = SQSIF_Y;
|
|
break;
|
|
case FORMATQQCIF :
|
|
width = QQCIF_X;
|
|
height = QQCIF_Y;
|
|
break;
|
|
case FORMATSSIF :
|
|
width = SSIF_X;
|
|
height = SSIF_Y;
|
|
break;
|
|
case FORMATSCIF :
|
|
width = SCIF_X;
|
|
height = SCIF_Y;
|
|
break;
|
|
default : // VGA
|
|
width = VGA_X;
|
|
height = VGA_Y;
|
|
break;
|
|
}
|
|
|
|
|
|
if (DeviceContext->CamStatus.PictureCompressing == COMPRESSION0)
|
|
{
|
|
// convert Philips P420 format to Intel I420 format
|
|
TranslateP420ToI420 ((PBYTE) RawFrameBuffer, (PBYTE) FrameBuffer,
|
|
width, height,
|
|
DeviceContext->CamStatus.ReleaseNumber);
|
|
}
|
|
else
|
|
{
|
|
// convert Philips PCFx format to Intel I420 format
|
|
TranslatePCFxToI420 ((PBYTE) RawFrameBuffer, (PBYTE) FrameBuffer,
|
|
width, height,
|
|
DeviceContext->CamStatus.ReleaseNumber);
|
|
}
|
|
|
|
return (ntStatus);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
* This routine is called at selection of a new stream
|
|
*/
|
|
|
|
extern NTSTATUS
|
|
PHILIPSCAM_StartCodec (PPHILIPSCAM_DEVICE_CONTEXT DeviceContext)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
InitDecoder ();
|
|
|
|
if (DeviceContext->CamStatus.ReleaseNumber < SSI_8117_N3)
|
|
{
|
|
int line, pix;
|
|
|
|
for (line = 0; line < CIF_Y; line++)
|
|
{
|
|
for (pix = 0; pix < 4; pix++)
|
|
{
|
|
FixGreenbarArray[line][pix] = (WORD) 0x8080;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (ntStatus);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
* This routine is called after stopping a stream.
|
|
* Used resources have to be made free.
|
|
*/
|
|
|
|
extern NTSTATUS
|
|
PHILIPSCAM_StopCodec(PPHILIPSCAM_DEVICE_CONTEXT DeviceContext)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
return (ntStatus);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
* This routine is called by mprpobj.c to announce a framerate selection
|
|
* in CIF mode, eventually resulting in change from compressed <-> uncompressed.
|
|
*/
|
|
|
|
extern NTSTATUS
|
|
PHILIPSCAM_FrameRateChanged (PPHILIPSCAM_DEVICE_CONTEXT DeviceContext)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
return (ntStatus);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* START STATIC METHODS DEFINITIONS
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef PIX12_FIX
|
|
|
|
|
|
static void
|
|
FixPix12InI420 (PBYTE p, BOOLEAN Compress, int width, int height,
|
|
DWORD camVersion)
|
|
{
|
|
int line;
|
|
PBYTE pStart;
|
|
|
|
if (width == SQCIF_X)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// only QCIF and CIF have to be fixed
|
|
|
|
pStart = p;
|
|
|
|
if (Compress)
|
|
{
|
|
for (line = height; line > 0; line--)
|
|
{
|
|
*(p + 0) = *(p + 1);
|
|
*(p + 2) = *(p + 3);
|
|
|
|
p += width;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (line = height; line > 0; line--)
|
|
{
|
|
*(p + 0) = *(p + 1);
|
|
*(p + 1) = *(p + 2);
|
|
|
|
p += width;
|
|
}
|
|
|
|
p = pStart + I420_NO_Y (width, height);
|
|
|
|
width >>= 1;
|
|
|
|
if (camVersion >= SSI_PIX12_FIX)
|
|
{
|
|
for (line = height; line > 0; line--)
|
|
{
|
|
// First all U's then all V's
|
|
|
|
*(p + 0) = *(p + 1);
|
|
|
|
p += width;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (line = height; line > 0; line--)
|
|
{
|
|
// First all U's then all V's
|
|
|
|
*(p + 0) = *(p + 2);
|
|
*(p + 1) = *(p + 2);
|
|
|
|
p += width;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif // PIX12_FIX
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// In the 8117 silicum versions N2 and before, the CIF decompressed
|
|
// picture contains little green bars at the end of the picture.
|
|
// These greenbars are 16 pixels width and 4 pixels height.
|
|
// This bug is fixed in the 3rd silicium version of the 8117 (N3)
|
|
// UV components of last 16 pixels in line : YYYYUU YYYYUU YYYYUU YYYYUU
|
|
// YYYYVV YYYYVV YYYYVV YYYYVV
|
|
// This are 2 blocks
|
|
// Greenbar bug : all V's do have the same value.
|
|
// This value is less then 'VREF_VALUE'
|
|
// pU points to 1st UUUU block, pU + 1 points to 1st VVVV block
|
|
|
|
|
|
|
|
static void
|
|
Fix16PixGreenbarInI420 (PBYTE pStart, int width)
|
|
{
|
|
int line;
|
|
int band;
|
|
PWORD pU;
|
|
PWORD pV;
|
|
|
|
#define VREF_VALUE 0x40
|
|
#define C_INC (I420_NO_C_PER_LINE_CIF / sizeof (WORD))
|
|
|
|
/* point to start of last 8 V's of first band V line */
|
|
|
|
pU = (PWORD) ((PBYTE) pStart + I420_NO_Y_CIF + I420_NO_C_PER_LINE_CIF - 8);
|
|
pV = (PWORD) ((PBYTE) pStart + I420_NO_Y_CIF + I420_NO_U_CIF + I420_NO_C_PER_LINE_CIF - 8);
|
|
|
|
|
|
for (band = 0; band < NO_BANDS_CIF; band++)
|
|
{
|
|
line = band * 4;
|
|
|
|
/*
|
|
* band : UUUU UUUU ...
|
|
* UUUU UUUU ...
|
|
* VVVV VVVV ... --> check the last 8 V's for error condition
|
|
* VVVV VVVV ...
|
|
*
|
|
* V1V2 V3V4 V5V6 V7V8 (last V's in first BLOCK_BAND V line)
|
|
* all V's have to be the same value. This value is < VREF_VALUE
|
|
* If so, a green bar will be visible --> correct with last correct
|
|
* pixel information
|
|
*/
|
|
|
|
if ( (*(pV + 0) == *(pV + 1)) &&
|
|
(*(pV + 0) == *(pV + 2)) &&
|
|
(*(pV + 0) == *(pV + 3)) &&
|
|
((*(pV + 0) & 0x00FF) == (((*pV + 0) & 0xFF00) >> 8)) &&
|
|
((*(pV + 0) & 0x00FF) < VREF_VALUE))
|
|
{
|
|
*(pU + (C_INC * 0) + 0) = FixGreenbarArray[line + 0][0];
|
|
*(pU + (C_INC * 0) + 1) = FixGreenbarArray[line + 0][1];
|
|
*(pU + (C_INC * 0) + 2) = FixGreenbarArray[line + 0][2];
|
|
*(pU + (C_INC * 0) + 3) = FixGreenbarArray[line + 0][3];
|
|
|
|
*(pV + (C_INC * 0) + 0) = FixGreenbarArray[line + 1][0];
|
|
*(pV + (C_INC * 0) + 1) = FixGreenbarArray[line + 1][1];
|
|
*(pV + (C_INC * 0) + 2) = FixGreenbarArray[line + 1][2];
|
|
*(pV + (C_INC * 0) + 3) = FixGreenbarArray[line + 1][3];
|
|
|
|
*(pU + (C_INC * 1) + 0) = FixGreenbarArray[line + 2][0];
|
|
*(pU + (C_INC * 1) + 1) = FixGreenbarArray[line + 2][1];
|
|
*(pU + (C_INC * 1) + 2) = FixGreenbarArray[line + 2][2];
|
|
*(pU + (C_INC * 1) + 3) = FixGreenbarArray[line + 2][3];
|
|
|
|
*(pV + (C_INC * 1) + 0) = FixGreenbarArray[line + 3][0];
|
|
*(pV + (C_INC * 1) + 1) = FixGreenbarArray[line + 3][1];
|
|
*(pV + (C_INC * 1) + 2) = FixGreenbarArray[line + 3][2];
|
|
*(pV + (C_INC * 1) + 3) = FixGreenbarArray[line + 3][3];
|
|
}
|
|
else
|
|
{
|
|
FixGreenbarArray[line + 0][0] = *(pU + (C_INC * 0) + 0);
|
|
FixGreenbarArray[line + 0][1] = *(pU + (C_INC * 0) + 1);
|
|
FixGreenbarArray[line + 0][2] = *(pU + (C_INC * 0) + 2);
|
|
FixGreenbarArray[line + 0][3] = *(pU + (C_INC * 0) + 3);
|
|
|
|
FixGreenbarArray[line + 1][0] = *(pV + (C_INC * 0) + 0);
|
|
FixGreenbarArray[line + 1][1] = *(pV + (C_INC * 0) + 1);
|
|
FixGreenbarArray[line + 1][2] = *(pV + (C_INC * 0) + 2);
|
|
FixGreenbarArray[line + 1][3] = *(pV + (C_INC * 0) + 3);
|
|
|
|
FixGreenbarArray[line + 2][0] = *(pU + (C_INC * 1) + 0);
|
|
FixGreenbarArray[line + 2][1] = *(pU + (C_INC * 1) + 1);
|
|
FixGreenbarArray[line + 2][2] = *(pU + (C_INC * 1) + 2);
|
|
FixGreenbarArray[line + 2][3] = *(pU + (C_INC * 1) + 3);
|
|
|
|
FixGreenbarArray[line + 3][0] = *(pV + (C_INC * 1) + 0);
|
|
FixGreenbarArray[line + 3][1] = *(pV + (C_INC * 1) + 1);
|
|
FixGreenbarArray[line + 3][2] = *(pV + (C_INC * 1) + 2);
|
|
FixGreenbarArray[line + 3][3] = *(pV + (C_INC * 1) + 3);
|
|
}
|
|
|
|
pU += (2 * C_INC);
|
|
pV += (2 * C_INC);
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
static void
|
|
TranslateP420ToI420 (PBYTE pInput, PBYTE pOutput, int width, int height,
|
|
DWORD camVersion)
|
|
{
|
|
int line;
|
|
int byte;
|
|
int dxSrc;
|
|
|
|
PDWORD pdwSrc;
|
|
PDWORD pdwY;
|
|
PWORD pwU;
|
|
PWORD pwV;
|
|
|
|
PBYTE pbSrc;
|
|
PBYTE pbY;
|
|
|
|
|
|
if (camVersion == SSI_YGAIN_MUL2)
|
|
{
|
|
// SSI version 4 --> Ygain has to be doubled
|
|
|
|
pbSrc = (PBYTE) pInput;
|
|
pbY = (PBYTE) pOutput;
|
|
pwU = (PWORD) ((PBYTE) pbY + (width * height));
|
|
pwV = (PWORD) ((PBYTE) pwU + ((width * height) >> 2));
|
|
|
|
switch (width)
|
|
{
|
|
case SQSIF_X :
|
|
pbSrc += ((((SQSIF_DY * SQCIF_X) + SQSIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * SQSIF_DX) * 3) / 2;
|
|
break;
|
|
case QSIF_X :
|
|
pbSrc += ((((QSIF_DY * QCIF_X) + QSIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * QSIF_DX) * 3) / 2;
|
|
break;
|
|
case SIF_X :
|
|
pbSrc += ((((SIF_DY * CIF_X) + SIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * SIF_DX) * 3) / 2;
|
|
break;
|
|
case QQCIF_X :
|
|
pbSrc += ((((QQCIF_DY * SQCIF_X) + QQCIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * QQCIF_DX) * 3) / 2;
|
|
break;
|
|
case SSIF_X : // SSIF || SCIF
|
|
if (height == SSIF_Y) {
|
|
pbSrc += ((((SSIF_DY * CIF_X) + SSIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * SSIF_DX) * 3) / 2;
|
|
}else{
|
|
pbSrc += ((((SCIF_DY * CIF_X) + SCIF_DX) * 3) / 2);
|
|
dxSrc = ((2 * SCIF_DX) * 3) / 2;
|
|
}
|
|
break;
|
|
default : // xxCIF
|
|
dxSrc = 0;
|
|
break;
|
|
}
|
|
|
|
for (line = height >> 1; line > 0; line--)
|
|
{
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
|
|
*pwU++ = (WORD) (* (PWORD) pbSrc);
|
|
pbSrc += 2;
|
|
}
|
|
|
|
pbSrc += dxSrc;
|
|
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
*pbY++ = (*pbSrc < 0x7F) ? (*pbSrc << 1) : 0xFF;
|
|
pbSrc++;
|
|
|
|
*pwV++ = (WORD) (* (PWORD) pbSrc);
|
|
pbSrc += 2;
|
|
}
|
|
|
|
pbSrc += dxSrc;
|
|
}
|
|
}
|
|
else // NO_YGAIN_MULTIPLY
|
|
{
|
|
pdwY = (PDWORD) pOutput;
|
|
pwU = (PWORD) ((PBYTE) pdwY + (width * height));
|
|
pwV = (PWORD) ((PBYTE) pwU + ((width * height) >> 2));
|
|
|
|
if (width == QQCIF_X)
|
|
{
|
|
pbSrc = (PBYTE) (pInput + ((((QQCIF_DY * SQCIF_X) + QQCIF_DX) * 3) / 2));
|
|
dxSrc = ((2 * QQCIF_DX) * 3) / 2;
|
|
|
|
for (line = height >> 1; line > 0; line--)
|
|
{
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pdwY++ = *((PDWORD) pbSrc)++;
|
|
*pwU++ = (WORD) (* (PWORD) pbSrc);
|
|
pbSrc += 2;
|
|
}
|
|
|
|
pbSrc += dxSrc;
|
|
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pdwY++ = *((PDWORD) pbSrc)++;
|
|
*pwV++ = (WORD) (* (PWORD) pbSrc);
|
|
pbSrc += 2;
|
|
}
|
|
|
|
pbSrc += dxSrc;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pdwSrc = (PDWORD) pInput;
|
|
|
|
switch (width)
|
|
{
|
|
case SQSIF_X :
|
|
pdwSrc += (((((SQSIF_DY * SQCIF_X) + SQSIF_DX) * 3) / 2) / sizeof (DWORD));
|
|
dxSrc = (((2 * SQSIF_DX) * 3) / 2) / sizeof (DWORD);
|
|
break;
|
|
case QSIF_X :
|
|
pdwSrc += (((((QSIF_DY * QCIF_X) + QSIF_DX) * 3) / 2) / sizeof (DWORD));
|
|
dxSrc = (((2 * QSIF_DX) * 3) / 2) / sizeof (DWORD);
|
|
break;
|
|
case SIF_X :
|
|
pdwSrc += (((((SIF_DY * CIF_X) + SIF_DX) * 3) / 2) / sizeof (DWORD));
|
|
dxSrc = (((2 * SIF_DX) * 3) / 2) / sizeof (DWORD);
|
|
break;
|
|
case SSIF_X : // SSIF || SCIF
|
|
if (height == SSIF_Y) {
|
|
pdwSrc += (((((SSIF_DY * CIF_X) + SSIF_DX) * 3) / 2) / sizeof (DWORD));
|
|
dxSrc = (((2 * SSIF_DX) * 3) / 2) / sizeof (DWORD);
|
|
}else{
|
|
pdwSrc += (((((SCIF_DY * CIF_X) + SCIF_DX) * 3) / 2) / sizeof (DWORD));
|
|
dxSrc = (((2 * SCIF_DX) * 3) / 2) / sizeof (DWORD);
|
|
}
|
|
break;
|
|
default : // xxCIF
|
|
dxSrc = 0;
|
|
break;
|
|
}
|
|
|
|
for (line = height >> 1; line > 0; line--)
|
|
{
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pdwY++ = *pdwSrc++;
|
|
*pwU++ = (WORD) (* (PWORD) pdwSrc);
|
|
pdwSrc = (PDWORD) ((PBYTE) pdwSrc + 2);
|
|
}
|
|
|
|
pdwSrc += dxSrc;
|
|
|
|
for (byte = NO_YYYYCC_PER_LINE(width); byte > 0; byte--)
|
|
{
|
|
*pdwY++ = *pdwSrc++;
|
|
*pwV++ = (WORD) (* (PWORD) pdwSrc);
|
|
pdwSrc = (PDWORD) ((PBYTE) pdwSrc + 2);
|
|
}
|
|
|
|
pdwSrc += dxSrc;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef PIX12_FIX
|
|
if (width == CIF_X || width == QCIF_X || width == SQCIF_X)
|
|
{
|
|
FixPix12InI420 (pOutput, FALSE, width, height, camVersion);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
===========================================================================
|
|
*/
|
|
|
|
static void
|
|
TranslatePCFxToI420 (PBYTE pInput, PBYTE pOutput, int width, int height,
|
|
DWORD camVersion)
|
|
{
|
|
int band;
|
|
int line;
|
|
int byte;
|
|
PBYTE pSrc;
|
|
PDWORD pYDst;
|
|
PDWORD pCDst;
|
|
|
|
PDWORD pSIF_Y;
|
|
PDWORD pSIF_C;
|
|
/*
|
|
* For formats != 352x288, cropping has to be done.
|
|
* The formats 320x240 and 240x180 can be derived from the 352x288 format.
|
|
* The compressed data consists of 72 bands. A band contains the data for
|
|
* 4 uncompressed lines. For the not 352x240 formats, the first 6 bands or
|
|
* first 13 bands (320x240 or 240x180) of compressed data can be skipped.
|
|
* This will be the cropping in the Y-direction.
|
|
* One band is 528 bytes big for 4x compressed mode and 704 bytes big for
|
|
* 3x compressed mode. It's dependent of the camera version which
|
|
* compression mode will be selected.
|
|
* For the not 352x288 formats, the uncompressed data is temporary stored
|
|
* in the first not used bands.
|
|
* One uncompressed band consists of 4x352=1408 bytes of Y followed by
|
|
* 2x176=352 bytes of U and followed by 2x176 bytes of V.
|
|
* This is a total of 2112 uncompressed bytes. So there's enough place
|
|
* for this temporary storage (6x528-2112=1056 bytes left worst case)
|
|
* This temporary uncompressed data is then cropped in the X direction.
|
|
* The result is written to the buffer pointed by 'pOutput'
|
|
*/
|
|
|
|
if (width == CIF_X)
|
|
{
|
|
pSrc = pInput;
|
|
pYDst = (PDWORD) pOutput;
|
|
pCDst = (PDWORD) pOutput + (I420_NO_Y_CIF / sizeof (DWORD));
|
|
band = NO_BANDS_CIF;
|
|
}
|
|
else
|
|
{
|
|
pSrc = pInput;
|
|
pYDst = (PDWORD) pInput;
|
|
pCDst = (PDWORD) pInput + (I420_NO_Y_PER_BAND_CIF / sizeof (DWORD));
|
|
pSIF_Y = (PDWORD) pOutput;
|
|
|
|
if (width == SIF_X)
|
|
{
|
|
pSIF_C = (PDWORD) pOutput + (I420_NO_Y_SIF / sizeof (DWORD));
|
|
|
|
if (camVersion >= SSI_CIF3)
|
|
{
|
|
pSrc += ((SIF_DY / NO_LINES_IN_BAND) * BytesPerBandCIF3);
|
|
}
|
|
else
|
|
{
|
|
pSrc += ((SIF_DY / NO_LINES_IN_BAND) * BytesPerBandCIF4);
|
|
}
|
|
|
|
band = NO_BANDS_SIF;
|
|
}
|
|
else // width == SSIF_X || width == SCIF
|
|
{
|
|
if (height == SSIF_Y) {
|
|
pSIF_C = (PDWORD) pOutput + (I420_NO_Y_SSIF / sizeof (DWORD));
|
|
|
|
// 13,5 bands to skip in start en 13,5 bands to skip at end
|
|
// To make it easier : 13 bands to skip in start and 14 bytes at end
|
|
|
|
if (camVersion >= SSI_CIF3)
|
|
{
|
|
pSrc += (((SSIF_DY - 2) / NO_LINES_IN_BAND) * BytesPerBandCIF3);
|
|
}
|
|
else
|
|
{
|
|
pSrc += (((SSIF_DY - 2) / NO_LINES_IN_BAND) * BytesPerBandCIF4);
|
|
}
|
|
|
|
band = NO_BANDS_SSIF;
|
|
}else{
|
|
pSIF_C = (PDWORD) pOutput + (I420_NO_Y_SCIF / sizeof (DWORD));
|
|
|
|
if (camVersion >= SSI_CIF3)
|
|
{
|
|
pSrc += (((SCIF_DY - 2) / NO_LINES_IN_BAND) * BytesPerBandCIF3);
|
|
}
|
|
else
|
|
{
|
|
pSrc += (((SCIF_DY - 2) / NO_LINES_IN_BAND) * BytesPerBandCIF4);
|
|
}
|
|
|
|
band = NO_BANDS_SCIF;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (; band > 0; band--)
|
|
{
|
|
DcDecompressBandToI420 (pSrc, (PBYTE) pYDst, camVersion,
|
|
Y_BLOCK_BAND, (BOOLEAN) (width != CIF_X));
|
|
|
|
if (width == CIF_X)
|
|
{
|
|
pYDst += (I420_NO_Y_PER_BAND_CIF / sizeof (DWORD));
|
|
}
|
|
else
|
|
{
|
|
if (width == SIF_X)
|
|
{
|
|
pYDst += (SIF_DX / sizeof (DWORD));
|
|
|
|
for (line = NO_LINES_IN_BAND; line > 0; line--)
|
|
{
|
|
for (byte = (SIF_X / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_Y++ = *pYDst++;
|
|
}
|
|
|
|
pYDst += (( 2 * SIF_DX) / sizeof (DWORD));
|
|
}
|
|
|
|
pYDst = (PDWORD) pInput;
|
|
}
|
|
else // width == SSIF_X || width == SCIF_X
|
|
{
|
|
if ( height == SSIF_Y ){
|
|
pYDst += (SSIF_DX / sizeof (DWORD));
|
|
|
|
for (line = NO_LINES_IN_BAND ; line > 0; line--)
|
|
{
|
|
for (byte = (SSIF_X / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_Y++ = *pYDst++;
|
|
}
|
|
|
|
pYDst += (( 2 * SSIF_DX) / sizeof (DWORD));
|
|
}
|
|
|
|
pYDst = (PDWORD) pInput;
|
|
}else{
|
|
pYDst += (SCIF_DX / sizeof (DWORD));
|
|
|
|
for (line = NO_LINES_IN_BAND ; line > 0; line--)
|
|
{
|
|
for (byte = (SCIF_X / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_Y++ = *pYDst++;
|
|
}
|
|
|
|
pYDst += (( 2 * SCIF_DX) / sizeof (DWORD));
|
|
}
|
|
|
|
pYDst = (PDWORD) pInput;
|
|
}
|
|
}
|
|
}
|
|
|
|
DcDecompressBandToI420 (pSrc, (PBYTE) pCDst, camVersion,
|
|
UV_BLOCK_BAND, (BOOLEAN) (width != CIF_X));
|
|
|
|
if (width == CIF_X)
|
|
{
|
|
pCDst += (I420_NO_U_PER_BAND_CIF / sizeof (DWORD));
|
|
}
|
|
else
|
|
{
|
|
if (width == SIF_X)
|
|
{
|
|
pCDst += ((SIF_DX / 2) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pSIF_C += ((I420_NO_U_SIF - I420_NO_U_PER_BAND_SIF) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pCDst = (PDWORD) pInput + (I420_NO_Y_PER_BAND_CIF / sizeof (DWORD));
|
|
pSIF_C -= (I420_NO_U_SIF / sizeof (DWORD));
|
|
}
|
|
else // width == SSIF_X || width == SCIF_X
|
|
{
|
|
if (height == SSIF_Y){
|
|
pCDst += ((SSIF_DX / 2) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SSIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SSIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pSIF_C += ((I420_NO_U_SSIF - I420_NO_U_PER_BAND_SSIF) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SSIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SSIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pCDst = (PDWORD) pInput + (I420_NO_Y_PER_BAND_CIF / sizeof (DWORD));
|
|
pSIF_C -= (I420_NO_U_SSIF / sizeof (DWORD));
|
|
}else{
|
|
pCDst += ((SCIF_DX / 2) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SCIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SCIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pSIF_C += ((I420_NO_U_SCIF - I420_NO_U_PER_BAND_SCIF) / sizeof (DWORD));
|
|
|
|
for (line = (NO_LINES_IN_BAND / 2); line > 0; line--)
|
|
{
|
|
for (byte = ((SCIF_X / 2) / sizeof (DWORD)); byte > 0; byte--)
|
|
{
|
|
*pSIF_C++ = *pCDst++;
|
|
}
|
|
|
|
pCDst += ((2 * (SCIF_DX / 2)) / sizeof (DWORD));
|
|
}
|
|
|
|
pCDst = (PDWORD) pInput + (I420_NO_Y_PER_BAND_CIF / sizeof (DWORD));
|
|
pSIF_C -= (I420_NO_U_SCIF / sizeof (DWORD));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
pSrc += (camVersion >= SSI_CIF3) ? BytesPerBandCIF3 : BytesPerBandCIF4;
|
|
}
|
|
|
|
if (width == CIF_X)
|
|
{
|
|
if (camVersion < SSI_8117_N3)
|
|
{
|
|
Fix16PixGreenbarInI420 (pOutput, width);
|
|
}
|
|
#ifdef PIX12_FIX
|
|
FixPix12InI420 (pOutput, TRUE, width, height, camVersion);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
|