Exemple #1
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);
     }
 }
Exemple #2
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);
     }
 }
Exemple #3
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);
            });
        }
Exemple #4
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);
            }
        }