windows-nt/Source/XPSP1/NT/drivers/wdm/capture/mini/testcap/vbixfer.c

349 lines
9.7 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1999 Microsoft Corporation. All Rights Reserved.
//
//==========================================================================;
#include "strmini.h"
#include "ksmedia.h"
#include "capmain.h"
#include "capdebug.h"
#include "vbixfer.h"
#include "vbidata.h"
/*
** DEBUG variables to play with
*/
#if DBG
unsigned short dCCScanWave = 0;
unsigned short dCCScanLog = 0;
unsigned short dCCLogOnce = 1;
unsigned short dCCEncode5A = 0;
#endif //DBG
/*
** CC_ImageSynth()
**
** Copies canned CC bytes
**
** Arguments:
**
** pSrb - The stream request block for the Video stream
**
** Returns:
** Nothing
**
** Side Effects: none
*/
void CC_ImageSynth (
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pSrb->StreamObject->StreamNumber;
PKSSTREAM_HEADER pStreamHeader = pSrb->CommandData.DataBufferArray;
PCC_HW_FIELD pCCfield = (PCC_HW_FIELD)pStreamHeader->Data;
unsigned int field;
unsigned int cc_index;
DEBUG_ASSERT(pSrb->NumberOfBuffers == 1);
field = (unsigned int)(pStrmEx->VBIFrameInfo.PictureNumber % CCfieldCount);
RtlZeroMemory(pCCfield, sizeof (*pCCfield));
cc_index = 0;
pCCfield->PictureNumber = pStrmEx->VBIFrameInfo.PictureNumber;
pCCfield->fieldFlags = (field & 1)? KS_VBI_FLAG_FIELD1 : KS_VBI_FLAG_FIELD2;
field >>= 1;
SETBIT(pCCfield->ScanlinesRequested.DwordBitArray, 21);
if (KS_VBI_FLAG_FIELD1 == pCCfield->fieldFlags) {
pCCfield->Lines[cc_index].Decoded[0] = CCfields[field][0];
pCCfield->Lines[cc_index].Decoded[1] = CCfields[field][1];
}
else {
pCCfield->Lines[cc_index].Decoded[0] = 0;
pCCfield->Lines[cc_index].Decoded[1] = 0;
}
//DbgKdPrint(("%c%c", CCfields[field][0] & 0x7F, CCfields[field][1] & 0x7F));
++cc_index;
pStreamHeader->DataUsed = sizeof (CC_HW_FIELD);
}
/*
** CC_EncodeWaveform()
**
** Writes out a CC waveform encoding the supplied data bytes
**
** Arguments:
**
** waveform - the buffer for the CC waveform data
** cc1 - the first byte to encode into the waveform
** cc2 - the second byte to encode into the waveform
**
** Returns:
** Nothing
**
** Side Effects: overwrites waveform with an EIA-608 signal
*/
void CC_EncodeWaveform(
unsigned char *waveform,
unsigned char cc1,
unsigned char cc2)
{
unsigned int waveIdx;
unsigned char DC_zero = CCsampleWave[0];
unsigned char DC_one = CCsampleWave[34];
unsigned short DC_last;
// 455/8 = 56.875 bytes per CC bit at KS_VBISAMPLINGRATE_5X_NABTS(~28.6mhz)
unsigned int CCstride = 455;
unsigned char *samp, *end, byte;
unsigned int bit, done;
#if DBG
if (dCCEncode5A) {
cc1 = 0x5A;
cc2 = 0x5A;
}
if (dCCScanWave) {
// Scan EIGHT bits worth of samples for low / high DC values
for (samp=CCsampleWave, end=CCsampleWave+CCstride; samp < end; ++samp) {
if (*samp > DC_one)
DC_one = *samp;
else if (*samp < DC_zero)
DC_zero = *samp;
}
for (samp = CCsampleWave + 500; samp < &CCsampleWave[550] ; ++samp) {
if (*samp >= DC_one - 5)
break;
}
waveIdx = (unsigned int)((samp - CCsampleWave) * 8);
if (dCCScanLog) {
DbgKdPrint(("testcap::CC_EncodeWaveform: DC_zero = %u, DC_one = %u, waveIdx = %u\n", DC_zero, DC_one, waveIdx/8));
dCCScanLog = 0;
}
}
else {
#endif //DBG
waveIdx = CCsampleWaveDataOffset * 8;
DC_zero = CCsampleWaveDC_zero;
DC_one = CCsampleWaveDC_one;
#if DBG
}
#endif //DBG
// Copy Run-in bytes and first three bits as-is
RtlCopyMemory(waveform, CCsampleWave, waveIdx/8);
DC_last = waveform[waveIdx/8 - 1] * 4;
// Now encode the requested bytes
samp = &waveform[waveIdx/8];
for (byte = cc1, done = 0; ; byte = cc2, done = 1)
{
unsigned int bitpos;
for (bitpos = 0; bitpos < 8; ++bitpos) {
bit = byte & 1;
byte >>= 1;
for (end = &waveform[(waveIdx + CCstride)/8]; samp < end; ++samp) {
if (bit == 1) {
if (DC_last/4 < DC_one) {
DC_last += 7;
if (DC_last/4 > DC_one)
DC_last = DC_one * 4;
}
}
else /* bit == 0 */ {
if (DC_last/4 > DC_zero) {
DC_last -= 7;
if (DC_last/4 < DC_zero)
DC_last = DC_zero * 4;
}
}
ASSERT(samp < &waveform[768*2]);
*samp = DC_last/4;
}
waveIdx += CCstride;
}
if (done)
break;
}
// Finish up at DC_zero
for (end = &waveform[768*2]; samp < end; ++samp) {
if (DC_last/4 > DC_zero) {
DC_last -= 7;
if (DC_last/4 < DC_zero)
DC_last = DC_zero * 4;
}
*samp = DC_last/4;
}
}
/*
** NABTS_ImageSynth()
**
** Copies canned NABTS bytes
**
** Arguments:
**
** pSrb - The stream request block for the Video stream
**
** Returns:
** Nothing
**
** Side Effects: none
*/
unsigned char HammingEncode[16] = {
0x15, 0x02, 0x49, 0x5E, 0x64, 0x73, 0x38, 0x2F,
0xD0, 0xC7, 0x8C, 0x9B, 0xA1, 0xB6, 0xFD, 0xEA
};
void NABTS_ImageSynth (
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pSrb->StreamObject->StreamNumber;
PKSSTREAM_HEADER pStreamHeader = pSrb->CommandData.DataBufferArray;
PNABTS_BUFFER pNbuf = (PNABTS_BUFFER)pStreamHeader->Data;
unsigned int field;
#ifdef VBIDATA_NABTS
DEBUG_ASSERT (pSrb->NumberOfBuffers == 1);
pNbuf->PictureNumber = pStrmEx->VBIFrameInfo.PictureNumber;
// Copy the next apropriate field
field = (unsigned int)(pStrmEx->VBIFrameInfo.PictureNumber % NABTSfieldCount);
RtlCopyMemory(pNbuf, NABTSfields[field], sizeof (NABTS_BUFFER));
#else /*VBIDATA_NABTS*/
unsigned char i, line, ci;
PNABTS_BUFFER_LINE pNline;
// Create a test pattern
RtlZeroMemory(pNbuf, sizeof (NABTS_BUFFER));
ci = (unsigned char)(pStrmEx->VBIFrameInfo.PictureNumber % 15);
pNbuf->PictureNumber = pStrmEx->VBIFrameInfo.PictureNumber;
for (line = 10, pNline = pNbuf->NabtsLines;
line < 21;
++line, ++pNline)
{
SETBIT(pNbuf->ScanlinesRequested.DwordBitArray, line);
pNline->Confidence = 102; // We're 102% sure this NABTS is OK
// NABTS Header bytes
pNline->Bytes[00] =
pNline->Bytes[01] = 0x55;
pNline->Bytes[02] = 0xE7;
// Set GroupID 0x8F4
pNline->Bytes[03] = HammingEncode[0x8];
pNline->Bytes[04] = HammingEncode[0xF];
pNline->Bytes[05] = HammingEncode[0x4];
pNline->Bytes[06] = HammingEncode[ci];
pNline->Bytes[07] = HammingEncode[0x0]; // PS = Reg, Full, No suffix
// NABTS Payload
i = 8;
pNline->Bytes[i++] = 0xA0; // Mark the start of payload,
pNline->Bytes[i++] = 0xA0; // just for fun
pNline->Bytes[i++] = ci; // Put frame # into payload
pNline->Bytes[i++] = line; // Put line # into payload
// The rest zeros for now...
}
#endif /*VBIDATA_NABTS*/
pStreamHeader->DataUsed = sizeof (NABTS_BUFFER);
}
/*
** VBI_ImageSynth()
**
** Copies canned VBI samples
**
** Arguments:
**
** pSrb - The stream request block for the Video stream
** ImageXferCommands - Index specifying the image to generate
**
** Returns:
** Nothing
**
** Side Effects: none
*/
void VBI_ImageSynth (
IN OUT PHW_STREAM_REQUEST_BLOCK pSrb
)
{
PSTREAMEX pStrmEx = pSrb->StreamObject->HwStreamExtension;
int StreamNumber = pSrb->StreamObject->StreamNumber;
PKSSTREAM_HEADER pStreamHeader = pSrb->CommandData.DataBufferArray;
PUCHAR pImage = pStreamHeader->Data;
unsigned int field, cc_field;
unsigned char cc1, cc2;
DEBUG_ASSERT (pSrb->NumberOfBuffers == 1);
// Check to make sure that the supplied buffer is large enough
if (pSrb->CommandData.DataBufferArray->FrameExtent < VBIfieldSize) {
DbgLogError(("testcap: VBI output pin handed buffer size %d, need %d\n",
pSrb->CommandData.DataBufferArray->FrameExtent,
VBIfieldSize));
TRAP;
return;
}
// Copy the next apropriate field
field = (unsigned int)(pStrmEx->VBIFrameInfo.PictureNumber % VBIfieldCount);
RtlCopyMemory(pImage, VBIsamples[field], VBIfieldSize);
// Now mangle the CC waveform to match the HW data
if (field & 1) {
cc_field = (unsigned int)
(pStrmEx->VBIFrameInfo.PictureNumber >> 1) % CCfieldCount;
cc1 = CCfields[cc_field][0];
cc2 = CCfields[cc_field][1];
}
else {
cc1 = 0;
cc2 = 0;
}
CC_EncodeWaveform(VBIsamples[field][21-10], cc1, cc2);
// Report back the actual number of bytes copied to the destination buffer
pStreamHeader->DataUsed = VBIfieldSize;
}