예제 #1
0
 public void EXPGolombReaderTest()
 {
     for (var i = 0; i < N; i++)
     {
         ExpGolombReader h264GolombReader = new ExpGolombReader(SPSNALu.RawData);
         h264GolombReader.ReadSPS();
     }
 }
예제 #2
0
        public void ParseNALUTest2()
        {
            JT1078Package Package         = null;
            var           lines           = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "jt1078_1.txt"));
            int           mergeBodyLength = 0;

            foreach (var line in lines)
            {
                var           data    = line.Split(',');
                var           bytes   = data[6].ToHexBytes();
                JT1078Package package = JT1078Serializer.Deserialize(bytes);
                mergeBodyLength += package.DataBodyLength;
                Package          = JT1078Serializer.Merge(package);
            }
            H264Decoder decoder = new H264Decoder();
            var         nalus   = decoder.ParseNALU(Package);

            Assert.Equal(4, nalus.Count);

            //SPS -> 7
            var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);

            Assert.NotNull(spsNALU);
            spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
            //"Z00AFJWoWCWQ"
            var             spsRawDataHex    = JsonConvert.SerializeObject(spsNALU.RawData);
            ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
            //(77, 20, 0, 352, 288)
            var spsInfo = h264GolombReader.ReadSPS();

            Assert.Equal(77, spsInfo.profileIdc);
            Assert.Equal(20, spsInfo.levelIdc);
            Assert.Equal(0u, spsInfo.profileCompat);
            Assert.Equal(288, spsInfo.height);
            Assert.Equal(352, spsInfo.width);

            //PPS -> 8
            var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);

            Assert.NotNull(ppsNALU);

            //IDR -> 5  关键帧
            var idrNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 5);

            Assert.NotNull(idrNALU);

            //SEI -> 6
            var seiNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 6);

            Assert.NotNull(seiNALU);
        }
예제 #3
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);
     }
 }
예제 #4
0
파일: FlvEncoder.cs 프로젝트: hlj671/JT1078
        /// <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);
            }
        }
예제 #5
0
        public void Test1()
        {
            ExpGolombReader h264GolombReader = new ExpGolombReader(new byte[] { 103, 77, 0, 20, 149, 168, 88, 37, 144, 0 });
            var             result           = h264GolombReader.ReadSPS();

            Assert.Equal(77, result.profileIdc);
            Assert.Equal(0u, result.profileCompat);
            Assert.Equal(20, result.levelIdc);
            Assert.Equal(352, result.width);
            Assert.Equal(288, result.height);
            //profileIdc 77
            //profileCompat 0
            //levelIdc 20
            //picOrderCntType 2
            //picWidthInMbsMinus1 21
            //picHeightInMapUnitsMinus1 17
            //frameMbsOnlyFlag 1
            //width 352
            //height 288
        }
예제 #6
0
        /// <summary>
        /// Identify NAL unit types and pass on the NALU, trackId, presentation and decode timestamps
        /// for the NALUs to the next stream component.
        /// Also, preprocess caption and sequence parameter NALUs.
        /// 常用Nalu_type:
        /// 0x67 (0 11 00111) SPS   非常重要              type = 7
        /// 0x68 (0 11 01000) PPS   非常重要              type = 8
        /// 0x65 (0 11 00101) IDR帧 关键帧(非常重要)      type = 5
        /// 0x61 (0 11 00001) I帧   重要                  type = 1  非IDR的I帧不大常见
        /// 0x41 (0 10 00001) P帧   重要                  type = 1
        /// 0x01 (0 00 00001) B帧   不重要                type = 1
        /// 0x06 (0 00 00110) SEI   不重要                type = 6
        /// <see cref="https://blog.csdn.net/huibailingyu/article/details/42879573"/>
        /// </summary>
        /// <param name="h264NALU"></param>
        /// <returns></returns>
        private void NALUTypeFilter(H264NALU h264NALU)
        {
            switch (h264NALU.NALUHeader.NalUnitType)
            {
            //IPB帧
            case 1:

                break;

            //IDR
            case 5:

                break;

            //SEI
            case 6:
                h264NALU.RawData = DiscardEmulationPreventionBytes(h264NALU.RawData);

                break;

            //SPS
            case 7:
                h264NALU.RawData = DiscardEmulationPreventionBytes(h264NALU.RawData);
                ExpGolombReader h264GolombReader = new ExpGolombReader(h264NALU.RawData);
                var             spsInfo          = h264GolombReader.ReadSPS();

                break;

            //PPS
            case 8:

                break;

            //AUD
            case 9:

                break;
            }
        }
