Beispiel #1
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 #2
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 #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);
            });
        }
Beispiel #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);
            }
        }