Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Auflösung bei TV-Karten capture (https://www.delphipraxis.net/91474-aufloesung-bei-tv-karten-capture.html)

TheReaper 5. Mai 2007 13:04


Auflösung bei TV-Karten capture
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!

ich will meine analoge tv-Karte über directshow zu capturen, was auch soweit ganz gut funktioniert. nur hab ich extreme probleme mit der qualität der bilder. Sehr geringe Auflösung (165*xxx), die Farben fehlen oder sind nur sehr schwach (siehe screenshot). Meine Frage: warum ist das so? muss ich da noch irgendwelche filter einbinden? oder kann ich das irgendwie anders anpassen?

Hier mal der Code:

Delphi-Quellcode:
function TVideo.InitTuner: Boolean;
var
  pEnum: IEnumMoniker;
  pmoniker: IMoniker;
  pDevEnum: ICreateDevEnum;
  pProcAmp: IAMVideoProcAmp;
  Flags: TVideoProcAmpFlags;
begin
  Result:= false;
  // Create the Filter Graph Manager.
  if Succeeded(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, GraphB)) then
  // Create the Capture Graph Builder.
  if Succeeded(CoCreateInstance(CLSID_CaptureGraphBuilder2, nil,
               CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, CaptureGraph)) then
  begin
    CaptureGraph.SetFiltergraph(GraphB);
  end;

  // get the SourceFilter
  if Succeeded(CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, pDevEnum)) then
  if Succeeded(pDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, pEnum, 0)) then
  if Succeeded(pEnum.Next(1, pmoniker, nil)) then
  if Succeeded(pmoniker.BindToObject(nil, nil, IID_IBaseFilter, sourceFilter)) then
  if Succeeded(Graphb.AddFilter(SourceFilter, 'Capture Filter')) then

  // Get Tuner Interface
  if Failed(CaptureGraph.FindInterface(@LOOK_UPSTREAM_ONLY, nil, SourceFilter, IID_IAMTVTuner, FTVTuner)) then
  begin
    Showmessage('No TV card in system!');
  end else
  if Succeeded(FTVTuner.put_InputType(0, TunerInputCable)) then
  if Succeeded(FTVTuner.put_Mode(AMTUNER_MODE_TV)) then

  // Render CaptureStream
  if Succeeded(CaptureGraph.RenderStream(@PIN_CATEGORY_PREVIEW, @MEDIATYPE_Video, SourceFilter, nil, nil)) then

  // Update ProcAmp um Farben anzupassen. Siht wenigstens etwas besser aus.
  // Query the capture filter for the IAMVideoProcAmp interface.
  if Succeeded(SourceFilter.QueryInterface(IID_IAMVideoProcAmp, pProcAmp)) then
  if Succeeded(pProcAmp.Set_(VideoProcAmp_Brightness, 7500, VideoProcAmp_Flags_Manual)) then
  if Succeeded(pProcAmp.Set_(VideoProcAmp_Hue, 2500, VideoProcAmp_Flags_Manual)) then
  if Succeeded(pProcAmp.Set_(VideoProcAmp_Saturation, 10000, VideoProcAmp_Flags_Manual)) then


  Result:= true;
  ShowGraph(Result);
  Mode:= vmCapture;

{ ... }

end;
und ein Screenshot

TheReaper 6. Mai 2007 18:05

Re: Auflösung bei TV-Karten capture
 
Ich habs nach langem hin und her selbst hin gekriegt. :lol: Der "automatische" Graphbuilder bindet den Overlay Mixer nich mit ein und kann deshalb das bild nich richtig darstellen.
Für die, die es interessiert, hier mal der komplette code:

Delphi-Quellcode:
uses
  DirectShow9;

var
  GraphB: IGraphBuilder = nil;
  FTVTuner : IAMTVTuner = nil;
  CaptureGraph: ICaptureGraphBuilder2 = nil;
  SourceFilter: IBaseFilter = nil;

