我正在使用ffmpeg的各种API在我的应用程序中绘制视频。到目前为止,这非常有效。因为我也有GIF,我想循环而不必一遍又一遍地加载文件。
在我的代码中,解码器循环如下所示:
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);
}
将视频读到最后的效果非常好,如果我没有将mRepeat
设置为true,则可以正确显示EOF并停止解析。但是,当我使用循环时,会发生以下情况:
AVERROR_EOF
发生在av_read_frame
EOF-repeat
已打印AVERROR_EOF
发生在av_read_frame
EOF-repeat
已打印你可以想象它就像我有一个旋转地球仪的GIF,经过一整圈之后,它开始随机跳跃,有时是正常的一小部分,有时是向后,有时只是随机到处。
我还尝试了avformat_seek_file
的几个版本,还有什么方法可以将所有内容重置为开头并从头开始重新开始?
答案 0 :(得分:5)
我发现我还需要将我的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;
}
现在视频正常循环:)