예제 #7
0
        public void 测试主次码流切换()
        {
            FileStream      fileStream = null;
            H264Decoder     decoder    = new H264Decoder();
            List <H264NALU> h264NALULs = new List <H264NALU>();
            FlvEncoder      encoder    = new FlvEncoder();

            try
            {
                var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_5.flv");
                var lines    = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_5.txt"));
                if (File.Exists(filepath))
                {
                    File.Delete(filepath);
                }

                JT1078Package Package = null;

                foreach (var line in lines)
                {
                    var           data    = line.Split(',');
                    var           bytes   = data[6].ToHexBytes();
                    JT1078Package package = JT1078Serializer.Deserialize(bytes);
                    Package = JT1078Serializer.Merge(package);
                    if (Package != null)
                    {
                        var tmp = decoder.ParseNALU(Package);
                        if (tmp != null && tmp.Count > 0)
                        {
                            h264NALULs = h264NALULs.Concat(tmp).ToList();
                        }
                    }
                }
                var            tmp1                = h264NALULs.Where(w => w.NALUHeader.NalUnitType == 7).ToList();
                List <SPSInfo> tmpSpss             = new List <SPSInfo>();
                List <ulong>   times               = new List <ulong>();
                List <ushort>  lastIFrameIntervals = new List <ushort>();
                List <ushort>  lastFrameIntervals  = new List <ushort>();
                List <int>     type                = new List <int>();
                foreach (var item in h264NALULs)
                {
                    //type.Add(item.NALUHeader.NalUnitType);
                    times.Add(item.Timestamp);
                    lastFrameIntervals.Add(item.LastFrameInterval);
                    lastIFrameIntervals.Add(item.LastIFrameInterval);
                    if (item.NALUHeader.NalUnitType == 7)
                    {
                        ExpGolombReader expGolombReader = new ExpGolombReader(item.RawData);
                        tmpSpss.Add(expGolombReader.ReadSPS());
                    }
                }
                fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
                var totalPage = (h264NALULs.Count + 10 - 1) / 10;
                for (var i = 0; i < totalPage; i++)
                {
                    var flv2 = encoder.CreateFlvFrame(h264NALULs.Skip(i * 10).Take(10).ToList());
                    if (flv2.Length != 0)
                    {
                        //fileStream.Write(flv2);
                    }
                }
            }
            catch (Exception ex)
            {
                Assert.Throws <Exception>(() => { });
            }
            finally
            {
                fileStream?.Close();
                fileStream?.Dispose();
            }
        }
