/// <summary> /// Scan matroska file and fill MkvTracks /// </summary> public void GetInfo() { // Debug log.Info("\r\nFile path: " + mpegFilePath + "\r\n" + "File name: " + mpegFileName + "\r\n" + "File size: " + mpegFileSize.ToString("#,##0")); streamManager = new MpegStreamManager(mpegFilePath); vStream = new MpegVideoStream(); aStream = new MpegAudioStream(); bool isVideo = mvp.Parse(ref streamManager); if (isVideo) { vStream = mvp.VideoStream; } bool isAudio = map.Parse(ref streamManager); if (isAudio) { aStream = map.AudioStream; } streamManager.Close(); return; }
/// <summary> /// Search audio stream using passed MpegStreamManager /// </summary> public bool Parse(ref MpegStreamManager msManager) { audioStream = new MpegAudioStream(); long offset = 0; // Search 0x00 0x00 0x01 0xC0 marker [Audio Stream] bool isAudioContains = msManager.SearchMarker(ref offset, new byte[4]{0x00, 0x00, 0x01, 0xC0}); if (!isAudioContains) { // there isn't audio return false; } offset += 13; bool isAudio = false; while (!isAudio && offset < (msManager.StreamSize - 10)) { if ((msManager.GetByte(offset) == 0xFF) && (msManager.GetByte(offset + 1) & 0xF0) == 0xF0) { isAudio = ParseAudioStream(ref msManager, offset); } offset ++; } if (isAudio) { // Audio information added return true; } return false; }
/// <summary> /// Search video stream using passed MpegStreamManager /// </summary> public bool Parse(ref MpegStreamManager msManager) { videoStream = new MpegVideoStream(); long offset = 0; // Search 0x00 0x00 0x01 0xB3 marker [Sequence header] bool isSeqHeader = msManager.SearchMarker(ref offset, new byte[4]{0x00, 0x00, 0x01, 0xB3}); if (!isSeqHeader) { // Sequence header not founded return false; } // skip marker bytes offset += 4; // read height and width videoStream.Width = msManager.GetSize(offset) >> 4; videoStream.Height = msManager.GetSize(offset + 1) & 0x0FFF; offset += 3; // read framerate int frameRateIndex = msManager.GetByte(offset) & 0x0F; if (frameRateIndex > 8) { // Reserved videoStream.FrameRate = 0.0d; } else { // Retrieve value from table videoStream.FrameRate = MpegConstants.FrameRateTable[frameRateIndex]; } // read aspectratio int aspectRatioIndex = (msManager.GetByte(offset) & 0xF0) >> 4; if (aspectRatioIndex <=4) { videoStream.AspectRatio = MpegConstants.AspectRatio[aspectRatioIndex]; } else { videoStream.AspectRatio = "Unknow"; } offset += 1; // read BitRate int bitRate = ((msManager.GetByte(offset) * 0x10000) + (msManager.GetByte(offset + 1) * 0x100) + msManager.GetByte(offset + 2) ) >> 6; videoStream.BitRate = bitRate; // calculate Duration videoStream.Duration = msManager.StreamSize / ((bitRate * 400) / 8.0); // Extract video format and chroma format GetVideoFormat(ref msManager, offset); return true; }
private void ParseExtension(long offset, ref MpegStreamManager msManager) { offset += 4; int ext = msManager.GetByte(offset) >> 4; if (ext == 1) { videoStream.Version = 2; videoStream.VideoFormat = (msManager.GetByte(offset + 1) & 0x06) >> 1; } else if (ext == 2) { videoStream.VideoFormat = (msManager.GetByte(offset) & 0x0E) >> 1; } }
/// <summary> /// Extract Video format and Chroma format /// </summary> private void GetVideoFormat(ref MpegStreamManager msManager, long offset) { byte marker = new byte(); bool isFounded = false; long _offset = offset; // search marker 0xB5 or 0xB8 was founded isFounded = msManager.FindNextMarker(ref _offset, ref marker); if (isFounded) { // founded one marker // if (marker == 0xB8) // { // // [Group of pictures] founded... // return; // } if (marker == 0xB5) { // [extension] ParseExtension(_offset, ref msManager); } else { // in all other cases return; } } else { // marker not founded return; } // Get Chroma Format Text if (videoStream.ChromaFormat >= 1 && videoStream.ChromaFormat <= 3) { // Get chroma format text from chroma format table videoStream.ChromaFormatText = MpegConstants.ChromaFormat[videoStream.ChromaFormat]; } else { // Unknow chroma format videoStream.ChromaFormatText = "Unknow"; } // Get Video Format Text if (videoStream.VideoFormat >= 0 && videoStream.VideoFormat <= 5) { // Get video format text from video format table videoStream.VideoFormatText = MpegConstants.VideoFormat[videoStream.VideoFormat]; } else { // Unknow video format videoStream.VideoFormatText = "Unknow"; } }
private bool ParseAudioStream(ref MpegStreamManager msManager, long offset) { if (Convert.ToBoolean((msManager.GetByte(offset + 1) & 0x08))) { audioStream.Version = 1.0d; } else { audioStream.Version = 2.0d; } audioStream.Layer = (msManager.GetByte(offset + 1) & 0x06) >> 1; if (audioStream.Layer < 1 || audioStream.Layer > 3) { return false; } audioStream.Protected = Convert.ToBoolean(msManager.GetByte(offset + 1) & 0x01); int bitrateIndex = msManager.GetByte(offset + 2) >> 4; int samplingIndex = (msManager.GetByte(offset + 2) & 0x0F) >> 2; if (samplingIndex >= 3 || bitrateIndex == 15) { return false; } audioStream.BitRate = MpegConstants.BitRateIndex[(int)audioStream.Version -1, audioStream.Layer -1, bitrateIndex]; audioStream.ByteRate = (float)((audioStream.BitRate * 1000) / 8.0d); audioStream.SamplingRate = MpegConstants.SamplingIndex[(int)audioStream.Version - 1, samplingIndex]; if (audioStream.BitRate <= 0 || audioStream.ByteRate <= 0 || audioStream.SamplingRate <= 0) { return false; } if (Convert.ToBoolean(msManager.GetByte(offset + 2) & 0x02)) { audioStream.Padding = true; } else { audioStream.Padding = false; } audioStream.ModeCode = msManager.GetByte(offset + 3) >> 6; // int modeExt = (msManager.GetByte(offset + 3) >> 4) & 0x03; if (Convert.ToBoolean(msManager.GetByte(offset + 3) & 0x08)) { audioStream.Copyright = true; } else { audioStream.Copyright = false; } if (Convert.ToBoolean(msManager.GetByte(offset + 3) & 0x04)) { audioStream.Original = true; } else { audioStream.Original = false; } audioStream.EmphasisIndex = msManager.GetByte(offset + 3) & 0x03; if (audioStream.Version == 1) { if (audioStream.Layer == 1) { audioStream.FrameLength = ((48000 * audioStream.BitRate) / audioStream.SamplingRate) + 4 * Convert.ToInt32(audioStream.Padding); } else { audioStream.FrameLength = ((144000 * audioStream.BitRate) / audioStream.SamplingRate) + Convert.ToInt32(audioStream.Padding); } } else if (audioStream.Version == 2) { if (audioStream.Layer == 1) { audioStream.FrameLength = ((24000 * audioStream.BitRate) / audioStream.SamplingRate) + 4 * Convert.ToInt32(audioStream.Padding); } else { audioStream.FrameLength = ((72000 * audioStream.BitRate) / audioStream.SamplingRate) + Convert.ToInt32(audioStream.Padding); } } else { return false; } if (audioStream.Protected) { // frame length sometimes gets offset by +- 2, // got to find out why its happening, // most likely its the protection switch (see above) audioStream.FrameLength += 2; } audioStream.Duration = ((msManager.StreamSize * 1.0d) / audioStream.BitRate) * 0.008d; return true; }