Permalink
Browse files

Fixed #13574 as well as several other bugs caused by improper DVDPlay…

…er usage in Karaoke code which has been replaced by the FFMpeg-based player.

Tried my best to add the files into the build systems, if missed, please add xbmc/music/karaoke/karaokevideobackground.cpp and xbmc/video/FFmpegVideoDecoder.cpp into the relevant builds.

Really sorry for the delay, this should have been fixed a while ago.
  • Loading branch information...
1 parent 6b058d3 commit 01a2ea04fa2f294ce6196d382a91e38f8ed862ae George Yunaev committed Dec 23, 2012
@@ -792,6 +792,7 @@
<ClCompile Include="..\..\xbmc\music\karaoke\karaokelyricstextlrc.cpp" />
<ClCompile Include="..\..\xbmc\music\karaoke\karaokelyricstextustar.cpp" />
<ClCompile Include="..\..\xbmc\music\karaoke\karaokewindowbackground.cpp" />
+ <ClCompile Include="..\..\xbmc\music\karaoke\karaokevideobackground.cpp" />
<ClCompile Include="..\..\xbmc\music\LastFmManager.cpp" />
<ClCompile Include="..\..\xbmc\music\MusicDatabase.cpp" />
<ClCompile Include="..\..\xbmc\music\MusicDbUrl.cpp" />
@@ -1080,6 +1081,8 @@
<ClInclude Include="..\..\xbmc\interfaces\python\preamble.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\PyContext.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\pythreadstate.h" />
+ <ClInclude Include="..\..\xbmc\music\karaoke\karaokevideobackground.h" />
+ <ClInclude Include="..\..\xbmc\video\FFmpegVideoDecoder.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\swig.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\XBPython.h" />
<ClInclude Include="..\..\xbmc\interfaces\python\XBPyThread.h" />
@@ -1628,6 +1631,7 @@
<ClCompile Include="..\..\xbmc\video\dialogs\GUIDialogVideoOSD.cpp" />
<ClCompile Include="..\..\xbmc\video\dialogs\GUIDialogVideoOverlay.cpp" />
<ClCompile Include="..\..\xbmc\video\dialogs\GUIDialogVideoSettings.cpp" />
+ <ClCompile Include="..\..\xbmc\video\FFmpegVideoDecoder.cpp" />
<ClCompile Include="..\..\xbmc\video\GUIViewStateVideo.cpp" />
<ClCompile Include="..\..\xbmc\video\Teletext.cpp" />
<ClCompile Include="..\..\xbmc\video\VideoDatabase.cpp" />
@@ -2942,4 +2946,4 @@
</VisualStudio>
</ProjectExtensions>
<Import Project="$(SolutionDir)\$(ProjectFileName).targets.user" Condition="Exists('$(SolutionDir)\$(ProjectFileName).targets.user')" />
-</Project>
+</Project>
@@ -2578,6 +2578,9 @@
<ClCompile Include="..\..\xbmc\utils\DatabaseUtils.cpp">
<Filter>utils</Filter>
</ClCompile>
+ <ClCompile Include="..\..\xbmc\music\karaoke\karaokevideobackground.cpp">
+ <Filter>music\karaoke</Filter>
+ </ClCompile>
<ClCompile Include="..\..\xbmc\filesystem\VideoDatabaseDirectory\DirectoryNodeTags.cpp">
<Filter>filesystem\VideoDatabaseDirectory</Filter>
</ClCompile>
@@ -5801,4 +5804,4 @@
<Filter>interfaces\swig</Filter>
</None>
</ItemGroup>
-</Project>
+</Project>
@@ -110,6 +110,10 @@ bool CGUIWindowKaraokeLyrics::OnMessage(CGUIMessage& message)
return CGUIWindow::OnMessage(message);
}
+void CGUIWindowKaraokeLyrics::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
+{
+ dirtyregions.push_back(CRect(0.0f, 0.0f, (float)g_graphicsContext.GetWidth(), (float)g_graphicsContext.GetHeight()));
+}
void CGUIWindowKaraokeLyrics::Render()
{
@@ -141,7 +145,7 @@ void CGUIWindowKaraokeLyrics::newSong(CKaraokeLyrics * lyrics)
// Start the required video
m_Lyrics->GetVideoParameters( path, offset );
- m_Background->StartVideo( path, offset );
+ m_Background->StartVideo( path );
}
else if ( m_Lyrics->HasBackground() && g_advancedSettings.m_karaokeAlwaysEmptyOnCdgs )
{
@@ -34,6 +34,7 @@ class CGUIWindowKaraokeLyrics : public CGUIWindow
virtual bool OnMessage(CGUIMessage& message);
virtual bool OnAction(const CAction &action);
virtual void Render();
+ virtual void Process(unsigned int currentTime, CDirtyRegionList &dirtyregions);
void newSong( CKaraokeLyrics * lyrics );
void pauseSong( bool now_paused );
@@ -8,6 +8,7 @@ SRCS += karaokelyricstext.cpp
SRCS += karaokelyricstextkar.cpp
SRCS += karaokelyricstextlrc.cpp
SRCS += karaokelyricstextustar.cpp
+SRCS += karaokevideobackground.cpp
SRCS += karaokewindowbackground.cpp
LIB = karaoke.a
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "karaokevideobackground.h"
+
+#include "guilib/Texture.h"
+#include "guilib/GUITexture.h"
+#include "settings/Settings.h"
+#include "Application.h"
+#include "DllAvFormat.h"
+#include "DllAvCodec.h"
+#include "DllAvUtil.h"
+#include "DllSwScale.h"
+#include "filesystem/SpecialProtocol.h"
+#include "settings/AdvancedSettings.h"
+#include "video/FFmpegVideoDecoder.h"
+#include "system.h"
+
+KaraokeVideoBackground::KaraokeVideoBackground()
+{
+ m_decoder = new FFmpegVideoDecoder();
+ m_timeFromPrevSong = 0.0;
+ m_texture = 0;
+}
+
+KaraokeVideoBackground::~KaraokeVideoBackground()
+{
+ delete m_decoder;
+ delete m_texture;
+}
+
+bool KaraokeVideoBackground::openVideoFile( const CStdString& filename )
+{
+ CStdString realPath = CSpecialProtocol::TranslatePath( filename );
+
+ if ( !m_decoder->open( realPath ) )
+ {
+ CLog::Log( LOGERROR, "Karaoke Video Background: %s, video file %s (%s)", m_decoder->getErrorMsg().c_str(), filename.c_str(), realPath.c_str() );
+ return false;
+ }
+
+ m_videoWidth = m_decoder->getWidth();
+ m_videoHeight = m_decoder->getHeight();
+ m_curVideoFile = filename;
+
+ // Find out the necessary aspect ratio for height (assuming fit by width) and width (assuming fit by height)
+ RESOLUTION res = g_graphicsContext.GetVideoResolution();
+ m_displayLeft = g_settings.m_ResInfo[res].Overscan.left;
+ m_displayRight = g_settings.m_ResInfo[res].Overscan.right;
+ m_displayTop = g_settings.m_ResInfo[res].Overscan.top;
+ m_displayBottom = g_settings.m_ResInfo[res].Overscan.bottom;
+
+ int screen_width = m_displayRight - m_displayLeft;
+ int screen_height = m_displayBottom - m_displayTop;
+
+ // Do we need to modify the output video size? This could happen in two cases:
+ // 1. Either video dimension is larger than the screen - video needs to be downscaled
+ // 2. Both video dimensions are smaller than the screen - video needs to be upscaled
+ if ( (m_videoWidth > screen_width || m_videoHeight > screen_height )
+ || ( m_videoWidth < screen_width && m_videoHeight < screen_height ) )
+ {
+ // Calculate the scale coefficients for width/height separately
+ double scale_width = (double) screen_width / (double) m_videoWidth;
+ double scale_height = (double) screen_height / (double) m_videoHeight;
+
+ // And apply the smallest
+ double scale = scale_width < scale_height ? scale_width : scale_height;
+ m_videoWidth = (int) (m_videoWidth * scale);
+ m_videoHeight = (int) (m_videoHeight * scale);
+ }
+
+ // Calculate the desktop dimensions to show the video
+ if ( m_videoWidth < screen_width || m_videoHeight < screen_height )
+ {
+ m_displayLeft = (screen_width - m_videoWidth) / 2;
+ m_displayRight -= m_displayLeft;
+
+ m_displayTop = (screen_height - m_videoHeight) / 2;
+ m_displayBottom -= m_displayTop;
+ }
+
+ m_millisecondsPerFrame = 1.0 / m_decoder->getFramesPerSecond();
+
+ CLog::Log( LOGDEBUG, "Karaoke Video Background: Video file %s (%dx%d) length %g seconds opened successfully, will be shown as %dx%d at (%d, %d - %d, %d) rectangle",
+ filename.c_str(),
+ m_decoder->getWidth(), m_decoder->getHeight(),
+ m_decoder->getDuration(),
+ m_videoWidth, m_videoHeight,
+ m_displayLeft, m_displayTop, m_displayRight, m_displayBottom );
+
+ return true;
+}
+
+void KaraokeVideoBackground::closeVideoFile()
+{
+ m_decoder->close();
+}
+
+void KaraokeVideoBackground::Render()
+{
+ // Just in case
+ if ( !m_texture )
+ return;
+
+ // Get the current song timing in ms.
+ // This will only fit songs up to 71,000 hours, so if you got a larger one, change to int64
+ double current = g_application.GetTime();
+
+ // We're supposed to show m_decoder->getFramesPerSecond() frames in one second.
+ if ( current >= m_nextFrameTime )
+ {
+ // We don't care to adjust for the exact timing as we don't worry about the exact frame rate
+ m_nextFrameTime = current + m_millisecondsPerFrame - (current - m_nextFrameTime);
+
+ while ( true )
+ {
+ if ( !m_decoder->nextFrame( m_texture ) )
+ {
+ // End of video; restart
+ m_decoder->seek( 0.0 );
+ m_nextFrameTime = 0.0;
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ // We got a frame. Draw it.
+ CRect vertCoords((float) m_displayLeft, (float) m_displayTop, (float) m_displayRight, (float) m_displayBottom );
+ CGUITexture::DrawQuad(vertCoords, 0xffffffff, m_texture );
+}
+
+bool KaraokeVideoBackground::Start( const CStdString& filename )
+{
+ if ( !filename.empty() )
+ {
+ if ( !openVideoFile( filename ) )
+ return false;
+
+ m_timeFromPrevSong = 0;
+ }
+ else
+ {
+ if ( !openVideoFile( g_advancedSettings.m_karaokeDefaultBackgroundFilePath ) )
+ return false;
+
+ if ( m_timeFromPrevSong != 0.0 && !m_decoder->seek( m_timeFromPrevSong ) )
+ m_timeFromPrevSong = 0;
+ }
+
+ // Allocate the texture
+ m_texture = new CTexture( m_videoWidth, m_videoHeight, XB_FMT_A8R8G8B8 );
+
+ if ( !m_texture )
+ {
+ CLog::Log( LOGERROR, "Karaoke Video Background: Could not allocate texture" );
+ return false;
+ }
+
+ m_nextFrameTime = 0.0;
+ return true;
+}
+
+void KaraokeVideoBackground::Stop()
+{
+ delete m_texture;
+ m_texture = 0;
+
+ m_timeFromPrevSong = m_decoder->getLastFrameTime();
+}
@@ -0,0 +1,86 @@
+#ifndef KARAOKEVIDEOFFMPEG_H
+#define KARAOKEVIDEOFFMPEG_H
+
+/*
+ * Copyright (C) 2005-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include "utils/StdString.h"
+
+class CBaseTexture;
+class FFmpegVideoDecoder;
+
+// C++ Interface: karaokevideoffmpeg
+// Contact: oldnemesis
+//
+// FFMpeg-based background video decoder for Karaoke background.
+// We are not using DVDPlayer for this because:
+// 1. DVDPlayer was not designed to run at the same time when music is being played and other things (like lyrics) rendered.
+// While this setup works from time to time, it constantly gets broken. Some modes, like VDPAU, lead to crash right away.
+//
+// 2. We do not need to decode audio, hence we don't have to use extra CPU.
+//
+// 3. We do not really care about frame rate. Jerky video is fine for the background. Lyrics sync is much more important.
+//
+class KaraokeVideoBackground
+{
+public:
+ KaraokeVideoBackground();
+ ~KaraokeVideoBackground();
+
+ // 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.
+ bool Start( const CStdString& filename = "" );
+
+ // Render the current frame into the screen. This function also must handle video loops and
+ // switching to the next video when necessary. Hence it shouldn't take too long.
+ void Render();
+
+ // 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();
+
+ // FFMpeg objects
+ FFmpegVideoDecoder * m_decoder;
+
+ CStdString m_curVideoFile;
+ int m_videoWidth; // shown video width, i.e. upscaled or downscaled as necessary
+ int m_videoHeight; // shown video height, i.e. upscaled or downscaled as necessary
+ int m_displayLeft, m_displayRight, m_displayTop, m_displayBottom; // Video as shown at the display
+ double m_millisecondsPerFrame;
+ double m_nextFrameTime;
+ double m_timeFromPrevSong;
+
+ CBaseTexture *m_texture;
+};
+
+#endif
Oops, something went wrong.

0 comments on commit 01a2ea0

Please sign in to comment.