Пример #1
0
 /// <summary>
 /// 编码首帧音频,即audioTag[0]
 /// <para>
 /// 注意:本方法已写入<see cref="previousTagSize"/>
 /// </para>
 /// </summary>
 /// <returns></returns>
 public byte[] EncoderFirstAudioTag(ulong timestamp)
 {
     byte[] buffer = FlvArrayPool.Rent(2048);
     try
     {
         FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
         //flv body audio tag
         //flv body tag header
         FlvTags flvTags = new FlvTags
         {
             Type      = TagType.Audio,
             Timestamp = (uint)timestamp,
             //flv body tag body
             AudioTagsData = new AudioTags(AACPacketType.AudioSpecificConfig)
         };
         flvMessagePackWriter.WriteUInt32(previousTagSize);
         flvMessagePackWriter.WriteFlvTag(flvTags);
         var data = flvMessagePackWriter.FlushAndGetArray();
         previousTagSize = (uint)(flvTags.DataSize + 11);
         return(data);
     }
     finally
     {
         FlvArrayPool.Return(buffer);
     }
 }
Пример #2
0
        private void CreateVideoTagOtherFrame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, H264NALU nALU)
        {
            //flv body PreviousTagSize
            flvMessagePackWriter.WriteUInt32(previousTagSize);
            //flv body video tag
            //flv body tag header
            FlvTags flvTags = new FlvTags();

            flvTags.Type         = TagType.Video;
            flvTags.Timestamp    = nALU.LastIFrameInterval;
            flvTags.TimestampExt = 0;
            flvTags.StreamId     = 0;
            //flv body tag body
            flvTags.VideoTagsData = new VideoTags();
            if (nALU.NALUHeader.NalUnitType == 5)
            {
                flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
            }
            else
            {
                flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
            }
            flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
            flvTags.VideoTagsData.VideoData.AvcPacketType   = AvcPacketType.Raw;
            flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval;
            flvTags.VideoTagsData.VideoData.Data            = nALU.RawData;
            flvMessagePackWriter.WriteFlvTag(flvTags);
        }
Пример #3
0
        public void Test1()
        {
            Span <byte>                   buffer = new byte[1024];
            FlvMessagePackWriter          flvMessagePackWriter          = new FlvMessagePackWriter(buffer);
            AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();

            aVCDecoderConfigurationRecord.AVCProfileIndication      = 0x64;
            aVCDecoderConfigurationRecord.ProfileCompatibility      = 0;
            aVCDecoderConfigurationRecord.AVCLevelIndication        = 0x1F;
            aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
            aVCDecoderConfigurationRecord.SPSBuffer = new byte[] {
                0x67, 0x64, 0x00, 0x1F,
                0xAC, 0xD9, 0x40, 0x88,
                0x1E, 0x68, 0x40, 0x00,
                0x00, 0x03, 0x01, 0x80,
                0x00, 0x00, 0x57, 0x83,
                0xC6, 0x0C, 0x65, 0x80
            };
            aVCDecoderConfigurationRecord.PPSBuffer = new byte[] {
                0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0
            };
            flvMessagePackWriter.WriteAVCDecoderConfigurationRecord(aVCDecoderConfigurationRecord);
            var hexData = flvMessagePackWriter.FlushAndGetArray().ToHexString();

            Assert.Equal("0164001FFFE100186764001FACD940881E6840000003018000005783C60C658001000668EBE3CB22C0", hexData);
            //0164001FFFE100186764001FACD940881E6840000003018000005783C60C658001000668EBE3CB22C0
            //0164001FFFE100186764001FACD940881E6840000003018000005783C60C658001000668EBE3CB22C0
        }
