Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi DSPack PushSource filter und Audio mixer synchronisieren (https://www.delphipraxis.net/117366-dspack-pushsource-filter-und-audio-mixer-synchronisieren.html)

Arnulf 16. Jul 2008 18:08


DSPack PushSource filter und Audio mixer synchronisieren
 
Hallo
Ich hab mich notgedrungen mit DSPack auseinander gesetzt und weiß nicht mehr weiter.
Ich verwende einen PushSource filter ( umgebaut um von einer memory map zu lesen ).
Dazu möchte ich vom mixer audio aufnehmen.

Mein Problem ist jetzt, dass ich nicht weiß wie ich Video und Audio synchron bekomme.
Ich hab das bereits auf http://www.progdigy.com/ gefragt, aber es is sehr wenig los dort.

hier meine konstruktion:
http://i59.photobucket.com/albums/g3...oe0/Filter.jpg

der memmapfilter ist 99% pushsourcedesktop filter.

hoffe es kann mir hier jemand helfen.

lg
Arnulf

Arnulf 18. Jul 2008 20:43

Re: DSPack PushSource filter und Audio mixer synchronisieren
 
Hi
also leider hab ich keine methode gefunden um das zu synchronisieren.
das hier hat leider auch nicht funktioniert, obwohl die msdn seite das behauptet:

Delphi-Quellcode:
with Multiplexer as IConfigAviMux do
     begin
          setmasterstream(1);
     end;

     with Multiplexer as IConfigInterleaving do
     begin
          put_Mode(INTERLEAVE_FULL);
     end;
sollte jemand sowas schon versucht haben und es geschafft haben das zu synchronisieren dann nicht aufhalten lassen mit tips zu geben :)

lg
Arnulf

lbccaleb 18. Jul 2008 23:08

Re: DSPack PushSource filter und Audio mixer synchronisieren
 
schreib mal einen dspack programmierer per email an...
weiterhelfen können die dir auf jedenfall, hast du auch schon das komplette forum auf der prodigy seite durchstöbert?? denn sehr geordnet ist das dort nicht, viele themen in einem fred beantwortet...

Arnulf 19. Jul 2008 20:59

Re: DSPack PushSource filter und Audio mixer synchronisieren
 
Ja das Forum hab ich durchstöbert.
Bin auf keine guten Vorschläge gestoßen.
Ich Beschäftige mich mit DSPack jetzt ca. eine Woche und hab nicht annähernd alles verstanden.

Aber die Methoden scheinen die einzigen vorschläge zu sein das zu synchronisieren.
Ich denke ich sollte ersteinmal einen anderen Codec finden.

Einen der schnell genug ist meine Daten auch zu verarbeiten.
Das ist momentan meine einzige Alternative.

Kennt also jemand einen Video Encoder, der Bitmaps akzeptiert und diese live komprimiert, bzw. schnell genug auf die Festplatte speichern kann?

Xvid scheint einfach zu langsam zu sein ( Microsoft DV hab ich ebenfalls versucht ).
Die Kompression ist nicht Vorrangig sondern es darf einfach kein frame drop stattfinden und er muss sehr schnell sein ( wenn frames verloren gehen, dann stimm auch audio nicht mehr - das ist schonmal eines meiner probleme denke ich ).

Hoffe es kann mir noch jemand helfen.

lg
Arnulf

lbccaleb 20. Jul 2008 01:07

Re: DSPack PushSource filter und Audio mixer synchronisieren
 
hast du dir mal das bsp aus dem ordner:

"dspack\demos\d6-d7\videocap"

angesehen?? das sollte eigentlich was für dich sein... damit bekommst du das hinn...


ich hätte aber auch noch ne (leider kostenpflichtige) sehr gute grabber komponente, den TVideoGrabber, finden kannst du ihn auf hier
der ist für video aufnahmen sehr zu empfehlen..

kannst dir ja mal ansehen...

Arnulf 21. Jul 2008 13:37

Re: DSPack PushSource filter und Audio mixer synchronisieren
 
Ui - 600 - 3000 $ ist mir etwas zu viel :).

Ich kann ja mal das Demo probieren.
Das Demo von DSPack - dürfte auch nich ganz sync sein, und scheinbar machen die nichts anderes als ich.
Das Problem bei mir ist, dass ich einen PushSource Filter habe und keinen Capture oder Preview.

Jedenfalls lasse ich mal Source Code sprechen - vielleicht fällt jemanden ja auf was kompletter unsinn ist.
Tut mir leid, dass der Code so ein Chaos ist, aber wenn man schon seit tagen alles mögliche herumprobiert, kommt sowas raus.

Main Project Filter Initialisation und Rendering:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var CaptureFile: WideString;
    Writer: IFileSinkFilter;
    Multiplexer : IBaseFilter;
    SysDev: TSysDevEnum;
