171 lines
4.5 KiB
C++
171 lines
4.5 KiB
C++
// RFC7741 RTP Payload Format for VP8 Video
|
|
|
|
#include "rtp-packet.h"
|
|
#include "rtp-profile.h"
|
|
#include "rtp-payload-helper.h"
|
|
#include "rtp-payload-internal.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <errno.h>
|
|
|
|
/*
|
|
0 1 2 3
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|V=2|P|X| CC |M| PT | sequence number |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| timestamp |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| synchronization source (SSRC) identifier |
|
|
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
| contributing source (CSRC) identifiers |
|
|
| .... |
|
|
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
| VP8 payload descriptor (integer #octets) |
|
|
: :
|
|
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| : VP8 payload header (3 octets) |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| VP8 pyld hdr : |
|
|
+-+-+-+-+-+-+-+-+ |
|
|
: Octets 4..N of VP8 payload :
|
|
| |
|
|
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| : OPTIONAL RTP padding |
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
*/
|
|
static int rtp_decode_vp8(void* p, const void* packet, int bytes)
|
|
{
|
|
uint8_t extended_control_bits;
|
|
uint8_t start_of_vp8_partition;
|
|
//uint8_t PID;
|
|
const uint8_t *ptr, *pend;
|
|
struct rtp_packet_t pkt;
|
|
struct rtp_payload_helper_t *helper;
|
|
|
|
helper = (struct rtp_payload_helper_t *)p;
|
|
if (!helper || 0 != rtp_packet_deserialize(&pkt, packet, bytes) || pkt.payloadlen < 1)
|
|
return -EINVAL;
|
|
|
|
rtp_payload_check(helper, &pkt);
|
|
|
|
ptr = (const uint8_t *)pkt.payload;
|
|
pend = ptr + pkt.payloadlen;
|
|
|
|
// VP8 payload descriptor
|
|
extended_control_bits = ptr[0] & 0x80;
|
|
start_of_vp8_partition = ptr[0] & 0x10;
|
|
//PID = ptr[0] & 0x0f;
|
|
ptr++;
|
|
|
|
if (extended_control_bits && ptr < pend)
|
|
{
|
|
/*
|
|
0 1 2 3 4 5 6 7
|
|
+-+-+-+-+-+-+-+-+
|
|
|X|R|N|S|R| PID | (REQUIRED)
|
|
+-+-+-+-+-+-+-+-+
|
|
X: |I|L|T|K| RSV | (OPTIONAL)
|
|
+-+-+-+-+-+-+-+-+
|
|
I: |M| PictureID | (OPTIONAL)
|
|
+-+-+-+-+-+-+-+-+
|
|
| PictureID |
|
|
+-+-+-+-+-+-+-+-+
|
|
L: | TL0PICIDX | (OPTIONAL)
|
|
+-+-+-+-+-+-+-+-+
|
|
T/K:|TID|Y| KEYIDX | (OPTIONAL)
|
|
+-+-+-+-+-+-+-+-+
|
|
*/
|
|
uint8_t pictureid_present;
|
|
uint8_t tl0picidx_present;
|
|
uint8_t tid_present;
|
|
uint8_t keyidx_present;
|
|
|
|
pictureid_present = ptr[0] & 0x80;
|
|
tl0picidx_present = ptr[0] & 0x40;
|
|
tid_present = ptr[0] & 0x20;
|
|
keyidx_present = ptr[0] & 0x10;
|
|
ptr++;
|
|
|
|
if (pictureid_present && ptr < pend)
|
|
{
|
|
uint16_t picture_id;
|
|
picture_id = ptr[0] & 0x7F;
|
|
if ((ptr[0] & 0x80) && ptr + 1 < pend)
|
|
{
|
|
picture_id = (picture_id << 8) | ptr[1];
|
|
ptr++;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
if (tl0picidx_present && ptr < pend)
|
|
{
|
|
// ignore temporal level zero index
|
|
ptr++;
|
|
}
|
|
|
|
if ((tid_present || keyidx_present) && ptr < pend)
|
|
{
|
|
// ignore KEYIDX
|
|
ptr++;
|
|
}
|
|
}
|
|
|
|
if (ptr >= pend)
|
|
{
|
|
assert(0);
|
|
//helper->size = 0;
|
|
helper->lost = 1;
|
|
//helper->flags |= RTP_PAYLOAD_FLAG_PACKET_LOST;
|
|
return -1; // invalid packet
|
|
}
|
|
|
|
// VP8 payload header (3 octets)
|
|
if (start_of_vp8_partition)
|
|
{
|
|
/*
|
|
0 1 2 3 4 5 6 7
|
|
+-+-+-+-+-+-+-+-+
|
|
|Size0|H| VER |P|
|
|
+-+-+-+-+-+-+-+-+
|
|
| Size1 |
|
|
+-+-+-+-+-+-+-+-+
|
|
| Size2 |
|
|
+-+-+-+-+-+-+-+-+
|
|
*/
|
|
// P: Inverse key frame flag. When set to 0, the current frame is a key
|
|
// frame. When set to 1, the current frame is an interframe.
|
|
// Defined in [RFC6386]
|
|
//int keyframe;
|
|
//keyframe = ptr[0] & 0x01; // PID == 0
|
|
|
|
// new frame begin
|
|
rtp_payload_onframe(helper);
|
|
}
|
|
|
|
pkt.payload = ptr;
|
|
pkt.payloadlen = (int)(pend - ptr);
|
|
rtp_payload_write(helper, &pkt);
|
|
|
|
if (pkt.rtp.m)
|
|
{
|
|
rtp_payload_onframe(helper);
|
|
}
|
|
|
|
return 1; // packet handled
|
|
}
|
|
|
|
struct rtp_payload_decode_t *rtp_vp8_decode()
|
|
{
|
|
static struct rtp_payload_decode_t unpacker = {
|
|
rtp_payload_helper_create,
|
|
rtp_payload_helper_destroy,
|
|
rtp_decode_vp8,
|
|
};
|
|
|
|
return &unpacker;
|
|
}
|