Пример #4
0
 /// <summary>
 /// 编码脚本Tag
 /// </summary>
 /// <param name="spsInfo">解析后的sps信息</param>
 /// <param name="hasAudio">是否有音频</param>
 /// <param name="frameRate">帧率 默认25d 即每秒25帧</param>
 /// <returns></returns>
 public byte[] EncoderScriptTag(SPSInfo spsInfo, bool hasAudio = false, double frameRate = 25d)
 {
     byte[] buffer = FlvArrayPool.Rent(1024);
     try
     {
         FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
         //flv body script tag
         //flv body tag header
         FlvTags flvTags = new FlvTags
         {
             Type = TagType.ScriptData,
             //flv body tag body
             DataTagsData = new Amf3
             {
                 Amf3Metadatas = new List <IAmf3Metadata>
                 {
                     new Amf3Metadata_Duration {
                         Value = 0d
                     },
                     new Amf3Metadata_VideoDataRate {
                         Value = 0d
                     },
                     new Amf3Metadata_VideoCodecId {
                         Value = 7d
                     },
                     new Amf3Metadata_FrameRate {
                         Value = frameRate
                     },
                     new Amf3Metadata_Width()
                     {
                         Value = spsInfo.width
                     },
                     new Amf3Metadata_Height()
                     {
                         Value = spsInfo.height
                     },
                 }
             }
         };
         if (hasAudio)
         {
             flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioCodecId());
             flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioSampleRate());
             flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioSampleSize());
             flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_AudioStereo());
         }
         flvMessagePackWriter.WriteFlvTag(flvTags);
         flvMessagePackWriter.WriteUInt32((uint)(flvTags.DataSize + 11));
         return(flvMessagePackWriter.FlushAndGetArray());
     }
     finally
     {
         FlvArrayPool.Return(buffer);
     }
 }
Пример #5
0
 public byte[] CreateFlvFrame(List <H264NALU> nALUs, int minimumLength = 10240)
 {
     byte[] buffer = FlvArrayPool.Rent(minimumLength);
     try
     {
         FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
         int      currentMarkPosition = 0;
         int      nextMarkPosition = 0;
         H264NALU?sps = null, pps = null;
         foreach (var naln in nALUs)
         {
             string key = naln.GetKey();
             if (!FrameInitDict.ContainsKey(key))
             {
                 if (naln.NALUHeader.NalUnitType == 7)
                 {
                     naln.RawData = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData);
                     sps          = naln;
                 }
                 else if (naln.NALUHeader.NalUnitType == 8)
                 {
                     pps = naln;
                 }
                 if (sps != null && pps != null)
                 {
                     flvMessagePackWriter.WriteArray(CreateFlvFirstFrame(sps, pps));
                     FrameInitDict.TryAdd(key, true);
                 }
                 else
                 {
                     continue;
                 }
             }
             if (PreviousTagSizeDict.TryGetValue(key, out uint previousTagSize))
             {
                 currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                 CreateVideoTagOtherFrame(ref flvMessagePackWriter, previousTagSize, naln);
                 nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                 uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
                 PreviousTagSizeDict.TryUpdate(key, tmpPreviousTagSize, previousTagSize);
             }
         }
         return(flvMessagePackWriter.FlushAndGetArray());
     }
     finally
     {
         FlvArrayPool.Return(buffer);
     }
 }
