示例#1
0
		/// <summary>
		/// Decodes RTMP packet header.
		/// </summary>
		/// <param name="context">RTMP protocol state.</param>
		/// <param name="lastHeader">Previous header.</param>
		/// <param name="stream">Buffer to be decoded.</param>
		/// <returns>Decoded RTMP header.</returns>
		public static RtmpHeader DecodeHeader(RtmpContext context, RtmpHeader lastHeader, ByteBuffer stream) {
			byte headerByte = stream.Get();
			int headerValue;
			int byteCount = 1;
			if ((headerByte & 0x3f) == 0) {
				// Two byte header
				headerValue = ((int)headerByte & 0xff) << 8 | ((int)stream.Get() & 0xff);
				byteCount = 2;
			} else if ((headerByte & 0x3f) == 1) {
				// Three byte header
				headerValue = ((int)headerByte & 0xff) << 16 | ((int)stream.Get() & 0xff) << 8 | ((int)stream.Get() & 0xff);
				byteCount = 3;
			} else {
				// Single byte header
				headerValue = (int)headerByte & 0xff;
				byteCount = 1;
			}
			byte channelId = DecodeChannelId(headerValue, byteCount);
			byte headerSize = DecodeHeaderSize(headerValue, byteCount);
			RtmpHeader header = new RtmpHeader();
			header.ChannelId = channelId;
			header.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;

			if ((HeaderType)headerSize != HeaderType.HeaderNew && lastHeader == null) {
#if !SILVERLIGHT
				if (log.IsErrorEnabled)
					log.Error(string.Format("Last header null not new, headerSize: {0}, channelId {1}", headerSize, channelId));
#endif
				lastHeader = new RtmpHeader();
				lastHeader.ChannelId = channelId;
				lastHeader.IsTimerRelative = (HeaderType)headerSize != HeaderType.HeaderNew;
			}


#if !SILVERLIGHT
			if (log.IsDebugEnabled)
				log.Debug(__Res.GetString(__Res.Rtmp_DecodeHeader, Enum.GetName(typeof(HeaderType), (HeaderType)headerSize)));
#endif

			switch ((HeaderType)headerSize) {
				case HeaderType.HeaderNew:
					header.Timer = stream.ReadUInt24();// ReadUnsignedMediumInt();
					header.Size = stream.ReadUInt24();// ReadMediumInt();
					header.DataType = stream.Get();
					header.StreamId = stream.ReadReverseInt();
					break;
				case HeaderType.HeaderSameSource:
					header.Timer = stream.ReadUInt24();// ReadUnsignedMediumInt();
					header.Size = stream.ReadUInt24();// ReadMediumInt();
					header.DataType = stream.Get();
					header.StreamId = lastHeader.StreamId;
					break;
				case HeaderType.HeaderTimerChange:
					header.Timer = stream.ReadUInt24();//ReadUnsignedMediumInt();
					header.Size = lastHeader.Size;
					header.DataType = lastHeader.DataType;
					header.StreamId = lastHeader.StreamId;
					break;
				case HeaderType.HeaderContinue:
					header.Timer = lastHeader.Timer;
					header.Size = lastHeader.Size;
					header.DataType = lastHeader.DataType;
					header.StreamId = lastHeader.StreamId;
					header.IsTimerRelative = lastHeader.IsTimerRelative;
					break;
				default:
#if !SILVERLIGHT
					log.Error("Unexpected header size: " + headerSize);
#endif
					return null;
			}
			if (header.Timer >= 0xffffff) {
				//Extended timestamp
				header.Timer = stream.GetInt();
			}

			return header;
		}