349 lines
9.7 KiB
C
349 lines
9.7 KiB
C
|
//==========================================================================;
|
||
|
//
|
||
|
// 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;
|
||
|
}
|