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; }