Фильтр с 2-мя входными пинами и одним выходным

 
Начать новую тему   Ответить на тему    Список форумов DirectShow форум -> Фильтры
Предыдущая тема :: Следующая тема  
Автор Сообщение
kostasoft
Активный


Зарегистрирован: 28.07.2007
Сообщения: 44

СообщениеДобавлено: Сб Июн 14, 2008 1:30 am    Заголовок сообщения: Фильтр с 2-мя входными пинами и одним выходным Ответить с цитатой

Нужно создать фильтр типа трансформ с двуми входными пинами. От какого класса нужно наследоваться?
Если есть готовый пример, ткните носом.
_________________
http://kostasoft.com - Наш софт!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение AIM Address
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 - Наш софт!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение AIM Address
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов DirectShow форум -> Фильтры Часовой пояс: GMT + 4
Страница 1 из 1
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2005 phpBB Group
Русская поддержка phpBB


Рейтинг@Mail.ru