Esempio n. 1
0
        public FlvReader(FileInfo file, bool generateMetadata)
        {
            _file = file;
            FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 65536);
            //_reader = new AMFReader(file.Open(FileMode.Open));
            _reader = new AMFReader(fs);
            _generateMetadata = generateMetadata;

            if (GetRemainingBytes() >= 9)
                DecodeHeader();
            _keyframeMeta = AnalyzeKeyFrames();
        }
Esempio n. 2
0
        public int Seek(int ts)
        {
            lock (_syncLock)
            {
		        if (_keyFrameMeta == null) 
                {
                    if (!(_reader is IKeyFrameDataAnalyzer)) 
                    {
				        // Seeking not supported
				        return ts;
			        }
                    _keyFrameMeta = (_reader as IKeyFrameDataAnalyzer).AnalyzeKeyFrames();
		        }

                if (_keyFrameMeta.Positions.Length == 0)
                {
			        // no video keyframe metainfo, it's an audio-only FLV
			        // we skip the seek for now.
			        // TODO add audio-seek capability
			        return ts;
		        }
                if (ts >= _keyFrameMeta.Duration)
                {
			        // Seek at or beyond EOF
			        _reader.Position = long.MaxValue;
			        return (int) _keyFrameMeta.Duration;
		        }
		        int frame = 0;
		        for (int i = 0; i < _keyFrameMeta.Positions.Length; i++) 
                {
			        if (_keyFrameMeta.Timestamps[i] > ts) {
				        break;
			        }
			        frame = i;
		        }
		        _reader.Position = _keyFrameMeta.Positions[frame];
		        return _keyFrameMeta.Timestamps[frame];
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Key frames analysis may be used as a utility method so synchronize it.
        /// </summary>
        /// <returns></returns>
        public KeyFrameMeta AnalyzeKeyFrames()
        {
            lock (this.SyncRoot)
            {
                if (_keyframeMeta != null)
                    return _keyframeMeta;

                // Lists of video positions and timestamps
                List<long> positionList = new List<long>();
                List<int> timestampList = new List<int>();
                // Lists of audio positions and timestamps
                List<long> audioPositionList = new List<long>();
                List<int> audioTimestampList = new List<int>();
                long origPos = GetCurrentPosition();
                // point to the first tag
                SetCurrentPosition(9);

                // Maps positions to tags
                _posTagMap = new Dictionary<long,int>();
                int idx = 0;
                bool audioOnly = true;
                while (this.HasMoreTags())
                {
                    long pos = GetCurrentPosition();
                    _posTagMap.Add(pos, idx++);
                    // Read tag header and duration
                    ITag tmpTag = this.ReadTagHeader();
                    _duration = tmpTag.Timestamp;
                    if (tmpTag.DataType == IOConstants.TYPE_VIDEO)
                    {
                        if (audioOnly)
                        {
                            audioOnly = false;
                            audioPositionList.Clear();
                            audioTimestampList.Clear();
                        }
                        if (_firstVideoTag == -1)
                        {
                            _firstVideoTag = pos;
                        }

                        // Grab Frame type
                        byte frametype = _reader.ReadByte();
                        if (((frametype & IOConstants.MASK_VIDEO_FRAMETYPE) >> 4) == IOConstants.FLAG_FRAMETYPE_KEYFRAME)
                        {
                            positionList.Add(pos);
                            timestampList.Add(tmpTag.Timestamp);
                        }
                    }
                    else if (tmpTag.DataType == IOConstants.TYPE_AUDIO)
                    {
                        if (_firstAudioTag == -1)
                        {
                            _firstAudioTag = pos;
                        }
                        if (audioOnly)
                        {
                            audioPositionList.Add(pos);
                            audioTimestampList.Add(tmpTag.Timestamp);
                        }
                    }
                    // This properly handles damaged FLV files - as far as duration/size is concerned
                    long newPosition = pos + tmpTag.BodySize + 15;
                    if (newPosition >= GetTotalBytes())
                    {
#if !SILVERLIGHT
                        log.Info("New position exceeds limit");
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Keyframe analysis");
                            log.Debug(" data type=" + tmpTag.DataType + " bodysize=" + tmpTag.BodySize);
                            log.Debug(" remaining=" + GetRemainingBytes() + " limit=" + GetTotalBytes() + " new pos=" + newPosition + " pos=" + pos);
                        }
#endif
                        break;
                    }
                    else
                    {
                        SetCurrentPosition(newPosition);
                    }
                }
                // restore the pos
                SetCurrentPosition(origPos);

                _keyframeMeta = new KeyFrameMeta();
                _keyframeMeta.Duration = _duration;
                _posTimeMap = new Dictionary<long,long>();
                if (audioOnly)
                {
                    // The flv only contains audio tags, use their lists to support pause and seeking
                    positionList = audioPositionList;
                    timestampList = audioTimestampList;
                }
                _keyframeMeta.AudioOnly = audioOnly;
                _keyframeMeta.Positions = new long[positionList.Count];
                _keyframeMeta.Timestamps = new int[timestampList.Count];
                for (int i = 0; i < _keyframeMeta.Positions.Length; i++)
                {
                    _keyframeMeta.Positions[i] = (long)positionList[i];
                    _keyframeMeta.Timestamps[i] = (int)timestampList[i];
                    _posTimeMap.Add((long)positionList[i], (long)((int)timestampList[i]));
                }
                return _keyframeMeta;
            }
        }