生活随笔
收集整理的这篇文章主要介绍了
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-暂停、逐帧、⾳量 的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔 网站内容还不错,欢迎将生活随笔 推荐给好友。