Allow frames that didn't decode to skip.

This commit is contained in:
Brandon W
2024-08-08 22:02:07 -04: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);
if (m_FrameBuffer[m_iFrameNumber].skip) {
LOG->Info("Frame %i not decoded, skipping...", m_iFrameNumber);
return true;
}
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;
}
@@ -344,19 +348,22 @@ int MovieDecoder_FFMpeg::DecodePacketInBuffer() {
m_FrameBuffer.back().packet.data = m_FrameBuffer.back().packet.size ? m_FrameBuffer.back().packet.data : nullptr;
int len = m_FrameBuffer.back().packet.size;
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)
{
LOG->Warn("avcodec_decode_video2: %i", len);
LOG->Warn("avcodec_decode_video2 fatal error, packet size negative: %i", len);
return -1;
}
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;
}
@@ -385,6 +392,13 @@ int MovieDecoder_FFMpeg::DecodePacketInBuffer() {
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 */
}
@@ -510,6 +524,17 @@ int MovieDecoder_FFMpeg::DecodePacket( float fTargetTime )
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)
{
avcodec::AVFrame pict;
@@ -30,6 +30,7 @@ struct FrameHolder {
float frameTimestamp;
float frameDelay;
bool decoded = false;
bool skip = false;
std::mutex lock; // Protects the frame as it's being initialized.
FrameHolder() = default;
@@ -42,6 +43,7 @@ struct FrameHolder {
frameTimestamp = fh.frameTimestamp;
frameDelay = fh.frameDelay;
decoded = fh.decoded;
skip = fh.skip;
}
};
@@ -102,6 +104,9 @@ public:
void Cancel() { cancel = true; };
// If the next frame to display had an issue decoding, skip it.
bool SkipNextFrame();
private:
void Init();
RString OpenCodec();
@@ -407,6 +407,10 @@ void MovieTexture_Generic::UpdateFrame()
/* Just in case we were invalidated: */
CreateTexture();
if (m_pDecoder->SkipNextFrame()) {
return;
}
if(m_pTextureLock != nullptr)
{
std::uintptr_t iHandle = m_pTextureIntermediate != nullptr ? m_pTextureIntermediate->GetTexHandle(): this->GetTexHandle();
@@ -54,6 +54,9 @@ public:
*/
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
* adjustments). */
virtual int GetWidth() const = 0;