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

Delphi控件源码

开发平台:

Delphi

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