예제 #8
0
        public void Test3()
        {
            H264Decoder decoder  = new H264Decoder();
            var         packages = ParseNALUTests();
            //10M
            FMp4MessagePackWriter writer = new FMp4MessagePackWriter(new byte[10 * 1024 * 1024]);
            var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.mp4");

            if (File.Exists(filepath))
            {
                File.Delete(filepath);
            }
            using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write);
            var jT1078Package = packages.FirstOrDefault();
            var nalus         = decoder.ParseNALU(jT1078Package);
            var spsNALU       = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);

            //SPS
            spsNALU.RawData = decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
            var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);

            ppsNALU.RawData = decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
            ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
            var             spsInfo          = h264GolombReader.ReadSPS();
            //ftyp
            FileTypeBox fileTypeBox = new FileTypeBox();

            fileTypeBox.MajorBrand   = "isom";
            fileTypeBox.MinorVersion = "\0\0\u0002\0";
            fileTypeBox.CompatibleBrands.Add("isom");
            fileTypeBox.CompatibleBrands.Add("iso6");
            fileTypeBox.CompatibleBrands.Add("iso2");
            fileTypeBox.CompatibleBrands.Add("avc1");
            fileTypeBox.CompatibleBrands.Add("mp41");
            //moov
            MovieBox movieBox = new MovieBox();

            movieBox.MovieHeaderBox = new MovieHeaderBox(0, 0);
            movieBox.MovieHeaderBox.CreationTime     = 0;
            movieBox.MovieHeaderBox.ModificationTime = 0;
            movieBox.MovieHeaderBox.Duration         = 0;
            movieBox.MovieHeaderBox.Timescale        = 1000;
            movieBox.MovieHeaderBox.NextTrackID      = 2;
            movieBox.TrackBox = new TrackBox();
            movieBox.TrackBox.TrackHeaderBox = new TrackHeaderBox(0, 3);
            movieBox.TrackBox.TrackHeaderBox.CreationTime     = 0;
            movieBox.TrackBox.TrackHeaderBox.ModificationTime = 0;
            movieBox.TrackBox.TrackHeaderBox.TrackID          = 1;
            movieBox.TrackBox.TrackHeaderBox.Duration         = 0;
            movieBox.TrackBox.TrackHeaderBox.TrackIsAudio     = false;
            movieBox.TrackBox.TrackHeaderBox.Width            = (uint)spsInfo.width;
            movieBox.TrackBox.TrackHeaderBox.Height           = (uint)spsInfo.height;
            movieBox.TrackBox.MediaBox = new MediaBox();
            movieBox.TrackBox.MediaBox.MediaHeaderBox = new MediaHeaderBox();
            movieBox.TrackBox.MediaBox.MediaHeaderBox.CreationTime     = 0;
            movieBox.TrackBox.MediaBox.MediaHeaderBox.ModificationTime = 0;
            movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale        = 1200000;
            movieBox.TrackBox.MediaBox.MediaHeaderBox.Duration         = 0;
            movieBox.TrackBox.MediaBox.HandlerBox             = new HandlerBox();
            movieBox.TrackBox.MediaBox.HandlerBox.HandlerType = HandlerType.vide;
            movieBox.TrackBox.MediaBox.HandlerBox.Name        = "VideoHandler";
            movieBox.TrackBox.MediaBox.MediaInformationBox    = new MediaInformationBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.VideoMediaHeaderBox = new VideoMediaHeaderBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox  = new DataInformationBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox = new DataReferenceBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List <DataEntryBox>();
            movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1));
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType);
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List <SampleEntry>();
            AVC1SampleEntry avc1 = new AVC1SampleEntry();

            avc1.AVCConfigurationBox = new AVCConfigurationBox();
            //h264
            avc1.Width  = (ushort)movieBox.TrackBox.TrackHeaderBox.Width;
            avc1.Height = (ushort)movieBox.TrackBox.TrackHeaderBox.Height;
            avc1.AVCConfigurationBox.AVCLevelIndication   = spsInfo.levelIdc;
            avc1.AVCConfigurationBox.AVCProfileIndication = spsInfo.profileIdc;
            avc1.AVCConfigurationBox.ProfileCompatibility = (byte)spsInfo.profileCompat;
            avc1.AVCConfigurationBox.PPSs = new List <byte[]>()
            {
                ppsNALU.RawData
            };
            avc1.AVCConfigurationBox.SPSs = new List <byte[]>()
            {
                spsNALU.RawData
            };
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1);
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox  = new TimeToSampleBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox    = new SampleSizeBox();
            movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox   = new ChunkOffsetBox();
            movieBox.MovieExtendsBox = new MovieExtendsBox();
            movieBox.MovieExtendsBox.TrackExtendsBoxs = new List <TrackExtendsBox>();
            TrackExtendsBox trex = new TrackExtendsBox();

            trex.TrackID = 1;
            trex.DefaultSampleDescriptionIndex = 1;
            trex.DefaultSampleDuration         = 0;
            trex.DefaultSampleSize             = 0;
            trex.DefaultSampleFlags            = 0;
            movieBox.MovieExtendsBox.TrackExtendsBoxs.Add(trex);
            fileTypeBox.ToBuffer(ref writer);
            movieBox.ToBuffer(ref writer);
            //fragment moof n
            foreach (var package in packages)
            {
                ulong       moofOffset    = (ulong)writer.GetCurrentPosition();
                var         package_nalus = decoder.ParseNALU(package);
                FragmentBox fragmentBox   = new FragmentBox();
                fragmentBox.MovieFragmentBox = new MovieFragmentBox();
                fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox();
                fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox.SequenceNumber = package.SN;
                fragmentBox.MovieFragmentBox.TrackFragmentBox = new TrackFragmentBox();
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox                                  = new TrackFragmentHeaderBox(0x39);
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID                          = 1;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.BaseDataOffset                   = moofOffset;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration            = 48000;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize                = (uint)package.Bodies.Length;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags               = 0x1010000;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox                     = new TrackFragmentBaseMediaDecodeTimeBox();
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = package.Timestamp * 1000;
                //trun
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x5);
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox.FirstSampleFlags = 0;
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos    = new List <TrackRunBox.TrackRunInfo>();
                fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox.TrackRunInfos.Add(new TrackRunBox.TrackRunInfo());
                fragmentBox.MediaDataBox      = new MediaDataBox();
                fragmentBox.MediaDataBox.Data = package_nalus.Select(s => s.RawData).ToList();
                fragmentBox.ToBuffer(ref writer);
            }
            var buffer = writer.FlushAndGetArray();

            fileStream.Write(buffer);
            fileStream.Close();
        }