procedure AddFilter(CLSID: TGUID; FriendlyName: string; out pFilter: IBaseFilter);
begin
  if Succeeded(CoCreateInstance(CLSID, nil, CLSCTX_SERVER, IID_IBaseFilter, pFilter)) then
  if Failed(GraphB.AddFilter(pFilter, StringToOLEStr(FriendlyName))) then
    Showmessage('Error while adding "' + FriendlyName + '" Filter');
end;

function InitTuner: Boolean;
var
  pEnum: IEnumMoniker;
  pmoniker: IMoniker;
  pDevEnum: ICreateDevEnum;
  pmt: PAMMediaType;
  pFilter, pFilter2: IBaseFilter;
  ipin, opin: DirectShow9.IPin;
  pEnumPins: IEnumPins;
begin
  Result:= true;
  // Create the Filter Graph Manager.
  if Succeeded(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, GraphB)) then
  // Create the Capture Graph Builder.
  if Succeeded(CoCreateInstance(CLSID_CaptureGraphBuilder2, nil,
               CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, CaptureGraph)) then
  begin
    CaptureGraph.SetFiltergraph(GraphB);
  end else Result:= false;

  // get the SourceFilter
  if Succeeded(CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, pDevEnum)) then
  if Succeeded(pDevEnum.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, pEnum, 0)) then
  if Succeeded(pEnum.Next(1, pmoniker, nil)) then
  if Succeeded(pmoniker.BindToObject(nil, nil, IID_IBaseFilter, sourceFilter)) then
  if Succeeded(Graphb.AddFilter(SourceFilter, StringToOleStr('Capture Filter'))) then

  // Get Tuner Interface
  if Failed(CaptureGraph.FindInterface(@LOOK_UPSTREAM_ONLY, nil, SourceFilter, IID_IAMTVTuner, FTVTuner)) then
  begin
    Showmessage('No TV card in system!');
    Result:= false;
  end else
  if Succeeded(FTVTuner.put_InputType(0, TunerInputCable)) then
  if Succeeded(FTVTuner.put_Mode(AMTUNER_MODE_TV)) then
  begin
    AddFilter(CLSID_OverlayMixer, 'Overlay Mixer', pFilter);
    AddFilter(CLSID_VideoRenderer, 'Video Renderer', pFilter2);

    // Overlay Mixer -> Video Renderer
    if Succeeded(pFilter.FindPin(StringToOlestr('Output'), oPin)) then
    if Succeeded(GraphB.FindFilterByName(StringToOlestr('Video Renderer'), pFilter2)) then
    if Succeeded(pFilter2.EnumPins(pEnumPins)) then
    if Succeeded(pEnumPins.Next(1, iPin, nil)) then
    if Succeeded(GraphB.Connect(oPin, ipin)) then

    // Capture Filter -> Overlay Mixer
    if Succeeded(CaptureGraph.FindPin(SourceFilter, PINDIR_OUTPUT, @PIN_CATEGORY_PREVIEW, nil, TRUE, 0, oPin)) then
    if Succeeded(pFilter.FindPin(stringtoolestr('Input0'),ipin)) then
      GraphB.Connect(ipin, opin)
    else Result:= false;
  end else Result:= false;

  // Show Graph
  ShowGraph(Result); // eigene Procedur die hier etwas den Rahmen sprengen würde.

  // Release Interfaces
  pMoniker:= nil;
  pDevEnum:= nil;
  pEnum:= nil;
  pEnumPins:= nil;
  iPin:= nil;
  oPin:= nil;
  pFilter:= nil;
  pFilter2:= nil;
 
  if not Result then
  begin
    FTVTuner:= nil;
    CaptureGraph:= nil;
    GraphB:= nil;
  end;
end;
Damit kann man jede Analoge TV-Karte Capturen. Ein Klick auf ein Button reicht zu. Der Code ist noch etwas buggig und schmutzig und noch sehr stark erweiterbar. aber wer lust hat, kann ihn noch verbessern. :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz