Allow frames that didn't decode to skip.
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user