Beispiel #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);
     }
 }
Beispiel #2
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);
     }
 }
Beispiel #3
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);
     }
 }
Beispiel #4
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);
     }
 }
Beispiel #5
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);
            }
        }
Beispiel #6
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);
            }
        }