bool SendServerBW() { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x02; // control channel (invoke) packet.HeaderType = HeaderType.Large; packet.PacketType = PacketType.ServerBW; packet.AllocPacket(4); packet.m_nBodySize = 4; List<byte> bytesToSend = new List<byte>(); EncodeInt32(bytesToSend, m_nServerBW); // was hard coded : 0x001312d0 packet.m_body = bytesToSend.ToArray(); return SendPacket(packet, false); }
public bool SendCreateStream() { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x03; // control channel (invoke) packet.HeaderType = HeaderType.Medium; packet.PacketType = PacketType.Invoke; Logger.Log("Sending createStream"); packet.AllocPacket(256); // should be enough List<byte> enc = new List<byte>(); EncodeString(enc, "createStream"); EncodeNumber(enc, ++m_numInvokes); enc.Add(0x05); // NULL packet.m_nBodySize = (uint)enc.Count; packet.m_body = enc.ToArray(); return SendPacket(packet); }
bool SendPlay() { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x08; // we make 8 our stream channel packet.HeaderType = HeaderType.Large; packet.PacketType = PacketType.Invoke; packet.m_nInfoField2 = m_stream_id; packet.AllocPacket(256); // should be enough List<byte> enc = new List<byte>(); EncodeString(enc, "play"); EncodeNumber(enc, ++m_numInvokes); enc.Add(0x05); // NULL EncodeString(enc, Link.playpath); /* Optional parameters start and len. * * start: -2, -1, 0, positive number * -2: looks for a live stream, then a recorded stream, if not found any open a live stream * -1: plays a live stream * >=0: plays a recorded streams from 'start' milliseconds */ if (Link.bLiveStream) { EncodeNumber(enc, -1000.0d); } else { if (Link.seekTime > 0.0) EncodeNumber(enc, Link.seekTime); else EncodeNumber(enc, 0.0d); } /* len: -1, 0, positive number * -1: plays live or recorded stream to the end (default) * 0: plays a frame 'start' ms away from the beginning * >0: plays a live or recoded stream for 'len' milliseconds */ packet.m_body = enc.ToArray(); packet.m_nBodySize = (uint)enc.Count; Logger.Log(string.Format("Sending play: '{0}' from time: '{1}'", Link.playpath, m_channelTimestamp[m_mediaChannel])); return SendPacket(packet); }
/// <summary> /// The type of Ping packet is 0x4 and contains two mandatory parameters and two optional parameters. /// The first parameter is the type of Ping (short integer). /// The second parameter is the target of the ping. /// As Ping is always sent in Channel 2 (control channel) and the target object in RTMP header is always 0 /// which means the Connection object, /// it's necessary to put an extra parameter to indicate the exact target object the Ping is sent to. /// The second parameter takes this responsibility. /// The value has the same meaning as the target object field in RTMP header. /// (The second value could also be used as other purposes, like RTT Ping/Pong. It is used as the timestamp.) /// The third and fourth parameters are optional and could be looked upon as the parameter of the Ping packet. /// Below is an unexhausted list of Ping messages. /// type 0: Clear the stream. No third and fourth parameters. The second parameter could be 0. After the connection is established, a Ping 0,0 will be sent from server to client. The message will also be sent to client on the start of Play and in response of a Seek or Pause/Resume request. This Ping tells client to re-calibrate the clock with the timestamp of the next packet server sends. /// type 1: Tell the stream to clear the playing buffer. /// type 3: Buffer time of the client. The third parameter is the buffer time in millisecond. /// type 4: Reset a stream. Used together with type 0 in the case of VOD. Often sent before type 0. /// type 6: Ping the client from server. The second parameter is the current time. /// type 7: Pong reply from client. The second parameter is the time the server sent with his ping request. /// type 26: SWFVerification request /// type 27: SWFVerification response /// type 31: Buffer empty /// type 32: Buffer full /// </summary> /// <param name="nType"></param> /// <param name="nObject"></param> /// <param name="nTime"></param> /// <returns></returns> bool SendPing(short nType, uint nObject, uint nTime) { Logger.Log(string.Format("Sending ping type: {0}", nType)); RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x02; // control channel (ping) packet.HeaderType = HeaderType.Medium; packet.PacketType = PacketType.Control; //packet.m_nInfoField1 = System.Environment.TickCount; int nSize = (nType == 0x03 ? 10 : 6); // type 3 is the buffer time and requires all 3 parameters. all in all 10 bytes. if (nType == 0x1B) nSize = 44; packet.AllocPacket(nSize); packet.m_nBodySize = (uint)nSize; List<byte> buf = new List<byte>(); EncodeInt16(buf, nType); if (nType == 0x1B) { buf.AddRange(Link.SWFVerificationResponse); } else { if (nSize > 2) EncodeInt32(buf, (int)nObject); if (nSize > 6) EncodeInt32(buf, (int)nTime); } packet.m_body = buf.ToArray(); return SendPacket(packet, false); }
bool SendConnect() { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x03; // control channel (invoke) packet.HeaderType = HeaderType.Large; packet.PacketType = PacketType.Invoke; packet.AllocPacket(4096); Logger.Log("Sending connect"); List<byte> enc = new List<byte>(); EncodeString(enc, "connect"); EncodeNumber(enc, ++m_numInvokes); enc.Add(0x03); //Object Datatype EncodeString(enc, "app", Link.app); Logger.Log(string.Format("app : {0}", Link.app)); if (String.IsNullOrEmpty(Link.flashVer)) EncodeString(enc, "flashVer", "WIN 10,0,32,18"); else EncodeString(enc, "flashVer", Link.flashVer); if (!string.IsNullOrEmpty(Link.swfUrl)) EncodeString(enc, "swfUrl", Link.swfUrl); EncodeString(enc, "tcUrl", Link.tcUrl); Logger.Log(string.Format("tcUrl : {0}", Link.tcUrl)); EncodeBoolean(enc, "fpad", false); EncodeNumber(enc, "capabilities", 15.0); EncodeNumber(enc, "audioCodecs", 3191.0); EncodeNumber(enc, "videoCodecs", 252.0); EncodeNumber(enc, "videoFunction", 1.0); if (!string.IsNullOrEmpty(Link.pageUrl)) EncodeString(enc, "pageUrl", Link.pageUrl); //EncodeNumber(enc, "objectEncoding", 0.0); enc.Add(0); enc.Add(0); enc.Add(0x09); // end of object - 0x00 0x00 0x09 // add auth string if (!string.IsNullOrEmpty(Link.auth)) { EncodeBoolean(enc, true); EncodeString(enc, Link.auth); } // add aditional arbitrary AMF connection properties if (Link.extras != null) { foreach (AMFObjectProperty aProp in Link.extras.m_properties) aProp.Encode(enc); } Array.Copy(enc.ToArray(), packet.m_body, enc.Count); packet.m_nBodySize = (uint)enc.Count; return SendPacket(packet); }
bool SendCheckBWResult(double txn) { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x03; // control channel (invoke) packet.HeaderType = HeaderType.Medium; packet.PacketType = PacketType.Invoke; packet.m_nTimeStamp = (uint)(0x16 * m_nBWCheckCounter); // temp inc value. till we figure it out. packet.AllocPacket(256); // should be enough List<byte> enc = new List<byte>(); EncodeString(enc, "_result"); EncodeNumber(enc, txn); enc.Add(0x05); // NULL EncodeNumber(enc, (double)m_nBWCheckCounter++); packet.m_nBodySize = (uint)enc.Count; packet.m_body = enc.ToArray(); return SendPacket(packet, false); }
bool SendBytesReceived() { RTMPPacket packet = new RTMPPacket(); packet.m_nChannel = 0x02; // control channel (invoke) packet.HeaderType = HeaderType.Medium; packet.PacketType = PacketType.BytesRead; packet.AllocPacket(4); packet.m_nBodySize = 4; List<byte> enc = new List<byte>(); EncodeInt32(enc, bytesReadTotal); packet.m_nBodySize = (uint)enc.Count; packet.m_body = enc.ToArray(); lastSentBytesRead = bytesReadTotal; Logger.Log(string.Format("Send bytes report. ({0} bytes)", bytesReadTotal)); return SendPacket(packet, false); }