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); } }
/// <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); } }