Récemment, le capturant de trame FFmpegFrameGrabber utilisant le package FFMPEG de JAVACV a synchronisé les cadres audio capturés et les cadres vidéo. La méthode de synchronisation utilisée est de synchroniser la vidéo en audio.
Programmes et codes source
Les idées spécifiques sont les suivantes:
(1) Introduisez d'abord la façon dont FFMPEG capture les images et les sons des fichiers vidéo
FfmpegFramegrabber fg = new ffmpegframegrabber ("un chemin de fichier vidéo ou une URL); Après avoir obtenu l'objet de capture de trame, l'appel de sa méthode Grab () renverra l'objet de trame capturé. Ce cadre peut être un cadre vidéo ou un cadre audio, car les cadres audio et vidéo sont disposés en premier au moment de la lecture en fonction de l'horodatage. Bien sûr, les cadres capturés sont tous décodés et stockés dans l'objet java.nio.buffer. Pour les cadres vidéo, le tampon doit stocker les données de pixels de l'image, comme RVB, puis passer
BufferedImage Bi = (new Java2DFraMeConverter ()). GetBufferedImage (f);
Vous pouvez obtenir l'image et l'image obtenue peut être traitée dans une série de processus ou affichée directement sur le composant swing sans traitement. Correspondant à la trame audio, le tampon est les données PCM qui stocke l'audio. Ce PCM peut être flottant ou court, puis la méthode SourceDataline.Write dans Java.sounds.sample peut être utilisée pour écrire ces données PCM audio sur le haut-parleur.
(2) Introduisez ensuite comment jouer en continu les cadres obtenus. Tout d'abord, lisez la vidéo séparément:
while (true) {cadre f = fg.grab (); if (f.image! = null) label.seticon (new ImageIcon ((new java2dframeConverter ()). getBufferedImage (f))); Thread.Sleep (1000 / fréquence d'images vidéo); } Il en va de même pour la lecture de l'audio séparément, écrivez simplement les données sur la carte son. exemple
(3) Production et modèle de consommation.
L'image ci-dessus est une méthode implémentée par le programme. Les cadres capturés sont jugés à l'aide du mode producteur. S'il s'agit d'un cadre vidéo, il sera produit dans la vidéo FIFO. S'il s'agit d'un cadre audio, il sera produit dans l'audio FIFO. Ensuite, le fil de lecture audio et le fil de lecture vidéo consomment les trames de leurs entrepôts de cadre respectifs respectivement. Le mode de consommation de production est adopté car la vitesse de capture du cadre est supérieure à la consommation de trames, nous préférons donc capturer des cadres pour la mise en mémoire tampon, ou prétraiter davantage les cadres capturés, tandis que les fils de lecture vidéo et audio n'ont besoin que de jouer et d'afficher directement les cadres traités.
(4) Méthodes pour réaliser la synchronisation audio et vidéo: lisez toutes les trames vidéo dans deux images d'audio.
Pour obtenir une synchronisation audio et vidéo, vous devez avoir un horodatage à cadre. Les cadres capturés ici ne sont que les pts de la lecture de lecture, et il n'y a pas de DTS d'horoddeau décodé, nous n'avons donc qu'à décider de l'horodatage de lecture en fonction de l'horodatage de lecture.
La mise en œuvre du programme est basée sur la figure ci-dessus. Lorsque le thread audio commence à lire le cadre audio A1, la méthode setRun du thread vidéo est appelée, et le curne d'homme du trame audio et le prochain coup de la trame audio suivante A2 sont transmises au thread vidéo dans l'état d'attente. Ensuite, le fil vidéo démarre et commence à éliminer le cadre vidéo G1 à partir de la vidéo FIFO, puis calcule la différence de temps entre G1 et A1 comme retard de lecture. Après Thread.Sleep (T1), le fil vidéo affiche l'image sur le composant swing, comme JLabel.seTICon (image). Ensuite, le fil vidéo supprime un autre cadre d'image G2 et compare l'horodatage de G2 avec l'horodatage d'A2. Si l'horodatage de G2 est inférieur à A2, le fil vidéo continue de retarder T2 et joue l'image G2. Ensuite, G3 est le même qu'il le devrait, jusqu'à ce que G4 soit obtenu et A2 est comparé à A2 et constate que l'horodatage de G4 est supérieur à A2, puis le fil vidéo entre dans l'état d'attente et attend le démarrage suivant. Ensuite, après que le fil audio a lu le cadre audio A1, il élimine le cadre audio A3 de l'entrepôt, puis passe l'horodatage d'A2 et les horodatages d'A3 au fil vidéo, puis commence à jouer A2, puis le fil vidéo bloqué continue de jouer.
(5) ajuster dynamiquement le temps de retard
Étant donné que les PCS personnels ne sont pas des systèmes d'exploitation en temps réel, c'est-à-dire que Thread.Sleep est inexact et est limité par la carte son pour lire le son, les idées de mise en œuvre de base ci-dessus doivent être améliorées. Tout d'abord, la méthode SourceDataline Java consiste à extraire les données écrites par le thread audio à partir du tampon interne à une certaine vitesse. Si les données écrites par l'audio sont retirées, la lecture audio sera bégayée. Cependant, si trop de données audio sont écrites à un moment donné, l'audio et la vidéo peuvent être hors synchronisation. Par conséquent, il est nécessaire de s'assurer que le tampon interne de la sourcédataline a certaines données, sinon elle entraînera un décalage, mais la quantité de données ne peut pas être trop. Par conséquent, nous ajustons la lecture sonore de G3 à A2. En raison de l'inexactitude du retard, les données écrites dans le cadre A1 peuvent être supprimées par la carte son avant l'atteinte de T6. Par conséquent, après avoir joué l'image G3, le fil du son jugera pour juger en fonction de la quantité de données renvoyées par SourceDataline.Vailable (). Si la quantité de données est sur le point d'être terminée, le temps de retard T4 de G3 à A2 est réduit. Cela garantit que le volume de données ne changera pas à 0 et ne provoquera pas le bégaiement.
(6) Voici le diagramme de résultat du test du programme sous Windows 64 et Ubuntu14: La lecture est relativement fluide, et la synchronisation est également possible, mais si la lecture est activée, elle sera bloquée si Penguin écrit du code dans IDE, comme l'idée. Après tout, l'idée est également développée en Java, donc le fonctionnement de l'idée affectera d'autres programmes Java, mais d'autres processus ne le feront pas.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.