예제 #9
0
        /// <summary>
        /// 编码首个视频盒子
        /// </summary>
        /// <param name="package">jt1078完整包</param>
        /// <returns></returns>
        public byte[] EncoderFirstVideoBox(JT1078Package package)
        {
            byte[] buffer = FMp4ArrayPool.Rent(package.Bodies.Length + 4096);
            FMp4MessagePackWriter writer = new FMp4MessagePackWriter(new byte[10 * 1024 * 1024]);

            try
            {
                var nalus   = h264Decoder.ParseNALU(package);
                var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
                //SPS
                spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
                var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
                ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
                ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
                var             spsInfo          = h264GolombReader.ReadSPS();
                //ftyp
                FileTypeBox fileTypeBox = new FileTypeBox();
                fileTypeBox.MajorBrand   = "isom";
                fileTypeBox.MinorVersion = "\0\0\u0002\0";
                fileTypeBox.CompatibleBrands.Add("isom");
                fileTypeBox.CompatibleBrands.Add("iso6");
                fileTypeBox.CompatibleBrands.Add("iso2");
                fileTypeBox.CompatibleBrands.Add("avc1");
                fileTypeBox.CompatibleBrands.Add("mp41");
                //moov
                MovieBox movieBox = new MovieBox();
                movieBox.MovieHeaderBox = new MovieHeaderBox(0, 0);
                movieBox.MovieHeaderBox.CreationTime     = 0;
                movieBox.MovieHeaderBox.ModificationTime = 0;
                movieBox.MovieHeaderBox.Duration         = 0;
                movieBox.MovieHeaderBox.Timescale        = 1000;
                movieBox.MovieHeaderBox.NextTrackID      = 2;
                movieBox.TrackBox = new TrackBox();
                movieBox.TrackBox.TrackHeaderBox = new TrackHeaderBox(0, 3);
                movieBox.TrackBox.TrackHeaderBox.CreationTime     = 0;
                movieBox.TrackBox.TrackHeaderBox.ModificationTime = 0;
                movieBox.TrackBox.TrackHeaderBox.TrackID          = 1;
                movieBox.TrackBox.TrackHeaderBox.Duration         = 0;
                movieBox.TrackBox.TrackHeaderBox.TrackIsAudio     = false;
                movieBox.TrackBox.TrackHeaderBox.Width            = (uint)spsInfo.width;
                movieBox.TrackBox.TrackHeaderBox.Height           = (uint)spsInfo.height;
                movieBox.TrackBox.MediaBox = new MediaBox();
                movieBox.TrackBox.MediaBox.MediaHeaderBox = new MediaHeaderBox();
                movieBox.TrackBox.MediaBox.MediaHeaderBox.CreationTime     = 0;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.ModificationTime = 0;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale        = 1200000;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.Duration         = 0;
                movieBox.TrackBox.MediaBox.HandlerBox             = new HandlerBox();
                movieBox.TrackBox.MediaBox.HandlerBox.HandlerType = HandlerType.vide;
                movieBox.TrackBox.MediaBox.HandlerBox.Name        = "VideoHandler";
                movieBox.TrackBox.MediaBox.MediaInformationBox    = new MediaInformationBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.VideoMediaHeaderBox = new VideoMediaHeaderBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox  = new DataInformationBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox = new DataReferenceBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List <DataEntryBox>();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1));
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType);
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List <SampleEntry>();
                AVC1SampleEntry avc1 = new AVC1SampleEntry();
                avc1.AVCConfigurationBox = new AVCConfigurationBox();
                //h264
                avc1.Width  = (ushort)movieBox.TrackBox.TrackHeaderBox.Width;
                avc1.Height = (ushort)movieBox.TrackBox.TrackHeaderBox.Height;
                avc1.AVCConfigurationBox.AVCLevelIndication   = spsInfo.levelIdc;
                avc1.AVCConfigurationBox.AVCProfileIndication = spsInfo.profileIdc;
                avc1.AVCConfigurationBox.ProfileCompatibility = (byte)spsInfo.profileCompat;
                avc1.AVCConfigurationBox.PPSs = new List <byte[]>()
                {
                    ppsNALU.RawData
                };
                avc1.AVCConfigurationBox.SPSs = new List <byte[]>()
                {
                    spsNALU.RawData
                };
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1);
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox  = new TimeToSampleBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox    = new SampleSizeBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox   = new ChunkOffsetBox();
                movieBox.MovieExtendsBox = new MovieExtendsBox();
                movieBox.MovieExtendsBox.TrackExtendsBoxs = new List <TrackExtendsBox>();
                TrackExtendsBox trex = new TrackExtendsBox();
                trex.TrackID = 1;
                trex.DefaultSampleDescriptionIndex = 1;
                trex.DefaultSampleDuration         = 0;
                trex.DefaultSampleSize             = 0;
                trex.DefaultSampleFlags            = 0;
                movieBox.MovieExtendsBox.TrackExtendsBoxs.Add(trex);
                fileTypeBox.ToBuffer(ref writer);
                movieBox.ToBuffer(ref writer);
                var data = writer.FlushAndGetArray();
                return(data);
            }
            finally
            {
                FMp4ArrayPool.Return(buffer);
            }
        }
