Keep video in sync with audio

This commit is contained in:
Paul Chote
2010-08-11 23:02:45 +12:00
parent ca6debde66
commit b88512df43
2 changed files with 42 additions and 29 deletions

View File

@@ -109,11 +109,15 @@ namespace OpenRA.FileFormats
CollectAudioData(); CollectAudioData();
// Load the first frame Reset();
currentFrame = 0;
AdvanceFrame();
} }
public void Reset()
{
currentFrame = cbOffset = cbChunk = 0;
LoadFrame();
}
void CollectAudioData() void CollectAudioData()
{ {
var ms = new MemoryStream(); var ms = new MemoryStream();
@@ -147,9 +151,18 @@ namespace OpenRA.FileFormats
audioData = AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex); audioData = AudLoader.LoadSound(ms.ToArray(), ref adpcmIndex);
} }
public void AdvanceFrame() public void AdvanceFrame()
{
currentFrame++;
LoadFrame();
}
void LoadFrame()
{ {
if (currentFrame >= Frames)
return;
// Seek to the start of the frame // Seek to the start of the frame
stream.Seek(offsets[currentFrame], SeekOrigin.Begin); stream.Seek(offsets[currentFrame], SeekOrigin.Begin);
BinaryReader reader = new BinaryReader(stream); BinaryReader reader = new BinaryReader(stream);
@@ -176,8 +189,6 @@ namespace OpenRA.FileFormats
// Chunks are aligned on even bytes; advance by a byte if the next one is null // Chunks are aligned on even bytes; advance by a byte if the next one is null
if (reader.PeekChar() == 0) reader.ReadByte(); if (reader.PeekChar() == 0) reader.ReadByte();
} }
if (++currentFrame == Frames)
currentFrame = cbOffset = cbChunk = 0;
} }
// VQA Frame // VQA Frame

View File

@@ -12,6 +12,7 @@ using System;
using System.Drawing; using System.Drawing;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Support;
namespace OpenRA.Widgets namespace OpenRA.Widgets
{ {
@@ -23,41 +24,42 @@ namespace OpenRA.Widgets
Sprite videoSprite; Sprite videoSprite;
VqaReader video = null; VqaReader video = null;
float invLength;
public void LoadVideo(string filename) public void LoadVideo(string filename)
{ {
video = new VqaReader(FileSystem.Open(filename)); video = new VqaReader(FileSystem.Open(filename));
timestep = 1e3f/video.Framerate; timestep = 1f/video.Framerate;
invLength = video.Framerate*1f/video.Frames;
var size = OpenRA.Graphics.Util.NextPowerOf2(Math.Max(video.Width, video.Height)); var size = OpenRA.Graphics.Util.NextPowerOf2(Math.Max(video.Width, video.Height));
videoSprite = new Sprite(new Sheet(new Size(size,size)), new Rectangle( 0, 0, video.Width, video.Height ), TextureChannel.Alpha); videoSprite = new Sprite(new Sheet(new Size(size,size)), new Rectangle( 0, 0, video.Width, video.Height ), TextureChannel.Alpha);
} }
int lastTime; bool first = true;
bool advanceNext = false; bool advanceNext = false;
Stopwatch sw = new Stopwatch();
public override void DrawInner(World world) public override void DrawInner(World world)
{ {
if (video == null) if (video == null)
{ LoadVideo(Video);
LoadVideo(Video);
Sound.PlayRaw(video.AudioData); var nextFrame = (int)float2.Lerp(0, video.Frames, (float)(sw.ElapsedTime()*invLength));
} if (first || nextFrame > video.Frames)
int t = Environment.TickCount;
int dt = t - lastTime;
if (advanceNext)
{
if (video.CurrentFrame == 0)
Sound.PlayRaw(video.AudioData);
advanceNext = false;
video.AdvanceFrame();
}
if (dt > timestep)
{ {
lastTime = t; video.Reset();
advanceNext = true; sw.Reset();
Sound.PlayRaw(video.AudioData);
nextFrame = 0;
videoSprite.sheet.Texture.SetData(video.FrameData()); videoSprite.sheet.Texture.SetData(video.FrameData());
first = false;
}
while (nextFrame > video.CurrentFrame)
{
video.AdvanceFrame();
if (nextFrame == video.CurrentFrame)
videoSprite.sheet.Texture.SetData(video.FrameData());
} }
Game.Renderer.RgbaSpriteRenderer.DrawSprite(videoSprite, new int2(RenderBounds.X,RenderBounds.Y), "chrome"); Game.Renderer.RgbaSpriteRenderer.DrawSprite(videoSprite, new int2(RenderBounds.X,RenderBounds.Y), "chrome");