Пример #6
0
 /// <summary>
 /// 编码首帧视频,即videoTag[0]
 /// <para>
 /// 注意:本方法已写入<see cref="previousTagSize"/>
 /// </para>
 /// </summary>
 /// <param name="sps"></param>
 /// <param name="pps"></param>
 /// <param name="sei"></param>
 /// <returns></returns>
 public byte[] EncoderFirstVideoTag(H264NALU sps, H264NALU pps, H264NALU sei)
 {
     byte[] buffer = FlvArrayPool.Rent(2048);
     try
     {
         FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
         var             rawData          = h264Decoder.DiscardEmulationPreventionBytes(sps.RawData);
         ExpGolombReader h264GolombReader = new ExpGolombReader(rawData);
         SPSInfo         spsInfo          = h264GolombReader.ReadSPS();
         //flv body video tag
         //flv body tag header
         FlvTags flvTags = new FlvTags
         {
             Type         = TagType.Video,
             Timestamp    = (uint)sps.Timestamp,
             TimestampExt = 0,
             StreamId     = 0,
             //flv body tag body
             VideoTagsData = new VideoTags()
         };
         flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
         flvTags.VideoTagsData.VideoData = new AvcVideoPacke
         {
             AvcPacketType   = AvcPacketType.SequenceHeader,
             CompositionTime = 0
         };
         AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord
         {
             AVCProfileIndication      = spsInfo.profileIdc,
             ProfileCompatibility      = (byte)spsInfo.profileCompat,
             AVCLevelIndication        = spsInfo.levelIdc,
             NumOfPictureParameterSets = 1,
             PPSBuffer = pps.RawData,
             SPSBuffer = sps.RawData
         };
         flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
         flvMessagePackWriter.WriteUInt32(previousTagSize);
         flvMessagePackWriter.WriteFlvTag(flvTags);
         var data = flvMessagePackWriter.FlushAndGetArray();
         previousTagSize = (uint)(flvTags.DataSize + 11);
         return(data);
     }
     finally
     {
         FlvArrayPool.Return(buffer);
     }
 }
Пример #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="sps">NalUnitType->7</param>
        /// <param name="pps">NalUnitType->8</param>
        /// <returns></returns>
        public byte[] CreateFlvFirstFrame(H264NALU sps, H264NALU pps)
        {
            byte[] buffer = FlvArrayPool.Rent(65535);
            int    currentMarkPosition = 0;
            int    nextMarkPosition    = 0;

            try
            {
                FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
                //flv header
                flvMessagePackWriter.WriteArray(VideoFlvHeaderBuffer);

                //SPS -> 7
                ExpGolombReader h264GolombReader = new ExpGolombReader(sps.RawData);
                var             spsInfo          = h264GolombReader.ReadSPS();

                currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                //flv body script tag
                CreateScriptTagFrame(ref flvMessagePackWriter, spsInfo.width, spsInfo.height);
                nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

                //flv body video tag
                uint scriptTagFramePreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
                AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();
                aVCDecoderConfigurationRecord.AVCProfileIndication      = spsInfo.profileIdc;
                aVCDecoderConfigurationRecord.ProfileCompatibility      = (byte)spsInfo.profileCompat;
                aVCDecoderConfigurationRecord.AVCLevelIndication        = spsInfo.levelIdc;
                aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
                aVCDecoderConfigurationRecord.PPSBuffer = pps.RawData;
                aVCDecoderConfigurationRecord.SPSBuffer = sps.RawData;

                currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                CreateVideoTag0Frame(ref flvMessagePackWriter, scriptTagFramePreviousTagSize, aVCDecoderConfigurationRecord);
                nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

                //flv body video tag 0
                uint videoTag0PreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
                //cache PreviousTagSize
                PreviousTagSizeDict.AddOrUpdate(sps.GetKey(), videoTag0PreviousTagSize, (a, b) => videoTag0PreviousTagSize);

                return(flvMessagePackWriter.FlushAndGetArray());
            }
            finally
            {
                FlvArrayPool.Return(buffer);
            }
        }
        public void FlvMessagePackWriter_FlvBody_Test_1()
        {
            Span <byte>          buffer = new byte[1024];
            FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
            FlvBody flvBody = new FlvBody()
            {
                PreviousTagSize = 0,
                Tag             = new FlvTags
                {
                    Type         = Enums.TagType.ScriptData,
                    DataSize     = 156,
                    DataTagsData = new Amf3
                    {
                        Amf3Metadatas = new List <Flv.Metadata.IAmf3Metadata> {
                            new Amf3Metadata_Duration {
                                Value = 7.22100
                            },
                            new Amf3Metadata_FileSize {
                                Value = 2005421.00000
                            },
                            new Amf3Metadata_FrameRate {
                                Value = 29.16667
                            },
                            new Amf3Metadata_Height {
                                Value = 960.00000
                            },
                            new Amf3Metadata_VideoCodecId {
                                Value = 7.00000
                            },
                            new Amf3Metadata_VideoDataRate {
                                Value = 0.00000
                            },
                            new Amf3Metadata_Width {
                                Value = 544.00000
                            }
                        }
                    }
                }
            };

            flvMessagePackWriter.WriteFlvBody(flvBody);
            var hex = flvMessagePackWriter.FlushAndGetArray().ToHexString();

            Assert.Equal("00000000120000A00000000000000002000A6F6E4D65746144617461080000000700086475726174696F6E00401CE24DD2F1A9FC000866696C6573697A6500413E99AD0000000000096672616D657261746500403D2AAAE297396D000668656967687400408E000000000000000C766964656F636F646563696400401C000000000000000D766964656F646174617261746500000000000000000000057769647468004081000000000000", hex);
        }
