1. 程式人生 > >ffmpeg+sdl教程----編寫一個簡單的播放器5(同步視訊到音訊)

ffmpeg+sdl教程----編寫一個簡單的播放器5(同步視訊到音訊)

    個人認為,這這部分教程的新增程式碼量雖然不是最多的,難度卻是最大的,重複看了多次才明白,因為有兩個問題的困擾,搞得還不清楚:

1.音訊和視訊既然都有各自的時間戳,各自按各自的時間戳來播放不就行了,為什麼還需要同步呢?

2.如果要把視訊同步到音訊,怎麼同步?或者說以什麼標準來同步?

    第一個問題的答案可能是,一是音訊和視訊的開始播放的時間是不一樣,二是播放每幀音訊或視訊時可能必須把解碼資料,視訊格式轉換消耗的時間考慮進來,解碼資料,視訊格式轉換等步驟又和不同的機器配置相關,設想一下這種極端的情況,有一幀圖片應該在此時刻播放了(根據時間戳),而解碼器還沒來及解碼完(程式程式碼或者機器配置太爛),解碼完後,可能需要丟棄該幀,不然視訊趕不上音訊。

    第二個問題的答案也不是很清楚,但根據這個教程的程式碼來分析,特別是video_refresh_timer函式中關於時間戳部分的程式碼告訴了這個問題答案,首先大結構體VideoState儲存了兩個用於同步的兩個重要變數audio_clock和video_clock,分別儲存了音訊和視訊的播放了多長時間,也就是教程中說的音訊和視訊的內部時鐘。把視訊同步到音訊的方法就是比較video_clock(當前視訊播放到的時刻)和audio_clock(當前音訊播放到的時刻)差的絕對值如果大於同步閾值sync_threshold,就重新計算延遲delay,這時視訊如果播放得太快就直接讓延遲delay = 2*delay,反之則立即播放。而video_clock和audio_clock之差在可接受範圍內,delay的值直接取上一幀和當前幀的延遲,delay將被用於下一幀的播放延遲。

    時鐘的同步,教程中分為三個部分。

    第一部分講如何儲存視訊幀的時間戳和video_clock,程式碼主要在video_thread函式中,該函式中的這行程式碼len1 = avcodec_decode_video(is->video_st->codec, pFrame, &frameFinished,packet->data, packet->size);解碼packet中的資料到pFrame時,會呼叫我們自己些的幀記憶體分配函式our_get_buffer,把第一個包的時間戳儲存到幀pFrame中(一個幀可能由多個數據包組成),幀的時間戳優先取最後一個包的dts,沒有才取第一個包的pts,都沒有就取video_clock。

   video_thread函式在解碼完一幀後,立馬呼叫synchronize_video函式,synchronize_video函式的作用就是維護video_clock的值,讓video_clock變數始終儲存視訊播放了多長時間的資訊,其中還考慮到了幀重複的問題。得到當前視訊幀的時間戳相對音訊來說簡單些。

    第二部分講,假設我們能得到當前音訊的時間戳,如何讓視訊同步到音訊,也就是上面第二個問題的答案。

    第三部分講如何獲得當前音訊幀的時間戳,程式碼主要在get_audio_clock函式中,這個並不是簡單地返回is->audio_clock了事,如果那樣做就忽略了把資料包轉移到輸出緩衝的時間花費,我們聲音時鐘中記錄的時間比實際的要早太多。所以我們必須要檢查一下我們還有多少沒有寫入。audio_clock的維護工作交給了audio_decode_frame函式來處理,首先在函式末尾初始化is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;然後解碼完一幀音訊後又有更新。

相關推薦

ffmpeg+sdl教程----編寫一個簡單播放5(同步視訊音訊)

    個人認為,這這部分教程的新增程式碼量雖然不是最多的,難度卻是最大的,重複看了多次才明白,因為有兩個問題的困擾,搞得還不清楚: 1.音訊和視訊既然都有各自的時間戳,各自按各自的時間戳來播放不就行了,為什麼還需要同步呢? 2.如果要把視訊同步到音訊,怎麼同步?或者說以什麼

分享個人寫的一個簡單播放