begin
     if FileExists('c:\test.avi') then deletefile('c:\test.avi');
     if InjectLibrary then
     begin

     //. todo : check for injected lib instead of sleep
     sleep (2000);
     memo1.Lines.Add('ok');

     SysDev:= TSysDevEnum.Create;
     //. todo - do not hardcode indexcategory
     SysDev.SelectIndexCategory(1);
     MemMapSelfCreated.BaseFilter.Moniker := SysDev.GetMoniker(SysDev.FilterIndexOfFriendlyName('Memory Map BitmapFilter'));
     memo1.Lines.Add(' using:' + SysDev.Filters[SysDev.FilterIndexOfFriendlyName('Memory Map BitmapFilter')].FriendlyName );

     if FilterGraph1.Active then FilterGraph1.Active := false;
     FilterGraph1.ClearGraph;
     FilterGraph1.Active:= True;
     FilterGraph1.GraphEdit := True;
     CaptureFile := 'c:\test.avi';
     MemMapSelfCreated.FilterGraph := FilterGraph1;
     //VideoWindow1.FilterGraph := FilterGraph1;
     with FilterGraph1 as ICaptureGraphBuilder2 do
     begin
          SetOutputFileName(MEDIASUBTYPE_Avi, PWideChar(CaptureFile), Multiplexer, writer);
          //ShowFilterPropertyPage(Self.Handle, Multiplexer as IBaseFilter, ppDefault);
          //RenderStream(nil, @MEDIATYPE_Video, MemMapSelfCreated as IBaseFilter,
          //        {DivXCompressor as IBaseFilter} nil, VideoWindow1 as IBaseFilter);
          RenderStream(nil{@PIN_CATEGORY_CAPTURE}, @MEDIATYPE_Video, MemMapSelfCreated{MemMapSource} as IBaseFilter,
                  DivXCompressor as IBaseFilter, Multiplexer as IBaseFilter);
          //ShowFilterPropertyPage(Self.Handle, DivXCompressor as IBaseFilter, ppVFWCompConfig);
          RenderStream(nil{@PIN_CATEGORY_CAPTURE}, @MEDIATYPE_Audio, AudioSource as IBaseFilter,
                  Mp3Compressor as IBaseFilter, Multiplexer as IBaseFilter);
     end;
     with Multiplexer as IConfigAviMux do
     begin
          setmasterstream(1);
     end;

     with Multiplexer as IConfigInterleaving do
     begin
          put_Mode(INTERLEAVE_FULL);
     end;
     FilterGraph1.Play;
     end;

end;
Anmerkung:
DivXCompressor: hier habe ich divx, HuffYuV und Mjpeg ausprobiert - mit teilweise besseren und schlechteren ergebnissen.
Mjpeg scheint am bessten zu funktionieren.
HuffYuV spielt im video dann als slow motion??? - keine ahnung warum
DivX hat zu viele frame loss - dürfte zu langsam sein für live capture von einem PushSoure filter ( 800x600 24 bit bitmap mit 25 fps )
Mp3Compressor: hier habe ich sowol mpeg layer3 also auch keinen kompressor versucht ... macht nicht viel unterschied.
Der Filter Selbst:
Delphi-Quellcode:
function TBCPushPinDesktop.FillBuffer(Sample: IMediaSample): HResult;
var
  pData: PByte;
  cbData: Longint;
  pvih: PVIDEOINFOHEADER;
  Start, Stop: REFERENCE_TIME;

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

function CopyMemToBitmap(pData : PByte;
    pHeader : PBitmapInfo) : boolean;
//var
    //FileHeader : BITMAPFILEHEADER;
begin
     Result := false;
    if not (FSpeicher = nil) then
    begin
         //copymemory(@FileHeader,FSpeicher,Sizeof(BITMAPFILEHEADER));
         copymemory(@pHeader.bmiHeader, Pointer(DWord(FSpeicher)+sizeOf(BITMAPFILEHEADER)), SizeOf(BITMAPINFOHEADER));
         copymemory(pData, Pointer(DWord(FSpeicher) + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)),pHeader.bmiHeader.biSizeImage);
    Result := true;
    end;

end;


begin
  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));

    pvih := 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.
    pVih.bmiHeader.biSizeImage := min(pVih.bmiHeader.biSizeImage, cbData);
    if (WaitForSingleObject(myMutex, 100) = WAIT_OBJECT_0) then
    begin
        CopyMemToBitmap(pData, @pVih.bmiHeader);
        Result := S_OK;
    end;// else Result := S_FALSE;
    ReleaseMutex(myMutex);
    Result := S_OK;

    // 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);
  finally
    FSharedState.UnLock;
  end;
end;
Anmerkung:
Hier habe ich vor allem mit dem Mutex gespielt - timeout von 100 ms funktionert im video window sehr gut ( sollte niemals so lange warten müssen ).
Auch mit dem Result hab ich herumprobiert, ob das jemals false werden sollte weiß ich nicht, aber es macht keinen unterschied nach meiner erfahrung.
start/stop Time und SetSyncPoint sind aus dem originalen pushsource filter und dürfte so stimmen, aber sicher bin ich nicht.

lg
Arnulf


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

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