Пример #1
0
 public void AddTag(FlvTag tag)
 {
     Tags.Add(tag);
     if (tag.TimeStamp >= target)
     {
         FinallizeFile();
     }
 }
        private void _WriteTagData(byte[] data)
        {
            int toRead = Math.Min(data.Length, (currentTag.TagSize - (int)_data.Position));

            _data.Write(data, 0, toRead);
            if ((int)_data.Position == currentTag.TagSize)
            {
                currentTag.Data = _data.ToArray();
                _data.SetLength(0); // reset data buffer
                _TagCreated(currentTag);
                currentTag = null;
                _AddBytes(data.Skip(toRead).ToArray());
            }
        }
Пример #3
0
        public void FinallizeFile()
        {
            try
            {
                if (!Directory.Exists(Path.GetDirectoryName(path)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                }
                using (var fs = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite))
                {
                    fs.Write(FlvStreamProcessor.FLV_HEADER_BYTES, 0, FlvStreamProcessor.FLV_HEADER_BYTES.Length);
                    fs.Write(new byte[] { 0, 0, 0, 0, }, 0, 4);

                    Header.Meta["duration"]      = (Tags[Tags.Count - 1].TimeStamp - Tags[0].TimeStamp) / 1000d;
                    Header.Meta["lasttimestamp"] = (Tags[Tags.Count - 1].TimeStamp - Tags[0].TimeStamp);

                    var t = new FlvTag
                    {
                        TagType = TagType.DATA,
                        Data    = Header.ToBytes()
                    };
                    t.WriteTo(fs);

                    int offset = Tags[0].TimeStamp;

                    HTags.ForEach(tag => tag.WriteTo(fs));
                    Tags.ForEach(tag => tag.WriteTo(fs, offset));

                    logger.Info("剪辑已保存:{0}", Path.GetFileName(path));

                    fs.Close();
                }
                Tags.Clear();
            }
            catch (Exception ex)
            {
                logger.Error(ex, "保存剪辑文件时出错");
            }
            ClipFinalized?.Invoke(this, new ClipFinalizedArgs()
            {
                ClipProcessor = this
            });
        }
        private void _ParseTag(byte[] data)
        {
            _buffer.Position = 0;
            _buffer.SetLength(0);
            byte[] b = new byte[4];
            _buffer.Write(data, 0, data.Length);
            long dataLen = _buffer.Position;

            _buffer.Position = 0;
            FlvTag tag = new FlvTag();

            // Previous Tag Size
            _buffer.Read(b, 0, 4);
            b = new byte[4];

            // TagType UI8
            tag.TagType = (TagType)_buffer.ReadByte();
            // Debug.Write(string.Format("Tag Type: {0}\n", tag.TagType));

            // DataSize UI24
            _buffer.Read(b, 1, 3);
            tag.TagSize = BitConverter.ToInt32(b.ToBE(), 0);

            // Timestamp UI24
            _buffer.Read(b, 1, 3);
            // TimestampExtended UI8
            _buffer.Read(b, 0, 1);
            tag.TimeStamp = BitConverter.ToInt32(b.ToBE(), 0);

            // StreamID UI24
            _buffer.Read(tag.StreamId, 0, 3);

            currentTag = tag;
            byte[] rest = _buffer.GetBuffer().Skip((int)_buffer.Position).Take((int)(dataLen - _buffer.Position)).ToArray();
            _buffer.Position = 0;

            _AddBytes(rest);
        }
        private void _TagCreated(FlvTag tag)
        {
            if (Metadata == null)
            {
                if (tag.TagType == TagType.DATA)
                {
                    _fs?.Write(FLV_HEADER_BYTES, 0, FLV_HEADER_BYTES.Length);
                    _fs?.Write(new byte[] { 0, 0, 0, 0, }, 0, 4);

                    Metadata = FlvMetadata.Parse(tag.Data);

                    // TODO: 添加录播姬标记、录制信息

                    tag.Data = Metadata.ToBytes();
                    tag.WriteTo(_fs);
                }
                else
                {
                    throw new Exception("onMetaData not found");
                }
            }
            else
            {
                if (!hasOffset)
                {
                    if (tag.TagType == TagType.VIDEO)
                    {
                        TagVideoCount++;
                        if (TagVideoCount < 2)
                        {
                            logger.Trace("第一个 Video Tag 时间戳 {0} ms", tag.TimeStamp);
                            HTags.Add(tag);
                        }
                        else
                        {
                            BaseTimeStamp = tag.TimeStamp;
                            hasOffset     = true;
                            logger.Trace("重设时间戳 {0} 毫秒", BaseTimeStamp);
                        }
                    }
                    else if (tag.TagType == TagType.AUDIO)
                    {
                        TagAudioCount++;
                        if (TagAudioCount < 2)
                        {
                            logger.Trace("第一个 Audio Tag 时间戳 {0} ms", tag.TimeStamp);
                            HTags.Add(tag);
                        }
                        else
                        {
                            BaseTimeStamp = tag.TimeStamp;
                            hasOffset     = true;
                            logger.Trace("重设时间戳 {0} 毫秒", BaseTimeStamp);
                        }
                    }
                }


                if (hasOffset)
                {
                    tag.TimeStamp -= BaseTimeStamp; // 修复时间戳
                    if (tag.TimeStamp < 0)
                    {
                        tag.TimeStamp = 0;
                    }
                    MaxTimeStamp = Math.Max(MaxTimeStamp, tag.TimeStamp);
                }
                else
                {
                    tag.TimeStamp = 0;
                }

                // 如果没有禁用 Clip 功能
                if (!_noClip)
                {
                    Tags.Add(tag); // Clip 缓存

                    // 移除过旧的数据
                    if (MaxTimeStamp - LasttimeRemovedTimestamp > 800)
                    {
                        LasttimeRemovedTimestamp = MaxTimeStamp;
                        int max_remove_index = Tags.FindLastIndex(x => x.IsVideoKeyframe && ((MaxTimeStamp - x.TimeStamp) > (Clip_Past * SEC_TO_MS)));
                        if (max_remove_index > 0)
                        {
                            Tags.RemoveRange(0, max_remove_index);
                        }
                        // Tags.RemoveRange(0, max_remove_index + 1 - 1);
                        // 给将来的备注:这里是故意 + 1 - 1 的,因为要保留选中的那个关键帧, + 1 就把关键帧删除了
                    }
                }

                // 写入硬盘
                tag.WriteTo(_fs);

                TagProcessed?.Invoke(this, new TagProcessedArgs()
                {
                    Tag = tag
                });
            } // if (Metadata == null) else
        }