📄 vbipin.cpp
字号:
/*+++ *******************************************************************\
*
* Copyright and Disclaimer:
*
* ---------------------------------------------------------------
* This software is provided "AS IS" without warranty of any kind,
* either expressed or implied, including but not limited to the
* implied warranties of noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2008 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
#include "VbiPin.h"
#include "debug.h"
#include "pindataranges.h"
#include "ivideoDecoder.h"
#include "device.h"
const ULONG VBI_FRAMES_TO_CYCLE = 8;
const DWORD SIXTY_HZ_MASK =
KS_AnalogVideo_NTSC_Mask |
KS_AnalogVideo_PAL_M |
KS_AnalogVideo_PAL_60;
DWORD VbiPin::getLineSize()
{
return 1440;
}
DWORD VbiPin::getLinesPerFrame()
{
return _lines_per_frame;
}
VbiPin::VbiPin(
PKSPIN p_ks_pin,
NTSTATUS &status):
BasePin(p_ks_pin),
_tv_info_changed(TRUE)
{
_info_hdr = ((reinterpret_cast<KS_DATAFORMAT_VBIINFOHEADER*>
(p_ks_pin->ConnectionFormat))->VBIInfoHeader);
LONG duration = _info_hdr.VideoStandard & SIXTY_HZ_MASK ?
FIELD_DURATION_60HZ : FIELD_DURATION_50HZ;
// Init the base class
status = init(
VBI_FRAMES_TO_CYCLE,
_info_hdr.BufferSize,
duration);
// This needs to be done so that the KSSTREAM_HEADER in the
// KSSTEAM_POINTER has the correct size for fillFrameInfo()
if(NT_SUCCESS(status))
{
p_ks_pin->StreamHeaderSize =
sizeof(KSSTREAM_HEADER) + sizeof(KS_VBI_FRAME_INFO);
}
//Initialize the TV info structure. This will get sent the
// first time the VBI pin starts if no channel change actually occured.
// The CC decoder doesn't start decoding until it has seen the flag at least once.
_tv_info.dwFlags = KS_TVTUNER_CHANGE_END_TUNE;
_tv_info.dwCountryCode = 1;
_tv_info.dwAnalogVideoStandard = KS_AnalogVideo_NTSC_M;
_tv_info.dwChannel = 4;
_lines_per_frame =
(_info_hdr.VideoStandard & NTSC_ASPECT_VIDEO_STANDARDS) ?
NTSC_VBI_LINES : PAL_VBI_LINES;
_lines_per_frame *= 2;
}
NTSTATUS VbiPin::dispatchCreate(PKSPIN p_ks_pin,
PIRP p_irp)
{
NTSTATUS status = STATUS_SUCCESS;
p_ks_pin->Context = new VbiPin(p_ks_pin, status);
if(!p_ks_pin->Context)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if(!NT_SUCCESS(status))
{
delete (VbiPin*)p_ks_pin->Context;
}
return status;
}
VOID VbiPin::fillFrameInfo(PKSSTREAM_HEADER p_strm_hdr, FIELD_TYPE field_type)
{
// This size is obtained from KSPIN->StreamHeaderSize
// which we initialize in the ctor
if(p_strm_hdr->Size < (sizeof(KSSTREAM_HEADER) + sizeof(KS_VBI_FRAME_INFO)))
{
DbgLogError((
"VbiPin::fillFrameInfo Size = %d\n",
p_strm_hdr->Size));
return;
}
KS_VBI_FRAME_INFO *p_frame_info =
reinterpret_cast<KS_VBI_FRAME_INFO*>(p_strm_hdr + 1);
p_frame_info->ExtendedHeaderSize = sizeof KS_VBI_FRAME_INFO;
p_frame_info->PictureNumber = ++_picture_num;
p_frame_info->DropCount = _dropped_cnt;
p_frame_info->dwSamplingFrequency = _info_hdr.SamplingFrequency;
p_frame_info->dwFrameFlags =
(field_type == FIELD_1) ? KS_VBI_FLAG_FIELD1 : KS_VBI_FLAG_FIELD2;
if(_tv_info_changed)
{
p_frame_info->TvTunerChangeInfo = _tv_info;
p_frame_info->dwFrameFlags |= KS_VBI_FLAG_TVTUNER_CHANGE;
//We need to set the VBI Info Header here for the CC decoder to get the
// correct format. This needs to be done once after we start
p_frame_info->dwFrameFlags |= KS_VBI_FLAG_VBIINFOHEADER_CHANGE;
IVideoDecoder* p_decoder = _p_device->getVidDec();
KS_VBIINFOHEADER* p_header = &g_stream_format_VBI.VBIInfoHeader;
DWORD VideoMode = p_decoder->getVideoMode();
if(( VideoMode == VIDEO_MODE_PAL)||
(VideoMode == VIDEO_MODE_SECAM)||
(VideoMode == VIDEO_MODE_PAL_N)||
(VideoMode == VIDEO_MODE_PAL_NC))
{
p_header = &g_stream_format_VBI_PAL.VBIInfoHeader;
}
RtlCopyMemory(
&p_frame_info->VBIInfoHeader,
p_header,
sizeof(KS_VBIINFOHEADER));
_tv_info_changed = false;
}
}
VOID VbiPin::start()
{
_tv_info_changed = TRUE;
}
NTSTATUS VbiPin::intersectRange(PKSFILTER p_filter,
PIRP p_irp,
PKSP_PIN p_pin_instance,
PKS_DATARANGE_VIDEO_VBI p_caller_range,
PKS_DATARANGE_VIDEO_VBI p_our_range,
ULONG buffer_size,
PVOID p_data,
PULONG p_data_size)
{
if(!IsEqualGUID(
p_caller_range->DataRange.Specifier,
KSDATAFORMAT_SPECIFIER_VBI))
{
return STATUS_NO_MATCH;
}
// Check that all the members of the two DATARANGES are the same
if((p_caller_range->bFixedSizeSamples != p_our_range->bFixedSizeSamples) ||
(p_caller_range->bTemporalCompression != p_our_range->bTemporalCompression) ||
(p_caller_range->StreamDescriptionFlags != p_our_range->StreamDescriptionFlags) ||
(p_caller_range->MemoryAllocationFlags != p_our_range->MemoryAllocationFlags) ||
(RtlCompareMemory(
&p_caller_range->ConfigCaps,
&p_our_range->ConfigCaps,
sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)) != sizeof(KS_VIDEO_STREAM_CONFIG_CAPS)) ||
(RtlCompareMemory(
&p_caller_range->VBIInfoHeader,
&p_our_range->VBIInfoHeader,
sizeof(KS_VBIINFOHEADER)) != sizeof(KS_VBIINFOHEADER)))
{
DbgLogError(("Vbi intersect NO MATCH\n"));
return STATUS_NO_MATCH;
}
// Set the required output buffer size
*p_data_size = sizeof KS_DATAFORMAT_VBIINFOHEADER;
// If buffer_size is 0 this is a size query
if(buffer_size == 0)
{
return STATUS_BUFFER_OVERFLOW;
}
// Check that the output data buffer is large enough
if(buffer_size < *p_data_size)
{
return STATUS_BUFFER_TOO_SMALL;
}
// Copy the data range structure from our
// decriptor into the target format buffer
KS_DATAFORMAT_VBIINFOHEADER *p_out_format =
reinterpret_cast<KS_DATAFORMAT_VBIINFOHEADER*>(p_data);
p_out_format->DataFormat =
static_cast<KSDATAFORMAT>(p_our_range->DataRange);
// Since the input structs are KS_DATARANGE_VIDEO_VBI and the
// output struct is a KS_DATAFORMAT_VBIINFOHEADER we need
// to set the FormatSize according to the output struct.
p_out_format->DataFormat.FormatSize = *p_data_size;
// Copy the KS_VBIINFOHEADER to the output struct
p_out_format->VBIInfoHeader = p_our_range->VBIInfoHeader;
return STATUS_SUCCESS;
}
PIN_TYPES VbiPin::getPinType()
{
return PIN_TYPE_VBI;
}
VOID VbiPin::setTVInfo(PKS_TVTUNER_CHANGE_INFO p_tv_info)
{
_tv_info = *p_tv_info;
_tv_info_changed = TRUE;
}
NTSTATUS VbiPin::dispatchSetFormat(PKSPIN p_ks_pin,
PKSDATAFORMAT p_old_data_format,
PKSMULTIPLE_ITEM p_attr_list,
PKSDATARANGE p_range,
PKSATTRIBUTE_LIST p_attr_range)
{
if( IsEqualGUID( p_ks_pin->ConnectionFormat->Specifier,
KSDATAFORMAT_SPECIFIER_VBI ) )
{
if( p_ks_pin->ConnectionFormat->FormatSize <
sizeof(KS_DATAFORMAT_VBIINFOHEADER))
return STATUS_INVALID_PARAMETER;
KS_DATAFORMAT_VBIINFOHEADER *p_new_format =
(KS_DATAFORMAT_VBIINFOHEADER*)
p_ks_pin->ConnectionFormat;
KS_DATARANGE_VIDEO_VBI* p_our_range =
(KS_DATARANGE_VIDEO_VBI*) p_range;
//Make sure the format is correct
if((p_new_format->VBIInfoHeader.StartLine != p_our_range->VBIInfoHeader.StartLine) ||
(p_new_format->VBIInfoHeader.EndLine != p_our_range->VBIInfoHeader.EndLine) ||
(p_new_format->VBIInfoHeader.SamplesPerLine != p_our_range->VBIInfoHeader.SamplesPerLine) ||
(p_new_format->VBIInfoHeader.BufferSize != p_our_range->VBIInfoHeader.BufferSize) ||
(p_new_format->DataFormat.SampleSize != p_our_range->VBIInfoHeader.BufferSize))
{
return STATUS_NO_MATCH;
}
return STATUS_SUCCESS;
}
return STATUS_NO_MATCH;
}
const KSPIN_DISPATCH VbiPinDispatch =
{
VbiPin::dispatchCreate, // Pin Create
BasePin::dispatchClose, // Pin Close
BasePin::dispatchProcess, // Pin Process
NULL, // Pin Reset
(PFNKSPINSETDATAFORMAT)VbiPin::dispatchSetFormat, // Pin Set Data Format
BasePin::dispatchSetState, // Pin Set Device State
NULL, // Pin Connect
NULL, // Pin Disconnect
NULL, // Clock Dispatch
NULL // Allocator Dispatch
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -