From 56400002816820a8baede8c34f69156d574c3b96 Mon Sep 17 00:00:00 2001
From: b1indy <b1indy@b956fd51-792f-4845-bead-9b4dfca2ff2c>
Date: Wed, 21 Nov 2007 20:10:27 +0000
Subject: backported ffmpeg video stuff (used an older version, so this needs
 to be testet with wine)

git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/1.0.1@623 b956fd51-792f-4845-bead-9b4dfca2ff2c
---
 Game/Code/Classes/UVideo.pas          | 466 ++++++++++++++++++++++++++++++++++
 Game/Code/Screens/UScreenSing.pas     |  27 +-
 Game/Code/Screens/UScreenSingModi.pas |   7 +-
 Game/Code/UltraStar.dpr               |  87 +++----
 4 files changed, 514 insertions(+), 73 deletions(-)
 create mode 100644 Game/Code/Classes/UVideo.pas

diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas
new file mode 100644
index 00000000..2040965f
--- /dev/null
+++ b/Game/Code/Classes/UVideo.pas
@@ -0,0 +1,466 @@
+{############################################################################
+#                   FFmpeg support for UltraStar deluxe                     #
+#                                                                           #
+#   Created by b1indy                                                       #
+#   based on 'An ffmpeg and SDL Tutorial' (http://www.dranger.com/ffmpeg/)  #
+#############################################################################}
+
+//{$define DebugDisplay}  // uncomment if u want to see the debug stuff
+//{$define DebugFrames}
+//{$define Info}
+
+
+unit UVideo;
+
+interface
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+{$ENDIF}
+
+
+uses SDL,
+     UGraphicClasses,
+     textgl,
+     avcodec,
+     avformat,
+     avutil,
+     math,
+     OpenGL12,
+     SysUtils,
+     {$ifdef DebugDisplay}
+     {$ifdef win32}
+     dialogs,
+     {$endif}
+     {$ENDIF}
+     UIni;
+
+procedure Init;
+procedure FFmpegOpenFile(FileName: pAnsiChar);
+procedure FFmpegClose;
+procedure FFmpegGetFrame(Time: Extended);
+procedure FFmpegDrawGL(Screen: integer);
+procedure FFmpegTogglePause;
+procedure FFmpegSkip(Time: Single);
+
+var
+  VideoOpened, VideoPaused: Boolean;
+  VideoFormatContext: PAVFormatContext;
+  VideoStreamIndex: Integer;
+  VideoCodecContext: PAVCodecContext;
+  VideoCodec: PAVCodec;
+  AVFrame: PAVFrame;
+  AVFrameRGB: PAVFrame;
+  myBuffer: pByte;
+  VideoTex: glUint;
+  TexX, TexY, dataX, dataY: Cardinal;
+  TexData: array of Byte;
+  ScaledVideoWidth, ScaledVideoHeight: Real;
+  VideoAspect: Real;
+  VideoTextureU, VideoTextureV: Real;
+  VideoTimeBase, VideoTime, LastFrameTime, TimeDifference, NegativeSkipTime: Extended;
+  VideoSkipTime: Single;
+  
+implementation
+
+{$ifdef DebugDisplay}
+{$ifNdef win32}
+
+procedure showmessage( aMessage : String );
+begin
+  writeln( aMessage );
+end;
+
+{$endif}
+{$ENDIF}
+
+procedure Init;
+begin
+  av_register_all;
+  {$ifdef DebugDisplay}
+  showmessage( 'AV_Register_ALL' );
+  {$endif}
+  
+  VideoOpened:=False;
+  VideoPaused:=False;
+  
+  glGenTextures(1, PglUint(@VideoTex));
+  SetLength(TexData,0);
+end;
+
+procedure FFmpegOpenFile(FileName: pAnsiChar);
+var errnum, i, x,y: Integer;
+  lStreamsCount : Integer;
+begin
+  VideoOpened    := False;
+  VideoPaused    := False;
+  VideoTimeBase  := 0;
+  VideoTime      := 0;
+  LastFrameTime  := 0;
+  TimeDifference := 0;
+  
+  errnum         := av_open_input_file(VideoFormatContext, FileName, Nil, 0, Nil);
+  
+  if(errnum <> 0) then
+  begin
+{$ifdef DebugDisplay}
+    case errnum of
+      AVERROR_UNKNOWN: showmessage('failed to open file '+Filename+#13#10+'AVERROR_UNKNOWN');
+      AVERROR_IO: showmessage('failed to open file '+Filename+#13#10+'AVERROR_IO');
+      AVERROR_NUMEXPECTED: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NUMEXPECTED');
+      AVERROR_INVALIDDATA: showmessage('failed to open file '+Filename+#13#10+'AVERROR_INVALIDDATA');
+      AVERROR_NOMEM: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOMEM');
+      AVERROR_NOFMT: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOFMT');
+      AVERROR_NOTSUPP: showmessage('failed to open file '+Filename+#13#10+'AVERROR_NOTSUPP');
+    else showmessage('failed to open file '+Filename+#13#10+'Error number: '+inttostr(Errnum));
+    end;
+{$ENDIF}
+    Exit;
+  end
+  else
+  begin
+    VideoStreamIndex:=-1;
+
+    // Find which stream contains the video
+    if(av_find_stream_info(VideoFormatContext) >= 0) then
+    begin
+      {$ifdef DebugDisplay}
+       writeln( 'FFMPEG debug...  VideoFormatContext^.nb_streams : '+ inttostr( VideoFormatContext^.nb_streams ) );
+      {$endif}
+      for i:= 0 to MAX_STREAMS-1 do
+      begin
+        {$ifdef DebugDisplay}
+        writeln( 'FFMPEG debug...  found stream '+ inttostr(i) + ' stream val ' + inttostr( integer(VideoFormatContext^.streams[i] ) ) );
+        {$endif}
+        try
+          if assigned( VideoFormatContext                    ) AND
+             assigned( VideoFormatContext^.streams[i]        ) AND
+             assigned( VideoFormatContext^.streams[i]^.codec ) THEN
+          begin
+              {$ifdef DebugDisplay}
+            writeln( 'FFMPEG debug...  found stream '+ inttostr(i) + ' code val ' + inttostr( integer(VideoFormatContext^.streams[i].codec ) ) );
+            writeln( 'FFMPEG debug...  found stream '+ inttostr(i) + ' code Type ' + inttostr( integer(VideoFormatContext^.streams[i].codec^.codec_type ) ) );
+              {$endif}
+            if(VideoFormatContext^.streams[i]^.codec^.codec_type=CODEC_TYPE_VIDEO) then
+            begin
+              {$ifdef DebugDisplay}
+              writeln( 'FFMPEG debug, found CODEC_TYPE_VIDEO stream' );
+              {$endif}
+              VideoStreamIndex:=i;
+            end
+            else
+          end;
+        except
+          // TODO : JB_Linux ... this is excepting at line 108...  ( Was 111 previously.. so its prob todo with streams[i]^.codec ..
+    {$ifdef DebugDisplay}
+          writeln( 'FFMPEG error, finding video stream' );
+    {$endif}
+        end;
+
+      end;
+    end;
+    
+    if(VideoStreamIndex >= 0) then
+    begin
+      VideoCodecContext:=VideoFormatContext^.streams[VideoStreamIndex]^.codec;
+      VideoCodec:=avcodec_find_decoder(VideoCodecContext^.codec_id);
+    end
+    else
+    begin
+{$ifdef DebugDisplay}
+      showmessage('found no video stream');
+{$ENDIF}
+      av_close_input_file(VideoFormatContext);
+      Exit;
+    end;
+    
+    if(VideoCodec<>Nil) then
+    begin
+      errnum:=avcodec_open(VideoCodecContext, VideoCodec);
+    end else begin
+{$ifdef DebugDisplay}
+      showmessage('no matching codec found');
+{$ENDIF}
+      avcodec_close(VideoCodecContext);
+      av_close_input_file(VideoFormatContext);
+      Exit;
+    end;
+    if(errnum >=0) then
+    begin
+{$ifdef DebugDisplay}
+       showmessage('Found a matching Codec:'+#13#10#13#10+
+        'Width='+inttostr(VideoCodecContext^.width)+
+        ', Height='+inttostr(VideoCodecContext^.height)+#13#10+
+        'Aspect: '+inttostr(VideoCodecContext^.sample_aspect_ratio.num)+'/'+inttostr(VideoCodecContext^.sample_aspect_ratio.den)+#13#10+
+        'Framerate: '+inttostr(VideoCodecContext^.time_base.num)+'/'+inttostr(VideoCodecContext^.time_base.den));
+{$endif}
+      // allocate space for decoded frame and rgb frame
+      AVFrame:=avcodec_alloc_frame;
+      AVFrameRGB:=avcodec_alloc_frame;
+    end;
+    myBuffer:=Nil;
+    if(AVFrame <> Nil) and (AVFrameRGB <> Nil) then
+    begin
+      myBuffer:=av_malloc(avpicture_get_size(PIX_FMT_RGB24, VideoCodecContext^.width,
+                            VideoCodecContext^.height));
+    end;
+    if myBuffer <> Nil then errnum:=avpicture_fill(PAVPicture(AVFrameRGB), myBuffer, PIX_FMT_RGB24,
+                VideoCodecContext^.width, VideoCodecContext^.height)
+    else begin
+{$ifdef DebugDisplay}
+      showmessage('failed to allocate video buffer');
+{$endif}
+      av_free(AVFrameRGB);
+      av_free(AVFrame);
+      avcodec_close(VideoCodecContext);
+      av_close_input_file(VideoFormatContext);
+      Exit;
+    end;
+    if errnum >=0 then
+    begin
+      VideoOpened:=True;
+
+      TexX := VideoCodecContext^.width;
+      TexY := VideoCodecContext^.height;
+      dataX := Round(Power(2, Ceil(Log2(TexX))));
+      dataY := Round(Power(2, Ceil(Log2(TexY))));
+      SetLength(TexData,dataX*dataY*3);
+      // calculate some information for video display
+      VideoAspect:=VideoCodecContext^.sample_aspect_ratio.num/VideoCodecContext^.sample_aspect_ratio.den;
+      if (VideoAspect = 0) then
+        VideoAspect:=VideoCodecContext^.width/VideoCodecContext^.height
+      else
+        VideoAspect:=VideoAspect*VideoCodecContext^.width/VideoCodecContext^.height;
+      if VideoAspect >= 4/3 then
+      begin
+        ScaledVideoWidth:=800.0;
+        ScaledVideoHeight:=800.0/VideoAspect;
+      end else
+      begin
+        ScaledVideoHeight:=600.0;
+        ScaledVideoWidth:=600.0*VideoAspect;
+      end;
+      VideoTimeBase:=VideoCodecContext^.time_base.num/VideoCodecContext^.time_base.den;
+      // hack to get reasonable timebase for divx
+{$ifdef DebugDisplay}
+      showmessage('framerate: '+inttostr(floor(1/videotimebase))+'fps');
+{$endif}
+      if VideoTimeBase < 0.02 then // 0.02 <-> 50 fps
+      begin
+        VideoTimeBase:=VideoCodecContext^.time_base.den/VideoCodecContext^.time_base.num;
+        while VideoTimeBase > 50 do VideoTimeBase:=VideoTimeBase/10;
+        VideoTimeBase:=1/VideoTimeBase;
+      end;
+{$ifdef DebugDisplay}
+      showmessage('corrected framerate: '+inttostr(floor(1/videotimebase))+'fps');
+      if ((VideoAspect*VideoCodecContext^.width*VideoCodecContext^.height)>200000) then
+        showmessage('you are trying to play a rather large video'+#13#10+
+                    'be prepared to experience some timing problems');
+{$endif}
+    end;
+  end;
+end;
+
+procedure FFmpegClose;
+begin
+  if VideoOpened then begin
+    av_free(myBuffer);
+    av_free(AVFrameRGB);
+    av_free(AVFrame);
+    avcodec_close(VideoCodecContext);
+    av_close_input_file(VideoFormatContext);
+    SetLength(TexData,0);
+    VideoOpened:=False;
+  end;
+end;
+
+procedure FFmpegTogglePause;
+begin
+  if VideoPaused then VideoPaused:=False
+  else VideoPaused:=True;
+end;
+
+procedure FFmpegSkip(Time: Single);
+begin
+  VideoSkiptime:=Time;
+  NegativeSkipTime:=Time;
+  if VideoSkipTime > 0 then begin
+    av_seek_frame(VideoFormatContext,-1,Floor((VideoSkipTime)*1000000),0);
+    VideoTime:=VideoSkipTime;
+  end;
+end;
+
+procedure FFmpegGetFrame(Time: Extended);
+var
+  FrameFinished: Integer;
+  AVPacket: TAVPacket;
+  errnum, x, y: Integer;
+  FrameDataPtr: PByteArray;
+  linesize: integer;
+  myTime: Extended;
+  DropFrame: Boolean;
+  droppedFrames: Integer;
+const
+  FRAMEDROPCOUNT=3;
+begin
+  if not VideoOpened then Exit;
+  if VideoPaused then Exit;
+  if (NegativeSkipTime < 0)and(Time+NegativeSkipTime>=0) then NegativeSkipTime:=0; 
+  myTime:=Time+VideoSkipTime;
+  TimeDifference:=myTime-VideoTime;
+  DropFrame:=False;
+{  showmessage('Time:      '+inttostr(floor(Time*1000))+#13#10+
+    'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+
+    'TimeBase:  '+inttostr(floor(VideoTimeBase*1000))+#13#10+
+    'TimeDiff:  '+inttostr(floor(TimeDifference*1000)));
+}
+  if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin
+{$ifdef DebugFrames}
+    // frame delay debug display
+    GoldenRec.Spawn(200,15,1,16,0,-1,ColoredStar,$00ff00);
+{$endif}
+{    showmessage('not getting new frame'+#13#10+
+    'Time:      '+inttostr(floor(Time*1000))+#13#10+
+    'VideoTime: '+inttostr(floor(VideoTime*1000))+#13#10+
+    'TimeBase:  '+inttostr(floor(VideoTimeBase*1000))+#13#10+
+    'TimeDiff:  '+inttostr(floor(TimeDifference*1000)));
+}
+    Exit;// we don't need a new frame now
+  end;
+  VideoTime:=VideoTime+VideoTimeBase;
+  TimeDifference:=myTime-VideoTime;
+  if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames
+{$ifdef DebugFrames}
+    //frame drop debug display
+    GoldenRec.Spawn(200,55,1,16,0,-1,ColoredStar,$ff0000);
+{$endif}
+//    showmessage('skipping frames'+#13#10+
+//    'TimeBase:  '+inttostr(floor(VideoTimeBase*1000))+#13#10+
+//    'TimeDiff:  '+inttostr(floor(TimeDifference*1000))+#13#10+
+//    'Time2Skip: '+inttostr(floor((Time-LastFrameTime)*1000)));
+//    av_seek_frame(VideoFormatContext,VideoStreamIndex,Floor(Time*VideoTimeBase),0);
+{    av_seek_frame(VideoFormatContext,-1,Floor((myTime+VideoTimeBase)*1500000),0);
+    VideoTime:=floor(myTime/VideoTimeBase)*VideoTimeBase;}
+    VideoTime:=VideoTime+FRAMEDROPCOUNT*VideoTimeBase;
+    DropFrame:=True;
+  end;
+
+  av_init_packet(AVPacket);
+  FrameFinished:=0;
+  // read packets until we have a finished frame (or there are no more packets)
+  while (FrameFinished=0) and (av_read_frame(VideoFormatContext, AVPacket)>=0) do
+  begin
+    // if we got a packet from the video stream, then decode it
+    if (AVPacket.stream_index=VideoStreamIndex) then
+      errnum:=avcodec_decode_video(VideoCodecContext, AVFrame, frameFinished,
+                                     AVPacket.data, AVPacket.size);
+    // release internal packet structure created by av_read_frame
+      av_free_packet(AVPacket);
+  end;
+  if DropFrame then
+    for droppedFrames:=1 to FRAMEDROPCOUNT do begin
+      FrameFinished:=0;
+      // read packets until we have a finished frame (or there are no more packets)
+      while (FrameFinished=0) and (av_read_frame(VideoFormatContext, AVPacket)>=0) do
+      begin
+        // if we got a packet from the video stream, then decode it
+        if (AVPacket.stream_index=VideoStreamIndex) then
+          errnum:=avcodec_decode_video(VideoCodecContext, AVFrame, frameFinished,
+                                         AVPacket.data, AVPacket.size);
+        // release internal packet structure created by av_read_frame
+          av_free_packet(AVPacket);
+      end;
+    end;
+
+  // if we did not get an new frame, there's nothing more to do
+  if Framefinished=0 then begin
+    GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff);
+    Exit;
+  end;
+  // otherwise we convert the pixeldata from YUV to RGB
+  errnum:=img_convert(PAVPicture(AVFrameRGB), PIX_FMT_RGB24,
+            PAVPicture(AVFrame), VideoCodecContext^.pix_fmt,
+			      VideoCodecContext^.width, VideoCodecContext^.height);
+//errnum:=1;
+  if errnum >=0 then begin
+    // copy RGB pixeldata to our TextureBuffer
+    // (line by line)
+    FrameDataPtr:=Pointer(AVFrameRGB^.data[0]);
+    linesize:=AVFrameRGB^.linesize[0];
+    for y:=0 to TexY-1 do begin
+      System.Move(FrameDataPtr[y*linesize],TexData[3*y*dataX],linesize);
+    end;
+
+    // generate opengl texture out of whatever we got
+    glBindTexture(GL_TEXTURE_2D, VideoTex);
+    glTexImage2D(GL_TEXTURE_2D, 0, 3, dataX, dataY, 0, GL_RGB, GL_UNSIGNED_BYTE, TexData);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+{$ifdef DebugFrames}
+    //frame decode debug display
+    GoldenRec.Spawn(200,35,1,16,0,-1,ColoredStar,$ffff00);
+{$endif}
+
+  end;
+end;
+
+procedure FFmpegDrawGL(Screen: integer);
+begin
+  // have a nice black background to draw on (even if there were errors opening the vid)
+  if Screen=1 then begin
+    glClearColor(0,0,0,0);
+    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+  end;
+  // exit if there's nothing to draw
+  if not VideoOpened then Exit;
+  // if we're still inside negative skip, then exit
+  if (NegativeSkipTime < 0) then Exit;
+
+  glEnable(GL_TEXTURE_2D);
+  glEnable(GL_BLEND);
+  glColor4f(1, 1, 1, 1);
+  glBindTexture(GL_TEXTURE_2D, VideoTex);
+  glbegin(gl_quads);
+    glTexCoord2f(         0,          0); glVertex2f(400-ScaledVideoWidth/2, 300-ScaledVideoHeight/2);
+    glTexCoord2f(         0, TexY/dataY); glVertex2f(400-ScaledVideoWidth/2, 300+ScaledVideoHeight/2);
+    glTexCoord2f(TexX/dataX, TexY/dataY); glVertex2f(400+ScaledVideoWidth/2, 300+ScaledVideoHeight/2);
+    glTexCoord2f(TexX/dataX,          0); glVertex2f(400+ScaledVideoWidth/2, 300-ScaledVideoHeight/2);
+  glEnd;
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_BLEND);
+
+{$ifdef Info}
+  if VideoSkipTime+VideoTime+VideoTimeBase < 0 then begin
+    glColor4f(0.7, 1, 0.3, 1);
+    SetFontStyle (1);
+    SetFontItalic(False);
+    SetFontSize(9);
+    SetFontPos (300, 0);
+    glPrint('Delay due to negative VideoGap');
+    glColor4f(1, 1, 1, 1);
+  end;
+{$endif}
+
+{$ifdef DebugFrames}
+    glColor4f(0, 0, 0, 0.2);
+    glbegin(gl_quads);
+      glVertex2f(0, 0);
+      glVertex2f(0, 70);
+      glVertex2f(250, 70);
+      glVertex2f(250, 0);
+    glEnd;
+
+    glColor4f(1,1,1,1);
+    SetFontStyle (1);
+    SetFontItalic(False);
+    SetFontSize(9);
+    SetFontPos (5, 0);
+    glPrint('delaying frame');
+    SetFontPos (5, 20);
+    glPrint('fetching frame');
+    SetFontPos (5, 40);
+    glPrint('dropping frame');
+{$endif}
+end;
+
+end.
diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas
index 5409d9a9..283c51d0 100644
--- a/Game/Code/Screens/UScreenSing.pas
+++ b/Game/Code/Screens/UScreenSing.pas
@@ -2,8 +2,8 @@ unit UScreenSing;
 
 interface
 
-uses UMenu, UMusic, SDL, SysUtils, UFiles, UTime, USongs, UIni, ULog, USmpeg, UTexture, ULyrics,
-  TextGL, OpenGL12, BASS, UThemes, ULCD, UGraphicClasses;
+uses UMenu, UMusic, SDL, SysUtils, UFiles, UTime, USongs, UIni, ULog, UTexture, ULyrics,
+  TextGL, OpenGL12, BASS, UThemes, ULCD, UGraphicClasses, UVideo;
 
 type
   TScreenSing = class(TMenu)
@@ -146,7 +146,7 @@ begin
     //stop Music
     Music.Pause;
     if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then //Video
-      PauseSmpeg; //Video
+      FFmpegTogglePause; //Video
   end
   else            //Pause ausschalten
   begin
@@ -154,8 +154,7 @@ begin
     Music.MoveTo (PauseTime);//Position of Music
     Music.Play; //Play Music
     if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then //Video
-      PlaySmpeg;
-      //SkipSmpeg(PauseTime);
+      FFmpegTogglePause;
     Paused := false;
   end;
 end;
@@ -223,6 +222,7 @@ begin
 
   LyricMain := TLyric.Create;
   LyricSub :=  TLyric.Create;
+  UVideo.Init;
 end;
 
 procedure TScreenSing.onShow;
@@ -350,9 +350,9 @@ begin
 
   // set movie
   if (AktSong.Video <> '') and FileExists(AktSong.Path + AktSong.Video) then begin
-    OpenSmpeg(AktSong.Path + AktSong.Video);
-    SkipSmpeg(AktSong.VideoGAP + AktSong.Start);
-    AktSong.VideoLoaded := true;
+    FFmpegOpenFile(PAnsiChar(AktSong.Path + AktSong.Video));
+    FFmpegSkip(AktSong.VideoGAP + AktSong.Start);
+    if (UVideo.VideoOpened) then AktSong.VideoLoaded := true;
   end;
 
   // set background
@@ -740,14 +740,14 @@ begin
   if AktSong.VideoLoaded then
   begin
     try
-      PlaySmpeg;
+      FFmpegGetFrame(Czas.Teraz);
     except
       //If an Error occurs Reading Video: prevent Video from being Drawn again and Close Video
       AktSong.VideoLoaded := False;
       Log.LogError('Error drawing Video, Video has been disabled for this Song/Session.');
       Log.LogError('Corrupted File: ' + AktSong.Video);
       try
-        CloseSmpeg;
+        FFmpegClose;
       except
 
       end;
@@ -1062,14 +1062,15 @@ begin
   // update and draw movie
   if ShowFinish and AktSong.VideoLoaded then begin
     try
-      UpdateSmpeg; // this only draws
+      FFmpegGetFrame(Czas.Teraz);
+      FFmpegDrawGL(ScreenAct); // this only draws
     except
       //If an Error occurs drawing: prevent Video from being Drawn again and Close Video
       AktSong.VideoLoaded := False;
       log.LogError('Error drawing Video, Video has been disabled for this Song/Session.');
       Log.LogError('Corrupted File: ' + AktSong.Video);
       try
-        CloseSmpeg;
+        FFmpegClose;
       except
 
       end;
@@ -1144,7 +1145,7 @@ begin
   end;
 
   if AktSong.VideoLoaded then begin
-    CloseSmpeg;
+    FFmpegClose;
     AktSong.VideoLoaded := false; // to prevent drawing closed video
   end;
 
diff --git a/Game/Code/Screens/UScreenSingModi.pas b/Game/Code/Screens/UScreenSingModi.pas
index 32526a07..8a52a4b8 100644
--- a/Game/Code/Screens/UScreenSingModi.pas
+++ b/Game/Code/Screens/UScreenSingModi.pas
@@ -2,8 +2,8 @@ unit UScreenSingModi;
 
 interface
 
-uses UMenu, UMusic, SDL, SysUtils, UFiles, UTime, USongs, UIni, ULog, USmpeg, UTexture, ULyrics,
-  TextGL, OpenGL12, BASS, UThemes, ULCD, UScreenSing, ModiSDK;
+uses UMenu, UMusic, SDL, SysUtils, UFiles, UTime, USongs, UIni, ULog, UTexture, ULyrics,
+  TextGL, OpenGL12, BASS, UThemes, ULCD, UScreenSing, ModiSDK, UVideo;
 
 type
   TScreenSingModi = class(TScreenSing)
@@ -944,7 +944,8 @@ end;
 
   // update and draw movie
   if ShowFinish and AktSong.VideoLoaded AND DllMan.Selected.LoadVideo then begin
-    UpdateSmpeg; // this only draws
+      FFmpegGetFrame(Czas.Teraz);
+      FFmpegDrawGL(ScreenAct); // this only draws
   end;
 
   // draw static menu (FG)
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr
index fe8b5a9d..03cb275b 100644
--- a/Game/Code/UltraStar.dpr
+++ b/Game/Code/UltraStar.dpr
@@ -5,43 +5,29 @@ program UltraStar;
 {$R 'UltraStar.res' 'UltraStar.rc'}
 
 uses
-//------------------------------
-  //Includes - 3rd Party Libraries
-  //------------------------------
-  SDL          in 'lib\JEDI-SDLv1.0\SDL\Pas\SDL.pas',
+  SDL in 'lib\JEDI-SDLv1.0\SDL\Pas\SDL.pas',
   moduleloader in 'lib\JEDI-SDLv1.0\SDL\Pas\moduleloader.pas',
-  sdlutils     in 'lib\JEDI-SDLv1.0\SDL\Pas\sdlutils.pas',
-  sdl_image    in 'lib\JEDI-SDLv1.0\SDL_Image\Pas\sdl_image.pas',
-  OpenGL12     in 'lib\JEDI-SDLv1.0\OpenGL\Pas\OpenGL12.pas',
-  sdl_ttf      in 'lib\JEDI-SDLv1.0\SDL_ttf\Pas\sdl_ttf.pas',
-  smpeg        in 'lib\JEDI-SDLv1.0\smpeg\Pas\smpeg.pas',
-
-
-  bass         in 'lib\bass\delphi\bass.pas',
-
-  PNGImage     in 'lib\PNGImage\PNGImage.pas',
-  PNGzLib      in 'lib\PNGImage\PNGzLib.pas',
-  pnglang      in 'lib\PNGImage\pnglang.pas',
-
-  midiout      in 'lib\midi\midiout.pas',
-  midiin       in 'lib\midi\midiin.pas',
-  Circbuf      in 'lib\midi\CIRCBUF.PAS',
-  MidiType     in 'lib\midi\MidiType.PAS',
-  MidiDefs     in 'lib\midi\MidiDefs.PAS',
-  MidiCons     in 'lib\midi\MidiCons.PAS',
-  MidiFile     in 'lib\midi\MidiFile.PAS',
-  Delphmcb     in 'lib\midi\Delphmcb.PAS',
-
-  zlportio     in 'lib\zlportio\zlportio.pas',
-  ddkint       in 'lib\zlportio\ddkint.pas',
-
+  sdlutils in 'lib\JEDI-SDLv1.0\SDL\Pas\sdlutils.pas',
+  sdl_image in 'lib\JEDI-SDLv1.0\SDL_Image\Pas\sdl_image.pas',
+  OpenGL12 in 'lib\JEDI-SDLv1.0\OpenGL\Pas\OpenGL12.pas',
+  sdl_ttf in 'lib\JEDI-SDLv1.0\SDL_ttf\Pas\sdl_ttf.pas',
+  smpeg in 'lib\JEDI-SDLv1.0\smpeg\Pas\smpeg.pas',
+  bass in 'lib\bass\delphi\bass.pas',
+  PNGImage in 'lib\PNGImage\PNGImage.pas',
+  PNGzLib in 'lib\PNGImage\PNGzLib.pas',
+  pnglang in 'lib\PNGImage\pnglang.pas',
+  midiout in 'lib\midi\midiout.pas',
+  midiin in 'lib\midi\midiin.pas',
+  CIRCBUF in 'lib\midi\CIRCBUF.PAS',
+  MidiType in 'lib\midi\MidiType.PAS',
+  MidiDefs in 'lib\midi\MidiDefs.PAS',
+  MidiCons in 'lib\midi\MidiCons.PAS',
+  MidiFile in 'lib\midi\MidiFile.PAS',
+  Delphmcb in 'lib\midi\Delphmcb.PAS',
+  zlportio in 'lib\zlportio\zlportio.pas',
+  ddkint in 'lib\zlportio\ddkint.pas',
   SQLiteTable3 in 'lib\SQLite\SQLiteTable3.pas',
-  SQLite3      in 'lib\SQLite\SQLite3.pas',
-
-
-  //------------------------------
-  //Includes - Menu System
-  //------------------------------
+  SQLite3 in 'lib\SQLite\SQLite3.pas',
   UDisplay in 'Menu\UDisplay.pas',
   UMenu in 'Menu\UMenu.pas',
   UMenuStatic in 'Menu\UMenuStatic.pas',
@@ -52,10 +38,6 @@ uses
   UMenuSelectSlide in 'Menu\UMenuSelectSlide.pas',
   UDrawTexture in 'Menu\UDrawTexture.pas',
   UMenuButtonCollection in 'Menu\UMenuButtonCollection.pas',
-
-  //------------------------------
-  //Includes - Classes
-  //------------------------------
   UGraphic in 'Classes\UGraphic.pas',
   UTexture in 'Classes\UTexture.pas',
   UMusic in 'Classes\UMusic.pas',
@@ -83,11 +65,7 @@ uses
   UDLLManager in 'Classes\UDLLManager.pas',
   UParty in 'Classes\UParty.pas',
   UPlaylist in 'Classes\UPlaylist.pas',
-  UCommandLine  in 'Classes\UCommandLine.pas',
-
-  //------------------------------
-  //Includes - Screens
-  //------------------------------
+  UCommandLine in 'Classes\UCommandLine.pas',
   UScreenLoading in 'Screens\UScreenLoading.pas',
   UScreenWelcome in 'Screens\UScreenWelcome.pas',
   UScreenMain in 'Screens\UScreenMain.pas',
@@ -116,27 +94,22 @@ uses
   UScreenStatDetail in 'Screens\UScreenStatDetail.pas',
   UScreenCredits in 'Screens\UScreenCredits.pas',
   UScreenPopup in 'Screens\UScreenPopup.pas',
-
-  //------------------------------
-  //Includes - Screens PartyMode
-  //------------------------------
   UScreenSingModi in 'Screens\UScreenSingModi.pas',
   UScreenPartyNewRound in 'Screens\UScreenPartyNewRound.pas',
   UScreenPartyScore in 'Screens\UScreenPartyScore.pas',
   UScreenPartyPlayer in 'Screens\UScreenPartyPlayer.pas',
   UScreenPartyOptions in 'Screens\UScreenPartyOptions.pas',
   UScreenPartyWin in 'Screens\UScreenPartyWin.pas',
-
-  //------------------------------
-  //Includes - Modi SDK
-  //------------------------------
   ModiSDK in '..\..\Modis\SDK\ModiSDK.pas',
-
-  //------------------------------
-  //Includes - Delphi
-  //------------------------------
   Windows,
-  SysUtils;
+  SysUtils,
+  UVideo in 'Classes\UVideo.pas',
+  avutil in 'lib\ffmpeg\avutil.pas',
+  avcodec in 'lib\ffmpeg\avcodec.pas',
+  avformat in 'lib\ffmpeg\avformat.pas',
+  opt in 'lib\ffmpeg\opt.pas',
+  rational in 'lib\ffmpeg\rational.pas',
+  avio in 'lib\ffmpeg\avio.pas';
 
 const
   Version = 'UltraStar Deluxe V 1.01';
-- 
cgit v1.2.3