热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Javacv使用ffmpeg实现音视频同步播放

这篇文章主要介绍了Javacv使用ffmpeg实现音视频同步播放,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

最近用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)接着介绍如何不断得将得到的帧播放出来。首先是单独播放视频:

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

单独播放音频同理,将数据写入到声卡即可。例子

(3)生产消费者模式。

上图是程序实现的方法,采用生产者模式将捕获到的帧进行判断,如果是视频帧就生产到视频FIFO中,如果是音频帧就生产到音频FIFO中,然后音频播放线程和视频播放线程分别从各自的帧仓库消费里面的帧。之所以采用生产消费者模式是因为帧捕获的速度是大于帧的消耗的,所以我们优先捕获帧来缓冲,或者进一步对捕获的帧进行预处理,而视频和音频播放线程只需要将处理过的帧直接播放显示即可。

(4)实现音视频同步的方法:播放两帧音频里面的所有视频帧。

想要实现音视频同步,必须要有帧的时间戳,这里捕获到的帧只有播放的时间戳PTS,没有译码时间戳DTS,所以我们只需要根据播放时间戳来决定播放即可。

程序的实现是根据上图来的, 当音频线程开始播放音频帧A1时,就调用视频线程的setRun方法,并且传递当前要播放的音频帧时间戳curTime和下一帧音频帧A2的时间戳nextTime给处于wait态的视频线程,然后视频线程启动,开始从视频FIFO中取出视频帧G1,然后计算G1和A1的时间差,作为播放的延时,Thread.sleep(t1)后,视频线程就将图片显示在swing组件上,比如JLabel.setIcon(image)。然后视频线程再取出一帧图像G2,比较G2的时间戳和A2的时间戳,如果G2时间戳小于A2,那么视频线程继续延时t2以后,播放这个G2图像,接着G3同理,直到取得G4,和A2比较发现G4时间戳大于A2,那么视频线程就进入wait态,等待下一次启动。然后音频线程播放完A1音频帧以后,就从仓库取出音频帧A3,然后将A2的时间戳和A3的时间戳传递给视频线程,然后开始播放A2,然后堵塞的视频线程同理继续播放。

(5)动态调节延时时间

由于个人PC都不是实时操作系统,也就是Thread.sleep是不精确的,并且受到声卡播放声音的制约,所以上面的基本实现思路是需要加以完善的。首先java的sourceDataLine的方法是依照一定的速度从内部缓冲区取出音频线程写入的数据,如果音频写入的数据被取光了,那么音频播放就会发生卡顿,但是如果一次音频数据写入过多,那么就会发生音视频可能就会不同步,所以要确保sourceDataLine的内部缓冲区是留有一定数据的,否则就会造成卡顿,但是数据量又不能过多,所以我们在G3到A2这段时间来进行声音播放的调节,由于延时的不精准性,写入的A1帧的数据可能时间还没满t6就可能被声卡取光了,所以在播放完G3图像以后,声音线程会判断根据sourceDataLine.available()返回的数据量进行判断,如果数据量快要完了,就减少G3到A2的延时时间t4。这样子就可以保证数据量是不会变为0造成声音卡顿。

(6)下面是程序在window64下测试和ubuntu14下测试的结果图:  播放是比较流畅的,同步也是可以的,但是开着播放比企鹅在IDE如IDEA中写代码的话,会卡,毕竟IDEA也是用java开发的,所以IDEA的运行会影响其他java程序,但是其他进程不会影响。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 本文介绍如何在Linux Mint系统上搭建Rust开发环境,包括安装IntelliJ IDEA、Rust工具链及必要的插件。通过详细步骤,帮助开发者快速上手。 ... [详细]
  • 自己用过的一些比较有用的css3新属性【HTML】
    web前端|html教程自己用过的一些比较用的css3新属性web前端-html教程css3刚推出不久,虽然大多数的css3属性在很多流行的浏览器中不支持,但我个人觉得还是要尽量开 ... [详细]
  • PHP 时间与日期工具类:星座、干支、生肖的实现
    本文介绍了一个PHP时间与日期工具类,涵盖了时区设置、有效日期和时间检查、星座、干支、生肖计算等功能。该工具类特别适用于需要处理中国农历及西方星座的应用场景。 ... [详细]
  • PHP插件机制的实现方案解析
    本文深入探讨了PHP中插件机制的设计与实现,旨在分享一种可行的实现方式,并邀请读者共同讨论和优化。该方案不仅涵盖了插件机制的基本概念,还详细描述了如何在实际项目中应用。 ... [详细]
  • 在Ubuntu 8.04中安装美观的Cairo-Dock桌面增强工具
    本文介绍如何在Ubuntu 8.04系统中安装和配置Cairo-Dock,这款桌面增强工具以其精美的界面和高效的功能备受用户青睐。文章将指导您通过简单的步骤完成安装,并提供一些实用的配置建议。 ... [详细]
  • 选择适合生产环境的Docker存储驱动
    本文旨在探讨如何在生产环境中选择合适的Docker存储驱动,并详细介绍不同Linux发行版下的配置方法。通过参考官方文档和兼容性矩阵,提供实用的操作指南。 ... [详细]
  • 云计算的优势与应用场景
    本文详细探讨了云计算为企业和个人带来的多种优势,包括成本节约、安全性提升、灵活性增强等。同时介绍了云计算的五大核心特点,并结合实际案例进行分析。 ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • ThinkPad USB 硬盘启动 Ubuntu 系统的详细步骤
    本文介绍如何通过USB硬盘在联想ThinkPad上启动Ubuntu系统,包括BIOS设置和启动优先级调整。 ... [详细]
  • 本文详细介绍了如何在预装Ubuntu系统的笔记本电脑上安装Windows 7。针对没有光驱的情况,提供了通过USB安装的具体方法,并解决了分区、驱动器无法识别等问题。 ... [详细]
  • JavaScript 中创建对象的多种方法
    本文详细介绍了 JavaScript 中创建对象的几种常见方式,包括对象字面量、构造函数和 Object.create 方法,并提供了示例代码和属性描述符的解释。 ... [详细]
  • 嵌入式开发环境搭建与文件传输指南
    本文详细介绍了如何为嵌入式应用开发搭建必要的软硬件环境,并提供了通过串口和网线两种方式将文件传输到开发板的具体步骤。适合Linux开发初学者参考。 ... [详细]
  • 本文详细介绍了如何在PHP中进行数组删除、清空等操作,并提供了在Visual Studio Code中创建PHP文件的步骤。 ... [详细]
author-avatar
牛涛fd_501
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有