public MKVFileSource(Document document) { _Document = document; _Segment = document.Segments[0]; //활성화된 트랙에서 필요한 코덱리스트를 생성 var codecs = CodecFactory.Create(_Segment.Tracks[0].TrackEntry.Where(x => x.FlagEnabled == 1).ToList()); //사용가능한 모든 코덱 추가 UsableCodecs = codecs.Where(x => x.IsSupported).Cast <KnownCodec>(); //사용가능한 미디어 코덱만 추가 UsableMediaCodecs = UsableCodecs.Where(x => x.CodecType == TrackTypes.Video || x.CodecType == TrackTypes.Audio); //사용가능한 자막 코덱 리스트를 생성 UsableSubtitleCodecs = UsableCodecs.Where(x => x.CodecType == TrackTypes.Subtitle); //디폴트 비디오 트랙의 코덱 var videoCodec = UsableMediaCodecs.FirstOrDefault(x => x.CodecType == TrackTypes.Video && x.TrackEntry.FlagDefault == 1); if (videoCodec == null) { videoCodec = UsableMediaCodecs.FirstOrDefault(x => x.CodecType == TrackTypes.Video); } var audioCodec = UsableMediaCodecs.FirstOrDefault(x => x.CodecType == TrackTypes.Audio && x.TrackEntry.FlagDefault == 1); if (audioCodec == null) { audioCodec = UsableMediaCodecs.FirstOrDefault(x => x.CodecType == TrackTypes.Audio); } //비디오나 오디오코덱을 사용할 수 없는 경우만 사용 불가능 코덱을 저장 if (videoCodec == null || audioCodec == null) { //사용 불가능한 미디어 코덱 저장 UnusableMediaCodecs = codecs.Where(x => !x.IsSupported && (x.CodecType == TrackTypes.Video || x.CodecType == TrackTypes.Audio)); } else { UnusableMediaCodecs = new List <ICodec>(); //디폴트 비디오/오디오 트랙으로 미디어 디스크립터 생성 CreateMediaStreamSource(audioCodec); } }
private MediaTypes EnqueueFrameData(Cluster cluster, Block block, ref long timecode) { MediaTypes currBlockType = MediaTypes.None; Block currBlock = null; BlockGroup blockGroup = null; Queue <FrameBufferData> frameQueue = null; //블록 자식 레벨 엘리먼트 로드 currBlock = block.GetBlock(out blockGroup); //큐 선택 if (currBlock.TrackNumber == VideoTrackID) { currBlockType = MediaTypes.Video; frameQueue = VideoFrameQueue; } else if (currBlock.TrackNumber == AudioTrackID) { currBlockType = MediaTypes.Audio; frameQueue = AudioFrameQueue; } else if (currBlock.TrackNumber == SubtitleTrackID) { currBlockType = MediaTypes.Subtitle; frameQueue = SubtitleFrameQueue; } else { return(MediaTypes.None); } var codec = UsableCodecs.FirstOrDefault(x => x.TrackNumber == currBlock.TrackNumber); var track = codec.TrackEntry; byte[] CompressHeader = codec.CompressHeader; timecode = ((long)cluster.Timecode + currBlock.Timecode) * Element.TIC_MILLISECONDS; long timecodeOffset = 0, duration = (long)(track.DefaultDuration / 100); //100나노 초가 1틱이므로 100으로 나눈다. if (blockGroup != null && blockGroup.BlockDuration > 0) { duration = (long)blockGroup.BlockDuration * Element.TIC_MILLISECONDS; } var dts = currBlock.GetBlockData(CompressHeader); foreach (var item in dts) { try { var frame = codec.GetFrameBufferData( item, (long)timecodeOffset + (long)timecode, duration, currBlock.IsKeyFrame, currBlock.Discardable, currBlock.Invisible); frameQueue.Enqueue(frame); timecodeOffset += duration; } catch (Exception) { throw; } } //리턴값 (마지막 시간) timecode += timecodeOffset; //블록 타입 return(currBlockType); }