⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upushsource.pas

📁 delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
      OutputDebugString('Could not allocate FImage');
      hr := E_OUTOFMEMORY;
      Exit;
    end;

    BytesRead := 0;
    if not (ReadFile(FFileHandle[i], FFileBuffer[i]^, FileSize, BytesRead, nil))
      then
    begin
      hr := HRESULTFROMWIN32(GetLastError());
      OutputDebugString('ReadFile failed');
      Exit;
    end;

    // WARNING - This code does not verify that the file is a valid bitmap file.
    // In your own filter, you would check this or else generate the bitmaps
    // yourself in memory.

    FileHeaderSize := SizeOf(BITMAPFILEHEADER);

    // Store the size of the BITMAPINFO
    BmpFileHeader := PBITMAPFILEHEADER(FFileBuffer[i]);
    FBitmapInfo[i] := Integer(BmpFileHeader.bfOffBits) - FileHeaderSize;

    // Store a pointer to the BITMAPINFO
    pb := PByte(FFileBuffer[i]);
    Inc(pb, FileHeaderSize);
    FBmi[i] := PBITMAPINFO(pb);

    // Store a pointer to the starting address of the pixel bits
    Inc(pb, FBitmapInfo[i]);
    FImage[i] := pb;

    // Close and invalidate the file handle, since we have copied its bitmap data
    CloseHandle(FFileHandle[i]);
    FFileHandle[i] := INVALID_HANDLE_VALUE;
    // Count this is a successful file load.  If not all files load
    // properly, then the filter will not operate correctly.
    Inc(FilesLoaded);
  end;

  // Make sure that ALL files were properly loaded
  if (FilesLoaded <> NUM_FILES) then
    hr := E_FAIL
  else
  begin
    FFilesLoaded := TRUE;
  end;
end;

destructor TBCPushPinBitmapSet.Destroy;
var
  i: Integer;
begin
{$IFDEF DEBUG}
  DbgLog(self, Format('Frames written %d', [FFrameNumber]));
{$ENDIF}

  for i := 0 to NUM_FILES - 1 do
  begin
    if Assigned(FFileBuffer[i]) then
    begin
      CoTaskMemFree(FFileBuffer[i]);
      FFileBuffer[i] := nil;
    end;

    // The constructor might quit early on error and not close the file...
    if (FFileHandle[i] <> INVALID_HANDLE_VALUE) then
      CloseHandle(FFileHandle[i]);
  end;

  if (FSharedState <> nil) then
    FreeAndNil(FSharedState);

  inherited;
end;

// GetMediaType: This method tells the downstream pin what types we support.

// Here is how CSourceStream deals with media types:
//
// If you support exactly one type, override GetMediaType(MediaType : PAMMediaType).
// It will then be called when (a) our filter proposes a media type,
// (b) the other filter proposes a type and we have to check that type.
//
// If you support > 1 type, override GetMediaType(iPosition : Integer;
//  out MediaType : PAMMediaType) AND CheckMediaType.
//
// In this case we support only one type, which we obtain from the bitmap file.

function TBCPushPinBitmapSet.GetMediaType(MediaType: PAMMediaType): HResult;
var
  pvi: PVIDEOINFOHEADER;

