protected override void InitProtected() { Codec = new H264Decoder(); if (Codec == null) { throw new Exception("codec not found"); } Context = MpegEncContext.avcodec_alloc_context(); picture = AVFrame.avcodec_alloc_frame(); // We do not send complete frames if ((Codec.capabilities & H264Decoder.CODEC_CAP_TRUNCATED) != 0) { Context.flags |= MpegEncContext.CODEC_FLAG_TRUNCATED; } // For some codecs, such as msmpeg4 and mpeg4, width and height // MUST be initialized there because this information is not // available in the bitstream. // Open it if (Context.avcodec_open(Codec) < 0) { throw new Exception("could not open codec"); } }
public void Test4() { FMp4Encoder fMp4Encoder = new FMp4Encoder(); H264Decoder h264Decoder = new H264Decoder(); var packages = ParseNALUTests(); var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.mp4"); if (File.Exists(filepath)) { File.Delete(filepath); } using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); var ftyp = fMp4Encoder.EncoderFtypBox(); fileStream.Write(ftyp); var package1 = packages[0]; var nalus1 = h264Decoder.ParseNALU(package1); var moov = fMp4Encoder.EncoderMoovBox(nalus1, package1.Bodies.Length); fileStream.Write(moov); foreach (var package in packages) { var otherNalus = h264Decoder.ParseNALU(package); var flag = package.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧 ? 1u : 0u; var otherMoofBuffer = fMp4Encoder.EncoderMoofBox(otherNalus, package.Bodies.Length, package.Timestamp, package.LastIFrameInterval, flag); var otherMdatBuffer = fMp4Encoder.EncoderMdatBox(otherNalus, package.Bodies.Length); fileStream.Write(otherMoofBuffer); fileStream.Write(otherMdatBuffer); } fileStream.Close(); }
public async Task Start_Completes_Async() { int frameCount = 0; Collection <string> imageHashes = new Collection <string>(); using (var stream = File.OpenRead("video.h264")) using (var decoder = new H264Decoder(stream)) { var frameBuffer = decoder.FrameBuffer; frameBuffer.FrameReceived += (sender, e) => { Assert.Equal(1334, frameBuffer.Height); Assert.Equal(3000, frameBuffer.Stride); Assert.Equal(750, frameBuffer.Width); Assert.Equal(750, frameBuffer.AlignedWidth); Assert.Equal(1334, frameBuffer.AlignedHeight); frameCount++; }; decoder.Start(); await Task.WhenAny( decoder.DecodeTask, Task.Delay(TimeSpan.FromSeconds(5))).ConfigureAwait(false); Assert.True(decoder.DecodeTask.IsCompleted, "The decode task did not complete in time"); } Assert.Equal(5, frameCount); }
public void 测试第一帧的数据() { 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(); //7 8 6 5 1 1 1 1 1 7 8 6 5 1 1 1 1 var nalus = decoder.ParseNALU(Package); Assert.Equal(4, nalus.Count); FlvEncoder encoder = new FlvEncoder(); var contents = encoder.CreateFlvFrame(nalus); var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.flv"); if (File.Exists(filepath)) { File.Delete(filepath); } FileStream fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); fileStream.Write(contents); fileStream.Close(); }
public void Start_IsCompleted() { using var stream = File.OpenRead("video.h264"); using var decoder = new H264Decoder(stream); decoder.Start(); Assert.Throws <InvalidOperationException>(() => decoder.Start()); }
public void Dispose_Twice() { using var stream = File.OpenRead("video.h264"); var decoder = new H264Decoder(stream); decoder.Dispose(); decoder.Dispose(); }
public void 测试可以播放的Flv2() { 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_4.flv"); var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_4.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(); } } } fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); fileStream.Write(FlvEncoder.VideoFlvHeaderBuffer); 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(); } }
public void Disposed_ThrowsException() { var decoder = new H264Decoder(Stream.Null); decoder.Dispose(); Assert.Throws <ObjectDisposedException>(() => decoder.Start()); Assert.Throws <ObjectDisposedException>(() => decoder.FrameBuffer.CopyFramebuffer(Array.Empty <byte>())); Assert.Throws <ObjectDisposedException>(() => decoder.Decode()); }
public ToWebSocketService( H264Decoder h264Decoder, WsSession wsSession, FMp4Encoder fMp4Encoder, ILoggerFactory loggerFactory, IHubContext <FMp4Hub> hubContext) { this.h264Decoder = h264Decoder; logger = loggerFactory.CreateLogger <ToWebSocketService>(); this.fMp4Encoder = fMp4Encoder; _hubContext = hubContext; this.wsSession = wsSession; }
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); }
public void Test4() { FMp4Encoder fMp4Encoder = new FMp4Encoder(); H264Decoder h264Decoder = new H264Decoder(); var packages = ParseNALUTests(); var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_5.mp4"); if (File.Exists(filepath)) { File.Delete(filepath); } using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); var ftyp = fMp4Encoder.EncoderFtypBox(); fileStream.Write(ftyp); var iNalus = h264Decoder.ParseNALU(packages[0]); //判断第一帧是否关键帧 var moov = fMp4Encoder.EncoderMoovBox( iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS), iNalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS)); fileStream.Write(moov); List <H264NALU> nalus = new List <H264NALU>(); foreach (var package in packages) { List <H264NALU> h264NALUs = h264Decoder.ParseNALU(package); foreach (var nalu in h264NALUs) { if (nalu.Slice) { //H264 NALU slice first_mb_in_slice nalus.Add(nalu); } else { if (nalus.Count > 0) { var otherBuffer = fMp4Encoder.EncoderOtherVideoBox(nalus); fileStream.Write(otherBuffer); nalus.Clear(); } nalus.Add(nalu); } } } fileStream.Close(); }
public void ParseNALUTest1() { H264Decoder demuxer = new H264Decoder(); var hexData = "3031636481e2274b01234567899901100000016cd3ed2fa900500050037f0000000161e022bfb28b470069769838a02eb3b5cc4bccd7b37eb98cd65b2a76ce85a6c82876385a8f646da3d0abb6af58ad1dc7db5dab9719577d9968f7efc9836f4bc8fb7e32f5689b190e9e6e07d2f4448efff9147175f22a4b0f83fd24374b881dddcac5998ab9b03d991eb0045ed98826699a5601cdd6bd1e4b3ca53c175ef36e9f46969018c01b7754304790a17888072647e4c473182f05922770f5aff81e02ea46637b5e90b4382f100a2b55c5f49e0fa0b8203804dcd7714fac1dbd15d0583f8ebdfdf980770d58b38349ad7ec5682f01dae88b2117c6f3b3b58b642354bc23735d9c269028df9774e8182f5d636cec09829886de3ee83406e035bffcce3ed24af0f9a2dee150fab93303f2139c8525eeb89516df169137ef46ed99962343ea7b078bcddd284e44be62936a6c44042d89acb17973eb65e1c21faee6d221627ba834d369f4c023acc122d7d3dd3f55a6c4fb2ba2854498d4041ea00b1252c6d9eb57ac0b10313e8905843054dfbf4c847180aee40980bdfe5cb53133214c77c8e95ebe7601cd0d331f75281d1fadd122985133e74855e13cbb10220bc6e0c946b519b35d933a29e38e175b1398dc0946fc58ec7b686b3aac4bfa9e42bb8e643be04dc55036289c7d378fe37c6c3e1fc06015f8b402a65afac23d78d9fb5e3e0115195c11227ee6f261b67834b51bc665e8a6803af835b5032786e58e7f66049dc767520bae35d527a72458834a846dcd1cccf198d772d3ce0a2db5eb1d8270c483840309e224b2798d9271b30729e0c4f51eb7798d0dd0d8adb3d246e686b42e47f351c482dda833747649e421bbbe04098ca220d4e0e60a3b2854029c95c70394a2991314c50199f2158b68635a622f55ebda0b5e41328843552723fba1d5228963e8562c9105838ec9d341fef19b33a438d903ebcef32cec2ad39fd32aff14c79f07de4ca75e65d20f6ee36e464ee3e5c27871ab594ae3a0b43583c6f4d55ac8b71090fca9a1f4379576e07678983935d6f3a236504c2e4d31f99d62c999f41c11b06c41a6adb07b6e62f50ec5c8dbdb6641c5bc55a695f0f7b4f4d430c1e2f38a77edfc3513f943e1c1d4c0a81ef6c26cc4e7b157d318b49802ea94aa8ab38dadd4986e5330ab49daaec010123c39da63943bfe63bdd1cdd6beec19e1469b989ac10877a24065d7b01ff9cee35632e97243eb7acd79ce9d188b786e44bbe0e922be205c1224a41f387fae0f20d4a203d0ba64a366b8adbe2b80".ToHexBytes(); JT1078Package package = JT1078Serializer.Deserialize(hexData); var nalus = demuxer.ParseNALU(package); Assert.Single(nalus); var nalu = nalus[0]; Assert.Equal(0, nalu.NALUHeader.ForbiddenZeroBit); Assert.Equal(3, nalu.NALUHeader.NalRefIdc); Assert.Equal(1, nalu.NALUHeader.NalUnitType); }
public void CopyFrameBuffer_ThrowsOnWrongSize() { using (var stream = File.OpenRead("video.h264")) using (var decoder = new H264Decoder(stream)) { var frameBuffer = decoder.FrameBuffer; frameBuffer.FrameReceived += (sender, e) => { byte[] array = new byte[20]; Assert.Throws <ArgumentOutOfRangeException>(() => frameBuffer.CopyFramebuffer(array)); }; decoder.Decode(); } }
public JT1078FMp4NormalMsgHostedService( MessageDispatchDataService messageDispatchDataService, IMemoryCache memoryCache, ILoggerFactory loggerFactory, H264Decoder h264Decoder, FMp4Encoder fM4Encoder, JT1078HttpSessionManager httpSessionManager) { Logger = loggerFactory.CreateLogger <JT1078FMp4NormalMsgHostedService>(); HttpSessionManager = httpSessionManager; FM4Encoder = fM4Encoder; H264Decoder = h264Decoder; this.memoryCache = memoryCache; this.messageDispatchDataService = messageDispatchDataService; avFrameDict = new ConcurrentDictionary <string, List <H264NALU> >(); }
public unsafe void DecodeTest() { int frameCount = 0; var imageHashes = new List <string>(); using (var stream = File.OpenRead("video.h264")) using (var decoder = new H264Decoder(stream)) { var frameBuffer = decoder.FrameBuffer; frameBuffer.FrameReceived += (sender, e) => { Assert.Equal(1334, frameBuffer.Height); Assert.Equal(3000, frameBuffer.Stride); Assert.Equal(750, frameBuffer.Width); Assert.Equal(750, frameBuffer.AlignedWidth); Assert.Equal(1334, frameBuffer.AlignedHeight); byte[] array = new byte[frameBuffer.FrameBufferSize]; frameBuffer.CopyFramebuffer(array); fixed(byte *ptr = array) { // Only reason we do this is to make sure the framebuffer data is relevant if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { using (var bitmap = new Bitmap(frameBuffer.Width, frameBuffer.Height, frameBuffer.Stride, PixelFormat.Format24bppRgb, (IntPtr)ptr)) { bitmap.Save($"stream-frame.{frameCount}.jpg", ImageFormat.Jpeg); } } } frameCount++; }; decoder.Decode(); } Assert.Equal(5, frameCount); }
/// <summary> /// /// </summary> public FMp4Encoder() { h264Decoder = new H264Decoder(); }
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(); }
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(); } }
//public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false) /// <summary> /// /// </summary> public FlvEncoder() { audioCodecFactory = new AudioCodecFactory(); h264Decoder = new H264Decoder(); }
private void Init() { avpkt.av_init_packet(); // Set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) Arrays.Fill(inbuf, INBUF_SIZE, MpegEncContext.FF_INPUT_BUFFER_PADDING_SIZE + INBUF_SIZE, (sbyte)0); // Find the mpeg1 video decoder codec = new H264Decoder(); if (codec == null) { throw (new Exception("codec not found")); } c = MpegEncContext.avcodec_alloc_context(); picture = AVFrame.avcodec_alloc_frame(); // We do not send complete frames if ((codec.capabilities & H264Decoder.CODEC_CAP_TRUNCATED) != 0) { c.flags |= MpegEncContext.CODEC_FLAG_TRUNCATED; } // For some codecs, such as msmpeg4 and mpeg4, width and height // MUST be initialized there because this information is not // available in the bitstream. // Open it if (c.avcodec_open(codec) < 0) { throw (new Exception("could not open codec")); } // The codec gives us the frame size, in samples frame = 0; // avpkt must contain exactly 1 NAL Unit in order for decoder to decode correctly. // thus we must read until we get next NAL header before sending it to decoder. // Find 1st NAL cacheRead[0] = fin.ReadByte(); cacheRead[1] = fin.ReadByte(); cacheRead[2] = fin.ReadByte(); while (!(cacheRead[0] == 0x00 && cacheRead[1] == 0x00 && cacheRead[2] == 0x01)) { cacheRead[0] = cacheRead[1]; cacheRead[1] = cacheRead[2]; cacheRead[2] = fin.ReadByte(); if (cacheRead[2] == -1) { throw(new EndOfStreamException()); } } // while // 4 first bytes always indicate NAL header inbuf_int[0] = inbuf_int[1] = inbuf_int[2] = 0x00; inbuf_int[3] = 0x01; hasMoreNAL = true; }
public void Test1() { var jT1078Package = ParseNALUTest(); H264Decoder decoder = new H264Decoder(); 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); //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 = 352; movieBox.TrackBox.TrackHeaderBox.Height = 288; 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; //MSE codecs avc1.4D0014 //4D 00 14 //AVCProfileIndication profile_compability AVCLevelIndication avc1.AVCConfigurationBox.AVCLevelIndication = 20; avc1.AVCConfigurationBox.AVCProfileIndication = 77; avc1.AVCConfigurationBox.PPSs = new List <byte[]>() { ppsNALU.RawData }; avc1.AVCConfigurationBox.SPSs = new List <byte[]>() { spsNALU.RawData }; avc1.AVCConfigurationBox.ProfileCompatibility = 0; 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); //用户自定义可以不用 //movieBox.UserDataBox = new UserDataBox(); //movieBox.UserDataBox.Data = "0000005a6d657461000000000000002168646c7200000000000000006d6469726170706c0000000000000000000000002d696c737400000025a9746f6f0000001d6461746100000001000000004c61766635382e34352e313030".ToHexBytes(); //fragment moof n List <FragmentBox> moofs = new List <FragmentBox>(); FragmentBox fragmentBox = new FragmentBox(); fragmentBox.MovieFragmentBox = new MovieFragmentBox(); fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox = new MovieFragmentHeaderBox(); fragmentBox.MovieFragmentBox.MovieFragmentHeaderBox.SequenceNumber = 1; fragmentBox.MovieFragmentBox.TrackFragmentBox = new TrackFragmentBox(); fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox = new TrackFragmentHeaderBox(0x39); fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.TrackID = 1; //todo:BaseDataOffset fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.BaseDataOffset = 0x000000000000028b; fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleDuration = 48000; fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleSize = (uint)jT1078Package.Bodies.Length; fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentHeaderBox.DefaultSampleFlags = 0x1010000; //fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox = new SampleDependencyTypeBox(); //fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox.SampleDependencyTypes = new List<SampleDependencyTypeBox.SampleDependencyType>(); //todo:fragmentBox.MovieFragmentBox.TrackFragmentBox.SampleDependencyTypeBox.SampleDependencyTypes fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox = new TrackFragmentBaseMediaDecodeTimeBox(); //todo:BaseMediaDecodeTime fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackFragmentBaseMediaDecodeTimeBox.BaseMediaDecodeTime = 0; //trun fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox = new TrackRunBox(flags: 0x5); fragmentBox.MovieFragmentBox.TrackFragmentBox.TrackRunBox.DataOffset = 120; 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 = nalus .Select(s => s.RawData) .ToList(); moofs.Add(fragmentBox); //mfra MovieFragmentRandomAccessBox movieFragmentRandomAccessBox = new MovieFragmentRandomAccessBox(); //mfra->tfra movieFragmentRandomAccessBox.TrackFragmentRandomAccessBox = new TrackFragmentRandomAccessBox(1); movieFragmentRandomAccessBox.TrackFragmentRandomAccessBox.TrackID = 0x01; movieFragmentRandomAccessBox.TrackFragmentRandomAccessBox.TrackFragmentRandomAccessInfos = new List <TrackFragmentRandomAccessBox.TrackFragmentRandomAccessInfo>(); TrackFragmentRandomAccessBox.TrackFragmentRandomAccessInfo trackFragmentRandomAccessInfo1 = new TrackFragmentRandomAccessBox.TrackFragmentRandomAccessInfo(); trackFragmentRandomAccessInfo1.Time = 0; //todo:MoofOffset trackFragmentRandomAccessInfo1.MoofOffset = 0x000000000000028b; trackFragmentRandomAccessInfo1.TrafNumber = 0x01; trackFragmentRandomAccessInfo1.TrunNumber = 0x01; trackFragmentRandomAccessInfo1.SampleNumber = 0x01; movieFragmentRandomAccessBox.TrackFragmentRandomAccessBox.TrackFragmentRandomAccessInfos.Add(trackFragmentRandomAccessInfo1); //mfra->mfro movieFragmentRandomAccessBox.MovieFragmentRandomAccessOffsetBox = new MovieFragmentRandomAccessOffsetBox(0); //todo:MfraSize movieFragmentRandomAccessBox.MovieFragmentRandomAccessOffsetBox.MfraSize = 0x00000043; FMp4Box fMp4Box = new FMp4Box(); fMp4Box.FileTypeBox = fileTypeBox; fMp4Box.MovieBox = movieBox; fMp4Box.FragmentBoxs = moofs; fMp4Box.MovieFragmentRandomAccessBox = movieFragmentRandomAccessBox; FMp4MessagePackWriter writer = new FMp4MessagePackWriter(new byte[65535]); fMp4Box.ToBuffer(ref writer); var buffer = writer.FlushAndGetArray(); var filepath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_1.mp4"); if (File.Exists(filepath)) { File.Delete(filepath); } using var fileStream = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write); fileStream.Write(buffer); fileStream.Close(); }