From 23f7ebd476b70de29dbdf58fff1ffb21e2e2518e Mon Sep 17 00:00:00 2001 From: Brandon W Date: Sat, 20 Jul 2024 11:51:18 -0400 Subject: [PATCH] Add FrameHolder struct and logic around finding totalFrames of movies. --- src/ActorMultiVertex.cpp | 2 +- src/RageTexture.h | 2 +- src/Sprite.cpp | 2 +- src/arch/MovieTexture/MovieTexture_FFMpeg.cpp | 14 +++++++++-- src/arch/MovieTexture/MovieTexture_FFMpeg.h | 23 +++++++++++++++++++ .../MovieTexture/MovieTexture_Generic.cpp | 2 +- src/arch/MovieTexture/MovieTexture_Generic.h | 2 +- 7 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/ActorMultiVertex.cpp b/src/ActorMultiVertex.cpp index e7c0e1003f..fa623ec8aa 100644 --- a/src/ActorMultiVertex.cpp +++ b/src/ActorMultiVertex.cpp @@ -611,7 +611,7 @@ void ActorMultiVertex::Update(float fDelta) UpdateAnimationState(); if(!skip_this_movie_update && _decode_movie) { - _Texture->DecodeSeconds(std::max(0.0f, time_passed)); + _Texture->UpdateMovie(std::max(0.0f, time_passed)); } } diff --git a/src/RageTexture.h b/src/RageTexture.h index 5b9f6df7a6..7cba58cc0d 100644 --- a/src/RageTexture.h +++ b/src/RageTexture.h @@ -23,7 +23,7 @@ public: // movie texture/animated texture stuff virtual void SetPosition( float /* fSeconds */ ) {} // seek - virtual void DecodeSeconds( float /* fSeconds */ ) {} // decode + virtual void UpdateMovie( float /* fSeconds */ ) {} // decode and update virtual void SetPlaybackRate( float ) {} virtual bool IsAMovie() const { return false; } virtual void SetLooping(bool) { } diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 4d339cf09e..ef205a17e1 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -474,7 +474,7 @@ void Sprite::Update( float fDelta ) // If the texture is a movie, decode frames. if(!bSkipThisMovieUpdate && m_DecodeMovie) - m_pTexture->DecodeSeconds( std::max(0.0f, fTimePassed) ); + m_pTexture->UpdateMovie( std::max(0.0f, fTimePassed) ); // update scrolling if( m_fTexCoordVelocityX != 0 || m_fTexCoordVelocityY != 0 ) diff --git a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp index 54d32d88d8..7434cd3165 100644 --- a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp +++ b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp @@ -156,6 +156,7 @@ void MovieDecoder_FFMpeg::Init() m_fTimestamp = 0; m_fLastFrameDelay = 0; m_iFrameNumber = -1; /* decode one frame and you're on the 0th */ + m_totalFrames = 0; m_fTimestampOffset = 0; m_fLastFrame = 0; m_swsctx = nullptr; @@ -453,8 +454,17 @@ RString MovieDecoder_FFMpeg::Open( RString sFile ) if( !sError.empty() ) return ssprintf( "AVCodec (%s): %s", sFile.c_str(), sError.c_str() ); - LOG->Trace( "Bitrate: %i", static_cast(m_pStreamCodec->bit_rate) ); - LOG->Trace( "Codec pixel format: %s", avcodec::av_get_pix_fmt_name(m_pStreamCodec->pix_fmt) ); + LOG->Trace("Bitrate: %i", static_cast(m_pStreamCodec->bit_rate)); + LOG->Trace("Codec pixel format: %s", avcodec::av_get_pix_fmt_name(m_pStreamCodec->pix_fmt)); + m_totalFrames = m_pStream->nb_frames; + if (m_totalFrames <= 0) { + // Sometimes we might not get a correct frame count. + // In that case, approximate and fix it later. + m_totalFrames = m_fctx->duration // microseconds + * (m_pStream->avg_frame_rate.num) / (m_pStream->avg_frame_rate.den) / (1000000); + LOG->Trace("Number of frames provided is inaccurate, estimating."); + } + LOG->Trace("Number of frames detected: %i", m_totalFrames); return RString(); } diff --git a/src/arch/MovieTexture/MovieTexture_FFMpeg.h b/src/arch/MovieTexture/MovieTexture_FFMpeg.h index 7c7e839551..3056f2ae97 100644 --- a/src/arch/MovieTexture/MovieTexture_FFMpeg.h +++ b/src/arch/MovieTexture/MovieTexture_FFMpeg.h @@ -6,6 +6,7 @@ #include "MovieTexture_Generic.h" #include +#include struct RageSurface; @@ -23,6 +24,27 @@ namespace avcodec #define STEPMANIA_FFMPEG_BUFFER_SIZE 4096 static const int sws_flags = SWS_BICUBIC; // XXX: Reasonable default? +struct FrameHolder { + avcodec::AVFrame frame; + avcodec::AVPacket packet; + float frameTimestamp; + float frameDelay; + bool decoded = false; + std::mutex lock; // Protects the frame as it's being initialized. + + FrameHolder() = default; + + // Copy constructor, unused but we need to make the compiler not copy + // the mutex. + FrameHolder(const FrameHolder& fh) { + frame = fh.frame; + packet = fh.packet; + frameTimestamp = fh.frameTimestamp; + frameDelay = fh.frameDelay; + decoded = fh.decoded; + } +}; + class MovieTexture_FFMpeg: public MovieTexture_Generic { public: @@ -76,6 +98,7 @@ private: float m_fTimestampOffset; float m_fLastFrameDelay; int m_iFrameNumber; + int m_totalFrames; // Total number of frames in the movie. unsigned char *m_buffer; avcodec::AVIOContext *m_avioContext; diff --git a/src/arch/MovieTexture/MovieTexture_Generic.cpp b/src/arch/MovieTexture/MovieTexture_Generic.cpp index 232eeec9e3..2c852370dd 100644 --- a/src/arch/MovieTexture/MovieTexture_Generic.cpp +++ b/src/arch/MovieTexture/MovieTexture_Generic.cpp @@ -413,7 +413,7 @@ float MovieTexture_Generic::CheckFrameTime() } /* Decode data. */ -void MovieTexture_Generic::DecodeSeconds( float fSeconds ) +void MovieTexture_Generic::UpdateMovie( float fSeconds ) { m_fClock += fSeconds * m_fRate; diff --git a/src/arch/MovieTexture/MovieTexture_Generic.h b/src/arch/MovieTexture/MovieTexture_Generic.h index e60a60afce..8d265e99d6 100644 --- a/src/arch/MovieTexture/MovieTexture_Generic.h +++ b/src/arch/MovieTexture/MovieTexture_Generic.h @@ -92,7 +92,7 @@ public: virtual void Reload(); virtual void SetPosition( float fSeconds ); - virtual void DecodeSeconds( float fSeconds ); + virtual void UpdateMovie( float fSeconds ); virtual void SetPlaybackRate( float fRate ) { m_fRate = fRate; } void SetLooping( bool bLooping=true ) { m_bLoop = bLooping; } std::uintptr_t GetTexHandle() const;