Example #1
0
        public void SaveAsAvi(string fileName)
        {
            var writer = new AviWriter(fileName)
            {
                FramesPerSecond = (1000000 + this.Header.FrameDelay / 2) / this.Header.FrameDelay,
                EmitIndex1      = true
            };

            try
            {
                IAviVideoStream videoStream = writer.AddMotionJpegVideoStream(this.Header.Width, this.Header.Height, 70);
                IAviAudioStream audioStream = writer.AddAudioStream(this.AudioHeader.NumChannels, this.AudioHeader.Frequency, 16);

                this.BeginPlay();

                try
                {
                    byte[] audio;
                    byte[] video;

                    while (this.RetrieveNextFrame(out audio, out video))
                    {
                        if (video != null)
                        {
                            byte[] buffer = SnmFile.Convert16BppTo32Bpp(video);
                            videoStream.WriteFrame(true, buffer, 0, buffer.Length);
                        }

                        if (audio != null)
                        {
                            audioStream.WriteBlock(audio, 0, audio.Length);
                        }
                    }
                }
                finally
                {
                    this.EndPlay();
                }
            }
            finally
            {
                writer.Close();
            }
        }
Example #2
0
        public static SnmFile FromFile(string fileName)
        {
            var snm = new SnmFile
            {
                FileName = fileName
            };

            Stream filestream = null;

            try
            {
                filestream = new FileStream(fileName, FileMode.Open, FileAccess.Read);

                byte[] magic = new byte[2];
                filestream.Read(magic, 0, 2);
                filestream.Seek(0, SeekOrigin.Begin);

                if (magic[0] == 0x1F && magic[1] == 0x8B)
                {
                    filestream = new GZipStream(filestream, CompressionMode.Decompress);
                }

                using (BinaryReader file = new BinaryReader(filestream))
                {
                    filestream = null;

                    if (Encoding.ASCII.GetString(file.ReadBytes(4)) != "SANM")
                    {
                        throw new InvalidDataException();
                    }

                    // movie size
                    file.ReadBigEndianInt32();

                    if (Encoding.ASCII.GetString(file.ReadBytes(4)) != "SHDR")
                    {
                        throw new InvalidDataException();
                    }

                    int headerSize = file.ReadBigEndianInt32();

                    if (headerSize != SnmHeader.Size)
                    {
                        throw new InvalidDataException();
                    }

                    snm.Header = new SnmHeader();
                    snm.Header.Read(file);

                    if (Encoding.ASCII.GetString(file.ReadBytes(4)) != "FLHD")
                    {
                        throw new InvalidDataException();
                    }

                    int flhdSize = file.ReadBigEndianInt32();

                    for (int flhdPosition = 0; flhdPosition < flhdSize;)
                    {
                        flhdPosition += 4;

                        if (flhdPosition == flhdSize)
                        {
                            // unknown value
                            file.ReadInt32();
                        }
                        else
                        {
                            string flhdFourcc = Encoding.ASCII.GetString(file.ReadBytes(4));

                            switch (flhdFourcc)
                            {
                            case "Wave":
                            {
                                //if (snm.AudioHeader != null)
                                //{
                                //    throw new InvalidDataException();
                                //}

                                int size = file.ReadBigEndianInt32();
                                flhdPosition += size + 4;

                                snm.AudioHeader = new SnmAudioHeader();
                                snm.AudioHeader.Read(file, size);
                                break;
                            }

                            case "Bl16":
                            {
                                int size = file.ReadBigEndianInt32();
                                flhdPosition += size + 4;

                                SnmVideoHeader header = new SnmVideoHeader();
                                header.Read(file);

                                snm.VideoHeaders.Add(header);
                                break;
                            }

                                //default:
                                //    throw new InvalidDataException();
                            }
                        }
                    }

                    string fourcc = Encoding.ASCII.GetString(file.ReadBytes(4));

                    if (fourcc == "ANNO")
                    {
                        int size = file.ReadBigEndianInt32();
                        snm.Annotation = Encoding.ASCII.GetString(file.ReadBytes(size)).TrimEnd('\0');

                        fourcc = Encoding.ASCII.GetString(file.ReadBytes(4));
                    }

                    for (int i = 0; i < snm.Header.NumFrames; i++)
                    {
                        if (fourcc != "FRME")
                        {
                            throw new InvalidDataException();
                        }

                        SnmFrame frame = new SnmFrame();

                        int frmeSize = file.ReadBigEndianInt32();

                        for (int frmePosition = 0; frmePosition < frmeSize;)
                        {
                            fourcc        = Encoding.ASCII.GetString(file.ReadBytes(4));
                            frmePosition += 4;

                            switch (fourcc)
                            {
                            case "Wave":
                            {
                                if (frame.Audio != null)
                                {
                                    throw new InvalidDataException();
                                }

                                int size = file.ReadBigEndianInt32();
                                frmePosition += size + 4;

                                frame.Audio = new SnmAudioFrame();
                                frame.Audio.Read(file, size);
                                break;
                            }

                            case "Bl16":
                            {
                                if (frame.Video != null)
                                {
                                    throw new InvalidDataException();
                                }

                                int size = file.ReadBigEndianInt32();
                                frmePosition += size + 4;

                                frame.Video = new SnmVideoFrame();
                                frame.Video.Read(file, size);
                                break;
                            }

                            default:
                            {
                                throw new InvalidDataException();
                            }
                            }
                        }

                        snm.Frames.Add(frame);

                        fourcc = Encoding.ASCII.GetString(file.ReadBytes(4));
                    }
                }
            }
            finally
            {
                if (filestream != null)
                {
                    filestream.Dispose();
                }
            }

            return(snm);
        }
