生活随笔
收集整理的這篇文章主要介紹了
ffplay.c学习-8-暂停、逐帧、⾳量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
ffplay.c學習-8-暫停、逐幀、?量
目錄
播放、暫停 暫停/繼續狀態切換 暫停狀態下的視頻播放 暫停狀態下的?頻播放 逐幀、調?量、靜? 逐幀 調?量 靜?
常?的播放器操作: 播放:程序啟動即播放,處于暫停時通過p或空格鍵 靜?:m鍵 ?量+:0鍵 ?量-:9鍵 暫停:p或空格鍵 快退/快進:左箭頭/右箭頭 逐幀:s鍵 退出:q或Esc鍵 全屏:f或者?標左鍵雙擊 event_loop做按鍵響應
1. 播放、暫停
畫?要停? 畫?停留在最后?幀 聲?要停? ?頻回調接?請求數據幀時直接填0 讀取數據是否要停?? ?視頻包緩存隊列滿時進?休眠。 暫停->繼續 :時鐘的恢復 暫停:toggle_pause()
1. 暫停/繼續狀態切換
函數調?關系如下
main ( ) -- >
event_loop ( ) -- >
toggle_pause ( ) -- >
stream_toggle_pause ( )
stream_toggle_pause()實現狀態翻轉:
static void
stream_toggle_pause ( VideoState
* is
)
{ if ( is
- > paused
) { is
- > frame_timer
+= av_gettime_relative ( ) / 1000000.0 - is
- > vidclk
. last_updated
; if ( is
- > read_pause_return
!= AVERROR ( ENOSYS
) ) { is
- > vidclk
. paused
= 0 ; } set_clock ( & is
- > vidclk
, get_clock ( & is
- > vidclk
) , is
- > vidclk
. serial
) ; } set_clock ( & is
- > extclk
, get_clock ( & is
- > extclk
) , is
- > extclk
. serial
) ; is
- > paused
= is
- > audclk
. paused
= is
- > vidclk
. paused
= is
- > extclk
. paused
= ! is
- > paused
; printf ( "is->step = %d; stream_toggle_pause\n" , is
- > step
) ;
}
2. 暫停狀態下的視頻播放
在video_refresh()函數中有如下代碼:
static void
video_refresh ( void
* opaque
, double
* remaining_time
) { ... ... if ( is
- > video_st
) { ... ... if ( is
- > paused
) goto display
; ... ... } ... ... }
在暫停狀態下,實際就是不停播放上?幀(最后?幀)圖像。畫?不更新.
3. 暫停狀態下的?頻播放
sdl_audio_callback -> audio_decode_frame
static
int audio_decode_frame ( VideoState
* is
) { int data_size
, resampled_data_size
; int64_t dec_channel_layout
; av_unused double audio_clock0
; int wanted_nb_samples
; Frame
* af
; ( is
- > paused
) return - 1 ; ... . }
2. 逐幀、調?量、靜?
1. 逐幀
逐幀播放的本質是,播放?幀圖像,然后暫停。 涉及到的函數和變量: step_to_next_frame() is->step = 1時單步播放?幀,然后paused 逐幀播放流程 按s鍵,如果當前處于暫停則啟動播放; 播放?幀數據然后進?暫停狀態 逐幀播放是?戶每按?次s鍵,播放器播放?幀畫面。 逐幀播放實現的?法是:每次按了s鍵,就將狀態切換為播放,播放?幀畫?后,將狀態切換為暫停。 函數調?關系如下:
main ( ) -- >
event_loop ( ) -- >
step_to_next_frame ( ) -- >
stream_toggle_pause ( )
實現代碼?較簡單,如下:
static void
step_to_next_frame ( VideoState
* is
) { if ( is
- > paused
) stream_toggle_pause ( is
) ; is
- > step
= 1 ; }
static void
video_refresh ( void
* opaque
, double
* remaining_time
) { ... ... if ( is
- > video_st
) { ... ... if ( is
- > step
&& ! is
- > paused
) stream_toggle_pause ( is
) ; ... ... } ... ... }
2. 調?量
?量控制的本質:控制采樣點的幅值 靜?,將采樣點數值置為0 ?量+,提升采樣點的幅值 ?量-,降低采樣點的幅值
1. ffplay控制?量的?式
最??量:輸出解碼后的原始數據 靜?:即是輸出數值為0的數據 toggle_mute() 改變?量:通過SDL_MixAudioFormat改變解碼后數據的幅值 update_volume() ?如下所示(sdl_audio_callback函數內): 以下是ffplay的?式供參考
if ( ! is
- > muted
&& is
- > audio_buf
&& is
- > audio_volume
== SDL_MIX_MAXVOLUME
) memcpy ( stream
, ( uint8_t
* ) is
- > audio_buf
+ is
- > audio_buf_index
, len1
) ; else { memset ( stream
, 0 , len1
) ; if ( ! is
- > muted
&& is
- > audio_buf
) SDL_MixAudioFormat ( stream
, ( uint8_t
* ) is
- > audio_buf
+ is
- > audio_buf_index
, AUDIO_S16SYS
, len1
, is
- > audio_volume
) ; }
3. 靜?
static void
toggle_mute ( VideoState
* is
) { is
- > muted
= ! is
- > muted
; }
`` `
go if ( ! is
- > muted
&& is
- > audio_buf
&& is
- > audio_volume
== SDL_MIX_MAXVOLUME
) memcpy ( stream
, ( uint8_t
* ) is
- > audio_buf
+ is
- > audio_buf_index
, len1
) ; else { memset ( stream
, 0 , len1
) ; if ( ! is
- > muted
&& is
- > audio_buf
) SDL_MixAudioFormat ( stream
, ( uint8_t
* ) is
- > audio_buf
+ is
- > audio_buf_index
, AUDIO_S16SYS
, len1
, is
- > audio_volume
) ; }
總結
以上是生活随笔 為你收集整理的ffplay.c学习-8-暂停、逐帧、⾳量 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。