begin
  FFilter.StateLock.Lock;
  try
    if (MediaType = nil) then
    begin
      Result := E_POINTER;
      Exit;
    end;

    // If the bitmap files were not loaded, just fail here.
    if not (FFilesLoaded) then
    begin
      Result := E_FAIL;
      Exit;
    end;

    // Allocate enough room for the VIDEOINFOHEADER and the color tables
    MediaType.cbFormat := SIZE_PREHEADER + FBitmapInfo[FCurrentBitmap];
    pvi := CoTaskMemAlloc(MediaType.cbFormat);
    if (pvi = nil) then
    begin
      Result := E_OUTOFMEMORY;
      Exit;
    end;

    ZeroMemory(pvi, MediaType.cbFormat);
    pvi.AvgTimePerFrame := FFrameLength;

    // Copy the header info
    CopyMemory(@pvi.bmiHeader, FBmi[FCurrentBitmap],
      FBitmapInfo[FCurrentBitmap]);

    // Set image size for use in FillBuffer
    pvi.bmiHeader.biSizeImage := GetBitmapSize(@pvi.bmiHeader);

    // Clear source and target rectangles
    // we want the whole image area rendered
    SetRectEmpty(pvi.rcSource);
    // no particular destination rectangle
    SetRectEmpty(pvi.rcTarget);

    MediaType.majortype := MEDIATYPE_Video;
    MediaType.formattype := FORMAT_VideoInfo;
    // Work out the GUID for the subtype from the header info.
    MediaType.subtype := GetBitmapSubtype(@pvi.bmiHeader);
    MediaType.bTemporalCompression := False;
    MediaType.bFixedSizeSamples := True;
    //MediaType.cbFormat := SizeOf(TBitmapInfo);
    MediaType.pbFormat := pvi;
    MediaType.lSampleSize := pvi.bmiHeader.biSizeImage;

    Result := S_OK;

  finally
    FFilter.StateLock.UnLock;
  end;
end;

function TBCPushPinBitmapSet.DecideBufferSize(Allocator: IMemAllocator;
  Properties: PAllocatorProperties): HRESULT;
var
  pvi: PVIDEOINFOHEADER;
  Actual: ALLOCATOR_PROPERTIES;

begin
  if (Allocator = nil) or (Properties = nil) then
  begin
    Result := E_POINTER;
    Exit;
  end;
  FFilter.StateLock.Lock;
  try
    // If the bitmap files were not loaded, just fail here.
    if not (FFilesLoaded) then
    begin
      Result := E_FAIL;
      Exit;
    end;

    pvi := AMMediaType.pbFormat;

    // Ensure a minimum number of buffers
    if (Properties.cBuffers = 0) then
      Properties.cBuffers := 2;
    Properties.cbBuffer := pvi.bmiHeader.biSizeImage;

    Result := Allocator.SetProperties(Properties^, Actual);
    if Failed(Result) then
      Exit;

    // Is this allocator unsuitable?
    if (Actual.cbBuffer < Properties.cbBuffer) then
      Result := E_FAIL
    else
      Result := S_OK;

  finally
    FFilter.StateLock.UnLock;
  end;
end;

// This is where we insert the DIB bits into the video stream.
// FillBuffer is called once for every sample in the stream.

function TBCPushPinBitmapSet.FillBuffer(Sample: IMediaSample): HResult;
var
  pData: PByte;
  cbData: Longint;
  pvi: PVIDEOINFOHEADER;
  Start, Stop: REFERENCE_TIME;

  function min(v1, v2: DWord): DWord;
  begin
    if v1 <= v2 then
      Result := v1
    else
      Result := v2;
  end;

begin
  // If the bitmap files were not loaded, just fail here.
  if not (FFilesLoaded) then
  begin
    Result := E_FAIL;
    Exit;
  end;

  if (Sample = nil) then
  begin
    Result := E_POINTER;
    Exit;
  end;

  FSharedState.Lock;
  try
    // Access the sample's data buffer
    Sample.GetPointer(pData);
    cbData := Sample.GetSize;

    // Check that we're still using video
    Assert(IsEqualGUID(AMMediaType.formattype, FORMAT_VideoInfo));

    pvi := AMMediaType.pbFormat;

    // Copy the DIB bits over into our filter's output buffer.
    // Since sample size may be larger than the image size, bound the copy size.
    // Remember that the new data has the same format
    // that we specified in GetMediaType.
    CopyMemory(pData, FImage[FCurrentBitmap],
      min(pvi.bmiHeader.biSizeImage, cbData));

    // Set the timestamps that will govern playback frame rate.
    // If this file is getting written out as an AVI,
    // then you'll also need to configure the AVI Mux filter to
    // set the Average Time Per Frame for the AVI Header.
    // The current time is the sample's start
    Start := FFrameNumber * FFrameLength;
    Stop := Start + FFrameLength;

    Sample.SetTime(@Start, @Stop);
    Inc(FFrameNumber);

    // Set TRUE on every sample for uncompressed frames
    Sample.SetSyncPoint(True);

    // Increment the current buffer so that the next FillBuffer() call
    // will use the bits from the next bitmap in the set.
    Inc(FCurrentBitmap);
    FCurrentBitmap := FCurrentBitmap mod NUM_FILES;

    Result := S_OK;

  finally
    FSharedState.UnLock;
  end;
