C++ 重复ffmpeg流(libavcodec/libavformat)
我正在使用ffmpeg中的各种API在我的应用程序中绘制视频。到目前为止,这种方法效果很好。由于我也有GIF,我想做循环而不必反复加载文件 在我的代码中,解码器循环如下所示:C++ 重复ffmpeg流(libavcodec/libavformat),c++,video,ffmpeg,C++,Video,Ffmpeg,我正在使用ffmpeg中的各种API在我的应用程序中绘制视频。到目前为止,这种方法效果很好。由于我也有GIF,我想做循环而不必反复加载文件 在我的代码中,解码器循环如下所示: AVPacket packet = {}; av_init_packet(&packet); while (mIsRunning) { int error = av_read_frame(mContext, &packet); if (error == AVERROR_EOF) {
AVPacket packet = {};
av_init_packet(&packet);
while (mIsRunning) {
int error = av_read_frame(mContext, &packet);
if (error == AVERROR_EOF) {
if(mRepeat) {
logger.info("EOF-repeat");
auto stream = mContext->streams[mVideoStream];
av_seek_frame(mContext, mVideoStream, 0, 0);
continue;
}
if (mReadVideo) {
avcodec_send_packet(mVideoCodec, nullptr);
}
if (mReadAudio) {
avcodec_send_packet(mAudioCodec, nullptr);
}
break;
}
if (error < 0) {
char err[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(err, AV_ERROR_MAX_STRING_SIZE, error);
logger.error("Failed to read next frame from stream: ", err);
throw std::runtime_error("Stream reading failed");
}
if (packet.stream_index == mVideoStream && mReadVideo) {
int32 err;
{
std::lock_guard<std::mutex> l(mVideoLock);
err = avcodec_send_packet(mVideoCodec, &packet);
}
mImageEvent.notify_all();
while (err == AVERROR(EAGAIN) && mIsRunning) {
{
std::unique_lock<std::mutex> l(mReaderLock);
mReaderEvent.wait(l);
}
{
std::lock_guard<std::mutex> l(mVideoLock);
err = avcodec_send_packet(mVideoCodec, &packet);
}
}
}
av_packet_unref(&packet);
}
AVPacket={};
av_初始_数据包(&数据包);
同时(误运行){
int error=av_读取_帧(mContext和数据包);
如果(错误==平均错误){
如果(mRepeat){
logger.info(“EOF repeat”);
自动流=mContext->streams[mVideoStream];
av_seek_帧(mContext、mVideoStream、0、0);
继续;
}
如果(mreaddevide){
avcodec_发送_数据包(mVideoCodec,nullptr);
}
如果(mReadAudio){
avcodec_发送_数据包(mAudioCodec,nullptr);
}
打破
}
如果(错误<0){
字符错误[AV_ERROR_MAX_STRING_SIZE];
av_make_error_string(错误,av_error_最大字符串大小,错误);
logger.error(“未能从流中读取下一帧:”,err);
throw std::runtime_错误(“流读取失败”);
}
if(packet.stream_index==mVideoStream&&mReadVideo){
int32错误;
{
std::锁紧保护装置l(mVideoLock);
err=avcodec\u send\u数据包(mVideoCodec和数据包);
}
mImageEvent.notify_all();
while(err==AVERROR(EAGAIN)&&mIsRunning){
{
std::唯一锁l(mReaderLock);
mReaderEvent.wait(l);
}
{
std::锁紧保护装置l(mVideoLock);
err=avcodec\u send\u数据包(mVideoCodec和数据包);
}
}
}
av_数据包_unref(&packet);
}
将视频读到最后效果非常好,如果我没有将mRepeat
正确设置为true,它将执行EOFs并停止解析。但是,当我使用循环时,会发生以下情况:
- 视频结束
发生在AVERROR\u EOF
av\u read\u帧
已打印EOF repeat
- 从流中读取(并渲染)随机帧
发生在AVERROR\u EOF
av\u read\u帧
已打印EOF repeat
- 从流中读取(并渲染)随机帧
我还尝试了几个版本的
avformat\u seek\u文件
还有什么其他方法可以将所有内容重置为开始,然后从头开始?我发现我还需要将IO上下文重置为开始:
if(mRepeat) {
auto stream = mContext->streams[mVideoStream];
avio_seek(mContext->pb, 0, SEEK_SET);
avformat_seek_file(mContext, mVideoStream, 0, 0, stream->duration, 0);
continue;
}
现在,视频将永远正确循环:)您的回答非常有用。谢谢。@Cromon我们如何传递帧号来播放视频文件?