예제 #10
0
        /// <summary>
        /// 编码moov盒子
        /// </summary>
        /// <returns></returns>
        public byte[] EncoderMoovBox(List <H264NALU> nalus, int naluLength)
        {
            byte[] buffer = FMp4ArrayPool.Rent(naluLength + 4096);
            FMp4MessagePackWriter writer = new FMp4MessagePackWriter(buffer);

            try
            {
                var spsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
                //SPS
                spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
                var ppsNALU = nalus.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
                ppsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(ppsNALU.RawData);
                ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
                var             spsInfo          = h264GolombReader.ReadSPS();
                //moov
                MovieBox movieBox = new MovieBox();
                movieBox.MovieHeaderBox = new MovieHeaderBox(0, 2);
                movieBox.MovieHeaderBox.CreationTime     = 0;
                movieBox.MovieHeaderBox.ModificationTime = 0;
                movieBox.MovieHeaderBox.Duration         = 0;
                movieBox.MovieHeaderBox.Timescale        = 1000;
                movieBox.MovieHeaderBox.NextTrackID      = 99;
                movieBox.TrackBox = new TrackBox();
                movieBox.TrackBox.TrackHeaderBox = new TrackHeaderBox(0, 3);
                movieBox.TrackBox.TrackHeaderBox.CreationTime     = 0;
                movieBox.TrackBox.TrackHeaderBox.ModificationTime = 0;
                movieBox.TrackBox.TrackHeaderBox.TrackID          = 1;
                movieBox.TrackBox.TrackHeaderBox.Duration         = 0;
                movieBox.TrackBox.TrackHeaderBox.TrackIsAudio     = false;
                movieBox.TrackBox.TrackHeaderBox.Width            = (uint)spsInfo.width;
                movieBox.TrackBox.TrackHeaderBox.Height           = (uint)spsInfo.height;
                movieBox.TrackBox.MediaBox = new MediaBox();
                movieBox.TrackBox.MediaBox.MediaHeaderBox = new MediaHeaderBox();
                movieBox.TrackBox.MediaBox.MediaHeaderBox.CreationTime     = 0;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.ModificationTime = 0;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.Timescale        = 1200000;
                movieBox.TrackBox.MediaBox.MediaHeaderBox.Duration         = 0;
                movieBox.TrackBox.MediaBox.HandlerBox             = new HandlerBox();
                movieBox.TrackBox.MediaBox.HandlerBox.HandlerType = HandlerType.vide;
                movieBox.TrackBox.MediaBox.HandlerBox.Name        = "VideoHandler";
                movieBox.TrackBox.MediaBox.MediaInformationBox    = new MediaInformationBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.VideoMediaHeaderBox = new VideoMediaHeaderBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox  = new DataInformationBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox = new DataReferenceBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes = new List <DataEntryBox>();
                movieBox.TrackBox.MediaBox.MediaInformationBox.DataInformationBox.DataReferenceBox.DataEntryBoxes.Add(new DataEntryUrlBox(1));
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox = new SampleTableBox();
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox = new SampleDescriptionBox(movieBox.TrackBox.MediaBox.HandlerBox.HandlerType);
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries = new List <SampleEntry>();
                AVC1SampleEntry avc1 = new AVC1SampleEntry();
                avc1.AVCConfigurationBox = new AVCConfigurationBox();
                //h264
                avc1.Width  = (ushort)movieBox.TrackBox.TrackHeaderBox.Width;
                avc1.Height = (ushort)movieBox.TrackBox.TrackHeaderBox.Height;
                avc1.AVCConfigurationBox.AVCLevelIndication   = spsInfo.levelIdc;
                avc1.AVCConfigurationBox.AVCProfileIndication = spsInfo.profileIdc;
                avc1.AVCConfigurationBox.ProfileCompatibility = (byte)spsInfo.profileCompat;
                avc1.AVCConfigurationBox.PPSs = new List <byte[]>()
                {
                    ppsNALU.RawData
                };
                avc1.AVCConfigurationBox.SPSs = new List <byte[]>()
                {
                    spsNALU.RawData
                };
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleDescriptionBox.SampleEntries.Add(avc1);
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.TimeToSampleBox = new TimeToSampleBox()
                {
                    //TimeToSampleInfos=new List<TimeToSampleBox.TimeToSampleInfo>
                    //{
                    //    new TimeToSampleBox.TimeToSampleInfo
                    //    {
                    //         SampleCount=0,
                    //         SampleDelta=0
                    //    }
                    //}
                };
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleToChunkBox = new SampleToChunkBox()
                {
                    //SampleToChunkInfos=new List<SampleToChunkBox.SampleToChunkInfo>()
                    //{
                    //     new SampleToChunkBox.SampleToChunkInfo
                    //     {

                    //     }
                    //}
                };
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.SampleSizeBox = new SampleSizeBox()
                {
                    //EntrySize = new List<uint>()
                    //{
                    //    0
                    //}
                };
                movieBox.TrackBox.MediaBox.MediaInformationBox.SampleTableBox.ChunkOffsetBox = new ChunkOffsetBox()
                {
                    //ChunkOffset=new List<uint>()
                    //{
                    //    0
                    //}
                };
                movieBox.MovieExtendsBox = new MovieExtendsBox();
                movieBox.MovieExtendsBox.TrackExtendsBoxs = new List <TrackExtendsBox>();
                TrackExtendsBox trex = new TrackExtendsBox();
                trex.TrackID = 1;
                trex.DefaultSampleDescriptionIndex = 1;
                trex.DefaultSampleDuration         = 0;
                trex.DefaultSampleSize             = 0;
                trex.DefaultSampleFlags            = 0;
                movieBox.MovieExtendsBox.TrackExtendsBoxs.Add(trex);
                movieBox.ToBuffer(ref writer);
                var data = writer.FlushAndGetArray();
                return(data);
            }
            finally
            {
                FMp4ArrayPool.Return(buffer);
            }
        }
예제 #11
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);
            }
        }