一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Javacv使用ffmpeg實現音視頻同步播放

Javacv使用ffmpeg實現音視頻同步播放

2021-03-10 14:39_Thomas Java教程

這篇文章主要介紹了Javacv使用ffmpeg實現音視頻同步播放,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

最近用javacv的ffmpeg包的ffmpegframegrabber幀捕捉器對捕捉到的音頻幀和視頻幀做了同步的播放。采用的同步方法是視頻向音頻同步。

程序和源碼

具體的思路如下:

(1)首先介紹ffmpeg是如何捕捉視頻文件的圖像和聲音的

?
1
ffmpegframegrabber fg = new ffmpegframegrabber("a video file path or a url);

得到幀捕捉器對象后,調用它的grab()方法就會返回捕捉到的frame對象。這個frame可以是視頻幀或者是音頻幀,這是因為音視頻幀時按照時間戳在播放時間先上排列的。當然捕捉到的幀都是已經譯碼過的,并且存儲在java.nio.buffer對象中,對于視頻幀,buffer是儲存圖像的像素數據比如rgb,然后通過

?
1
bufferedimage bi = (new java2dframeconverter()).getbufferedimage(f);

就可以得到圖片,得到的圖片可以進行一系列的處理或者不處理直接顯示在swing組件上。對應音頻幀,buffer是儲存音頻的pcm數據,這個pcm可以是float或者short的,然后用java.sounds.sample里面的sourcedataline.write方法就可以將這些音頻pcm數據寫入到揚聲器中。

(2)接著介紹如何不斷得將得到的幀播放出來。首先是單獨播放視頻:

?
1
2
3
4
5
6
7
while(true)
{
  frame f = fg.grab(); 
  if(f.image!=null)
  label.seticon(new imageicon((new java2dframeconverter()).getbufferedimage(f)));
  thread.sleep(1000/視頻幀率); 
}

單獨播放音頻同理,將數據寫入到聲卡即可。例子

(3)生產消費者模式。

Javacv使用ffmpeg實現音視頻同步播放

上圖是程序實現的方法,采用生產者模式將捕獲到的幀進行判斷,如果是視頻幀就生產到視頻fifo中,如果是音頻幀就生產到音頻fifo中,然后音頻播放線程和視頻播放線程分別從各自的幀倉庫消費里面的幀。之所以采用生產消費者模式是因為幀捕獲的速度是大于幀的消耗的,所以我們優先捕獲幀來緩沖,或者進一步對捕獲的幀進行預處理,而視頻和音頻播放線程只需要將處理過的幀直接播放顯示即可。

(4)實現音視頻同步的方法:播放兩幀音頻里面的所有視頻幀。

想要實現音視頻同步,必須要有幀的時間戳,這里捕獲到的幀只有播放的時間戳pts,沒有譯碼時間戳dts,所以我們只需要根據播放時間戳來決定播放即可。

Javacv使用ffmpeg實現音視頻同步播放

程序的實現是根據上圖來的, 當音頻線程開始播放音頻幀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程序,但是其他進程不會影響。

Javacv使用ffmpeg實現音視頻同步播放

Javacv使用ffmpeg實現音視頻同步播放

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/A694543965/article/details/78317479

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精品久久亚洲 | 日本高清视频在线免费观看 | 日本中文字幕二区三区 | 久久久96| 欧美区视频| 亲爱的客栈第二季免费观看完整版 | 久久久久久久久女黄 | 国产91短视频| 色综久久天天综合绕视看 | 波多野结衣在线观看中文字幕 | 亚洲人成毛片线播放 | 描写细腻的高h肉 | 精品国产剧情在线观看 | 欧美乱妇高清无乱码视频在线 | 天天爽天天 | 四虎国产精品免费久久久 | 亚洲性69影视 | 国产精品久久久久久吹潮 | 日韩精品视频在线播放 | 亚洲国产视频一区 | 天天色综合色 | 欧美性4khd720 | 免费成年人在线视频 | 亚洲爱v | 九九热只有精品 | 95视频免费看片 | 国产精品微拍 | 色香视频在线 | 亚洲va天堂va国产va久久 | 日本乱中文字幕系列在线观看 | www久久精品 | 好男人好资源在线观看免费 | 亚洲AV午夜精品麻豆AV | 猛男强攻变sao货 | 糖心视频在线观看 | 亚洲国产精品日韩高清秒播 | 亚洲欧美国产精品久久久 | 欧美日韩国产一区二区三区伦 | 九九精品国产亚洲A片无码 九九99热久久999精品 | 骚虎网站在线观看 | 麻豆在线md0087免费 |