end;

function TBCPushPinBitmapSet.Notify(Filter: IBaseFilter; q: TQuality): HRESULT;
begin
  Result := E_FAIL;
end;

(**********************************************
 *
 *  CPushSourceBitmapSet Class
 *
 **********************************************)

constructor TBCPushSourceBitmapSet.Create(ObjName: string; Unk: IUnKnown;
  out hr: HRESULT);
begin
  inherited Create(ObjName, Unk, CLSID_PushSourceBitmapSet);

  // The pin magically adds itself to our pin array.
  FPin := TBCPushPinBitmapSet.Create(hr, Self);

  if (hr <> S_OK) then
    if (FPin = nil) then
      hr := E_OUTOFMEMORY;
end;

constructor TBCPushSourceBitmapSet.CreateFromFactory(Factory: TBCClassFactory;
  const Controller: IUnknown);
var
  hr: HRESULT;
begin
  Create(Factory.Name, Controller, hr);
end;

destructor TBCPushSourceBitmapSet.Destroy;
begin
  FreeAndNil(FPin);
  inherited;
end;

// --- TBCPushPinDesktop --------------

constructor TBCPushPinDesktop.Create(out hr: HResult; Filter: TBCSource);
var
  DC: HDC;

begin
  inherited Create('_ Push Source Desktop', hr, Filter, 'Out');

  FFramesWritten := 0;
  FZeroMemory := False;
  FFrameNumber := 0;
  // Display 5 bitmap frames per second
  FFrameLength := FPS_5;
  FSharedState := TBCCritSec.Create;
  FCurrentBitDepth := 32;

  // The main point of this sample is to demonstrate how to take a DIB
  // in host memory and insert it into a video stream.

  // To keep this sample as simple as possible, we just read the desktop image
  // from a file and copy it into every frame that we send downstream.

  // In the filter graph, we connect this filter to the AVI Mux, which creates
   // the AVI file with the video frames we pass to it. In this case,
   // the end result is a screen capture video (GDI images only, with no
   // support for overlay surfaces).

   // Get the device context of the main display
  DC := CreateDC('DISPLAY', nil, nil, nil);

  // Get the dimensions of the main desktop window
  FScreenRect.Left := 0;
  FScreenRect.Top := 0;
  FScreenRect.Right := GetDeviceCaps(DC, HORZRES);
  FScreenRect.Bottom := GetDeviceCaps(DC, VERTRES);

  // Save dimensions for later use in FillBuffer()
  FImageWidth := FScreenRect.Right - FScreenRect.Left;
  FImageHeight := FScreenRect.Bottom - FScreenRect.Top;

  // Release the device context
  DeleteDC(DC);

  hr := S_OK;
end;

destructor TBCPushPinDesktop.Destroy;
begin
{$IFDEF DEBUG}
  DbgLog(self, Format('Frames written %d', [FFrameNumber]));
{$ENDIF}
  inherited;
end;

// GetMediaType
//
// Prefer 5 formats - 8, 16 (*2), 24 or 32 bits per pixel
//
// Prefered types should be ordered by quality, with zero as highest quality.
// Therefore, iPosition =
//      0    Return a 32bit mediatype
//      1    Return a 24bit mediatype
//      2    Return 16bit RGB565
//      3    Return a 16bit mediatype (rgb555)
//      4    Return 8 bit palettised format
//      >4   Invalid
//

function TBCPushPinDesktop.GetMediaType(iPosition: Integer;
  out MediaType: PAMMediaType): HResult;
var
  pvi: PVIDEOINFO;
  i: Integer;

begin
  FFilter.StateLock.Lock;
  try
    if (MediaType = nil) then
    begin
      Result := E_POINTER;
      Exit;
    end;

    if (iPosition < 0) then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -