main.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:10k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit main;
  2. {$DEFINE DEBUG}
  3. interface
  4. uses BaseClass, ActiveX, DirectShow9, Windows, DSUtil;
  5. const
  6.   CLSID_WavDest : TGUID = '{3C78B8E2-6C4D-11d1-ADE2-0000F8754B99}';
  7. type
  8.   TWavDestOutputPin = class(TBCTransformOutputPin)
  9.   public
  10.     constructor Create(Filter: TBCTransformFilter; out hr: HRESULT);
  11.     function EnumMediaTypes(out ppEnum: IEnumMediaTypes): HRESULT; override; stdcall;
  12.     function CheckMediaType(pmt: PAMMediaType): HRESULT; override;
  13.   end;
  14.   TWavDestFilter = class(TBCTransformFilter)
  15.   private
  16.     FWavData: Cardinal;
  17.     FHeader : Cardinal;
  18.   public
  19.     constructor Create(Unk: IUnKnown; out hr: HRESULT);
  20.     constructor CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown); override;
  21.     function Copy(Source, dest: IMediaSample): HRESULT;
  22.     function Transform(pIn, pOut: IMediaSample): HRESULT; overload; override;
  23.     function Receive(Sample: IMediaSample): HRESULT; override;
  24.     function CheckInputType(mtIn: PAMMediaType): HRESULT; override;
  25.     function CheckTransform(mtIn, mtOut: PAMMediaType): HRESULT; override;
  26.     function GetMediaType(Position: integer; out MediaType: PAMMediaType): HRESULT; override;
  27.     function DecideBufferSize(Alloc: IMemAllocator; Properties: PAllocatorProperties): HRESULT; override;
  28.     function StartStreaming: HRESULT; override;
  29.     function StopStreaming: HRESULT; override;
  30.     function CompleteConnect(direction: TPINDIRECTION; ReceivePin: IPin): HRESULT; override;
  31.   end;
  32. implementation
  33. { TWavDestOutputPin }
  34. function TWavDestOutputPin.CheckMediaType(pmt: PAMMediaType): HRESULT;
  35. begin
  36.   if IsEqualGUID(pmt.majortype, MEDIATYPE_Stream) and IsEqualGUID(pmt.subtype, MEDIASUBTYPE_WAVE) then
  37.        result := S_OK
  38.   else result := S_FALSE;
  39. end;
  40. constructor TWavDestOutputPin.Create(Filter: TBCTransformFilter;
  41.   out hr: HRESULT);
  42. begin
  43.   inherited Create('WavDest output pin', Filter, hr, 'Out');
  44. end;
  45. function TWavDestOutputPin.EnumMediaTypes(
  46.   out ppEnum: IEnumMediaTypes): HRESULT;
  47. begin
  48.   result := inherited EnumMediaTypes(ppEnum);
  49. end;
  50. { TWavDestFilter }
  51. function TWavDestFilter.CheckInputType(mtIn: PAMMediaType): HRESULT;
  52. begin
  53.   if IsEqualGUID(mtIn.formattype, FORMAT_WaveFormatEx) then
  54.        result := S_OK
  55.   else result := S_FALSE;
  56. end;
  57. function TWavDestFilter.CheckTransform(mtIn,
  58.   mtOut: PAMMediaType): HRESULT;
  59. begin
  60.   result := CheckInputType(mtIn);
  61.   if FAILED(result) then exit;
  62.   result := NOERROR;
  63. end;
  64. function TWavDestFilter.CompleteConnect(direction: TPINDIRECTION;
  65.   ReceivePin: IPin): HRESULT;
  66. begin
  67.   result := S_OK;
  68. end;
  69. function TWavDestFilter.Copy(Source, dest: IMediaSample): HRESULT;
  70. var
  71.   SourceBuffer, DestBuffer: PBYTE;
  72.   SourceSize: LongInt;
  73.   TimeStart, TimeEnd: TReferenceTime;
  74.   MediaStart, MediaEnd: int64;
  75.   MediaType: PAMMEDIATYPE;
  76.   DataLength: Integer;
  77. begin
  78.   // Copy the sample data
  79.   SourceSize := Source.GetActualDataLength;
  80. {$ifdef DEBUG}
  81.   ASSERT(Dest.GetSize >= SourceSize);
  82. {$endif}
  83.   Source.GetPointer(SourceBuffer);
  84.   Dest.GetPointer(DestBuffer);
  85.   CopyMemory(DestBuffer, SourceBuffer, SourceSize);
  86.   // Copy the sample times
  87.   if (NOERROR = Source.GetTime(TimeStart, TimeEnd)) then
  88.     Dest.SetTime(@TimeStart, @TimeEnd);
  89.   if (Source.GetMediaTime(MediaStart,MediaEnd) = NOERROR) then
  90.     Dest.SetMediaTime(@MediaStart, @MediaEnd);
  91.   // Copy the media type
  92.   Source.GetMediaType(MediaType);
  93.   Dest.SetMediaType(MediaType^);
  94.   DeleteMediaType(MediaType);
  95.   // Copy the actual data length
  96.   DataLength := Source.GetActualDataLength;
  97.   Dest.SetActualDataLength(DataLength);
  98.   result := NOERROR;
  99. end;
  100. constructor TWavDestFilter.Create(Unk: IUnKnown; out hr: HRESULT);
  101. var
  102.   pOut: TWavDestOutputPin;
  103.   pIn : TBCTransformInputPin;
  104. begin
  105.   inherited Create('WavDest filter', Unk, CLSID_WavDest);
  106.   ASSERT(FOutput = nil);
  107.   if SUCCEEDED(hr) then
  108.   begin
  109.       // Create an output pin so we can have control over the connection
  110.       // media type.
  111.       pOut := TWavDestOutputPin.Create(self, hr);
  112.       if(pOut <> nil) then
  113.         begin
  114.           if SUCCEEDED(hr) then
  115.                FOutput := pOut
  116.           else pOut.Free;
  117.         end
  118.       else
  119.         hr := E_OUTOFMEMORY;
  120.       //
  121.       // NOTE!: If we've created our own output pin we must also create
  122.       // the input pin ourselves because the CTransformFilter base class
  123.       // will create an extra output pin if the input pin wasn't created.
  124.       //
  125.       pIn := TBCTransformInputPin.Create('Transform input pin',
  126.                                           self,  // Owner filter
  127.                                           hr,    // Result code
  128.                                           'In'); // Pin name
  129.       // a failed return code should delete the object
  130.       if (pIn <> nil) then
  131.         begin
  132.           if SUCCEEDED(hr) then
  133.                FInput := pIn
  134.           else pIn.Free;
  135.         end
  136.       else
  137.         hr := E_OUTOFMEMORY;
  138.   end;
  139. end;
  140. constructor TWavDestFilter.CreateFromFactory(Factory: TBCClassFactory; const Controller: IUnknown);
  141. var hr: HRESULT;
  142. begin
  143.   Create(Controller, hr);
  144. end;
  145. function TWavDestFilter.DecideBufferSize(Alloc: IMemAllocator;
  146.   Properties: PAllocatorProperties): HRESULT;
  147. var
  148.   InProps, Actual: TALLOCATORPROPERTIES;
  149.   InAlloc: IMemAllocator;
  150. begin
  151.   // Is the input pin connected
  152.   if not FInput.IsConnected then
  153.     begin
  154.       result := E_UNEXPECTED;
  155.       exit;
  156.     end;
  157.   ASSERT(Alloc <> nil);
  158.   ASSERT(Properties <> nil);
  159.   Properties.cBuffers := 1;
  160.   Properties.cbAlign  := 1;
  161.   // Get input pin's allocator size and use that
  162.   result := FInput.GetAllocator(InAlloc);
  163.   if SUCCEEDED(result) then
  164.   begin
  165.     result := InAlloc.GetProperties(InProps);
  166.     if SUCCEEDED(result) then
  167.       Properties.cbBuffer := InProps.cbBuffer;
  168.     InAlloc := nil;
  169.   end;
  170.   if FAILED(result) then exit;
  171.   ASSERT(Properties.cbBuffer <> 0);
  172.   // Ask the allocator to reserve us some sample memory, NOTE the function
  173.   // can succeed (that is return NOERROR) but still not have allocated the
  174.   // memory that we requested, so we must check we got whatever we wanted
  175.   result := Alloc.SetProperties(Properties^, Actual);
  176.   if FAILED(result) then exit;
  177.   ASSERT(Actual.cBuffers = 1);
  178.   if (Properties.cBuffers > Actual.cBuffers) or
  179.      (Properties.cbBuffer > Actual.cbBuffer) then
  180.   result := E_FAIL else
  181.   result := NOERROR;
  182. end;
  183. function TWavDestFilter.GetMediaType(Position: integer;
  184.   out MediaType: PAMMediaType): HRESULT;
  185. begin
  186.   ASSERT((Position = 0) or (Position = 1));
  187.   if(Position = 0) then
  188.   begin
  189.     MediaType.majortype := MEDIATYPE_Stream;
  190.     MediaType.Subtype   := MEDIASUBTYPE_WAVE;
  191.     result := S_OK;
  192.     exit;
  193.   end;
  194.   result := VFW_S_NO_MORE_ITEMS;
  195. end;
  196. function TWavDestFilter.Receive(Sample: IMediaSample): HRESULT;
  197. var Old: Cardinal;
  198. begin
  199.   Old := FWavData;
  200.   result := inherited Receive(Sample);
  201.   // don't update the count if Deliver() downstream fails.
  202.   if(result <> S_OK) then FWavData := Old;
  203. end;
  204. function TWavDestFilter.StartStreaming: HRESULT;
  205. begin
  206.   // leave space for the header
  207.   FHeader := sizeof(TRIFFLIST) +
  208.                sizeof(TRIFFCHUNK) +
  209.                FInput.AMMEdiaType.cbFormat +
  210.                sizeof(TRIFFCHUNK);
  211.   FWavData := 0;
  212.   result := S_OK;
  213. end;
  214. function TWavDestFilter.StopStreaming: HRESULT;
  215. type TByteDynArray = array of Byte;
  216. var
  217.   Stream: IStream;
  218.   DwnstrmInputPin: IPin;
  219.   pb: PByte;
  220.   RiffWave: PRIFFLIST;
  221.   RiffFmt, RiffData : PRIFFCHUNK;
  222.   li, newposition: Int64;
  223. begin
  224.     if not FOutput.IsConnected then
  225.       begin
  226.         result := E_FAIL;
  227.         exit;
  228.       end;
  229.     DwnstrmInputPin := FOutput.GetConnected;
  230.     if (DwnstrmInputPin = nil) then
  231.       begin
  232.         result := E_FAIL;
  233.         exit;
  234.       end;
  235.     result := DwnstrmInputPin.QueryInterface(IStream, Stream);
  236.     if SUCCEEDED(result) then
  237.     begin
  238.         GetMem(pb, FHeader);
  239.         RiffWave := PRIFFLIST(pb);
  240.         RiffFmt  := PRIFFCHUNK(Cardinal(RiffWave) + SizeOf(TRIFFLIST));
  241.         RiffData := PRIFFCHUNK((Cardinal(RiffFmt) + SizeOf(TRIFFCHUNK)) + FInput.ammediatype.cbFormat);
  242.         RiffData.fcc := FCC('data');
  243.         RiffData.cb := FWavData;
  244.         RiffFmt.fcc := FCC('fmt ');
  245.         RiffFmt.cb  := FInput.AMMediaType.cbFormat;
  246.         CopyMemory(Pointer(Cardinal(RiffFmt) + SizeOf(TRIFFCHUNK)), FInput.AMMediaType.pbFormat, RiffFmt.cb);
  247.         RiffWave.fcc := FCC('RIFF');
  248.         RiffWave.cb  := FWavData + FHeader - sizeof(TRIFFCHUNK);
  249.         RiffWave.fccListType := FCC('WAVE');
  250.         ZeroMemory(@li, sizeof(li));
  251.         newposition := 0;
  252.         result := Stream.Seek(li, STREAM_SEEK_SET, newposition);
  253.         if SUCCEEDED(result) then
  254.           result := Stream.Write(pb, FHeader, nil);
  255.         Stream := nil;
  256.         freemem(pb);
  257.     end;
  258. end;
  259. function TWavDestFilter.Transform(pIn, pOut: IMediaSample): HRESULT;
  260. var
  261.   rtStart, rtEnd: TReferenceTime;
  262.   Actual: Cardinal;
  263. begin
  264.   // First just copy the data to the output sample
  265.   result := Copy(pIn, pOut);
  266.   if FAILED(result) then exit;
  267.   // Prepare it for writing
  268.   Actual := pOut.GetActualDataLength;
  269.   if (FWavData + FHeader + Actual) < (FWavData + FHeader ) then
  270.     begin // overflow
  271.       result := E_FAIL;
  272.       exit;
  273.     end;
  274.   rtStart := FWavData + FHeader;
  275.   rtEnd   := rtStart + Actual;
  276.   FWavData := FWavData + Actual;
  277.   ASSERT(pOut.SetTime(@rtStart, @rtEnd) = S_OK);
  278.   result := S_OK;
  279. end;
  280. initialization
  281.   TBCClassFactory.CreateFilter(TWavDestFilter, 'WAV Dest', CLSID_WavDest,
  282.     CLSID_LegacyAmFilterCategory, MERIT_DO_NOT_USE, 0, nil);
  283. end.