Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 重复ffmpeg流(libavcodec/libavformat)_C++_Video_Ffmpeg - Fatal编程技术网

C++ 重复ffmpeg流(libavcodec/libavformat)

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) {

我正在使用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);
 }
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
    已打印
  • 从流中读取(并渲染)随机帧
你可以想象它就像我有一个旋转地球的gif,在一整圈后,它开始随机地跳来跳去,有时正确地跳了几秒钟,有时向后跳,有时到处乱跳


我还尝试了几个版本的
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我们如何传递帧号来播放视频文件?