/// <summary> /// Initialized the demux for given stream. After calling this you can /// query A/V stream info and create decoders to play back those streams. /// </summary> /// <param name="sourceStream">Source stream.</param> /// <param name="loadOptions">Load options.</param> public override void Init(Stream sourceStream, LoadOptions loadOptions = null) { var watch = new System.Diagnostics.Stopwatch(); watch.Start(); reader = new AtomicBinaryReader(sourceStream); var riffParser = new RiffParser(reader); avi = new AVIFile(); idx1EntryOffset = -1; idx1Offset = -1; currentStrh4CC = 0; while (riffParser.ReadNext(ProcessAviChunk, ProcessAviList, ProcessAviRiff)) { ; } if (avi.strhVideo != null) { videoStreamInfo = new VideoStreamInfo(); videoStreamInfo.codecFourCC = avi.strhVideo.fccHandler; videoStreamInfo.bitsPerPixel = avi.strfVideo.biBitCount; videoStreamInfo.frameCount = avi.odml != null ? (int)avi.odml.dwTotalFrames : (int)avi.avih.dwTotalFrames; videoStreamInfo.width = (int)avi.avih.dwWidth; videoStreamInfo.height = (int)avi.avih.dwHeight; videoStreamInfo.framerate = (float)avi.strhVideo.dwRate / (float)avi.strhVideo.dwScale; } else { videoStreamInfo = null; } if (avi.strhAudio != null) { audioStreamInfo = new AudioStreamInfo(); audioStreamInfo.codecFourCC = avi.strhAudio.fccHandler; audioStreamInfo.audioFormat = avi.strfAudio.wFormatTag; audioStreamInfo.sampleCount = (int)avi.strhAudio.dwLength; audioStreamInfo.sampleSize = (int)avi.strhAudio.dwSampleSize; audioStreamInfo.channels = (int)avi.strfAudio.nChannels; audioStreamInfo.sampleRate = (int)avi.strfAudio.nSamplesPerSec; } else { audioStreamInfo = null; } // we may already have indexes here. it happens when the AVI contained OpenDML indx elements. // if we don't have indexes yet, then try to parse then out from an old idx1 chunk. if (hasVideo) { if (avi.videoIndex == null) { avi.videoIndex = ParseOldIndex(idx1Offset, riffParser.reader, idx1Size, AviDemux.ID_00dc, idx1EntryOffset); } if (avi.videoIndex == null) { // currently we're just throwing an exception here, but we could also rebuild the index. It's slow, but doable. throw new MpException("No video index found (required for playback and seeking)"); } PrepareVideoStream(); } if (hasAudio) { if (avi.audioIndex == null) { avi.audioIndex = ParseOldIndex(idx1Offset, riffParser.reader, idx1Size, AviDemux.ID_01wb, idx1EntryOffset); } if (avi.audioIndex == null) { // currently we're just throwing an exception here, but we could also rebuild the index. It's slow, but doable. throw new MpException("No audio index found (required for playback and seeking)"); } PrepareAudioStream(); } // if not all the frames are indexed, fix it if (videoStreamInfo != null && avi.videoIndex != null && videoStreamInfo.frameCount > avi.videoIndex.entries.Count) { #if MP_DEBUG Debug.LogWarning("Not all video frames are indexed. Adjusting video length to match indexed frame count " + avi.videoIndex.entries.Count + ". AVI header told that there should be " + videoStreamInfo.frameCount + " frames." + " It's likely that your encoder has a bug."); #endif videoStreamInfo.frameCount = avi.videoIndex.entries.Count; } watch.Stop(); #if MP_DEBUG Debug.Log("AVI loaded in " + (watch.Elapsed.TotalMilliseconds * 0.001f) + " seconds"); #endif nextVideoFrame = 0; nextAudioSample = 0; }