(function(win,doc){ var playerSetting = { width:150, height:300, controlsBoxColor:"#000", controlsBoxMinHeight:"40px", currentTimeLineBox:"

TextureView+MediaPlayer的一個簡單播放

1.佈局檔案: <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.androi

Golang中使用heap編寫一個簡單高效的定時模塊

true pop 邏輯 .com light 初始化 callback before cell 定時器模塊在服務端開發中非常重要,一個高性能的定時器模塊能夠大幅度提升引擎的運行效率。使用Golang和heap實現一個通用的定時器模塊,代碼來自:https://github.

如何用Java編寫一個簡單的服務和客戶機

exce 解決 對賬 location exceptio acc 明顯 隊列 客戶 今天我要向大家介紹的是自己編寫的一個比較簡單的服務器和客戶機程序,註意一下哦,比較簡單。好了,閑話休提,砸門直入主題。 小編先從客戶機和服務器的模型開始講解。

Android簡單編寫一個txt閱讀(沒有處理字符編碼),適用於新手學習

選項 tro 源碼 tin open 打開文件 package idt pac   本程序只是使用了一些基本的知識點編寫了一個比較簡單粗陋的txt文本閱讀器,效率不高,只適合新手練習。所以大神勿噴。   其實想到編寫這種程序源自本人之前喜歡看小說,而很多小說更新太慢,所以本

ffmpeg 簡單播放

#include <unistd.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h>

Golang中使用heap編寫一個簡單高效的定時模組

package timer import ( "container/heap" // Golang提供的heap庫 "fmt" "os" "runtime/debug" "sync" "time" ) const ( MIN_TIMER_INTERVAL = 1

Qt編寫的RTSP播放+視訊監控(ffmpeg版本)

記得四年前就寫了個簡易版本的,當時寫得非常粗糙,程式碼實在慘不忍睹,時隔多年後,重新寫了個版本,同時還解決了以前不支援6畫面8畫面切換等異形佈局的問題。1:可以用過目錄下的rtsp.txt設定要顯示的視訊流地址。2:支援4畫面+6畫面+8畫面+9畫面+16畫面切換。3:支援雙

ROS學習--(十二)編寫一個簡單的釋出(publisher)

1.mkdir -p ~/catkin_ws/src/beginner_tutorials/src 先在beginner_tutorials下建立一個src。 -p的意思是如果路徑中有不存在的資料夾,則建立 2。在新建的資料夾裡面新建cpp檔案,talker

OSGI實戰教程【Spring DM】編寫一個簡單的Bundle元件

OSGI實戰教程 關鍵字: Spring DM 、 Felix 、 Karaf 、ServiceMix 、 OSGI 本教程使用相關工具: 1、開發工具:Eclipse 2、依賴管理:Maven 3、OSGI容器:ServiceMix 目標:教程

【原】shell編寫一個簡單的jmeter自動化壓測腳本

image tac vbo 用戶數 osx dot png das uvc 在公司做壓力測試也挺長時間了,每次測試前環境數據準備都需要話費較長時間,所以一直在考慮能不能將整個過程實現自動化進行,於是就抽空寫了一個自動化腳本,當然這個腳本目前功能十分簡陋,代碼也不完善,很有很

手把手教你編寫一個簡單的PHP模塊形態的後門

cpp rest xtu job ring 事先 們的 original call 看到Freebuf 小編發表的用這個隱藏於PHP模塊中的rootkit,就能持久接管服務器文章,很感興趣,苦無作者沒留下PoC,自己研究一番,有了此文 0×00. 引言 PHP是一個非常流行

編寫一個簡單的TCP服務端和客戶端

不同的 大連 終端 服務器端 com 讀寫 所有 字數 資料 下面的實驗環境是linux系統。 效果如下: 1.啟動服務端程序,監聽在6666端口上 2.啟動客戶端,與服務端建立TCP連接 3.建立完TCP連接,在客戶端上向服務端發送消息 4.斷開

編寫一個簡單的單元測試用例

ide bsp span log 加減乘除 self teardown __main__ str 開發一個簡單的計算器,用於計算兩個數的加減乘除,示例: 1 class Calculator(): 2 ‘‘‘實現簡單的加減乘除‘‘‘ 3 def _

用javascript和html5做一個音樂播放,附帶源碼

功能 優化 str 自由 所有 音樂app 作者 弧形 ner 效果圖: 實現的功能 1、首頁 2、底部播放控件 3、播放頁面 4、播放列表 5、排行榜 6、音樂搜索 輸入搜索關鍵詞,點擊放大鏡圖標 7、側邊欄 目錄結構 開發心得與總結 1、輪播圖 首

使用js編寫一個簡單的運動框架

parse 獲取當前值 進一步 filter 獲取 win logs alt htm 下班後,,沒事搗鼓搗鼓個人的小愛好。 首先,說明我的這個運動框架(css所有屬性)也是常見的框架一種,健壯性並不是太好,對於新手學習倒是挺好,,若是大神,老司機請拐彎。

編寫一個簡單登錄驗證需要記錄日誌,Servlet中的Cookie

cookie java servlet j2ee javaweb 登錄驗證並記錄日誌之前介紹了如何使用Server、mysql、tomcat等知識點編寫了一個簡單的登錄驗證。但是現在有了一個新的需求,我想要在登錄成功的時候往數據庫記錄一條日誌,登錄失敗的時候也要記錄一下。這個日誌要記錄用戶

如何用VBS編寫一個簡單的惡搞腳本

程序 一個 復制 文件夾 組合 不支持 文字 sendkeys 選項 windows系統的電腦, 首先右擊桌面,選擇新建-文本文檔,在桌面上新建一個文本文檔; 隨後打開計算機或者是我的電腦,點擊其中的組織(xp系統多為工具),選擇下面的文件夾和搜索

QT制作一個圖片播放

相對 顯示圖片 itl 列表 獲取目錄 ima 完整 功能 state 前言:使用qt制作了一個簡單的圖片播放器,可以播放gif、png等格式圖片 先來看看播放器的功能(當然是很簡陋的,沒有很深入的設計): 1、點擊圖片列表中圖片進行播放。 2、自動播放,