Hello, I am developing a PCI capture driver, and I use "avshws" as
sample to
develp the driver.
I can capture AVI with H.264 codec by AMCAP, and the avi file can play
well.
My problem is as following:
I would like to set bTemporalCompression(in KS_DATARANGE_VIDEO) to be
TRUE.
Then, the captured AVI frames will be not all marked as key frame.
I connect capture pin to dump filter. When I trace in avshws,
bTemporalCompression is really true. But when I trace into dump
filter, it
shows bTemporalCompression as FALSE.
In addition, in "IntersectHandler" function, the sample code doesn't
copy
"bTemporalCompression" and "bFixedSizeSamples" into
"Data"(PKS_DATAFORMAT_VIDEOINFOHEADER).
If I write following code:
FormatVideoInfoHeader->DataFormat.SampleSize = 0;
Then, I can see "bFixedSizeSamples" in "Dump" filter is updated to
FALSE.
Therefore, should I copy "bTemporalCompression" into somewhere to make
the flag enable?
Can somebody kindly help me to solve this problem?
My data range defines as following:
KS_DATARANGE_VIDEO
FormatH264_Capture = {
//
// KSDATARANGE
//
{
sizeof (KS_DATARANGE_VIDEO), // FormatSize
0, // Flags
DMAX_X * DMAX_Y * 2, // SampleSize
0, // Reserved
STATICGUIDOF (KSDATAFORMAT_TYPE_VIDEO), // aka.
MEDIATYPE_Video
0x34363248, 0x0000, 0x0010, 0x80, 0x00,
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71, //aka.
MEDIASUBTYPE_YUY2,
STATICGUIDOF (KSDATAFORMAT_SPECIFIER_VIDEOINFO) //
FORMAT_VideoInfo
},
FALSE, // BOOL, bFixedSizeSamples (all samples same
size?)
TRUE, // BOOL, bTemporalCompression (all I frames?)
0, // Reserved (was StreamDescriptionFlags)
0, // Reserved (was MemoryAllocationFlags
// (KS_VIDEO_ALLOC_*))
//
// _KS_VIDEO_STREAM_CONFIG_CAPS
//
{
STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VIDEOINFO ), // GUID
KS_AnalogVideo_None, //
AnalogVideoStandard
DMAX_X, DMAX_Y, // InputSize, (the inherent size of the
incoming signal
D_X,D_Y, // MinCroppingSize, smallest rcSrc cropping
rect
DMAX_X, DMAX_Y, // MaxCroppingSize, largest rcSrc cropping
rect allowed
8, // CropGranularityX, granularity of cropping
size
1, // CropGranularityY
8, // CropAlignX, alignment of cropping rect
1, // CropAlignY;
D_X, D_Y, // MinOutputSize, smallest bitmap stream can
produce
DMAX_X, DMAX_Y, // MaxOutputSize, largest bitmap stream can
produce
8, // OutputGranularityX, granularity of output
bitmap size
1, // OutputGranularityY;
0, // StretchTapsX (0 no stretch, 1 pix dup, 2
interp...)
0, // StretchTapsY
0, // ShrinkTapsX
0, // ShrinkTapsY
1428571, // MinFrameInterval, 100 nS units >>7 frames
per second
640000000, // MaxFrameInterval, 100 nS units
8 * 2 * 30 * D_X * D_Y, // MinBitsPerSecond;
8 * 2 * 30 * DMAX_X * DMAX_Y, // MaxBitsPerSecond;
},
//
// KS_VIDEOINFOHEADER (default format)
//
{
0, 0, D_X, D_Y, // RECT rcSource;
0, 0, 0, 0, // RECT rcTarget;
DMAX_X * DMAX_Y * 2 * 30, // DWORD dwBitRate;
0L, // DWORD dwBitErrorRate;
1428571, // REFERENCE_TIME
AvgTimePerFrame;
sizeof (KS_BITMAPINFOHEADER), // DWORD biSize;
DMAX_X, // LONG biWidth;
DMAX_Y, // LONG biHeight;
1, // WORD biPlanes;
16, // WORD biBitCount;
FOURCC_H264, // DWORD biCompression;
DMAX_X * DMAX_Y * 2, // DWORD biSizeImage;
0, // LONG biXPelsPerMeter;
0, // LONG biYPelsPerMeter;
0, // DWORD biClrUsed;
0 // DWORD biClrImportant;
}
}
My IntersectHandler is as following:
NTSTATUS
CCapturePin::
IntersectHandler (
IN PKSFILTER Filter,
IN PIRP Irp,
IN PKSP_PIN PinInstance,
IN PKSDATARANGE CallerDataRange,
IN PKSDATARANGE DescriptorDataRange,
IN ULONG BufferSize,
OUT PVOID Data OPTIONAL,
OUT PULONG DataSize
)
{
PAGED_CODE();
const GUID VideoInfoSpecifier =
{STATICGUIDOF(KSDATAFORMAT_SPECIFIER_VIDEOINFO)};
ASSERT(Filter);
ASSERT(Irp);
ASSERT(PinInstance);
ASSERT(CallerDataRange);
ASSERT(DescriptorDataRange);
ASSERT(DataSize);
ULONG DataFormatSize;
//
// Specifier FORMAT_VideoInfo for VIDEOINFOHEADER
//
if (IsEqualGUID(CallerDataRange->Specifier, VideoInfoSpecifier) &&
CallerDataRange -> FormatSize >= sizeof (KS_DATARANGE_VIDEO))
{
PKS_DATARANGE_VIDEO callerDataRange =
reinterpret_cast <PKS_DATARANGE_VIDEO> (CallerDataRange);
PKS_DATARANGE_VIDEO descriptorDataRange =
reinterpret_cast <PKS_DATARANGE_VIDEO>
(DescriptorDataRange);
PKS_DATAFORMAT_VIDEOINFOHEADER FormatVideoInfoHeader;
//
// Check that the other fields match
//
if ((callerDataRange->bFixedSizeSamples !=
descriptorDataRange->bFixedSizeSamples) ||
(callerDataRange->bTemporalCompression !=
descriptorDataRange->bTemporalCompression) ||
(callerDataRange->StreamDescriptionFlags !=
descriptorDataRange->StreamDescriptionFlags) ||
(callerDataRange->MemoryAllocationFlags !=
descriptorDataRange->MemoryAllocationFlags) ||
(RtlCompareMemory (&callerDataRange->ConfigCaps,
&descriptorDataRange->ConfigCaps,
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)) !=
sizeof (KS_VIDEO_STREAM_CONFIG_CAPS)))
{
return STATUS_NO_MATCH;
}
//
// KS_SIZE_VIDEOHEADER() below is relying on bmiHeader.biSize
from
// the caller's data range. This **MUST** be validated; the
// extended bmiHeader size (biSize) must not extend past the
end
// of the range buffer. Possible arithmetic overflow is also
// checked for.
//
{
ULONG VideoHeaderSize = KS_SIZE_VIDEOHEADER (
&callerDataRange->VideoInfoHeader
);
ULONG DataRangeSize =
FIELD_OFFSET (KS_DATARANGE_VIDEO, VideoInfoHeader) +
VideoHeaderSize;
//
// Check that biSize does not extend past the buffer.
The
// first two checks are for arithmetic overflow on the
// operations to compute the alleged size. (On unsigned
// math, a+b < a iff an arithmetic overflow occurred).
//
if (
VideoHeaderSize < callerDataRange->
VideoInfoHeader.bmiHeader.biSize ||
DataRangeSize < VideoHeaderSize ||
DataRangeSize > callerDataRange ->
DataRange.FormatSize
) {
return STATUS_INVALID_PARAMETER;
}
}
DataFormatSize =
sizeof (KSDATAFORMAT) +
KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader);
//
// If the passed buffer size is 0, it indicates that this is a
size
// only query. Return the size of the intersecting data
format and
// pass back STATUS_BUFFER_OVERFLOW.
//
if (BufferSize == 0) {
*DataSize = DataFormatSize;
return STATUS_BUFFER_OVERFLOW;
}
//
// Verify that the provided structure is large enough to
// accept the result.
//
if (BufferSize < DataFormatSize)
{
return STATUS_BUFFER_TOO_SMALL;
}
//
// Copy over the KSDATAFORMAT, followed by the actual
VideoInfoHeader
//
*DataSize = DataFormatSize;
FormatVideoInfoHeader =
PKS_DATAFORMAT_VIDEOINFOHEADER( Data );
//
// Copy over the KSDATAFORMAT. This is precisely the same as
the
// KSDATARANGE (it's just the GUIDs, etc... not the format
information
// following any data format.
//
RtlCopyMemory (
&FormatVideoInfoHeader->DataFormat,
DescriptorDataRange,
sizeof (KSDATAFORMAT));
FormatVideoInfoHeader->DataFormat.FormatSize = DataFormatSize;
//
// Copy over the callers requested VIDEOINFOHEADER
//
RtlCopyMemory (
&FormatVideoInfoHeader->VideoInfoHeader,
&callerDataRange->VideoInfoHeader,
KS_SIZE_VIDEOHEADER (&callerDataRange->VideoInfoHeader)
);
//
// Calculate biSizeImage for this request, and put the result
in both
// the biSizeImage field of the bmiHeader AND in the
SampleSize field
// of the DataFormat.
//
// Note that for compressed sizes, this calculation will
probably not
// be just width * height * bitdepth
//
FormatVideoInfoHeader->VideoInfoHeader.bmiHeader.biSizeImage =
KS_DIBSIZE (FormatVideoInfoHeader-
//
// REVIEW - Perform other validation such as cropping and
scaling checks
//
return STATUS_SUCCESS;
} // End of VIDEOINFOHEADER specifier
return STATUS_NO_MATCH;
}
Thanks!
Gordon