private void H264Decode(string path, int fps) { var decoder = new OpenH264Lib.Decoder("openh264-1.7.0-win32.dll"); var aviFile = System.IO.File.OpenRead(path); var riff = new RiffFile(aviFile); var frames = riff.Chunks.OfType <RiffChunk>().Where(x => x.FourCC == "00dc"); var enumerator = frames.GetEnumerator(); var timer = new System.Timers.Timer(1000 / fps) { SynchronizingObject = this, AutoReset = true }; timer.Elapsed += (s, e) => { if (enumerator.MoveNext() == false) { timer.Stop(); return; } var chunk = enumerator.Current; var frame = chunk.ReadToEnd(); var image = decoder.Decode(frame, frame.Length); if (image == null) { return; } pbxScreen.Image = image; }; timer.Start(); }
// インデックスには、データ チャンクのリストとファイル内でのその位置が含まれている。 // インデックスは、AVIOLDINDEX 構造体で構成され、各データ チャンクのエントリが含まれている。 // ファイルにインデックスが含まれる場合、AVIMAINHEADER 構造体の dwFlags メンバにある AVIF_HASINDEX フラグを設定する。 private static void WriteIdx1Chunk(RiffFile riff, List <Idx1Entry> IndexList) { const int AVIIF_KEYFRAME = 0x00000010; // 前後のフレームの情報なしにこのフレームの完全な情報を含んでいる var chunk = riff.CreateChunk("idx1"); int offset = 4; foreach (var item in IndexList) { int length = item.Length; chunk.Write(ToFourCC(item.ChunkId)); chunk.Write(item.KeyFrame? AVIIF_KEYFRAME: 0x00); chunk.Write(offset); chunk.Write(length); offset += 8 + length; // 8は多分00dcとデータサイズ if (item.Padding) { offset += 1; } } chunk.Close(); }
public AviWriter(System.IO.Stream outputAvi, string fourCC, int width, int height, float fps) { // RIFFファイルは、RIFFヘッダーとその後ろに続く 0個以上のリストとチャンクで構成されている。 // RIFFヘッダーは、'RIFF'のFOURCC、4バイトのデータサイズ、データを識別するFOURCC、データから構成されている。 // リストは、'LIST'のFOURCC、4バイトのデータサイズ、データを識別するFOURCC、データから構成されている。 // チャンクは、データを識別するFOURCC、4バイトのデータサイズ、データから構成されている。 // チャンクデータを識別するFOURCCは、2桁のストリーム番号とその後に続く2文字コード(dc=ビデオ,wb=音声,tx=字幕など)で構成されている。 // AVIファイルは、'AVI 'のFOURCCと、2つの必須のLISTチャンク('hdrl''movi')、オプションのインデックスチャンクから構成されるRIFFファイルである。 var riffFile = new RiffFile(outputAvi, "AVI "); // hdrlリストを仮のフレーム数で作成 var hdrlList = riffFile.CreateList("hdrl"); WriteHdrlList(hdrlList, fourCC, width, height, fps, 0); hdrlList.Close(); // moviリストを作成し、OnAddImageごとにデータチャンクを追加 var idx1List = new List <Idx1Entry>(); var moviList = riffFile.CreateList("movi"); this.OnAddImage += (data, keyFrame) => { var idx1 = WriteMoviList(moviList, "00dc", data); idx1.KeyFrame = keyFrame; idx1List.Add(idx1); }; // ファイルをクローズ this.OnClose += () => { // moviリストを閉じる moviList.Close(); // idx1チャンクを作成 WriteIdx1Chunk(riffFile, idx1List); // hdrlListを正しいフレーム数で上書き var offset = hdrlList.Offset; riffFile.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin); // hdrlリストの先頭まで戻る riffFile.BaseStream.Seek(12, System.IO.SeekOrigin.Current); // hdrlリストのヘッダ分飛ばす WriteHdrlList(riffFile, fourCC, width, height, fps, idx1List.Count); // hdrlリストのデータを正しいフレーム数で上書き riffFile.BaseStream.Seek(0, System.IO.SeekOrigin.End); // 元の場所に戻る // ファイルをクローズ riffFile.Close(); if (outputAvi.GetType() == typeof(MemoryStream)) { finishedData = ((MemoryStream)outputAvi).ToArray(); } outputAvi.Dispose(); }; }
public RiffBase(System.IO.Stream output, string fourCC) { this.FourCC = fourCC; this.Offset = output.Position; Writer = new System.IO.BinaryWriter(output); Writer.Write(RiffFile.ToFourCC(fourCC)); this.SizeOffset = output.Position; uint dummy_size = 0; Writer.Write(dummy_size); this.DataOffset = output.Position; }