English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Javacv die Verwendung von ffmpeg für die Synchronisation der Audio-Video-Wiedergabe

最近用javaCV的ffmpeg包的FFmpegFrameGrabber帧捕捉器对捕捉到的音频帧和视频帧做了同步的播放。采用的同步方法是视频向音频同步。

程序和源码

具体的思路如下:

)1首先介绍ffmpeg是如何捕捉视频文件的图像和声音的

FFmpegFrameGrabber fg = new FFmpegFrameGrabber("a video file path or a url"); 

得到帧捕捉器对象后,调用它的grab()方法就会返回捕捉到的Frame对象。这个Frame可以是视频帧或者是音频帧,这是因为音视频帧是按照时间戳在播放时间先上排列的。当然捕捉到的帧都是已经解码过的,并且存储在java.nio.Buffer对象中,对于视频帧,Buffer是存储图像的像素数据比如RGB,然后通过

BufferedImage bi = (new Java2DFrameConverter()).getBufferedImage(f); 

可以得到图片,得到的图片可以进行一系列的处理或者不处理直接显示在swing组件上。对应音频帧,Buffer是存储音频的PCM数据,这个PCM可以是float或者short的,然后用java.sounds.sample里面的sourceDataLine.write方法就可以将这些音频PCM数据写入到扬声器中。

)2)Dann wird erläutert, wie die erhaltenen Frames kontinuierlich wiedergegeben werden. Zunächst das Abspielen eines Videos allein:

while(true) 
{ 
  Frame f = fg.grab();  
  if(f.image!=null) 
  label.setIcon(new ImageIcon((new Java2DFrameConverter()).getBufferedImage(f))); 
  Thread.sleep(1000/Videoframerate);  
} 

Einzelnes Abspielen von Audio funktioniert ebenfalls, indem die Daten in die Soundkarte geschrieben werden. Beispiel

)3)Produktions- und Verbrauchermuster.

Das obige Bild ist die Methode der Programmimplementierung. Es wird der Produktionsmodus verwendet, um die erfassten Frames zu bewerten. Wenn es sich um ein Videoframe handelt, wird es in den VideofIFO produziert, wenn es sich um ein Audiodatenpaket handelt, wird es in den Audiodaten-FIFO produziert. Dann konsumieren die Audiostream- und Videostream-Playthreads die Frames aus ihren eigenen Frame-Lagern. Der Grund, warum das Produktions- und Verbrauchermuster verwendet wird, ist, dass die Geschwindigkeit der Frame-Capture schneller ist als der Verbrauch der Frames, daher wird der Frame bevorzugt erfasst, um zu puffern, oder weiter vorzuverarbeiten, und die Videostream- und Audiostream-Playthreads müssen nur die behandelten Frames direkt abspielen und anzeigen.

)4)Methode zur Synchronisation von Audio und Video: Abspielen aller Video-Frames in zwei Audio-Frames.

Um die Synchronisation von Audio und Video zu erreichen, müssen Zeitstempel der Frames vorhanden sein. Hier wurde nur der Wiedergabezeitstempel PTS des Frames erfasst, nicht der Dekodierungszeitstempel DTS, daher müssen wir nur basierend auf dem Wiedergabezeitstempel entscheiden, ob abgespielt wird.

Die Implementierung des Programms basiert auf dem obigen Bild, wenn der Audiostream beginnt, das Audiodatenpaket A abzuspielen1Aufruf der Methode setRun des Videostreams, und Übermittlung des aktuellen Zeitstempels des abzuspielenden Audiodatenpakets curTime und des nächsten Audiodatenpakets A2Zeitstempel nextTime wird dem im Wartezustand befindlichen Videostream übergeben, dann startet der Videostream und beginnt, das VideofIFO auszulesen, um das Videodatenpaket G herauszunehmen1Dann wird G1und A1Differenz in Zeitstempeln, als Verzögerung zur Wiedergabe, Thread.sleep(t1)Dann wird das Bild im Swing-Component, wie z.B. JLabel.setIcon(image), angezeigt. Dann wird ein weiteres Bild G aus dem Lager ausgegeben2Vergleich G2Zeitstempel und A2Zeitstempel, wenn G2Zeitstempel kleiner als A2Dann wird der Videostream weiter verzögert um t2Danach wird dieses G abgespielt2Bilder, dann G3Dasselbe, bis G erreicht wird4, und A2Vergleich zeigt G4Zeitstempel größer als A2Dann tritt der Videostream in den Wartezustand ein und wartet auf den nächsten Start. Dann wird der Audiostream A abgespielt1Nachdem das Audiodatenpaket A abgespielt wurde, wird aus dem Lager das Audiodatenpaket A entnommen.3Dann wird A2Zeitstempel und A3Zeitstempel wird an den Videostream übergeben und dann wird A abgespielt.2Dann wird der blockierte Videostream analog fortgesetzt.

)5)动态调节延时时间