Пример #9
0
        private void CreateScriptTagFrame(ref FlvMessagePackWriter flvMessagePackWriter, int width, int height)
        {
            //flv body PreviousTagSize awalys 0
            flvMessagePackWriter.WriteUInt32(0);
            //flv body script tag
            //flv body tag header
            FlvTags flvTags = new FlvTags();

            flvTags.Type         = TagType.ScriptData;
            flvTags.Timestamp    = 0;
            flvTags.TimestampExt = 0;
            flvTags.StreamId     = 0;
            //flv body tag body
            flvTags.DataTagsData = new Amf3();
            flvTags.DataTagsData.Amf3Metadatas = new List <IAmf3Metadata>();
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Duration
            {
                Value = 0d
            });
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoDataRate
            {
                Value = 0d
            });
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoCodecId
            {
                Value = 7d
            });
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_FrameRate
            {
                Value = 25d
            });
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Width
            {
                Value = width
            });
            flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Height
            {
                Value = height
            });
            flvMessagePackWriter.WriteFlvTag(flvTags);
        }
Пример #10
0
        private void CreateVideoTag0Frame(ref FlvMessagePackWriter flvMessagePackWriter, uint previousTagSize, AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord)
        {
            //flv body PreviousTagSize ScriptTag
            flvMessagePackWriter.WriteUInt32(previousTagSize);
            //flv body video tag
            //flv body tag header
            FlvTags flvTags = new FlvTags();

            flvTags.Type         = TagType.Video;
            flvTags.Timestamp    = 0;
            flvTags.TimestampExt = 0;
            flvTags.StreamId     = 0;
            //flv body tag body
            flvTags.VideoTagsData           = new VideoTags();
            flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
            flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
            flvTags.VideoTagsData.VideoData.AvcPacketType           = AvcPacketType.SequenceHeader;
            flvTags.VideoTagsData.VideoData.CompositionTime         = 0;
            flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
            flvMessagePackWriter.WriteFlvTag(flvTags);
        }
