main.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
- unit main;
- {$DEFINE DEBUG}
- {$IFDEF VER150}
- {$WARN UNSAFE_CODE OFF}
- {$WARN UNSAFE_TYPE OFF}
- {$WARN UNSAFE_CAST OFF}
- {$ENDIF}
- interface
- uses BaseClass, ActiveX, DirectShow9, Windows, DSUtil;
- const
- CLSID_WavDest : TGUID = '{3C78B8E2-6C4D-11d1-ADE2-0000F8754B99}';
- type
- TWavDestOutputPin = class(TBCTransformOutputPin)
- public
- constructor Create(Filter: TBCTransformFilter; out hr: HRESULT);
- function EnumMediaTypes(out ppEnum: IEnumMediaTypes): HRESULT; override; stdcall;
- function CheckMediaType(pmt: PAMMediaType): HRESULT; override;
- end;
- TWavDestFilter = class(TBCTransformFilter)
- private
- FWavData: Cardinal;
- FHeader : Cardinal;
- public
- constructor Create(Unk: IUnKnown; out hr: HRESULT);
- constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown); override;
- function Copy(Source, dest: IMediaSample): HRESULT;
- function Transform(pIn, pOut: IMediaSample): HRESULT; overload; override;
- function Receive(Sample: IMediaSample): HRESULT; override;
- function CheckInputType(mtIn: PAMMediaType): HRESULT; override;
- function CheckTransform(mtIn, mtOut: PAMMediaType): HRESULT; override;
- function GetMediaType(Position: integer; out MediaType: PAMMediaType): HRESULT; override;
- function DecideBufferSize(Alloc: IMemAllocator; Properties: PAllocatorProperties): HRESULT; override;
- function StartStreaming: HRESULT; override;
- function StopStreaming: HRESULT; override;
- function CompleteConnect(direction: TPinDirection; ReceivePin: IPin): HRESULT; override;
- end;
- implementation
- { TWavDestOutputPin }
- function TWavDestOutputPin.CheckMediaType(pmt: PAMMediaType): HRESULT;
- begin
- if IsEqualGUID(pmt.majortype, MEDIATYPE_Stream) and IsEqualGUID(pmt.subtype, MEDIASUBTYPE_WAVE) then
- result := S_OK
- else result := S_FALSE;
- end;
- constructor TWavDestOutputPin.Create(Filter: TBCTransformFilter;
- out hr: HRESULT);
- begin
- inherited Create('WavDest output pin', Filter, hr, 'Out');
- end;
- function TWavDestOutputPin.EnumMediaTypes(
- out ppEnum: IEnumMediaTypes): HRESULT;
- begin
- result := inherited EnumMediaTypes(ppEnum);
- end;
- { TWavDestFilter }
- function TWavDestFilter.CheckInputType(mtIn: PAMMediaType): HRESULT;
- begin
- if IsEqualGUID(mtIn.formattype, FORMAT_WaveFormatEx) then
- result := S_OK
- else result := S_FALSE;
- end;
- function TWavDestFilter.CheckTransform(mtIn,
- mtOut: PAMMediaType): HRESULT;
- begin
- result := CheckInputType(mtIn);
- if FAILED(result) then exit;
- result := NOERROR;
- end;
- function TWavDestFilter.CompleteConnect(direction: TPinDirection;
- ReceivePin: IPin): HRESULT;
- begin
- result := S_OK;
- end;
- function TWavDestFilter.Copy(Source, dest: IMediaSample): HRESULT;
- var
- SourceBuffer, DestBuffer: PBYTE;
- SourceSize: LongInt;
- TimeStart, TimeEnd: TReferenceTime;
- MediaStart, MediaEnd: int64;
- MediaType: PAMMediaType;
- DataLength: Integer;
- begin
- // Copy the sample data
- SourceSize := Source.GetActualDataLength;
- {$ifdef DEBUG}
- ASSERT(Dest.GetSize >= SourceSize);
- {$endif}
- Source.GetPointer(SourceBuffer);
- Dest.GetPointer(DestBuffer);
- CopyMemory(DestBuffer, SourceBuffer, SourceSize);
- // Copy the sample times
- if (NOERROR = Source.GetTime(TimeStart, TimeEnd)) then
- Dest.SetTime(@TimeStart, @TimeEnd);
- if (Source.GetMediaTime(MediaStart,MediaEnd) = NOERROR) then
- Dest.SetMediaTime(@MediaStart, @MediaEnd);
- // Copy the media type
- Source.GetMediaType(MediaType);
- Dest.SetMediaType(MediaType^);
- DeleteMediaType(MediaType);
- // Copy the actual data length
- DataLength := Source.GetActualDataLength;
- Dest.SetActualDataLength(DataLength);
- result := NOERROR;
- end;
- constructor TWavDestFilter.Create(Unk: IInterface; out hr: HRESULT);
- var
- pOut: TWavDestOutputPin;
- pIn : TBCTransformInputPin;
- begin
- inherited Create('WavDest filter', Unk, CLSID_WavDest);
- ASSERT(FOutput = nil);
- if SUCCEEDED(hr) then
- begin
- // Create an output pin so we can have control over the connection
- // media type.
- pOut := TWavDestOutputPin.Create(self, hr);
- if(pOut <> nil) then
- begin
- if SUCCEEDED(hr) then
- FOutput := pOut
- else pOut.Free;
- end
- else
- hr := E_OUTOFMEMORY;
- //
- // NOTE!: If we've created our own output pin we must also create
- // the input pin ourselves because the CTransformFilter base class
- // will create an extra output pin if the input pin wasn't created.
- //
- pIn := TBCTransformInputPin.Create('Transform input pin',
- self, // Owner filter
- hr, // Result code
- 'In'); // Pin name
- // a failed return code should delete the object
- if (pIn <> nil) then
- begin
- if SUCCEEDED(hr) then
- FInput := pIn
- else pIn.Free;
- end
- else
- hr := E_OUTOFMEMORY;
- end;
- end;
- constructor TWavDestFilter.CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown);
- var hr: HRESULT;
- begin
- Create(Controller, hr);
- end;
- function TWavDestFilter.DecideBufferSize(Alloc: IMemAllocator;
- Properties: PAllocatorProperties): HRESULT;
- var
- InProps, Actual: TAllocatorProperties;
- InAlloc: IMemAllocator;
- begin
- // Is the input pin connected
- if not FInput.IsConnected then
- begin
- result := E_UNEXPECTED;
- exit;
- end;
- ASSERT(Alloc <> nil);
- ASSERT(Properties <> nil);
- Properties.cBuffers := 1;
- Properties.cbAlign := 1;
- // Get input pin's allocator size and use that
- result := FInput.GetAllocator(InAlloc);
- if SUCCEEDED(result) then
- begin
- result := InAlloc.GetProperties(InProps);
- if SUCCEEDED(result) then
- Properties.cbBuffer := InProps.cbBuffer;
- InAlloc := nil;
- end;
- if FAILED(result) then exit;
- ASSERT(Properties.cbBuffer <> 0);
- // Ask the allocator to reserve us some sample memory, NOTE the function
- // can succeed (that is return NOERROR) but still not have allocated the
- // memory that we requested, so we must check we got whatever we wanted
- result := Alloc.SetProperties(Properties^, Actual);
- if FAILED(result) then exit;
- ASSERT(Actual.cBuffers = 1);
- if (Properties.cBuffers > Actual.cBuffers) or
- (Properties.cbBuffer > Actual.cbBuffer) then
- result := E_FAIL else
- result := NOERROR;
- end;
- function TWavDestFilter.GetMediaType(Position: integer;
- out MediaType: PAMMediaType): HRESULT;
- begin
- ASSERT((Position = 0) or (Position = 1));
- if(Position = 0) then
- begin
- MediaType.majortype := MEDIATYPE_Stream;
- MediaType.Subtype := MEDIASUBTYPE_WAVE;
- result := S_OK;
- exit;
- end;
- result := VFW_S_NO_MORE_ITEMS;
- end;
- function TWavDestFilter.Receive(Sample: IMediaSample): HRESULT;
- var Old: Cardinal;
- begin
- Old := FWavData;
- result := inherited Receive(Sample);
- // don't update the count if Deliver() downstream fails.
- if(result <> S_OK) then FWavData := Old;
- end;
- function TWavDestFilter.StartStreaming: HRESULT;
- begin
- // leave space for the header
- FHeader := sizeof(TRIFFLIST) +
- sizeof(TRIFFCHUNK) +
- FInput.AMMEdiaType.cbFormat +
- sizeof(TRIFFCHUNK);
- FWavData := 0;
- result := S_OK;
- end;
- function TWavDestFilter.StopStreaming: HRESULT;
- type TByteDynArray = array of Byte;
- var
- Stream: IStream;
- DwnstrmInputPin: IPin;
- pb: PByte;
- RiffWave: PRIFFLIST;
- RiffFmt, RiffData : PRIFFCHUNK;
- li, newposition: Int64;
- begin
- if not FOutput.IsConnected then
- begin
- result := E_FAIL;
- exit;
- end;
- DwnstrmInputPin := FOutput.GetConnected;
- if (DwnstrmInputPin = nil) then
- begin
- result := E_FAIL;
- exit;
- end;
- result := DwnstrmInputPin.QueryInterface(IStream, Stream);
- if SUCCEEDED(result) then
- begin
- GetMem(pb, FHeader);
- RiffWave := PRIFFLIST(pb);
- RiffFmt := PRIFFCHUNK(Cardinal(RiffWave) + SizeOf(TRIFFLIST));
- RiffData := PRIFFCHUNK((Cardinal(RiffFmt) + SizeOf(TRIFFCHUNK)) + FInput.ammediatype.cbFormat);
- RiffData.fcc := FCC('data');
- RiffData.cb := FWavData;
- RiffFmt.fcc := FCC('fmt ');
- RiffFmt.cb := FInput.AMMediaType.cbFormat;
- CopyMemory(Pointer(Cardinal(RiffFmt) + SizeOf(TRIFFCHUNK)), FInput.AMMediaType.pbFormat, RiffFmt.cb);
- RiffWave.fcc := FCC('RIFF');
- RiffWave.cb := FWavData + FHeader - sizeof(TRIFFCHUNK);
- RiffWave.fccListType := FCC('WAVE');
- ZeroMemory(@li, sizeof(li));
- newposition := 0;
- result := Stream.Seek(li, STREAM_SEEK_SET, newposition);
- if SUCCEEDED(result) then
- result := Stream.Write(pb, FHeader, nil);
- Stream := nil;
- freemem(pb);
- end;
- end;
- function TWavDestFilter.Transform(pIn, pOut: IMediaSample): HRESULT;
- var
- rtStart, rtEnd: TReferenceTime;
- Actual: Cardinal;
- begin
- // First just copy the data to the output sample
- result := Copy(pIn, pOut);
- if FAILED(result) then exit;
- // Prepare it for writing
- Actual := pOut.GetActualDataLength;
- if (FWavData + FHeader + Actual) < (FWavData + FHeader ) then
- begin // overflow
- result := E_FAIL;
- exit;
- end;
- rtStart := FWavData + FHeader;
- rtEnd := rtStart + Actual;
- FWavData := FWavData + Actual;
- ASSERT(pOut.SetTime(@rtStart, @rtEnd) = S_OK);
- result := S_OK;
- end;
- initialization
- TBCClassFactory.CreateFilter(TWavDestFilter, 'WAV Dest', CLSID_WavDest,
- CLSID_LegacyAmFilterCategory, MERIT_DO_NOT_USE, 0, nil);
- end.