You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
7.8 KiB

  1. using JT1078.Flv.Enums;
  2. using JT1078.Flv.H264;
  3. using JT1078.Flv.MessagePack;
  4. using JT1078.Flv.Metadata;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. namespace JT1078.Flv
  10. {
  11. public class FlvEncoder
  12. {
  13. private static readonly FlvHeader VideoFlvHeader = new FlvHeader(true, false);
  14. private static readonly H264Decoder h264Decoder = new H264Decoder();
  15. public byte[] FlvFirstFrame(List<H264NALU> nALUs)
  16. {
  17. byte[] buffer = FlvArrayPool.Rent(10240);
  18. try
  19. {
  20. FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
  21. //flv header
  22. flvMessagePackWriter.WriteArray(VideoFlvHeader.ToArray());
  23. //SPS -> 7
  24. var spsNALU = nALUs.FirstOrDefault(n => n.NALUHeader.NalUnitType == 7);
  25. spsNALU.RawData = h264Decoder.DiscardEmulationPreventionBytes(spsNALU.RawData);
  26. ExpGolombReader h264GolombReader = new ExpGolombReader(spsNALU.RawData);
  27. var spsInfo = h264GolombReader.ReadSPS();
  28. //PPS -> 8
  29. var ppsNALU = nALUs.FirstOrDefault(n => n.NALUHeader.NalUnitType == 8);
  30. //IDR -> 5 关键帧
  31. var idrNALU = nALUs.FirstOrDefault(n => n.NALUHeader.NalUnitType == 5);
  32. //SEI -> 6
  33. //var seiNALU = nALUs.FirstOrDefault(n => n.NALUHeader.NalUnitType == 6);
  34. //flv body script tag
  35. var scriptTag = CreateScriptTagFrame(spsInfo.width, spsInfo.height);
  36. //flv body video tag
  37. AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord = new AVCDecoderConfigurationRecord();
  38. aVCDecoderConfigurationRecord.AVCProfileIndication = spsInfo.profileIdc;
  39. aVCDecoderConfigurationRecord.ProfileCompatibility =(byte)spsInfo.profileCompat;
  40. aVCDecoderConfigurationRecord.AVCLevelIndication = spsInfo.levelIdc;
  41. aVCDecoderConfigurationRecord.NumOfPictureParameterSets = 1;
  42. aVCDecoderConfigurationRecord.PPSBuffer = spsNALU.RawData;
  43. aVCDecoderConfigurationRecord.SPSBuffer = ppsNALU.RawData;
  44. var videoTag = CreateVideoTag0Frame((uint)scriptTag.Length, aVCDecoderConfigurationRecord);
  45. return flvMessagePackWriter.FlushAndGetArray();
  46. }
  47. finally
  48. {
  49. FlvArrayPool.Return(buffer);
  50. }
  51. }
  52. public byte[] CreateScriptTagFrame(int width,int height)
  53. {
  54. byte[] buffer = FlvArrayPool.Rent(1024);
  55. try
  56. {
  57. FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
  58. //flv body PreviousTagSize awalys 0
  59. flvMessagePackWriter.WriteUInt32(0);
  60. //flv body script tag
  61. //flv body tag header
  62. FlvTags flvTags = new FlvTags();
  63. flvTags.Type = TagType.ScriptData;
  64. flvTags.Timestamp = 0;
  65. flvTags.TimestampExt = 0;
  66. flvTags.StreamId = 0;
  67. //flv body tag body
  68. flvTags.DataTagsData = new Amf3();
  69. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Duration
  70. {
  71. Value = 0d
  72. });
  73. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoDataRate
  74. {
  75. Value = 0d
  76. });
  77. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_VideoCodecId
  78. {
  79. Value = 7d
  80. });
  81. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_FrameRate
  82. {
  83. Value = 25d
  84. });
  85. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Width
  86. {
  87. Value = width
  88. });
  89. flvTags.DataTagsData.Amf3Metadatas.Add(new Amf3Metadata_Height
  90. {
  91. Value = height
  92. });
  93. flvMessagePackWriter.WriteFlvTag(flvTags);
  94. return flvMessagePackWriter.FlushAndGetArray();
  95. }
  96. finally
  97. {
  98. FlvArrayPool.Return(buffer);
  99. }
  100. }
  101. public byte[] CreateVideoTag0Frame(uint previousTagSize,AVCDecoderConfigurationRecord aVCDecoderConfigurationRecord)
  102. {
  103. byte[] buffer = FlvArrayPool.Rent(1024);
  104. try
  105. {
  106. FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
  107. //flv body PreviousTagSize ScriptTag
  108. flvMessagePackWriter.WriteUInt32(previousTagSize);
  109. //flv body video tag
  110. //flv body tag header
  111. FlvTags flvTags = new FlvTags();
  112. flvTags.Type = TagType.Video;
  113. flvTags.Timestamp = 0;
  114. flvTags.TimestampExt = 0;
  115. flvTags.StreamId = 0;
  116. //flv body tag body
  117. flvTags.VideoTagsData = new VideoTags();
  118. flvTags.VideoTagsData.FrameType = FrameType.KeyFrame;
  119. flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
  120. flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.SequenceHeader;
  121. flvTags.VideoTagsData.VideoData.CompositionTime = 0;
  122. flvTags.VideoTagsData.VideoData.AVCDecoderConfiguration = aVCDecoderConfigurationRecord;
  123. flvMessagePackWriter.WriteFlvTag(flvTags);
  124. return flvMessagePackWriter.FlushAndGetArray();
  125. }
  126. finally
  127. {
  128. FlvArrayPool.Return(buffer);
  129. }
  130. }
  131. public byte[] CreateVideoTagOtherFrame(uint previousTagSize, H264NALU nALU)
  132. {
  133. byte[] buffer = FlvArrayPool.Rent(2048);
  134. try
  135. {
  136. FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
  137. //flv body PreviousTagSize ScriptTag
  138. flvMessagePackWriter.WriteUInt32(previousTagSize);
  139. //flv body video tag
  140. //flv body tag header
  141. FlvTags flvTags = new FlvTags();
  142. flvTags.Type = TagType.Video;
  143. flvTags.Timestamp = nALU.LastIFrameInterval;
  144. flvTags.TimestampExt = 0;
  145. flvTags.StreamId = 0;
  146. //flv body tag body
  147. flvTags.VideoTagsData = new VideoTags();
  148. flvTags.VideoTagsData.FrameType = FrameType.InterFrame;
  149. flvTags.VideoTagsData.VideoData = new AvcVideoPacke();
  150. flvTags.VideoTagsData.VideoData.AvcPacketType = AvcPacketType.Raw;
  151. flvTags.VideoTagsData.VideoData.CompositionTime = nALU.LastIFrameInterval;
  152. flvTags.VideoTagsData.VideoData.Data = nALU.RawData;
  153. flvMessagePackWriter.WriteFlvTag(flvTags);
  154. return flvMessagePackWriter.FlushAndGetArray();
  155. }
  156. finally
  157. {
  158. FlvArrayPool.Return(buffer);
  159. }
  160. }
  161. public byte[] FlvOtherFrame()
  162. {
  163. byte[] buffer = FlvArrayPool.Rent(10240);
  164. try
  165. {
  166. FlvMessagePackWriter flvMessagePackWriter = new FlvMessagePackWriter(buffer);
  167. #warning 目前只支持视频
  168. // NalUnitType == 1
  169. //flv body
  170. //flv body PreviousTagSize
  171. //flv body tag
  172. //flv body tag header
  173. //flv body tag body
  174. return flvMessagePackWriter.FlushAndGetArray();
  175. }
  176. finally
  177. {
  178. FlvArrayPool.Return(buffer);
  179. }
  180. }
  181. }
  182. }