Ich verwende die verschiedenen APIs von ffmpeg, um Videos in meiner Anwendung zu zeichnen. Bis jetzt funktioniert das sehr gut. Da ich auch Gifs habe, möchte ich Schleifen machen, ohne die Datei immer wieder neu laden zu müssen.Repeating ffmpeg stream (libavcodec/libavformat)
In meinem Code sucht der Decoder-Schleife wie folgt aus:
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);
}
ein Video zu Ende Lesen funktioniert sehr gut, und wenn ich gesetzt Dont mRepeat
auf true es richtig EOFs und stoppt das Parsen. Jedoch, wenn ich den folgenden Anwendungs Looping geschieht:
- das Video endet
AVERROR_EOF
geschieht beiav_read_frame
EOF-repeat
gedruckt wird- Ein zufälliger Rahmen wird aus dem Strom zu lesen (und gerendert)
AVERROR_EOF
passiert beiav_read_frame
EOF-repeat
wird gedruckt
- Ein zufälliger Rahmen aus dem Stream gelesen wird (und gerendert)
- ...
Sie können es sich vorstellen, wie ich ein gif einer drehenden Globus haben und nach einer vollen Umdrehung es um zufällig gerade beginnt Springen, manchmal für einen Bruchteil einer Sekunde richtig, manchmal rückwärts und manchmal nur zufällig überall.
Ich habe auch mehrere Versionen mit avformat_seek_file
ausprobiert, wie anders wäre es, alles auf den Anfang zurückzusetzen und wieder von vorne anzufangen?