//==========================================================================; // // 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); if (pSrb->CommandData.DataBufferArray->FrameExtent < sizeof (CC_HW_FIELD)) { DbgLogError(("testcap: CC output pin handed buffer size %d, need %d\n", pSrb->CommandData.DataBufferArray->FrameExtent, sizeof (CC_HW_FIELD))); TRAP; return; } 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 // Check to make sure that the supplied buffer is large enough if (pSrb->CommandData.DataBufferArray->FrameExtent < sizeof (NABTS_BUFFER)) { DbgLogError(("testcap: NABTS output pin handed buffer size %d, need %d\n", pSrb->CommandData.DataBufferArray->FrameExtent, sizeof (NABTS_BUFFER))); TRAP; return; } 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; // Check to make sure that the supplied buffer is large enough if (pSrb->CommandData.DataBufferArray->FrameExtent < sizeof (NABTS_BUFFER)) { DbgLogError(("testcap: NABTS output pin handed buffer size %d, need %d\n", pSrb->CommandData.DataBufferArray->FrameExtent, sizeof (NABTS_BUFFER))); TRAP; return; } // 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; }