📄 videopin.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 "VideoPin.h"
#include "Device.h"
#include "RegistryAccess.h"
#include "debug.h"
#include "stdlib.h"
#include "pindataranges.h"
#include "ivideodecoder.h"
#include "miscfuncs.h"
#include <mmsystem.h>
const ULONG VIDEO_FRAMES_TO_CYCLE = 10;
VideoPin::VideoPin(PKSPIN p_ks_pin,
NTSTATUS &status):
BasePin(p_ks_pin)
{
_info_hdr = ((reinterpret_cast<KS_DATAFORMAT_VIDEOINFOHEADER*>
(p_ks_pin->ConnectionFormat))->VideoInfoHeader);
_format = FormatData(&_info_hdr);
PVOID p_context = KsPinGetDevice(p_ks_pin)->Context;
Device* p_device = static_cast<Device*>(p_context);
status = init(
VIDEO_FRAMES_TO_CYCLE,
_info_hdr.bmiHeader.biSizeImage,
_info_hdr.AvgTimePerFrame);
if(NT_SUCCESS(status))
{
p_ks_pin->StreamHeaderSize = sizeof KSSTREAM_HEADER + sizeof KS_FRAME_INFO;
}
//TODO: Set the resolution
}
DWORD VideoPin::getLineSize()
{
return _format.imageWidth()*2;
}
DWORD VideoPin::getLinesPerFrame()
{
return abs(_format.imageHeight());
}
BOOLEAN VideoPin::isSingleFieldStream()
{
DWORD height = abs(_format.imageHeight());
DWORD max_single_field_height = 240;
IVideoDecoder* p_decoder = _p_device->getVidDec();
if(p_decoder->getVideoMode() == VIDEO_MODE_PAL)
{
max_single_field_height = 288;
}
return FALSE;
}
VOID VideoPin::start()
{
IVideoDecoder* p_decoder = _p_device->getVidDec();
p_decoder->setResolution(_format.imageWidth(), abs(_format.imageHeight()));
RegistryAccess registry_access(_p_device->getPdo());
DWORD board_type = POLARIS_BOARD_DVT;
registry_access.readDword("BoardType", &board_type);
if(board_type == POLARIS_BOARD_FPGA)
{
// enable TS1 data pin to output 656 to FPGA
p_decoder->enableVideoOutput();
}
}
NTSTATUS VideoPin::dispatchCreate(PKSPIN p_ks_pin,
PIRP p_irp)
{
NTSTATUS status = STATUS_SUCCESS;
p_ks_pin->Context = new VideoPin(p_ks_pin, status);
if( !p_ks_pin->Context )
return STATUS_INSUFFICIENT_RESOURCES;
if( !NT_SUCCESS( status ) )
delete (VideoPin*)p_ks_pin->Context;
return status;
}
static BOOLEAN checkDimension(
INT dimension,
INT lower_bound,
INT upper_bound,
INT step)
{
if( dimension >= lower_bound &&
dimension <= upper_bound &&
(dimension - lower_bound) % step == 0 )
return TRUE;
return FALSE;
}
static BOOLEAN checkDimensions(
PKS_VIDEOINFOHEADER p_info_to_check,
PKS_VIDEOINFOHEADER p_info,
PKS_VIDEO_STREAM_CONFIG_CAPS p_caps,
BOOLEAN softEncoderEnabled)
{
FormatData format( p_info_to_check );
if(!checkDimension(
format.imageWidth(),
(softEncoderEnabled ? p_caps->MaxOutputSize.cx : p_caps->MinOutputSize.cx),
p_caps->MaxOutputSize.cx,
p_caps->OutputGranularityX))
{
return FALSE;
}
if(!checkDimension(
abs(format.imageHeight()),
(softEncoderEnabled ? p_caps->MaxOutputSize.cy : p_caps->MinOutputSize.cy),
p_caps->MaxOutputSize.cy,
p_caps->OutputGranularityY))
{
return FALSE;
}
if((p_info_to_check->bmiHeader.biCompression != p_info->bmiHeader.biCompression) ||
(p_info_to_check->bmiHeader.biBitCount != p_info->bmiHeader.biBitCount))
{
return FALSE;
}
return TRUE;
}
NTSTATUS VideoPin::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_VIDEOINFO ) )
{
if( p_ks_pin->ConnectionFormat->FormatSize <
sizeof KS_DATAFORMAT_VIDEOINFOHEADER )
return STATUS_INVALID_PARAMETER;
KS_DATAFORMAT_VIDEOINFOHEADER *p_new_format =
(KS_DATAFORMAT_VIDEOINFOHEADER*)
p_ks_pin->ConnectionFormat;
KS_DATARANGE_VIDEO *p_data_range =
(KS_DATARANGE_VIDEO*)p_range;
PVOID p_context = KsPinGetDevice(p_ks_pin)->Context;
Device* p_device = static_cast<Device*>(p_context);
// Check that we support the requested image dimensions.
if(!checkDimensions(
&p_new_format->VideoInfoHeader,
&p_data_range->VideoInfoHeader,
&p_data_range->ConfigCaps,
p_device->IsSoftEncoderEnabled()))
{
return STATUS_NO_MATCH;
}
// Check that the image size in the info
// header matches its dimensions
if( p_new_format->VideoInfoHeader.bmiHeader.biSizeImage !=
KS_DIBSIZE( p_new_format->VideoInfoHeader.bmiHeader ) )
{
return STATUS_INVALID_PARAMETER;
}
// If p_old_data_format != NULL it means that dispatchCreate()
// has already been called and "this dispatch contains the
// actual surface parameters" see DDK->Data Range Intersections
// in AVStream. Since only the stride should change we need
// make sure this is the case, and return fail otherwise.
if(p_old_data_format)
{
//If we are in a running state, we can't change the format
if(KsPinGetFirstCloneStreamPointer(p_ks_pin))
{
DbgLogError(("SetDataFormat after buffers received\n"));
return STATUS_INVALID_DEVICE_STATE;
}
VideoPin* p_vid_pin = (VideoPin*)p_ks_pin->Context;
FormatData old_format = p_vid_pin->_format;
FormatData new_format(&p_new_format->VideoInfoHeader);
// Make sure only the stride changed
if((p_new_format->VideoInfoHeader.AvgTimePerFrame !=p_vid_pin->_info_hdr.AvgTimePerFrame) ||
(abs(new_format.imageHeight()) != abs( old_format.imageHeight())) ||
(new_format.imageWidth() != old_format.imageWidth()) ||
(new_format.bitCount() != old_format.bitCount()) ||
(new_format.compression() != old_format.compression()))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -