| Предыдущая тема :: Следующая тема |
| Автор |
Сообщение |
kostasoft Активный
Зарегистрирован: 28.07.2007 Сообщения: 44
|
Добавлено: Сб Июн 14, 2008 1:30 am Заголовок сообщения: Фильтр с 2-мя входными пинами и одним выходным |
|
|
Нужно создать фильтр типа трансформ с двуми входными пинами. От какого класса нужно наследоваться?
Если есть готовый пример, ткните носом. _________________ http://kostasoft.com - Наш софт! |
|
| Вернуться к началу |
|
 |
mr_balu Новенький
Зарегистрирован: 01.07.2008 Сообщения: 9 Откуда: Minsk, Belarus
|
Добавлено: Вт Июл 01, 2008 5:37 pm Заголовок сообщения: |
|
|
| возьми любой готовый фильтр из SDK(у меня лежит C:\MDSDK\Samples\C++\DirectShow\filters\) да и пиши в структуру const AMOVIESETUP_PIN нужное тебе кол-во входных и выходных пинов. про типы поддерживаемых носителей для входного и выходного пинов тоже не забудь |
|
| Вернуться к началу |
|
 |
kostasoft Активный
Зарегистрирован: 28.07.2007 Сообщения: 44
|
Добавлено: Ср Июл 02, 2008 4:28 pm Заголовок сообщения: |
|
|
Не все так просто.
Вот код:
| Код: | unit main;
interface
uses
BaseClass, DirectShow9, ActiveX, Windows, Classes;
const
CLSID_CryptFilter : TGUID = '{0DA2D2B2-2077-4B34-932E-37967A22E888}';
MyPinTypes: TRegPinTypes =
(clsMajorType: @MEDIATYPE_Video;
clsMinorType: @MEDIASUBTYPE_NULL);
MyPins : array[0..2] of TRegFilterPins =
((
strName: 'In0'; // pin name
bRendered: FALSE; // is it rendered
bOutput: FALSE; // is it an output pin
bZero: FALSE; // are we allowed none
bMany: FALSE; // and allowed many
oFilter: nil; // connects to filter
strConnectsToPin: nil; // connects to pin
nMediaTypes: 1; // number or types
lpMediaType: @MyPinTypes // pin information
),
(
strName: 'In1'; // pin name
bRendered: FALSE; // is it rendered
bOutput: FALSE; // is it an output pin
bZero: FALSE; // are we allowed none
bMany: FALSE; // and allowed many
oFilter: nil; // connects to filter
strConnectsToPin: nil; // connects to pin
nMediaTypes: 1; // number or types
lpMediaType: @MyPinTypes // pin information
),
(
strName: 'Output';
bRendered: FALSE;
bOutput: TRUE;
bZero: FALSE;
bMany: FALSE;
oFilter: nil;
strConnectsToPin: nil;
nMediaTypes: 1;
lpMediaType: @MyPinTypes
)
);
type
TDualFilter = class(TBCTransformFilter, IPersist)
private
in_w, in_h: Integer;
bytesPerPixel: Integer;
ttt: Boolean;
function Copy(pSource, pDest : IMediaSample) : HRESULT;
protected
FInput1 : TBCTransformInputPin;
public
constructor Create(ObjName: String; Unk: IUnKnown; out hr: HRESULT);
constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IInterface); override;
destructor Destroy; override;
function Transform(pIn, pOut: IMediaSample): HRESULT; overload; override;
function CheckInputType(mtIn: PAMMediaType): HRESULT; override;
function CheckTransform(mtIn, mtOut: PAMMediaType): HRESULT; override;
function GetMediaType(Position: integer; out pMediaType: PAMMediaType): HRESULT; override;
function DecideBufferSize(Alloc: IMemAllocator; Properties: PAllocatorProperties): HRESULT; override;
function GetPinCount: integer; override;
function GetPin(n: integer): TBCBasePin; override;
function FindPin(Id: PWideChar; out ppPin: IPin): HRESULT; override; stdcall;
published
end;
procedure CopyMediaType(pmtTarget: PAMMEDIATYPE; pmtSource: PAMMEDIATYPE);
procedure DeleteMediaType(pmt: PAMMediaType);
procedure FreeMediaType(mt: PAMMediaType);
implementation
uses SysUtils, Dialogs, Math;
// ----------------------------------------------------------------
// ----------------------------------------------------------------
procedure CopyMediaType(pmtTarget: PAMMEDIATYPE; pmtSource: PAMMEDIATYPE);
begin
ASSERT(pmtSource <> pmtTarget);
move(pmtSource^, pmtTarget^, SizeOf(TAMMediaType));
if (pmtSource.cbFormat <> 0) then begin
ASSERT(pmtSource.pbFormat <> nil);
pmtTarget.pbFormat := CoTaskMemAlloc(pmtSource.cbFormat);
if (pmtTarget.pbFormat = nil) then
pmtTarget.cbFormat := 0
else
CopyMemory(pmtTarget.pbFormat, pmtSource.pbFormat, pmtTarget.cbFormat);
end;
if (pmtTarget.pUnk <> nil) then pmtTarget.pUnk._AddRef;
end;
procedure DeleteMediaType(pmt: PAMMediaType);
begin
if (pmt = nil) then exit;
FreeMediaType(pmt);
CoTaskMemFree(pmt);
end;
procedure FreeMediaType(mt: PAMMediaType);
begin
if (mt^.cbFormat <> 0) then begin
CoTaskMemFree(mt^.pbFormat);
mt^.cbFormat := 0;
mt^.pbFormat := nil;
end;
if (mt^.pUnk <> nil) then mt^.pUnk := nil;
end;
// ----------------------------------------------------------------
// ----------------------------------------------------------------
constructor TDualFilter.Create(ObjName: String; Unk: IUnKnown; out hr: HRESULT);
begin
inherited Create(ObjName, Unk, CLSID_CryptFilter);
end;
constructor TDualFilter.CreateFromFactory
(Factory : TBCClassFactory; const Controller: IInterface);
var
hr: HRESULT;
begin
Create(Factory.Name, Controller, hr);
end;
destructor TDualFilter.Destroy;
begin
if FInput1 <> nil then FInput1.Free;
inherited;
end;
function TDualFilter.Transform(pIn, pOut: IMediaSample): HRESULT;
var
hr: HRESULT;
pSourceBuffer, pDestBuffer : PBYTE;
len:integer;
begin
hr := Copy(pIn, pOut);
if (FAILED(hr)) then begin
Result := hr;
exit;
end;
pIn.GetPointer(pSourceBuffer);
pOut.GetPointer(pDestBuffer);
len:=in_w * in_h * bytesPerPixel;
if ttt then Inc(pDestBuffer, len);
Copymemory(pDestBuffer,pSourceBuffer,len);
pOut.SetActualDataLength(len*2);
ttt:= not ttt;
Result := S_OK;
end;
function TDualFilter.Copy(pSource, pDest : IMediaSample) : HRESULT;
var
//lSourceSize, lDestSize, lDataLength : INTEGER;
TimeStart, TimeEnd : TReferenceTime;
MediaStart, MediaEnd : INT64;
hr : HRESULT;
//pMediaType : PAMMediaType;
begin
// Copy the sample times
if pSource.GetTime(TimeStart, TimeEnd) = NOERROR
then pDest.SetTime(@TimeStart, @TimeEnd);
if pSource.GetMediaTime(MediaStart,MediaEnd) = NOERROR
then pDest.SetMediaTime(@MediaStart,@MediaEnd);
// Copy the Sync point property
hr := pSource.IsSyncPoint;
if hr in [S_OK, S_FALSE]
then pDest.SetSyncPoint(hr = S_OK)
else begin Result := E_UNEXPECTED; EXIT; end;
// Copy the preroll property
hr := pSource.IsPreroll;
if hr in [S_OK, S_FALSE]
then pDest.SetPreroll(hr = S_OK)
else begin Result := E_UNEXPECTED; EXIT; end;
// Copy the discontinuity property
hr := pSource.IsDiscontinuity;
if hr in [S_OK, S_FALSE]
then pDest.SetDiscontinuity(hr = S_OK)
else begin Result := E_UNEXPECTED; EXIT; end;
Result := NOERROR;
end;
function TDualFilter.CheckInputType(mtIn: PAMMediaType): HRESULT;
var
pvi: PVIDEOINFOHEADER;
begin
if (IsEqualGUID(mtIn.majortype, MEDIATYPE_Video))
and ((IsEqualGUID(mtIn.formattype, FORMAT_VideoInfo)) (*or (IsEqualGUID(mtIn.formattype, FORMAT_VideoInfo2)) *) )
and ((IsEqualGUID(mtIn.subtype, MEDIASUBTYPE_RGB32)) (*or (IsEqualGUID(mtIn.subtype, MEDIASUBTYPE_RGB24))*) )
then begin
pvi := mtIn.pbFormat;
if (pvi.bmiHeader.biBitCount = 32) then
begin
in_w := pvi.bmiHeader.biWidth;
in_h := pvi.bmiHeader.biHeight;
bytesPerPixel := pvi.bmiHeader.biBitCount div 8;
Result := S_OK
end
else Result := VFW_E_TYPE_NOT_ACCEPTED;
end else begin
Result := VFW_E_TYPE_NOT_ACCEPTED;
end;
end;
function TDualFilter.CheckTransform(mtIn,
mtOut: PAMMediaType): HRESULT;
begin
if IsEqualGUID(mtIn.subtype, mtOut.subtype) then begin
Result := S_OK
end else begin
Result := VFW_E_INVALID_MEDIA_TYPE;// VFW_E_TYPE_NOT_ACCEPTED;
end;
end;
// GetMediaType (output pin)
function TDualFilter.GetMediaType(Position : INTEGER; out pMediaType : PAMMediaType) : HRESULT;
var
pvi: PVIDEOINFOHEADER;
begin
if not (FInput.IsConnected or FInput1.IsConnected) then begin
Result := E_UNEXPECTED;
exit;
end;
if Position < 0 then begin
Result := E_INVALIDARG;
exit;
end;
if Position > 0 then begin
Result := VFW_S_NO_MORE_ITEMS;
exit;
end;
if FInput.IsConnected
then CopyMediaType(pMediaType, FInput.CurrentMediaType.MediaType)
else CopyMediaType(pMediaType, FInput1.CurrentMediaType.MediaType);
pvi := pMediaType.pbFormat;
pvi.bmiHeader.biWidth := in_w;
pvi.bmiHeader.biHeight := in_h*2;
pvi.bmiHeader.biSizeImage := in_w * in_h * bytesPerPixel*2;
pMediaType.lSampleSize := pvi.bmiHeader.biSizeImage;
Result := NOERROR; //S_OK;
end;
function TDualFilter.DecideBufferSize(Alloc: IMemAllocator;
Properties: PAllocatorProperties): HRESULT;
var
Actual: TAllocatorProperties;
begin
if not (FInput.IsConnected or FInput1.IsConnected) then begin
result := E_UNEXPECTED;
exit;
end;
Properties.cBuffers := 1;
Properties.cbBuffer := in_w * in_h * bytesPerPixel*2;
result := Alloc.SetProperties(Properties^, Actual);
if FAILED(result) then exit;
if (Properties.cBuffers > Actual.cBuffers)
or (Properties.cbBuffer > Actual.cbBuffer) then
result := E_FAIL
else
result := NOERROR;
end;
function TDualFilter.FindPin(Id: PWideChar; out ppPin: IPin): HRESULT;
begin
if(WideString(Id) = 'In0') then ppPin := GetPin(0) else
if(WideString(Id) = 'In1') then ppPin := GetPin(1) else
if(WideString(Id) = 'Out') then ppPin := GetPin(2) else
begin
ppPin := nil;
result := VFW_E_NOT_FOUND;
exit;
end;
result := NOERROR;
if(ppPin = nil) then result := E_OUTOFMEMORY;
end;
function TDualFilter.GetPin(n: integer): TBCBasePin;
var hr: HRESULT;
begin
hr := S_OK;
if(FInput = nil) then
begin
FInput := TBCTransformInputPin.Create('Transform input pin',
self, // Owner filter
hr, // Result code
'In0'); // Pin name
ASSERT(SUCCEEDED(hr));
if(FInput = nil) then
begin
result := nil;
exit;
end;
end;
if(FInput1 = nil) then
begin
FInput1 := TBCTransformInputPin.Create('Transform input pin',
self, // Owner filter
hr, // Result code
'In1'); // Pin name
ASSERT(SUCCEEDED(hr));
if(FInput1 = nil) then
begin
result := nil;
exit;
end;
end;
if(FOutput = nil) then
begin
FOutput := TBCTransformOutputPin.Create('Transform output pin',
self, // Owner filter
hr, // Result code
'Out'); // Pin name
ASSERT(SUCCEEDED(hr));
if(FOutput = nil) then
begin
FreeAndNil(FInput);
FreeAndNil(FInput1);
end;
end;
case n of
0 : result := FInput;
1 : result := FInput1;
2 : result := FOutput;
else
result := nil;
end;
end;
function TDualFilter.GetPinCount: integer;
begin
result := 3;
end;
initialization
TBCClassFactory.CreateFilter(
TDualFilter, // COM class
'_DualFilter', // class name
CLSID_CryptFilter, // GUID
CLSID_LegacyAmFilterCategory, // filter category
MERIT_DO_NOT_USE, // filter merit
3, // pin count
@MyPins // pins info
);
end. |
В итоге в функции Transform в pSourceBuffer попадают данные с обоих пинов. Как определить где какие данные? _________________ http://kostasoft.com - Наш софт! |
|
| Вернуться к началу |
|
 |
|
|
|
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|
|
|