Example #3
0
        public static SnmFile FromAviFile(string fileName)
        {
            if (!File.Exists(fileName))
            {
                throw new FileNotFoundException();
            }

            var snm        = new SnmFile();
            var aviManager = new AviManager(fileName);

            try
            {
                AudioStream audioStream = aviManager.GetWaveStream();
                byte[]      audioData   = null;

                if (audioStream != null)
                {
                    if (audioStream.ChannelsCount != 2 || audioStream.BitsPerSample != 16)
                    {
                        throw new InvalidDataException();
                    }

                    if (audioStream.SamplesPerSecond != 22050 && audioStream.SamplesPerSecond != 44100)
                    {
                        throw new NotSupportedException();
                    }

                    snm.AudioHeader = new SnmAudioHeader
                    {
                        Frequency   = audioStream.SamplesPerSecond,
                        NumChannels = audioStream.ChannelsCount
                    };

                    audioData = audioStream.GetStreamData();

                    if (snm.AudioHeader.Frequency == 44100)
                    {
                        snm.AudioHeader.Frequency = 22050;
                        audioData = SnmFile.ConvertAudio44100To22050(audioData);
                    }
                }

                VideoStream videoStream = aviManager.GetVideoStream();

                if (videoStream.BitsPerPixel != 24 && videoStream.BitsPerPixel != 32)
                {
                    throw new NotSupportedException();
                }

                snm.Header.FrameDelay = (int)(1000000 / videoStream.FrameRate + 0.5);
                snm.Header.Width      = (short)videoStream.Width;
                snm.Header.Height     = (short)videoStream.Height;
                snm.Header.NumFrames  = (short)videoStream.FramesCount;

                for (int i = 0; i < videoStream.FramesCount; i++)
                {
                    snm.VideoHeaders.Add(new SnmVideoHeader
                    {
                        Width  = snm.Header.Width,
                        Height = snm.Header.Height
                    });
                }

                videoStream.GetFrameOpen();

                try
                {
                    int fps             = (1000000 + snm.Header.FrameDelay / 2) / snm.Header.FrameDelay;
                    int samplesPerFrame = snm.AudioHeader.Frequency / fps;

                    if (samplesPerFrame * fps != snm.AudioHeader.Frequency)
                    {
                        throw new InvalidDataException();
                    }

                    for (int i = 0; i < videoStream.FramesCount; i++)
                    {
                        byte[] videoData = videoStream.GetFrameData(i);

                        var frame = new SnmFrame();

                        if (audioData != null)
                        {
                            int audioPosition = i * samplesPerFrame * 4;
                            int audioLength   = Math.Min(samplesPerFrame * 4, audioData.Length - audioPosition);

                            if (audioPosition < audioData.Length && audioLength != 0)
                            {
                                frame.Audio = new SnmAudioFrame
                                {
                                    NumSamples = audioLength / 4
                                };

                                byte[] buffer = new byte[audioLength];
                                Array.Copy(audioData, audioPosition, buffer, 0, audioLength);

                                //frame.Audio.Data = Imc.Vima.Compress(buffer, 2);

                                frame.Audio.Data = buffer;
                            }
                        }

                        if (videoData != null)
                        {
                            frame.Video = new SnmVideoFrame
                            {
                                Width         = snm.Header.Width,
                                Height        = snm.Header.Height,
                                RleOutputSize = snm.Header.Width * snm.Header.Height * 2,

                                SubcodecId = (byte)videoStream.BitsPerPixel,
                                Data       = videoData
                            };

                            //byte[] buffer;

                            //if (videoStream.BitsPerPixel == 24)
                            //{
                            //    buffer = SnmFile.Convert24BppTo16Bpp(videoData);
                            //}
                            //else
                            //{
                            //    buffer = SnmFile.Convert32BppTo16Bpp(videoData);
                            //}

                            //byte subcodecId;
                            //frame.Video.Data = Blocky16.Compress(buffer, out subcodecId);
                            //frame.Video.SubcodecId = subcodecId;
                        }

                        snm.Frames.Add(frame);
                    }
                }
                finally
                {
                    videoStream.GetFrameClose();
                }
            }
            finally
            {
                aviManager.Close();
            }

            snm.Frames
            .AsParallel()
            .ForAll(frame =>
            {
                if (frame.Audio != null)
                {
                    frame.Audio.Data = Imc.Vima.Compress(frame.Audio.Data, 2);
                }

                if (frame.Video != null)
                {
                    byte[] buffer;

                    if (frame.Video.SubcodecId == 24)
                    {
                        buffer = SnmFile.Convert24BppTo16Bpp(frame.Video.Data);
                    }
                    else
                    {
                        buffer = SnmFile.Convert32BppTo16Bpp(frame.Video.Data);
                    }

                    frame.Video.Data       = Blocky16.Compress(buffer, out byte subcodecId);
                    frame.Video.SubcodecId = subcodecId;
                }
            });

            return(snm);
        }
