mirror of
https://github.com/aaru-dps/Aaru.VideoNow.git
synced 2025-12-16 19:24:36 +00:00
Export decoded video and audio to uncompressed AVI.
This commit is contained in:
@@ -49,6 +49,9 @@
|
|||||||
<Link>README.md</Link>
|
<Link>README.md</Link>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="SharpAvi" Version="2.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using SharpAvi;
|
||||||
|
using SharpAvi.Output;
|
||||||
|
|
||||||
namespace DiscImageChef.VideoNow
|
namespace DiscImageChef.VideoNow
|
||||||
{
|
{
|
||||||
@@ -77,15 +79,6 @@ namespace DiscImageChef.VideoNow
|
|||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF
|
||||||
};
|
};
|
||||||
|
|
||||||
static readonly byte[] bitmapHeader
|
|
||||||
= {
|
|
||||||
0x42, 0x4D, 0x36, 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
|
|
||||||
0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x87, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
object[] attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
object[] attributes = typeof(MainClass).Assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
||||||
@@ -154,31 +147,17 @@ namespace DiscImageChef.VideoNow
|
|||||||
Console.WriteLine("First frame {0} at a sector boundary", framePosition % 2352 == 0 ? "is" : "is not");
|
Console.WriteLine("First frame {0} at a sector boundary", framePosition % 2352 == 0 ? "is" : "is not");
|
||||||
char progress = ' ';
|
char progress = ' ';
|
||||||
|
|
||||||
FileStream outFs = new FileStream(args[0] + ".audio.wav", FileMode.Create, FileAccess.ReadWrite,
|
AviWriter aviWriter = new AviWriter(args[0] + ".avi") {EmitIndex1 = true, FramesPerSecond = 18};
|
||||||
FileShare.Read);
|
IAviVideoStream videoStream = aviWriter.AddVideoStream(144, 80, BitsPerPixel.Bpp24);
|
||||||
|
videoStream.Codec = KnownFourCCs.Codecs.Uncompressed;
|
||||||
WaveHeader waveHeader = new WaveHeader {id = 0x46464952, format = 0x45564157};
|
var audioStream = aviWriter.AddAudioStream(2, 17640, 8);
|
||||||
FormatChunk fmtChunk = new FormatChunk
|
|
||||||
{
|
|
||||||
id = 0x20746D66,
|
|
||||||
size = 16,
|
|
||||||
format = 1,
|
|
||||||
channels = 2,
|
|
||||||
sampleRate = 17640,
|
|
||||||
bitsPerSample = 8
|
|
||||||
};
|
|
||||||
fmtChunk.byteRate = fmtChunk.sampleRate * fmtChunk.channels * fmtChunk.bitsPerSample / 8;
|
|
||||||
fmtChunk.blockAlign = (ushort)(fmtChunk.channels * fmtChunk.bitsPerSample / 8);
|
|
||||||
DataChunkHeader dataChunkHeader = new DataChunkHeader {id = 0x61746164};
|
|
||||||
|
|
||||||
long headersSize = Marshal.SizeOf(waveHeader) + Marshal.SizeOf(fmtChunk) + Marshal.SizeOf(dataChunkHeader);
|
|
||||||
outFs.Write(new byte[headersSize], 0, (int)headersSize);
|
|
||||||
|
|
||||||
fs.Position = framePosition;
|
fs.Position = framePosition;
|
||||||
byte[] frameBuffer = new byte[19600];
|
byte[] frameBuffer = new byte[19600];
|
||||||
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
||||||
frameBuffer = SwapBuffer(frameBuffer);
|
frameBuffer = SwapBuffer(frameBuffer);
|
||||||
|
|
||||||
|
var outFs = new MemoryStream();
|
||||||
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
||||||
{
|
{
|
||||||
switch(i / 10 % 4)
|
switch(i / 10 % 4)
|
||||||
@@ -201,12 +180,9 @@ namespace DiscImageChef.VideoNow
|
|||||||
outFs.WriteByte(frameBuffer[i]);
|
outFs.WriteByte(frameBuffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream frameFs = new FileStream($"{args[0]}.frame0000.bmp", FileMode.Create, FileAccess.ReadWrite,
|
byte[] videoFrame = DecodeFrame(frameBuffer);
|
||||||
FileShare.Read);
|
videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length);
|
||||||
frameFs.Write(bitmapHeader, 0, bitmapHeader.Length);
|
audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length);
|
||||||
frameBuffer = DecodeFrame(frameBuffer);
|
|
||||||
frameFs.Write(frameBuffer, 0, frameBuffer.Length);
|
|
||||||
frameFs.Close();
|
|
||||||
|
|
||||||
int totalFrames = 1;
|
int totalFrames = 1;
|
||||||
framePosition += 19600;
|
framePosition += 19600;
|
||||||
@@ -256,6 +232,7 @@ namespace DiscImageChef.VideoNow
|
|||||||
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
||||||
frameBuffer = SwapBuffer(frameBuffer);
|
frameBuffer = SwapBuffer(frameBuffer);
|
||||||
|
|
||||||
|
outFs = new MemoryStream();
|
||||||
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
||||||
{
|
{
|
||||||
switch(i / 10 % 4)
|
switch(i / 10 % 4)
|
||||||
@@ -277,12 +254,9 @@ namespace DiscImageChef.VideoNow
|
|||||||
Console.Write("\rExtracting audio {0} ", progress);
|
Console.Write("\rExtracting audio {0} ", progress);
|
||||||
outFs.WriteByte(frameBuffer[i]);
|
outFs.WriteByte(frameBuffer[i]);
|
||||||
}
|
}
|
||||||
frameFs = new FileStream($"{args[0]}.frame{totalFrames:D6}.bmp", FileMode.Create, FileAccess.ReadWrite,
|
videoFrame = DecodeFrame(frameBuffer);
|
||||||
FileShare.Read);
|
videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length);
|
||||||
frameFs.Write(bitmapHeader, 0, bitmapHeader.Length);
|
audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length);
|
||||||
frameBuffer = DecodeFrame(frameBuffer);
|
|
||||||
frameFs.Write(frameBuffer, 0, frameBuffer.Length);
|
|
||||||
frameFs.Close();
|
|
||||||
|
|
||||||
totalFrames++;
|
totalFrames++;
|
||||||
Console.Write("\r \r");
|
Console.Write("\r \r");
|
||||||
@@ -313,6 +287,7 @@ namespace DiscImageChef.VideoNow
|
|||||||
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
fs.Read(frameBuffer, 0, frameBuffer.Length);
|
||||||
frameBuffer = SwapBuffer(frameBuffer);
|
frameBuffer = SwapBuffer(frameBuffer);
|
||||||
|
|
||||||
|
outFs = new MemoryStream();
|
||||||
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
for(int i = 9; i <= frameBuffer.Length; i += 10)
|
||||||
{
|
{
|
||||||
switch(i / 10 % 4)
|
switch(i / 10 % 4)
|
||||||
@@ -334,12 +309,9 @@ namespace DiscImageChef.VideoNow
|
|||||||
Console.Write("\rExtracting audio {0} ", progress);
|
Console.Write("\rExtracting audio {0} ", progress);
|
||||||
outFs.WriteByte(frameBuffer[i]);
|
outFs.WriteByte(frameBuffer[i]);
|
||||||
}
|
}
|
||||||
frameFs = new FileStream($"{args[0]}.frame{totalFrames:D6}.bmp", FileMode.Create, FileAccess.ReadWrite,
|
videoFrame = DecodeFrame(frameBuffer);
|
||||||
FileShare.Read);
|
videoStream.WriteFrame(true, videoFrame, 0, videoFrame.Length);
|
||||||
frameFs.Write(bitmapHeader, 0, bitmapHeader.Length);
|
audioStream.WriteBlock(outFs.ToArray(), 0, (int)outFs.Length);
|
||||||
frameBuffer = DecodeFrame(frameBuffer);
|
|
||||||
frameFs.Write(frameBuffer, 0, frameBuffer.Length);
|
|
||||||
frameFs.Close();
|
|
||||||
|
|
||||||
totalFrames++;
|
totalFrames++;
|
||||||
fs.Position = framePosition;
|
fs.Position = framePosition;
|
||||||
@@ -351,33 +323,8 @@ namespace DiscImageChef.VideoNow
|
|||||||
Console.WriteLine("Found {0} frames", totalFrames);
|
Console.WriteLine("Found {0} frames", totalFrames);
|
||||||
|
|
||||||
fs.Close();
|
fs.Close();
|
||||||
outFs.Position = 0;
|
|
||||||
|
|
||||||
dataChunkHeader.size = (uint)(outFs.Length - headersSize);
|
|
||||||
waveHeader.size = (uint)(outFs.Length - 8);
|
|
||||||
|
|
||||||
buffer = new byte[Marshal.SizeOf(waveHeader)];
|
|
||||||
IntPtr ptr = Marshal.AllocHGlobal(buffer.Length);
|
|
||||||
Marshal.StructureToPtr(waveHeader, ptr, false);
|
|
||||||
Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
outFs.Write(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
buffer = new byte[Marshal.SizeOf(fmtChunk)];
|
|
||||||
ptr = Marshal.AllocHGlobal(buffer.Length);
|
|
||||||
Marshal.StructureToPtr(fmtChunk, ptr, false);
|
|
||||||
Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
outFs.Write(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
buffer = new byte[Marshal.SizeOf(dataChunkHeader)];
|
|
||||||
ptr = Marshal.AllocHGlobal(buffer.Length);
|
|
||||||
Marshal.StructureToPtr(dataChunkHeader, ptr, false);
|
|
||||||
Marshal.Copy(ptr, buffer, 0, buffer.Length);
|
|
||||||
Marshal.FreeHGlobal(ptr);
|
|
||||||
outFs.Write(buffer, 0, buffer.Length);
|
|
||||||
|
|
||||||
outFs.Close();
|
outFs.Close();
|
||||||
|
aviWriter.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintCopyright()
|
static void PrintCopyright()
|
||||||
@@ -475,42 +422,8 @@ namespace DiscImageChef.VideoNow
|
|||||||
}
|
}
|
||||||
|
|
||||||
frameBuffer = videoFs.ToArray();
|
frameBuffer = videoFs.ToArray();
|
||||||
byte[] tmp = new byte[144 * 3];
|
Array.Reverse(frameBuffer);
|
||||||
for(int i = 0; i < 80; i++)
|
|
||||||
{
|
|
||||||
Array.Copy(frameBuffer, i * tmp.Length, tmp, 0, tmp.Length);
|
|
||||||
Array.Reverse(tmp);
|
|
||||||
Array.Copy(tmp, 0, frameBuffer, i *tmp.Length, tmp.Length);
|
|
||||||
}
|
|
||||||
return frameBuffer;
|
return frameBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
struct WaveHeader
|
|
||||||
{
|
|
||||||
public uint id;
|
|
||||||
public uint size;
|
|
||||||
public uint format;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
struct FormatChunk
|
|
||||||
{
|
|
||||||
public uint id;
|
|
||||||
public uint size;
|
|
||||||
public ushort format;
|
|
||||||
public ushort channels;
|
|
||||||
public uint sampleRate;
|
|
||||||
public uint byteRate;
|
|
||||||
public ushort blockAlign;
|
|
||||||
public ushort bitsPerSample;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
struct DataChunkHeader
|
|
||||||
{
|
|
||||||
public uint id;
|
|
||||||
public uint size;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user