音视频开发:ffplay使用ffmpeg滤镜实现倍速播放
前言
曾经为实现倍速播放使用过ffmpeg,对音频使用atempo滤镜即可实现变速不变调。但是当时效果并不是特别好,和soundtouch相比处理后的音质有明显的区别。最近用新版本的ffmpeg滤镜重新实现了倍速播放,发现效果变好,已经达到可接受的程度,所以在此分享具体实现。
一、ffmpeg滤镜
ffmpeg倍速滤镜一般可以用下面这几个:
(1)视频
setpts=0.5*PTS
(2)音频
atempo = 2.0
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
二、ffplay中使用滤镜
在ffplay中可以直接使用ffmpeg的滤镜,在这里实现倍速播放我们只需要处理音频,然后让时钟同步到音频即可。没有音频的情况比较简单,只需要修改视频的pts即可,这里不做说明。
1、定义字段
在VideoState中添加滤镜刷新字段,用以实现动态控制倍速。
默认值为0,当值为1时则刷新滤镜。
int req_afilter_reconfigure;
2、设置滤镜
直接使用音频滤镜即可,atempo的取值范围是0.5-2.0即倍速值。
afilters = "atempo=2";
定义一个设置倍速方法,方便使用。(作为示例没有加线程安全机制)
void set_speed(double value)
{if (value < 0.5 || value>2)return;VideoState* is = (VideoState*)play;is->speed = value;
#if CONFIG_AVFILTERif (!is->afilters){is->afilters = av_malloc(32);}sprintf(is->afilters, "atempo=%lf", value);is->req_afilter_reconfigure = 1;
#endif
}
3、更新滤镜
修改了倍速后,需要播放器动态响应。在ffplay的audio_thread中已经有了更新滤镜的机制,如果音频参数修改了则会进行滤镜更新,我们只需要使用上面定义的req_afilter_reconfigure来触发其更新滤镜即可。代码如下:(作为示例没有加线程安全机制)
if (reconfigure||is->req_afilter_reconfigure) {is->req_afilter_reconfigure = 0;
//ffplay更新滤镜源码
}
4、调整时钟
经过滤镜处理的数据得到的avframe时间戳pts以及pkt_pos也被相应的调整了,在ffplay中播放效果是声音变快了,但时钟不变,画面也按照原来速度播放,这肯定是不符合需求的,所以需要重新调整时间相关参数。其实有一种方法,直接使用滤镜处理前的时间参数即可:由于倍速处理后nb_samples和bufferSize都变了,而时间参数(pts以及pkt_pos)不变就会使得sdl_audio_callback同步时钟发生相应变化。
在audio_thread中:
先记录avframe原来的参数
//使用原来的pts
double pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
double pos = frame->pkt_pos;
int serial = is->auddec.pkt_serial;
double duration = av_q2d((AVRational) { frame->nb_samples, frame->sample_rate });
//使用原来的pts --end
滤镜处理后使用原来的参数
//使用原来的pts
af->pts = pts;// (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
af->pos = pos;//frame->pkt_pos;
af->serial = serial;// is->auddec.pkt_serial;
af->duration = duration;// av_q2d((AVRational) { frame->nb_samples, frame->sample_rate });
//使用原来的pts --end
5、释放资源
由于上述方法中afilters指向的是av_malloc的空间,所以关闭播放器时需要将其释放。
在stream_close中添加
#if CONFIG_AVFILTERif (is->afilters){av_free(is->afilters);is->afilters = NULL;}
#endif
如果你对音视频开发感兴趣,觉得文章对您有帮助,别忘了点赞、收藏哦!或者对本文的一些阐述有自己的看法,有任何问题,欢迎在下方评论区讨论!
本文福利, 免费领取C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
