diff --git a/.idea/.idea.DiscImageChef.VideoNow/.idea/contentModel.xml b/.idea/.idea.DiscImageChef.VideoNow/.idea/contentModel.xml index b3f3cf0..9da8a41 100644 --- a/.idea/.idea.DiscImageChef.VideoNow/.idea/contentModel.xml +++ b/.idea/.idea.DiscImageChef.VideoNow/.idea/contentModel.xml @@ -26,6 +26,7 @@ + diff --git a/DiscImageChef.VideoNow/Program.cs b/DiscImageChef.VideoNow/Program.cs index eb9a9a2..cb25997 100644 --- a/DiscImageChef.VideoNow/Program.cs +++ b/DiscImageChef.VideoNow/Program.cs @@ -197,7 +197,7 @@ namespace DiscImageChef.VideoNow : Localization.FirstFrameIsNotAtSectorBoundary); if(xp) - Console.WriteLine("VideoNow XP discs are not yet supported"); + Xp.Decode(args[0], fs, swapped, framePosition); else Color.Decode(args[0], fs, swapped, framePosition); diff --git a/DiscImageChef.VideoNow/Properties/AssemblyInfo.cs b/DiscImageChef.VideoNow/Properties/AssemblyInfo.cs index f47dcf4..9cad5e7 100644 --- a/DiscImageChef.VideoNow/Properties/AssemblyInfo.cs +++ b/DiscImageChef.VideoNow/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.1.0")] -[assembly: AssemblyFileVersion("1.0.1.0")] \ No newline at end of file +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] \ No newline at end of file diff --git a/DiscImageChef.VideoNow/Xp.cs b/DiscImageChef.VideoNow/Xp.cs index bc1ebbd..5124435 100644 --- a/DiscImageChef.VideoNow/Xp.cs +++ b/DiscImageChef.VideoNow/Xp.cs @@ -1,3 +1,9 @@ +using System; +using System.IO; +using System.Linq; +using SharpAvi; +using SharpAvi.Output; + namespace DiscImageChef.VideoNow { public static class Xp @@ -145,5 +151,229 @@ namespace DiscImageChef.VideoNow 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }; + + public static void Decode(string filename, Stream fs, bool swapped, long framePosition) + { + char progress = ' '; + + var aviWriter = new AviWriter(filename + ".avi") + { + EmitIndex1 = true, FramesPerSecond = 18 + }; + + IAviVideoStream videoStream = aviWriter.AddVideoStream(144, 80, BitsPerPixel.Bpp24); + videoStream.Codec = KnownFourCCs.Codecs.Uncompressed; + IAviAudioStream audioStream = aviWriter.AddAudioStream(2, 17784, 8); + + fs.Position = framePosition; + byte[] frameBuffer = new byte[19760]; + fs.Read(frameBuffer, 0, frameBuffer.Length); + + int audioStart = swapped ? 9 : 8; + byte[] frameMarkerToUse = swapped ? SwappedFrameMarker : FrameMarker; + byte[] frameMaskToUse = swapped ? SwappedFrameMask : FrameMask; + + if(swapped) + frameBuffer = Swapping.SwapBuffer(frameBuffer); + + var outFs = new MemoryStream(); + + for(int i = 9; i <= frameBuffer.Length; i += 10) + { + switch(i / 10 % 4) + { + case 0: + progress = '-'; + + break; + case 1: + progress = '\\'; + + break; + case 2: + progress = '|'; + + break; + case 3: + progress = '/'; + + break; + } + + Console.Write($"\r{Localization.ExtractingAudio}", progress); + outFs.WriteByte(frameBuffer[i]); + } + + byte[] videoFrame = Color.DecodeFrame(frameBuffer); + videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length); + audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length); + + int totalFrames = 1; + framePosition += 19760; + byte[] buffer = new byte[frameMarkerToUse.Length]; + + while(framePosition + 19760 < fs.Length) + { + switch(totalFrames % 4) + { + case 0: + progress = '-'; + + break; + case 1: + progress = '\\'; + + break; + case 2: + progress = '|'; + + break; + case 3: + progress = '/'; + + break; + } + + Console.Write($"\r{Localization.LookingForMoreFrames}", progress); + + for(int i = 0; i < buffer.Length; i++) + buffer[i] &= frameMaskToUse[i]; + + if(!buffer.SequenceEqual(frameMarkerToUse)) + { + Console.Write("\r \r"); + Console.WriteLine(Localization.FrameAndNextAreNotAligned, totalFrames); + long expectedFramePosition = framePosition; + + while(framePosition < fs.Length) + { + fs.Position = framePosition; + fs.Read(buffer, 0, buffer.Length); + + for(int i = 0; i < buffer.Length; i++) + buffer[i] &= frameMaskToUse[i]; + + if(buffer.SequenceEqual(frameMarkerToUse)) + { + Console.Write("\r \r"); + + fs.Position = framePosition; + frameBuffer = new byte[19760]; + fs.Read(frameBuffer, 0, frameBuffer.Length); + + if(swapped) + frameBuffer = Swapping.SwapBuffer(frameBuffer); + + outFs = new MemoryStream(); + + for(int i = 9; i <= frameBuffer.Length; i += 10) + { + switch(i / 10 % 4) + { + case 0: + progress = '-'; + + break; + case 1: + progress = '\\'; + + break; + case 2: + progress = '|'; + + break; + case 3: + progress = '/'; + + break; + } + + Console.Write($"\r{Localization.ExtractingAudio}", progress); + outFs.WriteByte(frameBuffer[i]); + } + + videoFrame = Color.DecodeFrame(frameBuffer); + videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length); + audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length); + + totalFrames++; + Console.Write("\r \r"); + + Console.WriteLine(Localization.FrameFoundAtPosition, framePosition, totalFrames, + framePosition - expectedFramePosition); + + Console. + WriteLine(framePosition % 2352 == 0 ? Localization.FrameIsAtSectorBoundary : Localization.FrameIsNotAtSectorBoundary, + totalFrames); + + framePosition += 19760; + + break; + } + + framePosition++; + } + + continue; + } + + if(framePosition % 2352 == 0) + { + Console.Write("\r \r"); + Console.WriteLine(Localization.FrameIsAtSectorBoundary, totalFrames); + } + + Console.Write("\r \r"); + fs.Position = framePosition; + frameBuffer = new byte[19760]; + fs.Read(frameBuffer, 0, frameBuffer.Length); + + if(swapped) + frameBuffer = Swapping.SwapBuffer(frameBuffer); + + outFs = new MemoryStream(); + + for(int i = 9; i <= frameBuffer.Length; i += 10) + { + switch(i / 10 % 4) + { + case 0: + progress = '-'; + + break; + case 1: + progress = '\\'; + + break; + case 2: + progress = '|'; + + break; + case 3: + progress = '/'; + + break; + } + + Console.Write($"\r{Localization.ExtractingAudio}", progress); + outFs.WriteByte(frameBuffer[i]); + } + + videoFrame = Color.DecodeFrame(frameBuffer); + videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length); + audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length); + + totalFrames++; + fs.Position = framePosition; + fs.Read(buffer, 0, buffer.Length); + framePosition += 19760; + } + + Console.Write("\r \r"); + Console.WriteLine(Localization.FramesFound, totalFrames); + + outFs.Close(); + aviWriter.Close(); + } } } \ No newline at end of file