Example #4
0
        public static SnmFile ConvertRead(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(nameof(fileName));
            }

            var snm = new SnmFile();

            byte[] aviAudioDataBytes;
            try
            {
                aviAudioDataBytes = GetAviAudioBytes(fileName);
            }
            catch
            {
                aviAudioDataBytes = null;
            }

            InitializeSourceReader(fileName, out IMFSourceReader reader, out int videoStreamIndex, out int audioStreamIndex);

            var audioData = new MemoryStream();

            try
            {
                GetSourceReaderAttributes(reader, out int width, out int height, out int fps);

                snm.AudioHeader = new SnmAudioHeader
                {
                    Frequency   = 22050,
                    NumChannels = 2
                };

                snm.Header.FrameDelay = (int)(1000000 / fps + 0.5);
                snm.Header.Width      = (short)width;
                snm.Header.Height     = (short)height;
                snm.Header.NumFrames  = 0;

                while (true)
                {
                    byte[] bytes = ReadSample(reader, audioStreamIndex, out int streamIndex, out long timestamp);

                    if (bytes == null)
                    {
                        break;
                    }

                    audioData.Write(bytes, 0, bytes.Length);
                }

                if (audioData.Length == 0 && aviAudioDataBytes != null)
                {
                    audioData.Write(aviAudioDataBytes, 0, aviAudioDataBytes.Length);
                }

                while (true)
                {
                    byte[] bytes = ReadSample(reader, videoStreamIndex, out int streamIndex, out long timestamp);

                    if (bytes == null)
                    {
                        break;
                    }

                    snm.VideoHeaders.Add(new SnmVideoHeader
                    {
                        Width  = snm.Header.Width,
                        Height = snm.Header.Height
                    });

                    var frame = new SnmFrame();

                    int audioPosition = snm.Header.NumFrames * snm.AudioHeader.Frequency / fps * 4;
                    int audioLength   = Math.Min(snm.AudioHeader.Frequency / fps * 4, (int)audioData.Length - audioPosition);

                    if (audioPosition < audioData.Length && audioLength != 0)
                    {
                        frame.Audio = new SnmAudioFrame
                        {
                            NumSamples = audioLength / 4
                        };

                        byte[] buffer = new byte[audioLength];
                        audioData.Seek(audioPosition, SeekOrigin.Begin);
                        audioData.Read(buffer, 0, buffer.Length);

                        frame.Audio.Data = buffer;
                    }

                    frame.Video = new SnmVideoFrame
                    {
                        Width         = snm.Header.Width,
                        Height        = snm.Header.Height,
                        RleOutputSize = snm.Header.Width * snm.Header.Height * 2,
                        SubcodecId    = 32,
                        Data          = bytes
                    };

                    snm.Frames.Add(frame);
                    snm.Header.NumFrames++;
                }
            }
            finally
            {
                audioData.Dispose();
                Marshal.ReleaseComObject(reader);
            }

            snm.Frames
            .AsParallel()
            .ForAll(frame =>
            {
                if (frame.Audio != null)
                {
                    frame.Audio.Data = Imc.Vima.Compress(frame.Audio.Data, 2);
                }

                if (frame.Video != null)
                {
                    byte[] buffer = Convert32BppTo16Bpp(frame.Video.Data);

                    frame.Video.Data       = Blocky16.Compress(buffer, out byte subcodecId);
                    frame.Video.SubcodecId = subcodecId;
                }
            });

            return(snm);
        }
