From d74ad507079659e5b1edd7b3985da9257ba4d29e Mon Sep 17 00:00:00 2001 From: Brandon W Date: Sat, 10 Aug 2024 18:17:31 -0400 Subject: [PATCH] Remove singlethreaded, old ffmpeg decoding code. --- src/arch/MovieTexture/MovieTexture_FFMpeg.cpp | 167 ------------------ src/arch/MovieTexture/MovieTexture_FFMpeg.h | 11 +- .../MovieTexture/MovieTexture_Generic.cpp | 65 ------- src/arch/MovieTexture/MovieTexture_Generic.h | 23 --- 4 files changed, 2 insertions(+), 264 deletions(-) diff --git a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp index 7772442f3e..291850a8c3 100644 --- a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp +++ b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp @@ -150,54 +150,14 @@ void MovieDecoder_FFMpeg::Init() { m_iEOF = 0; m_fTimestamp = 0; - m_fLastFrameDelay = 0; m_iFrameNumber = 0; m_totalFrames = 0; m_fTimestampOffset = 0; - m_fLastFrame = 0; m_swsctx = nullptr; m_avioContext = nullptr; m_buffer = nullptr; } -/* Read until we get a frame, EOF or error. Return -1 on error, 0 on EOF, 1 if we have a frame. */ -int MovieDecoder_FFMpeg::DecodeFrame( float fTargetTime ) -{ - //hack to filter out stuttering - if(fTargetTime 0 ) - { - return 0; /* eof */ - } - ASSERT( ret == 0 ); - ret = ReadPacket(); - if( ret < 0 ) - { - return ret; /* error */ - } - } -} - float MovieDecoder_FFMpeg::GetTimestamp() const { // Always display the first frame. @@ -233,11 +193,6 @@ bool MovieDecoder_FFMpeg::IsCurrentFrameReady() { return m_FrameBuffer[m_iFrameNumber].decoded; } -float MovieDecoder_FFMpeg::GetFrameDuration() const -{ - return m_fLastFrameDelay; -} - int MovieDecoder_FFMpeg::DecodeNextFrame() { // Add in a new FrameBuffer entry, and lock it immediately. @@ -402,128 +357,6 @@ int MovieDecoder_FFMpeg::DecodePacketInBuffer() { return 0; /* packet done */ } - -/* Read a packet. Return -1 on error, 0 on EOF, 1 on OK. */ -int MovieDecoder_FFMpeg::ReadPacket() -{ - if( m_iEOF > 0 ) - return 0; - - for(;;) - { - if( m_iCurrentPacketOffset != -1 ) - { - m_iCurrentPacketOffset = -1; - avcodec::av_packet_unref( &m_Packet ); - } - - int ret = avcodec::av_read_frame( m_fctx, &m_Packet ); - /* XXX: why is avformat returning AVERROR_NOMEM on EOF? */ - if( ret < 0 ) - { - /* EOF. */ - m_iEOF = 1; - m_Packet.size = 0; - - return 0; - } - - if( m_Packet.stream_index == m_pStream->index ) - { - m_iCurrentPacketOffset = 0; - return 1; - } - - /* It's not for the video stream; ignore it. */ - avcodec::av_packet_unref( &m_Packet ); - } -} - -/* Decode data from the current packet. Return -1 on error, 0 if the packet is finished, - * and 1 if we have a frame (we may have more data in the packet). */ -int MovieDecoder_FFMpeg::DecodePacket( float fTargetTime ) -{ - if( m_iEOF == 0 && m_iCurrentPacketOffset == -1 ) - return 0; /* no packet */ - - while( m_iEOF == 1 || (m_iEOF == 0 && m_iCurrentPacketOffset < m_Packet.size) ) - { - /* If we have no data on the first frame, just return EOF; passing an empty packet - * to avcodec_decode_video in this case is crashing it. However, passing an empty - * packet is normal with B-frames, to flush. This may be unnecessary in newer - * versions of avcodec, but I'm waiting until a new stable release to upgrade. */ - if( m_Packet.size == 0 && m_iFrameNumber == -1 ) - return 0; /* eof */ - - bool bSkipThisFrame = - fTargetTime != -1 && - GetTimestamp() + GetFrameDuration() < fTargetTime && - (m_pStreamCodec->frame_number % 2) == 0; - - int iGotFrame; - int len; - /* Hack: we need to send size = 0 to flush frames at the end, but we have - * to give it a buffer to read from since it tries to read anyway. */ - m_Packet.data = m_Packet.size ? m_Packet.data : nullptr; - len = m_Packet.size; - avcodec::avcodec_send_packet(m_pStreamCodec, &m_Packet); - iGotFrame = !avcodec::avcodec_receive_frame(m_pStreamCodec, m_Frame); - - if( len < 0 ) - { - LOG->Warn("avcodec_decode_video2: %i", len); - return -1; // XXX - } - - m_iCurrentPacketOffset += len; - - if( !iGotFrame ) - { - if( m_iEOF == 1 ) - m_iEOF = 2; - continue; - } - - if( m_Frame->pkt_dts != AV_NOPTS_VALUE ) - { - m_fTimestamp = (float) (m_Frame->pkt_dts * av_q2d(m_pStream->time_base)); - } - else - { - /* If the timestamp is zero, this frame is to be played at the - * time of the last frame plus the length of the last frame. */ - m_fTimestamp += m_fLastFrameDelay; - } - - /* Length of this frame: */ - m_fLastFrameDelay = (float) av_q2d(m_pStream->time_base); - m_fLastFrameDelay += m_Frame->repeat_pict * (m_fLastFrameDelay * 0.5f); - - ++m_iFrameNumber; - - if( m_iFrameNumber == 0 ) - { - /* Some videos start with a timestamp other than 0. I think this is used - * when audio starts before the video. We don't want to honor that, since - * the DShow renderer doesn't and we don't want to break sync compatibility. */ - const float expect = 0; - const float actual = m_fTimestamp; - if( actual - expect > 0 ) - { - LOG->Trace("Expect %f, got %f -> %f", expect, actual, actual - expect ); - m_fTimestampOffset = actual - expect; - } - } - - if( bSkipThisFrame ) - continue; - - return 1; - } - - return 0; /* packet done */ -} - bool MovieDecoder_FFMpeg::SkipNextFrame() { if (m_iFrameNumber > (m_totalFrames - 1)) { return true; diff --git a/src/arch/MovieTexture/MovieTexture_FFMpeg.h b/src/arch/MovieTexture/MovieTexture_FFMpeg.h index 9d572c6df7..7bc79afa38 100644 --- a/src/arch/MovieTexture/MovieTexture_FFMpeg.h +++ b/src/arch/MovieTexture/MovieTexture_FFMpeg.h @@ -100,7 +100,6 @@ public: RageSurface *CreateCompatibleSurface( int iTextureWidth, int iTextureHeight, bool bPreferHighColor, MovieDecoderPixelFormatYCbCr &fmtout ); float GetTimestamp() const; - float GetFrameDuration() const; void Cancel() { cancel = true; }; @@ -110,8 +109,6 @@ public: private: void Init(); RString OpenCodec(); - int ReadPacket(); - int DecodePacket( float fTargetTime ); // Read a packet and send it to our frame data buffer. // Returns -2 on cancel, -1 on error, 0 on EOF, 1 on OK. @@ -130,7 +127,6 @@ private: avcodec::AVFormatContext *m_fctx; float m_fTimestamp; float m_fTimestampOffset; - float m_fLastFrameDelay; int m_iFrameNumber; int m_totalFrames; // Total number of frames in the movie. @@ -140,13 +136,10 @@ private: // The movie buffer. std::vector m_FrameBuffer; - avcodec::AVPacket m_Packet; int m_iCurrentPacketOffset; - float m_fLastFrame; - /* 0 = no EOF - * 1 = EOF from ReadPacket - * 2 = EOF from ReadPacket and DecodePacket */ + // 0 = no EOF + // 1 = EOF while decoding int m_iEOF; // If true, received a cancel signal from the MovieTexture. diff --git a/src/arch/MovieTexture/MovieTexture_Generic.cpp b/src/arch/MovieTexture/MovieTexture_Generic.cpp index 80e5cfdab2..97713a795a 100644 --- a/src/arch/MovieTexture/MovieTexture_Generic.cpp +++ b/src/arch/MovieTexture/MovieTexture_Generic.cpp @@ -34,11 +34,8 @@ MovieTexture_Generic::MovieTexture_Generic( RageTextureID ID, MovieDecoder *pDec m_bLoop = true; m_pSurface = nullptr; m_pTextureLock = nullptr; - m_ImageWaiting = FRAME_NONE; m_fRate = 1; - m_bWantRewind = false; m_fClock = 0; - m_bFrameSkipMode = false; m_pSprite = new Sprite; } @@ -132,12 +129,6 @@ public: m_PixFmt = pixfmt; m_iSourceWidth = iWidth; m_iSourceHeight = iHeight; -/* int iMaxSize = std::min( GetID().iMaxSize, DISPLAY->GetMaxTextureSize() ); - m_iImageWidth = std::min( m_iSourceWidth, iMaxSize ); - m_iImageHeight = std::min( m_iSourceHeight, iMaxSize ); - m_iTextureWidth = power_of_two( m_iImageWidth ); - m_iTextureHeight = power_of_two( m_iImageHeight ); -*/ m_iImageWidth = iImageWidth; m_iImageHeight = iImageHeight; @@ -315,62 +306,6 @@ void MovieTexture_Generic::CreateTexture() m_uTexHandle = DISPLAY->CreateTexture( pixfmt, m_pSurface, false ); } -/* Handle decoding for a frame. Return true if a frame was decoded, false if not - * (due to quit, error, EOF, etc). If true is returned, we'll be in FRAME_DECODED. */ -bool MovieTexture_Generic::DecodeFrame() -{ - bool bTriedRewind = false; - do - { - if( m_bWantRewind ) - { - if( bTriedRewind ) - { - LOG->Trace( "File \"%s\" looped more than once in one frame", GetID().filename.c_str() ); - return false; - } - m_bWantRewind = false; - bTriedRewind = true; - - /* When resetting the clock, set it back by the length of the last frame, - * so it has a proper delay. */ - float fDelay = m_pDecoder->GetFrameDuration(); - - /* Restart. */ - m_pDecoder->Rewind(); - - m_fClock = -fDelay; - } - - /* Read a frame. */ - float fTargetTime = -1; - if( m_bFrameSkipMode && m_fClock > m_pDecoder->GetTimestamp() ) - fTargetTime = m_fClock; - - int ret = m_pDecoder->DecodeFrame( fTargetTime ); - if( ret == -1 ) - return false; - - if( m_bWantRewind && m_pDecoder->GetTimestamp() == 0 ) - m_bWantRewind = false; /* ignore */ - - if( ret == 0 ) - { - /* EOF. */ - if( !m_bLoop ) - return false; - - LOG->Trace( "File \"%s\" looping", GetID().filename.c_str() ); - m_bWantRewind = true; - continue; - } - - /* We got a frame. */ - } while( m_bWantRewind ); - - return true; -} - /* * Returns: * <= 0 if it's time for the next frame to display diff --git a/src/arch/MovieTexture/MovieTexture_Generic.h b/src/arch/MovieTexture/MovieTexture_Generic.h index 1521b96fb8..2ae716202e 100644 --- a/src/arch/MovieTexture/MovieTexture_Generic.h +++ b/src/arch/MovieTexture/MovieTexture_Generic.h @@ -37,18 +37,6 @@ public: // Returns true if the frame we want to display has been decoded already. virtual bool IsCurrentFrameReady() = 0; - /* - * Decode a frame. Return 1 on success, 0 on EOF, -1 on fatal error. - * - * If we're lagging behind the video, fTargetTime will be the target - * timestamp. The decoder may skip frames to catch up. On return, - * the current timestamp must be <= fTargetTime. - * - * Otherwise, fTargetTime will be -1, and the next frame should be - * decoded; skip frames only if necessary to recover from errors. - */ - virtual int DecodeFrame( float fTargetTime ) = 0; - /* * Get the currently-decoded frame. */ @@ -88,9 +76,6 @@ public: // Cancels the decoding of the movie. virtual void Cancel() = 0; - - /* Get the duration, in seconds, to display the current frame. */ - virtual float GetFrameDuration() const = 0; }; @@ -124,17 +109,10 @@ private: std::unique_ptr decoding_thread; float m_fRate; - enum { - FRAME_NONE, /* no frame available; call GetFrame to get one */ - FRAME_DECODED /* frame decoded; waiting until it's time to display it */ - } m_ImageWaiting; bool m_bLoop; // If true, halts all decoding and display. bool m_failure = false; - bool m_bWantRewind; - - enum State { DECODER_QUIT, DECODER_RUNNING } m_State; std::uintptr_t m_uTexHandle; RageTextureRenderTarget *m_pRenderTarget; @@ -147,7 +125,6 @@ private: /* The time the movie is actually at: */ float m_fClock; - bool m_bFrameSkipMode; void UpdateFrame();