










一、概述
在日常的开发中,经常会遇到视频截取的需求,如:视频编辑。用ffmpeg的视频截取功能非常简单,只需要调用av_frame_seek函数即可。
但是需要理解av_frame_seek参数的含义,其主要功能是对音视频流的位置进行定位。
int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags);
功能:
将文件指针定位到指定时间戳(timestamp)附近的关键帧,为后续的解码操作做准备。
参数说明:
s:输入的媒体格式上下文(AVFormatContext)。stream_index:目标流的索引(例如视频流或音频流)。若设为 -1,则会尝试在所有流中寻找时间戳最接近的关键帧。timestamp:目标时间戳,其单位由 AVStream.time_base 决定。flags:控制定位行为的标志,常用标志如下:
AVSEEK_FLAG_BACKWARD:向后查找最近的关键帧(适用于定位到指定时间之前)。AVSEEK_FLAG_ANY:允许定位到非关键帧(可能会导致解码错误,需谨慎使用)。AVSEEK_FLAG_FRAME:基于帧号而非时间戳进行定位(需配合 AVSEEK_FLAG_BYTE 使用)。 返回值:
成功时返回 0,失败时返回负错误码
二、代码示例
if (begin_seconds > 0 && end_seconds > 0) { //计算开始的pts和结束的pts //pts = seconds/(num/den)=seconds*(den/num) if (vs && vs->time_base.num > 0) { double t = (double)vs->time_base.den / (double)vs->time_base.num;//den分母/num分子 begin_pts = begin_seconds * t; end_pts = end_seconds * t; } if (as && as->time_base.num > 0) { begin_audio_pts = begin_seconds * ((double)as->time_base.den / (double)as->time_base.num); } }
//移动到关键帧seek if (vs) { re = av_seek_frame(ic, vs->index, begin_pts, AVSEEK_FLAG_FRAME | AVSEEK_FLAG_BACKWARD); PrintError(re, "av_seek_frame"); }
if (begin_seconds > 0 && end_seconds > 0) { AVStream* in_stream = ic->streams[pkt.stream_index]; AVStream* out_stream = nullptr; long long offset_pts = 0; //偏移pts,用于截断的开头pts运算 if (vs && pkt.stream_index == vs->index) { qDebug() << "视频:"; //超过设定的时间就退出 if (pkt.pts > end_pts) { av_packet_unref(&pkt); break; } out_stream = oc->streams[0]; offset_pts = begin_pts; } else if (as && pkt.stream_index == as->index) { qDebug() << "音频:"; out_stream = oc->streams[1]; offset_pts = begin_audio_pts; } //重新计算pts dts duration //`a * bq(输入basetime) / cq(输出basetime)` if (out_stream) { pkt.pts = av_rescale_q_rnd(pkt.pts - offset_pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX) ); pkt.dts = av_rescale_q_rnd(pkt.dts - offset_pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX) ); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); } pkt.pos = -1; }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。