J'utilise les différentes API de ffmpeg pour dessiner des vidéos dans mon application. Jusqu'à présent, cela fonctionne très bien. Comme j'ai aussi des gifs, je veux faire une boucle sans avoir à charger le fichier encore et encore.Répétition du flux ffmpeg (libavcodec/libavformat)
Dans mon code de la boucle de décodeur ressemble à ceci:
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);
}
La lecture d'une vidéo à la fin fonctionne parfaitement bien et si je ne mets mRepeat
à true correctement EOF et arrête l'analyse syntaxique. Cependant quand on utilise une boucle qui suit se produit:
- La vidéo se termine
AVERROR_EOF
arrive àav_read_frame
EOF-repeat
est imprimé- Une trame aléatoire est lue à partir du courant (et rendu)
AVERROR_EOF
arrive àav_read_frame
EOF-repeat
est imprimé- Une trame aléatoire est lue à partir du flux (et rendu)
- ...
Vous pouvez l'imaginer comme je l'ai un gif d'un globe en rotation et après un tour complet, il commence juste sauter au hasard autour, parfois pour une fraction de seconde correctement, parfois en arrière et parfois juste au hasard partout.
J'ai également essayé plusieurs versions avec avformat_seek_file
quelle autre façon de tout réinitialiser au début et recommencer à zéro?