/*
- * RTP parser for VP9 payload format (draft version 0) - experimental
+ * RTP parser for VP9 payload format (draft version 02) - experimental
* Copyright (c) 2015 Thomas Volkert <thomas@homer-conferencing.com>
*
* This file is part of Libav.
const uint8_t *buf, int len, uint16_t seq,
int flags)
{
- int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data, has_su_data;
- av_unused int pic_id = 0, non_key_frame = 0;
+ int has_pic_id, has_layer_idc, has_ref_idc, has_ss_data;
+ av_unused int pic_id = 0, non_key_frame = 0, inter_picture_layer_frame;
av_unused int layer_temporal = -1, layer_spatial = -1, layer_quality = -1;
int ref_fields = 0, has_ref_field_ext_pic_id = 0;
int first_fragment, last_fragment;
*
* 0 1 2 3 4 5 6 7
* +-+-+-+-+-+-+-+-+
- * |I|L|F|B|E|V|U|-| (REQUIRED)
+ * |I|P|L|F|B|E|V|-| (REQUIRED)
* +-+-+-+-+-+-+-+-+
*
* I: PictureID present
+ * P: Inter-picture predicted layer frame
* L: Layer indices present
- * F: Reference indices present
+ * F: Flexible mode
* B: Start of VP9 frame
* E: End of picture
* V: Scalability Structure (SS) present
- * U: Scalability Structure Update (SU) present
*/
has_pic_id = !!(buf[0] & 0x80);
- has_layer_idc = !!(buf[0] & 0x40);
- has_ref_idc = !!(buf[0] & 0x20);
- first_fragment = !!(buf[0] & 0x10);
- last_fragment = !!(buf[0] & 0x08);
- has_ss_data = !!(buf[0] & 0x04);
- has_su_data = !!(buf[0] & 0x02);
+ inter_picture_layer_frame = !!(buf[0] & 0x40);
+ has_layer_idc = !!(buf[0] & 0x20);
+ has_ref_idc = !!(buf[0] & 0x10);
+ first_fragment = !!(buf[0] & 0x08);
+ last_fragment = !!(buf[0] & 0x04);
+ has_ss_data = !!(buf[0] & 0x02);
rtp_m = !!(flags & RTP_FLAG_MARKER);
* X: 1 if this layer index has an extended relative Picture ID.
*/
if (has_ss_data) {
- avpriv_report_missing_feature(ctx, "VP9 scalability structure data");
- return AVERROR(ENOSYS);
- }
-
- /*
- * decode the scalability update structure (SU)
- *
- * spec. is tbd
- */
- if (has_su_data) {
- avpriv_report_missing_feature(ctx, "VP9 scalability update structure data");
- return AVERROR(ENOSYS);
+ int n_s, y, g, i;
+ if (len < 1) {
+ av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+ return AVERROR_INVALIDDATA;
+ }
+ n_s = buf[0] >> 5;
+ y = !!(buf[0] & 0x10);
+ g = !!(buf[0] & 0x08);
+ buf++;
+ len--;
+ if (n_s > 0) {
+ avpriv_report_missing_feature(ctx, "VP9 scalability structure with multiple layers");
+ return AVERROR_PATCHWELCOME;
+ }
+ if (y) {
+ if (len < 4 * (n_s + 1)) {
+ av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+ return AVERROR_INVALIDDATA;
+ }
+ for (i = 0; i < n_s + 1; i++) {
+ av_unused int w, h;
+ w = AV_RB16(buf);
+ h = AV_RB16(buf + 2);
+ buf += 4;
+ len -= 4;
+ }
+ }
+ if (g) {
+ int n_g;
+ if (len < 1) {
+ av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+ return AVERROR_INVALIDDATA;
+ }
+ n_g = buf[0];
+ buf++;
+ len--;
+ for (i = 0; i < n_g; i++) {
+ av_unused int t, u, r, j;
+ if (len < 1) {
+ av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+ return AVERROR_INVALIDDATA;
+ }
+ t = buf[0] >> 5;
+ u = !!(buf[0] & 0x10);
+ r = (buf[0] >> 2) & 0x03;
+ buf++;
+ len--;
+ if (len < r) {
+ av_log(ctx, AV_LOG_ERROR, "Too short RTP/VP9 packet\n");
+ return AVERROR_INVALIDDATA;
+ }
+ for (j = 0; j < r; j++) {
+ av_unused int p_diff = buf[0];
+ buf++;
+ len--;
+ }
+ }
+ }
}
/*