Пример #11
0
        /// <summary>
        ///
        /// </summary>
        private void CreateFlvKeyFrame(ref FlvMessagePackWriter flvMessagePackWriter, string key, byte[] spsRawData, byte[] ppsRawData, SPSInfo spsInfo, uint previousTagSize = 0)
        {
            int currentMarkPosition = 0;
            int nextMarkPosition    = 0;

            currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
            //flv body script tag
            CreateScriptTagFrame(ref flvMessagePackWriter, spsInfo.width, spsInfo.height, previousTagSize);
            nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

            //flv body video tag
            uint scriptTagFramePreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
            AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();

            aVCDecoderConfigurationRecord.AVCProfileIndication      = spsInfo.profileIdc;
            aVCDecoderConfigurationRecord.ProfileCompatibility      = (byte)spsInfo.profileCompat;
            aVCDecoderConfigurationRecord.AVCLevelIndication        = spsInfo.levelIdc;
            aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
            aVCDecoderConfigurationRecord.PPSBuffer = ppsRawData;
            aVCDecoderConfigurationRecord.SPSBuffer = spsRawData;

            currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
            CreateVideoTag0Frame(ref flvMessagePackWriter, scriptTagFramePreviousTagSize, aVCDecoderConfigurationRecord);
            nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();

            //flv body video tag 0
            uint videoTag0PreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);

            //cache PreviousTagSize
            FlvFrameInfoDict.AddOrUpdate(key, new FlvFrameInfo {
                PreviousTagSize = videoTag0PreviousTagSize
            }, (a, b) => {
                b.PreviousTagSize = videoTag0PreviousTagSize;
                return(b);
            });
        }
        public void FlvMessagePackWriter_Amf3_Test_1()
        {
            Span <byte>          buffer = new byte[1024];
            FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);

            flvMessagePackWriter.WriteAmf3(new Flv.Metadata.Amf3 {
                Amf3Metadatas = new List <Flv.Metadata.IAmf3Metadata> {
                    new Amf3Metadata_Duration {
                        Value = 7.22100
                    },
                    new Amf3Metadata_FileSize {
                        Value = 2005421.00000
                    },
                    new Amf3Metadata_FrameRate {
                        Value = 29.16667
                    },
                    new Amf3Metadata_Height {
                        Value = 960.00000
                    },
                    new Amf3Metadata_VideoCodecId {
                        Value = 7.00000
                    },
                    new Amf3Metadata_VideoDataRate {
                        Value = 0.00000
                    },
                    new Amf3Metadata_Width {
                        Value = 544.00000
                    }
                }
            });

            buffer = buffer.Slice(5);//amf3 5个字节
            Amf3Metadata_Duration amf3Metadata = new Amf3Metadata_Duration();

            amf3Metadata.Value = 7.22100;
            var hex = amf3Metadata.ToBuffer().ToArray().ToHexString();

            Assert.Equal("00086475726174696F6E00401CE24DD2F1A9FC", buffer.Slice(0, hex.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex.Length / 2);
            Amf3Metadata_FileSize amf3Metadata_FileSize = new Amf3Metadata_FileSize();

            amf3Metadata_FileSize.Value = 2005421.00000;
            var hex1 = amf3Metadata_FileSize.ToBuffer().ToArray().ToHexString();

            Assert.Equal("000866696C6573697A6500413E99AD00000000", buffer.Slice(0, hex1.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex1.Length / 2);
            Amf3Metadata_FrameRate amf3Metadata_FrameRate = new Amf3Metadata_FrameRate();

            amf3Metadata_FrameRate.Value = 29.16667;
            var hex2 = amf3Metadata_FrameRate.ToBuffer().ToArray().ToHexString();

            Assert.Equal("00096672616D657261746500403D2AAAE297396D", buffer.Slice(0, hex2.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex2.Length / 2);
            Amf3Metadata_Height amf3Metadata_Height = new Amf3Metadata_Height();

            amf3Metadata_Height.Value = 960.00000;
            var hex3 = amf3Metadata_Height.ToBuffer().ToArray().ToHexString();

            Assert.Equal("000668656967687400408E000000000000", buffer.Slice(0, hex3.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex3.Length / 2);
            Amf3Metadata_VideoCodecId amf3Metadata_VideoCodecId = new Amf3Metadata_VideoCodecId();

            amf3Metadata_VideoCodecId.Value = 7.00000;
            var hex4 = amf3Metadata_VideoCodecId.ToBuffer().ToArray().ToHexString();

            Assert.Equal("000C766964656F636F646563696400401C000000000000", buffer.Slice(0, hex4.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex4.Length / 2);
            Amf3Metadata_VideoDataRate amf3Metadata_VideoDataRate = new Amf3Metadata_VideoDataRate();

            amf3Metadata_VideoDataRate.Value = 0.00000;
            var hex5 = amf3Metadata_VideoDataRate.ToBuffer().ToArray().ToHexString();

            Assert.Equal("000D766964656F6461746172617465000000000000000000", buffer.Slice(0, hex5.Length / 2).ToArray().ToHexString());

            buffer = buffer.Slice(hex5.Length / 2);
            Amf3Metadata_Width amf3Metadata_Width = new Amf3Metadata_Width();

            amf3Metadata_Width.Value = 544.00000;
            var hex6 = amf3Metadata_Width.ToBuffer().ToArray().ToHexString();

            Assert.Equal("00057769647468004081000000000000", buffer.Slice(0, hex6.Length / 2).ToArray().ToHexString());
        }
Пример #13
0
        public byte[] CreateFlvFrame(List <H264NALU> nALUs, int minimumLength = 65535)
        {
            byte[] buffer = FlvArrayPool.Rent(minimumLength);
            try
            {
                FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
                int      currentMarkPosition = 0;
                int      nextMarkPosition = 0;
                H264NALU sps = null, pps = null;
                SPSInfo  spsInfo = new SPSInfo();
                foreach (var naln in nALUs)
                {
                    string key = naln.GetKey();
                    if (sps != null && pps != null)
                    {
                        if (VideoSPSDict.TryGetValue(key, out var spsInfoCache))
                        {
                            if (spsInfoCache.height != spsInfo.height && spsInfoCache.width != spsInfo.width)
                            {
                                if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
                                {
                                    CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, flvFrameInfo.PreviousTagSize);
                                    FlvFirstFrameCache.TryRemove(key, out _);
                                    FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray());
                                    VideoSPSDict.TryUpdate(key, spsInfo, spsInfo);
                                    flvFrameInfo.LastFrameInterval = 0;
                                    FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
                                }
                            }
                            sps = null;
                            pps = null;
                        }
                        else
                        {
                            CreateFlvKeyFrame(ref flvMessagePackWriter, key, sps.RawData, pps.RawData, spsInfo, 0);
                            FlvFirstFrameCache.TryAdd(key, flvMessagePackWriter.FlushAndGetArray());
                            VideoSPSDict.TryAdd(key, spsInfo);
                            sps = null;
                            pps = null;
                        }
                    }
                    //7 8 6 5 1 1 1 1 7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 1
                    switch (naln.NALUHeader.NalUnitType)
                    {
                    case 5:    // IDR
                    case 1:    // I/P/B
                        if (FlvFrameInfoDict.TryGetValue(key, out FlvFrameInfo flvFrameInfo))
                        {
                            currentMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                            CreateVideoTagOtherFrame(ref flvMessagePackWriter, flvFrameInfo, naln);
                            nextMarkPosition = flvMessagePackWriter.GetCurrentPosition();
                            uint tmpPreviousTagSize = (uint)(nextMarkPosition - currentMarkPosition - PreviousTagSizeFixedLength);
                            flvFrameInfo.PreviousTagSize    = tmpPreviousTagSize;
                            flvFrameInfo.LastFrameInterval += naln.LastFrameInterval;
                            FlvFrameInfoDict.TryUpdate(key, flvFrameInfo, flvFrameInfo);
                        }
                        break;

                    case 7:    // sps
                        sps = naln;
                        var             rawData          = H264Decoder.DiscardEmulationPreventionBytes(naln.RawData);
                        ExpGolombReader h264GolombReader = new ExpGolombReader(rawData);
                        spsInfo = h264GolombReader.ReadSPS();
                        break;

                    case 8:    // pps
                        pps = naln;
                        break;

                    case 6:    //SEI
                        break;

                    default:
                        break;
                    }
                }
                return(flvMessagePackWriter.FlushAndGetArray());
            }
            finally
            {
                FlvArrayPool.Return(buffer);
            }
        }