dynamisch die Verzögerungszeit anpassen3bis A2da die meisten PC nicht Echtzeitbetriebssysteme sind, dh Thread.sleep ist nicht genau und wird durch die Soundkarte begrenzt, daher muss die obige grundlegende Implementierungsweise verbessert werden. Zunächst holen die Methoden von java.sourceDataLine nach einem bestimmten Tempo Daten aus dem internen Puffer ab, die vom Audio-Thread in die Datenmenge geschrieben werden. Wenn die Datenmenge vollständig abgeholt wird, tritt eine Verlangsamung beim Abspielen von Audio auf, aber wenn zu viele Daten einmalig in die Datenmenge geschrieben werden, könnte es zu einer möglichen Un synchronisation von Audio und Video kommen, daher muss sichergestellt werden, dass der interne Puffer von sourceDataLine eine bestimmte Datenmenge aufweist, sonst könnte es zu Verlangsamungen kommen, aber die Datenmenge darf nicht zu groß sein, daher müssen wir in G1Diese Zeit wird zur Anpassung der Tonabspielfunktion verwendet, da die Verzögerung nicht genau ist, kann die in A geschriebene Datenmenge aufgrund der Verzögerung nicht genau sein6könnte vollständig von der Soundkarte abgeholt werden, daher könnten die Daten des G nach dem Abspielen der Datenmenge noch nicht vollständig sein t3Nachdem das Bild der Bilder abgespielt wurde, wird der Sound-Thread beurteilen, basierend auf der Datenmenge, die von sourceDataLine.available() zurückgegeben wird. Wenn die Datenmenge fast aufgebraucht ist, wird G reduziert3bis A2Verzögerungszeit t4. Auf diese Weise kann sichergestellt werden, dass die Datenmenge nicht 0 wird, was das Abspielen von Tönen verlangsamen könnte.

)6)Hier ist das Programm im Fenster64Test und Ubuntu14Das Testergebnisbild unten: DerPlayback läuft flüssig ab, die Synchronisation ist ebenfalls in Ordnung, aber wenn man gleichzeitig spielt und im IDE wie IDEA codiert, wird es flüchtig, da IDEA auch in Java entwickelt wurde. Daher kann die Ausführung von IDEA andere Java-Programme beeinflussen, aber andere Prozesse nicht.


Das ist der vollständige Inhalt dieses Artikels. Wir hoffen, dass er Ihnen bei Ihrem Lernen hilft und dass Sie die Anleitung mehr unterstützen.

Erklärung: Der Inhalt dieses Artikels wurde aus dem Internet übernommen und gehört dem Urheberrecht des jeweiligen Autors. Der Inhalt wurde von Internetnutzern freiwillig beigesteuert und hochgeladen. Diese Website besitzt keine Eigentumsrechte und hat den Inhalt nicht manuell bearbeitet. Sie übernimmt auch keine Haftung für relevante rechtliche Verantwortlichkeiten. Wenn Sie Inhalte entdecken, die möglicherweise gegen das Urheberrecht verstoßen, sind Sie herzlich eingeladen, eine E-Mail an notice#w zu senden.3codebox.com (Bitte ersetzen Sie # durch @ beim Senden einer E-Mail zur Meldung von Verstößen und stellen Sie relevante Beweise zur Verfügung. Sobald nachgewiesen wird, dass eine Verletzung vorliegt, wird diese Website die betreffenden Inhalte sofort löschen.)

Gefällt mir