static void Main(string[] args) { String url = "rtsp://admin:@192.168.17.92"; String now = DateTime.Now.ToString("yyyyMMdd_HHmmss"); FileStream fs_v = null; // used to write the video FileStream fs_a = null; // used to write the audio bool h264 = false; bool h265 = false; // Create a RTSP Client RTSPClient c = new RTSPClient(); // The SPS/PPS comes from the SDP data // or it is the first SPS/PPS from the H264 video stream c.Received_SPS_PPS += (byte[] sps, byte[] pps) => { h264 = true; if (fs_v == null) { String filename = "rtsp_capture_" + now + ".264"; fs_v = new FileStream(filename, FileMode.Create); } if (fs_v != null) { fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(sps, 0, sps.Length); fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(pps, 0, pps.Length); fs_v.Flush(true); } }; c.Received_VPS_SPS_PPS += (byte[] vps, byte[] sps, byte[] pps) => { h265 = true; if (fs_v == null) { String filename = "rtsp_capture_" + now + ".265"; fs_v = new FileStream(filename, FileMode.Create); } if (fs_v != null) { fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(vps, 0, vps.Length); fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(sps, 0, sps.Length); fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(pps, 0, pps.Length); fs_v.Flush(true); } }; // Video NALs. May also include the SPS and PPS in-band for H264 c.Received_NALs += (List <byte[]> nal_units) => { if (fs_v != null) { foreach (byte[] nal_unit in nal_units) { // Output some H264 stream information if (h264 && nal_unit.Length > 0) { int nal_ref_idc = (nal_unit[0] >> 5) & 0x03; int nal_unit_type = nal_unit[0] & 0x1F; String description = ""; if (nal_unit_type == 1) { description = "NON IDR NAL"; } else if (nal_unit_type == 5) { description = "IDR NAL"; } else if (nal_unit_type == 6) { description = "SEI NAL"; } else if (nal_unit_type == 7) { description = "SPS NAL"; } else if (nal_unit_type == 8) { description = "PPS NAL"; } else if (nal_unit_type == 9) { description = "ACCESS UNIT DELIMITER NAL"; } else { description = "OTHER NAL"; } Console.WriteLine("NAL Ref = " + nal_ref_idc + " NAL Type = " + nal_unit_type + " " + description); } // Output some H265 stream information if (h265 && nal_unit.Length > 0) { int nal_unit_type = (nal_unit[0] >> 1) & 0x3F; String description = ""; if (nal_unit_type == 1) { description = "NON IDR NAL"; } else if (nal_unit_type == 19) { description = "IDR NAL"; } else if (nal_unit_type == 32) { description = "VPS NAL"; } else if (nal_unit_type == 33) { description = "SPS NAL"; } else if (nal_unit_type == 34) { description = "PPS NAL"; } else if (nal_unit_type == 39) { description = "SEI NAL"; } else { description = "OTHER NAL"; } Console.WriteLine("NAL Type = " + nal_unit_type + " " + description); } fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Write Start Code fs_v.Write(nal_unit, 0, nal_unit.Length); // Write NAL } fs_v.Flush(true); } }; c.Received_G711 += (string format, List <byte[]> g711) => { if (fs_a == null && format.Equals("PCMU")) { String filename = "rtsp_capture_" + now + ".ul"; fs_a = new FileStream(filename, FileMode.Create); } if (fs_a == null && format.Equals("PCMA")) { String filename = "rtsp_capture_" + now + ".al"; fs_a = new FileStream(filename, FileMode.Create); } if (fs_a != null) { foreach (byte[] data in g711) { fs_a.Write(data, 0, data.Length); } } }; c.Received_AMR += (string format, List <byte[]> amr) => { if (fs_a == null && format.Equals("AMR")) { String filename = "rtsp_capture_" + now + ".amr"; fs_a = new FileStream(filename, FileMode.Create); byte[] header = new byte[] { 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A }; // #!AMR<0x0A> fs_a.Write(header, 0, header.Length); } if (fs_a != null) { foreach (byte[] data in amr) { fs_a.Write(data, 0, data.Length); } } }; c.Received_AAC += (string format, List <byte[]> aac, uint ObjectType, uint FrequencyIndex, uint ChannelConfiguration) => { if (fs_a == null) { String filename = "rtsp_capture_" + now + ".aac"; fs_a = new FileStream(filename, FileMode.Create); } if (fs_a != null) { foreach (byte[] data in aac) { // ASDT header format int protection_absent = 1; // int profile = 2; // Profile 2 = AAC Low Complexity (LC) // int sample_freq = 4; // 4 = 44100 Hz // int channel_config = 2; // 2 = Stereo Rtsp.BitStream bs = new Rtsp.BitStream(); bs.AddValue(0xFFF, 12); // (a) Start of data bs.AddValue(0, 1); // (b) Version ID, 0 = MPEG4 bs.AddValue(0, 2); // (c) Layer always 2 bits set to 0 bs.AddValue(protection_absent, 1); // (d) 1 = No CRC bs.AddValue((int)ObjectType - 1, 2); // (e) MPEG Object Type / Profile, minus 1 bs.AddValue((int)FrequencyIndex, 4); // (f) bs.AddValue(0, 1); // (g) private bit. Always zero bs.AddValue((int)ChannelConfiguration, 3); // (h) bs.AddValue(0, 1); // (i) originality bs.AddValue(0, 1); // (j) home bs.AddValue(0, 1); // (k) copyrighted id bs.AddValue(0, 1); // (l) copyright id start bs.AddValue(data.Length + 7, 13); // (m) AAC data + size of the ASDT header bs.AddValue(2047, 11); // (n) buffer fullness ??? int num_acc_frames = 1; bs.AddValue(num_acc_frames - 1, 1); // (o) num of AAC Frames, minus 1 // If Protection was On, there would be a 16 bit CRC if (protection_absent == 0) { bs.AddValue(0xABCD /*CRC*/, 16); // (p) } byte[] header = bs.ToArray(); fs_a.Write(header, 0, header.Length); fs_a.Write(data, 0, data.Length); } } }; // Connect to RTSP Server Console.WriteLine("Connecting"); c.Connect(url, RTSPClient.RTP_TRANSPORT.TCP); // Wait for user to terminate programme // Check for null which is returned when running under some IDEs // OR wait for the Streaming to Finish - eg an error on the RTSP socket Console.WriteLine("Press ENTER to exit"); String readline = null; while (readline == null && c.StreamingFinished() == false) { readline = Console.ReadLine(); // Avoid maxing out CPU on systems that instantly return null for ReadLine if (readline == null) { Thread.Sleep(500); } } c.Stop(); Console.WriteLine("Finished"); Console.WriteLine("Press ENTER to exit"); while (readline == null) { readline = Console.ReadLine(); // Avoid maxing out CPU on systems that instantly return null for ReadLine if (readline == null) { Thread.Sleep(500); } } }
private void Initialize() { // создадим коннектор потока rtsp_con = new rtsp_connector(); //Видео блок // Получим SPS/PPS из SDP описания // или из видео потока H264 rtsp_con.Received_SPS_PPS += (byte[] _sps, byte[] _pps) => { stream_video_format = "h264"; sps = _sps; pps = _pps; }; rtsp_con.Received_VPS_SPS_PPS += (byte[] _vps, byte[] _sps, byte[] _pps) => { stream_video_format = "h265"; vps = _vps; sps = _sps; pps = _pps; }; // NALs. Так-же могут включать SPS/PPS для H264 rtsp_con.Received_NALs += (List <byte[]> nal_units) => { //блок контроля связи - начало if (NowReconnecting) { NowReconnecting = false; EVENT_LOG.WriteEntry("Связь с камерой " + rstp_url + " востановлена"); if (!video_rec_uid.Equals("")) { keepalive_autostop_rec.Stop(); keepalive_autostop_rec = null; } } NowConnected = true; keepalive_stopwatch_timer_checker(); keepalive_stopwatch.Restart(); //блок контроля связи - конец if (fs_v != null) { foreach (byte[] nal_unit in nal_units) { fs_v.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 }, 0, 4); // Запись начального значения fs_v.Write(nal_unit, 0, nal_unit.Length); // Запись NAL } fs_v.Flush(true); } }; //Звуковой блок rtsp_con.Received_G711 += (string format, List <byte[]> g711) => { if (format.Equals("PCMU")) { stream_audio_format = "PCMU"; } else if (format.Equals("PCMA")) { stream_audio_format = "PCMA"; } if (fs_a != null) { foreach (byte[] data in g711) { fs_a.Write(data, 0, data.Length); } } }; rtsp_con.Received_AMR += (string format, List <byte[]> amr) => { if (format.Equals("AMR")) { stream_audio_format = "AMR"; } if (fs_a != null) { foreach (byte[] data in amr) { fs_a.Write(data, 0, data.Length); } } }; rtsp_con.Received_AAC += (string format, List <byte[]> aac, uint ObjectType, uint FrequencyIndex, uint ChannelConfiguration) => { stream_audio_format = "AAC"; if (fs_a != null) { foreach (byte[] data in aac) { // ASDT header format int protection_absent = 1; // int profile = 2; // Profile 2 = AAC Low Complexity (LC) // int sample_freq = 4; // 4 = 44100 Hz // int channel_config = 2; // 2 = Stereo Rtsp.BitStream bs = new Rtsp.BitStream(); bs.AddValue(0xFFF, 12); // (a) Start of data bs.AddValue(0, 1); // (b) Version ID, 0 = MPEG4 bs.AddValue(0, 2); // (c) Layer always 2 bits set to 0 bs.AddValue(protection_absent, 1); // (d) 1 = No CRC bs.AddValue((int)ObjectType - 1, 2); // (e) MPEG Object Type / Profile, minus 1 bs.AddValue((int)FrequencyIndex, 4); // (f) bs.AddValue(0, 1); // (g) private bit. Always zero bs.AddValue((int)ChannelConfiguration, 3); // (h) bs.AddValue(0, 1); // (i) originality bs.AddValue(0, 1); // (j) home bs.AddValue(0, 1); // (k) copyrighted id bs.AddValue(0, 1); // (l) copyright id start bs.AddValue(data.Length + 7, 13); // (m) AAC data + size of the ASDT header bs.AddValue(2047, 11); // (n) buffer fullness ??? int num_acc_frames = 1; bs.AddValue(num_acc_frames - 1, 1); // (o) num of AAC Frames, minus 1 // If Protection was On, there would be a 16 bit CRC if (protection_absent == 0) { bs.AddValue(0xABCD /*CRC*/, 16); // (p) } byte[] header = bs.ToArray(); fs_a.Write(header, 0, header.Length); fs_a.Write(data, 0, data.Length); } } }; // Подключиться к источнику потока rtsp_con.Connect(rstp_url, rtsp_connector.RTP_TRANSPORT.TCP); }