Allow frames that didn't decode to skip.

This commit is contained in:
Brandon W
2024-08-10 11:48:20 -07:00
committed by teejusb
parent b938ac449f
commit eb8f76023e
4 changed files with 42 additions and 5 deletions
+30 -5
View File
@@ -223,8 +223,12 @@ bool MovieDecoder_FFMpeg::IsCurrentFrameReady() {
} }
std::lock_guard<std::mutex>(m_FrameBuffer[m_iFrameNumber].lock); std::lock_guard<std::mutex>(m_FrameBuffer[m_iFrameNumber].lock);
if (m_FrameBuffer[m_iFrameNumber].skip) {
LOG->Info("Frame %i not decoded, skipping...", m_iFrameNumber);
return true;
}
if (!m_FrameBuffer[m_iFrameNumber].decoded) { if (!m_FrameBuffer[m_iFrameNumber].decoded) {
LOG->Info("Frame %i not decoded, total frames: %i", m_iFrameNumber, m_totalFrames); LOG->Info("Frame %i not decoded and was not skipped, total frames: %i", m_iFrameNumber, m_totalFrames);
} }
return m_FrameBuffer[m_iFrameNumber].decoded; return m_FrameBuffer[m_iFrameNumber].decoded;
} }
@@ -344,19 +348,22 @@ int MovieDecoder_FFMpeg::DecodePacketInBuffer() {
m_FrameBuffer.back().packet.data = m_FrameBuffer.back().packet.size ? m_FrameBuffer.back().packet.data : nullptr; m_FrameBuffer.back().packet.data = m_FrameBuffer.back().packet.size ? m_FrameBuffer.back().packet.data : nullptr;
int len = m_FrameBuffer.back().packet.size; int len = m_FrameBuffer.back().packet.size;
avcodec::avcodec_send_packet(m_pStreamCodec, &m_FrameBuffer.back().packet); avcodec::avcodec_send_packet(m_pStreamCodec, &m_FrameBuffer.back().packet);
int iGotFrame = !avcodec::avcodec_receive_frame(m_pStreamCodec, &m_FrameBuffer.back().frame); int avcodec_return = avcodec::avcodec_receive_frame(m_pStreamCodec, &m_FrameBuffer.back().frame);
if (len < 0) if (len < 0)
{ {
LOG->Warn("avcodec_decode_video2: %i", len); LOG->Warn("avcodec_decode_video2 fatal error, packet size negative: %i", len);
return -1; return -1;
} }
m_iCurrentPacketOffset += len; m_iCurrentPacketOffset += len;
if (!iGotFrame) if (avcodec_return != 0)
{ {
LOG->Warn("Frame number %i not successfully decoded into buffer.", static_cast<int>(m_FrameBuffer.size() - 1)); LOG->Warn(
"Frame number %i not successfully decoded into buffer. avcodec_receive_frame status: %i",
static_cast<int>(m_FrameBuffer.size() - 1),
avcodec_return);
continue; continue;
} }
@@ -385,6 +392,13 @@ int MovieDecoder_FFMpeg::DecodePacketInBuffer() {
return 1; return 1;
} }
// This if statement means the packet did not decode correctly. This is not
// necessarily fatal for video playback, but out of caution the frame should
// be skipped.
if (!m_FrameBuffer.back().decoded) {
m_FrameBuffer.back().skip = true;
}
return 0; /* packet done */ return 0; /* packet done */
} }
@@ -510,6 +524,17 @@ int MovieDecoder_FFMpeg::DecodePacket( float fTargetTime )
return 0; /* packet done */ return 0; /* packet done */
} }
bool MovieDecoder_FFMpeg::SkipNextFrame() {
if (m_iFrameNumber > (m_totalFrames - 1)) {
return true;
}
if (m_FrameBuffer[m_iFrameNumber].skip) {
m_iFrameNumber++;
return true;
}
return false;
}
bool MovieDecoder_FFMpeg::GetFrame(RageSurface* pSurface) bool MovieDecoder_FFMpeg::GetFrame(RageSurface* pSurface)
{ {
avcodec::AVFrame pict; avcodec::AVFrame pict;
@@ -30,6 +30,7 @@ struct FrameHolder {
float frameTimestamp; float frameTimestamp;
float frameDelay; float frameDelay;
bool decoded = false; bool decoded = false;
bool skip = false;
std::mutex lock; // Protects the frame as it's being initialized. std::mutex lock; // Protects the frame as it's being initialized.
FrameHolder() = default; FrameHolder() = default;
@@ -42,6 +43,7 @@ struct FrameHolder {
frameTimestamp = fh.frameTimestamp; frameTimestamp = fh.frameTimestamp;
frameDelay = fh.frameDelay; frameDelay = fh.frameDelay;
decoded = fh.decoded; decoded = fh.decoded;
skip = fh.skip;
} }
}; };
@@ -102,6 +104,9 @@ public:
void Cancel() { cancel = true; }; void Cancel() { cancel = true; };
// If the next frame to display had an issue decoding, skip it.
bool SkipNextFrame();
private: private:
void Init(); void Init();
RString OpenCodec(); RString OpenCodec();
@@ -407,6 +407,10 @@ void MovieTexture_Generic::UpdateFrame()
/* Just in case we were invalidated: */ /* Just in case we were invalidated: */
CreateTexture(); CreateTexture();
if (m_pDecoder->SkipNextFrame()) {
return;
}
if(m_pTextureLock != nullptr) if(m_pTextureLock != nullptr)
{ {
std::uintptr_t iHandle = m_pTextureIntermediate != nullptr ? m_pTextureIntermediate->GetTexHandle(): this->GetTexHandle(); std::uintptr_t iHandle = m_pTextureIntermediate != nullptr ? m_pTextureIntermediate->GetTexHandle(): this->GetTexHandle();
@@ -54,6 +54,9 @@ public:
*/ */
virtual bool GetFrame( RageSurface *pOut ) = 0; virtual bool GetFrame( RageSurface *pOut ) = 0;
// Returns true if the frame should be skipped.
virtual bool SkipNextFrame() = 0;
/* Return the dimensions of the image, in pixels (before aspect ratio /* Return the dimensions of the image, in pixels (before aspect ratio
* adjustments). */ * adjustments). */
virtual int GetWidth() const = 0; virtual int GetWidth() const = 0;