Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
        }