diff --git a/xbmc/music/karaoke/karaokevideobackground.cpp b/xbmc/music/karaoke/karaokevideobackground.cpp index e402614a1b065..14a11068f7f18 100644 --- a/xbmc/music/karaoke/karaokevideobackground.cpp +++ b/xbmc/music/karaoke/karaokevideobackground.cpp @@ -28,6 +28,9 @@ #include "settings/AdvancedSettings.h" #include "karaokevideobackground.h" +static bool PERSISTENT_OBJECT = 0; + + KaraokeVideoFFMpeg::KaraokeVideoFFMpeg() { pFormatCtx = 0; @@ -44,12 +47,9 @@ KaraokeVideoFFMpeg::KaraokeVideoFFMpeg() KaraokeVideoFFMpeg::~KaraokeVideoFFMpeg() { - closeVideoFile(); + Dismiss(); - m_dllAvCodec.Unload(); - m_dllAvUtil.Unload(); - m_dllSwScale.Unload(); - m_dllAvFormat.Unload(); + delete m_texture; } bool KaraokeVideoFFMpeg::Init() @@ -63,9 +63,22 @@ bool KaraokeVideoFFMpeg::Init() m_dllAvCodec.avcodec_register_all(); m_dllAvFormat.av_register_all(); + CLog::Log( LOGDEBUG, "Karaoke Video Background: init succeed" ); return true; } +void KaraokeVideoFFMpeg::Dismiss() +{ + closeVideoFile(); + + m_dllAvCodec.Unload(); + m_dllAvUtil.Unload(); + m_dllSwScale.Unload(); + m_dllAvFormat.Unload(); + + CLog::Log( LOGDEBUG, "Karaoke Video Background: dismiss succeed" ); +} + bool KaraokeVideoFFMpeg::openVideoFile( const CStdString& filename ) { // See http://dranger.com/ffmpeg/tutorial01.html @@ -149,6 +162,7 @@ bool KaraokeVideoFFMpeg::openVideoFile( const CStdString& filename ) m_height = pCodecCtx->height; m_timeBase = 0; m_currentFrameNumber = 0; + m_maxFrame = 0; m_curVideoFile = filename; CLog::Log( LOGDEBUG, "Karaoke Video Background: Video file %s (%dx%d) opened successfully", filename.c_str(), m_width, m_height ); @@ -176,13 +190,12 @@ void KaraokeVideoFFMpeg::closeVideoFile() if ( pFormatCtx ) m_dllAvFormat.av_close_input_file( pFormatCtx ); - //delete[] pBuf_rgb32; - pFormatCtx = 0; pCodecCtx = 0; pCodec = 0; pFrame = 0; pFrameRGB = 0; + m_curVideoFile.clear(); } bool KaraokeVideoFFMpeg::readFrame( int frame ) @@ -286,20 +299,34 @@ void KaraokeVideoFFMpeg::Render() bool KaraokeVideoFFMpeg::Start( const CStdString& filename ) { + if ( !m_dllAvFormat.IsLoaded() ) + { + if ( !Init() ) + return false; + } + if ( !filename.empty() ) { if ( !openVideoFile( filename ) ) return false; - m_timeBase = 0; + m_lastTimeFrame = 0; } - - if ( m_curVideoFile.empty() ) + else { + // m_currentFrameNumber is set to 0 in openVideoFile + unsigned int curframe = m_currentFrameNumber; + if ( !openVideoFile( g_advancedSettings.m_karaokeDefaultBackgroundFilePath ) ) return false; - m_timeBase = 0; + if ( curframe > 0 && m_dllAvFormat.av_seek_frame( pFormatCtx, videoStream, curframe, 0 ) >= 0 ) + { + m_dllAvCodec.avcodec_flush_buffers( pCodecCtx ); + m_currentFrameNumber = curframe; + } + else + m_lastTimeFrame = 0; } m_timeBase = m_lastTimeFrame; @@ -319,6 +346,15 @@ bool KaraokeVideoFFMpeg::Start( const CStdString& filename ) void KaraokeVideoFFMpeg::Stop() { + if ( !m_dllAvFormat.IsLoaded() ) + { + CLog::Log( LOGERROR, "KaraokeVideoFFMpeg::Start: internal error, called on unitinialized object" ); + return; + } + delete m_texture; m_texture = 0; + + if ( !PERSISTENT_OBJECT ) + Dismiss(); } diff --git a/xbmc/music/karaoke/karaokevideobackground.h b/xbmc/music/karaoke/karaokevideobackground.h index c317f621f7143..e48d420f4a824 100644 --- a/xbmc/music/karaoke/karaokevideobackground.h +++ b/xbmc/music/karaoke/karaokevideobackground.h @@ -47,10 +47,6 @@ class KaraokeVideoFFMpeg KaraokeVideoFFMpeg(); ~KaraokeVideoFFMpeg(); - // Initialize the object. This function is called only once when the object is created. If it returns false, - // the video rendering is disabled and KaraokeVideoFFMpeg object is deleted - bool Init(); - // Start playing the video. It is called each time a new song is being played. Should continue playing existing // video from the position it was paused. If it returns false, the video rendering is disabled and // KaraokeVideoFFMpeg object is deleted. Must write the reason for failure into the log file. @@ -63,8 +59,15 @@ class KaraokeVideoFFMpeg // Stops playing the video. It is called once the song is finished and the Render() is not going to be called anymore. // The object, however, is kept and should keep its state because it must continue on next Start() call. void Stop(); - + private: + // Initialize the object. This function is called only once when the object is created or after it has been dismissed. + // If it returns false, the video rendering is disabled and KaraokeVideoFFMpeg object is deleted + bool Init(); + + // Dismisses the object, freeing all the memory and unloading the libraries. The object must be inited before using again. + void Dismiss(); + bool openVideoFile( const CStdString& filename ); void closeVideoFile(); bool readFrame( int frame ); diff --git a/xbmc/music/karaoke/karaokewindowbackground.cpp b/xbmc/music/karaoke/karaokewindowbackground.cpp index 0624ac7736f98..635712f605272 100644 --- a/xbmc/music/karaoke/karaokewindowbackground.cpp +++ b/xbmc/music/karaoke/karaokewindowbackground.cpp @@ -183,18 +183,8 @@ void CKaraokeWindowBackground::StartImage( const CStdString& path ) void CKaraokeWindowBackground::StartVideo( const CStdString& path ) { if ( !m_videoPlayer ) - { m_videoPlayer = new KaraokeVideoFFMpeg(); - if ( !m_videoPlayer->Init() ) - { - delete m_videoPlayer; - m_videoPlayer = 0; - m_currentMode = BACKGROUND_NONE; - return; - } - } - if ( !m_videoPlayer->Start( path ) ) { delete m_videoPlayer;