stream-deploy/ZLM/3rdpart/media-server/librtp/payload/rtp-vp9-unpack.c

218 lines
5.5 KiB
C++

// RTP Payload Format for VP9 Video draft-ietf-payload-vp9-03
#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 |
| .... |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| VP9 payload descriptor (integer #octets) |
: :
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| : VP9 pyld hdr | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
+ |
: Bytes 2..N of VP9 payload :
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| : OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int rtp_decode_vp9(void* p, const void* packet, int bytes)
{
uint8_t pictureid_present;
uint8_t inter_picture_predicted_layer_frame;
uint8_t layer_indices_preset;
uint8_t flex_mode;
uint8_t start_of_layer_frame;
uint8_t end_of_layer_frame;
uint8_t scalability_struct_data_present;
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;
// VP9 payload descriptor
/*
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|I|P|L|F|B|E|V|-| (REQUIRED)
+-+-+-+-+-+-+-+-+
*/
pictureid_present = ptr[0] & 0x80;
inter_picture_predicted_layer_frame = ptr[0] & 0x40;
layer_indices_preset = ptr[0] & 0x20;
flex_mode = ptr[0] & 0x10;
start_of_layer_frame = ptr[0] & 0x08;
end_of_layer_frame = ptr[0] & 0x04;
scalability_struct_data_present = ptr[0] & 0x02;
ptr++;
if (pictureid_present && ptr < pend)
{
// +-+-+-+-+-+-+-+-+
// I: |M| PICTURE ID | (RECOMMENDED)
// +-+-+-+-+-+-+-+-+
// M: | EXTENDED PID | (RECOMMENDED)
// +-+-+-+-+-+-+-+-+
//uint16_t picture_id;
//picture_id = ptr[0] & 0x7F;
if ((ptr[0] & 0x80) && ptr + 1 < pend)
{
//picture_id = (ptr[0] << 8) | ptr[1];
ptr++;
}
ptr++;
}
if (layer_indices_preset && ptr < pend)
{
// +-+-+-+-+-+-+-+-+
// L: | T | U | S | D | (CONDITIONALLY RECOMMENDED)
// +-+-+-+-+-+-+-+-+
// | TL0PICIDX | (CONDITIONALLY REQUIRED)
// +-+-+-+-+-+-+-+-+
// ignore Layer indices
if (0 == flex_mode)
ptr++; // TL0PICIDX
ptr++;
}
if (inter_picture_predicted_layer_frame && flex_mode && ptr < pend)
{
// +-+-+-+-+-+-+-+-+ -\
// P,F: | P_DIFF |N| (CONDITIONALLY REQUIRED) - up to 3 times
// +-+-+-+-+-+-+-+-+ -/
// ignore Reference indices
if (ptr[0] & 0x01)
{
if ((ptr[1] & 0x01) && ptr + 1 < pend)
ptr++;
ptr++;
}
ptr++;
}
if (scalability_struct_data_present && ptr < pend)
{
/*
+-+-+-+-+-+-+-+-+
V: | N_S |Y|G|-|-|-|
+-+-+-+-+-+-+-+-+ -\
Y: | WIDTH | (OPTIONAL) .
+ + .
| | (OPTIONAL) .
+-+-+-+-+-+-+-+-+ . - N_S + 1 times
| HEIGHT | (OPTIONAL) .
+ + .
| | (OPTIONAL) .
+-+-+-+-+-+-+-+-+ -/ -\
G: | N_G | (OPTIONAL)
+-+-+-+-+-+-+-+-+ -\
N_G:| T |U| R |-|-| (OPTIONAL) .
+-+-+-+-+-+-+-+-+ -\ . - N_G times
| P_DIFF | (OPTIONAL) . - R times .
+-+-+-+-+-+-+-+-+ -/ -/
*/
uint8_t N_S, Y, G;
N_S = ((ptr[0] >> 5) & 0x07) + 1;
Y = ptr[0] & 0x10;
G = ptr[0] & 0x08;
ptr++;
if (Y)
{
ptr += N_S * 4;
}
if (G && ptr < pend)
{
uint8_t i;
uint8_t N_G = ptr[0];
ptr++;
for (i = 0; i < N_G && ptr < pend; i++)
{
uint8_t j;
uint8_t R;
R = (ptr[0] >> 2) & 0x03;
ptr++;
for (j = 0; j < R && ptr < pend; j++)
{
// ignore P_DIFF
ptr++;
}
}
}
}
if (ptr >= pend)
{
assert(0);
//helper->size = 0;
helper->lost = 1;
//helper->flags |= RTP_PAYLOAD_FLAG_PACKET_LOST;
return -1; // invalid packet
}
if (start_of_layer_frame)
{
// 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_vp9_decode()
{
static struct rtp_payload_decode_t unpacker = {
rtp_payload_helper_create,
rtp_payload_helper_destroy,
rtp_decode_vp9,
};
return &unpacker;
}