Example #5
0
        public static void ConvertWrite(SnmFile snm, string fileName)
        {
            if (snm == null)
            {
                throw new ArgumentNullException(nameof(snm));
            }

            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentNullException(nameof(fileName));
            }

            int  fps           = (1000000 + snm.Header.FrameDelay / 2) / snm.Header.FrameDelay;
            long frameDuration = 10 * 1000 * 1000 / fps;

            InitializeSinkWriter(
                fileName,
                snm.Header.Width,
                snm.Header.Height,
                fps,
                out IMFSinkWriter writer,
                out int videoStream,
                out int audioStream);

            try
            {
                snm.BeginPlay();

                try
                {
                    long rtStartVideo = 0;
                    long rtStartAudio = 0;

                    while (snm.RetrieveNextFrame(out byte[] audioData, out byte[] videoData))
                    {
                        if (videoData != null)
                        {
                            WriteVideoFrame(snm.Header.Width, snm.Header.Height, frameDuration, writer, videoStream, rtStartVideo, videoData);
                            rtStartVideo += frameDuration;
                        }

                        if (audioData != null)
                        {
                            byte[] buffer   = ConvertAudio22050To44100(audioData);
                            long   duration = (long)(10 * 1000 * 1000) * audioData.Length / (22050 * 4);
                            WriteAudioFrame(duration, writer, audioStream, rtStartAudio, buffer);
                            rtStartAudio += duration;
                        }
                    }
                }
                finally
                {
                    snm.EndPlay();
                }

                writer.Finalize_();
            }
            finally
            {
                Marshal.ReleaseComObject(writer);
            }
        }