static struct rtmp_packet_t* rtmp_packet_parse(struct rtmp_t* rtmp, const uint8_t* buffer)
{
	uint8_t fmt = 0;
	uint32_t cid = 0;
	struct rtmp_packet_t* packet;
	
	// chunk base header
	buffer += rtmp_chunk_basic_header_read(buffer, &fmt, &cid);

	// load previous header
	packet = rtmp_packet_find(rtmp, cid);
	if (NULL == packet)
	{
		if (RTMP_CHUNK_TYPE_0 != fmt && RTMP_CHUNK_TYPE_1 != fmt)
			return NULL; // don't know stream length

		packet = rtmp_packet_create(rtmp, cid);
		if (NULL == packet)
			return NULL;
	}

	// chunk message header
	packet->header.cid = cid;
	packet->header.fmt = fmt;
	rtmp_chunk_message_header_read(buffer, &packet->header);

	return packet;
}
static struct rtmp_packet_t* rtmp_packet_create(struct rtmp_t* rtmp, uint32_t cid)
{
	uint32_t i;
	struct rtmp_packet_t* pkt;

	// The protocol supports up to 65597 streams with IDs 3-65599
	assert(cid <= 65535 + 64 && cid >= 2 /* Protocol Control Messages */);
	assert(NULL == rtmp_packet_find(rtmp, cid));
	for (i = 0; i < N_CHUNK_STREAM; i++)
	{
		pkt = rtmp->in_packets + ((i + cid) % N_CHUNK_STREAM);
		if (0 == pkt->header.cid)
			return pkt;
	}
	return NULL;
}
static const struct rtmp_chunk_header_t* rtmp_chunk_header_zip(struct rtmp_t* rtmp, const struct rtmp_chunk_header_t* header)
{
	struct rtmp_packet_t* pkt; // previous saved chunk header
	struct rtmp_chunk_header_t h;

	assert(0 != header->cid && 1 != header->cid);
	assert(RTMP_CHUNK_TYPE_0 == header->fmt || RTMP_CHUNK_TYPE_1 == header->fmt);
	
	memcpy(&h, header, sizeof(h));

	// find previous chunk header
	pkt = rtmp_packet_find(rtmp, h.cid);
	if (NULL == pkt)
	{
		//pkt = rtmp_packet_create(rtmp, h.cid);
		//if (NULL == pkt)
		//	return NULL; // too many chunk stream id
		assert(0);
		return NULL; // can't find chunk stream id 
	}

	h.fmt = RTMP_CHUNK_TYPE_0;
	if (RTMP_CHUNK_TYPE_0 != header->fmt /* enable compress */
		&& header->cid == pkt->header.cid /* not the first packet */
		&& header->timestamp >= pkt->clock /* timestamp wrap */
		&& header->timestamp - pkt->clock < 0xFFFFFF /* timestamp delta < 1 << 24 */
		&& header->stream_id == pkt->header.stream_id /* message stream id */)
	{
		h.fmt = RTMP_CHUNK_TYPE_1;
		h.timestamp -= pkt->clock; // timestamp delta

		if (header->type == pkt->header.type && header->length == pkt->header.length)
		{
			h.fmt = RTMP_CHUNK_TYPE_2;
			if (h.timestamp == pkt->header.timestamp)
				h.fmt = RTMP_CHUNK_TYPE_3;
		}
	}

	memcpy(&pkt->header, &h, sizeof(h));
	pkt->clock = header->timestamp; // save timestamp
	return &pkt->header;
}