1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include "libavutil/avassert.h" 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "cbs.h" 22cabdff1aSopenharmony_ci#include "cbs_internal.h" 23cabdff1aSopenharmony_ci#include "cbs_vp9.h" 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_cistatic int cbs_vp9_read_s(CodedBitstreamContext *ctx, GetBitContext *gbc, 27cabdff1aSopenharmony_ci int width, const char *name, 28cabdff1aSopenharmony_ci const int *subscripts, int32_t *write_to) 29cabdff1aSopenharmony_ci{ 30cabdff1aSopenharmony_ci uint32_t magnitude; 31cabdff1aSopenharmony_ci int position, sign; 32cabdff1aSopenharmony_ci int32_t value; 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_ci if (ctx->trace_enable) 35cabdff1aSopenharmony_ci position = get_bits_count(gbc); 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_ci if (get_bits_left(gbc) < width + 1) { 38cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at " 39cabdff1aSopenharmony_ci "%s: bitstream ended.\n", name); 40cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 41cabdff1aSopenharmony_ci } 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci magnitude = get_bits(gbc, width); 44cabdff1aSopenharmony_ci sign = get_bits1(gbc); 45cabdff1aSopenharmony_ci value = sign ? -(int32_t)magnitude : magnitude; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci if (ctx->trace_enable) { 48cabdff1aSopenharmony_ci char bits[33]; 49cabdff1aSopenharmony_ci int i; 50cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 51cabdff1aSopenharmony_ci bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0'; 52cabdff1aSopenharmony_ci bits[i] = sign ? '1' : '0'; 53cabdff1aSopenharmony_ci bits[i + 1] = 0; 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, position, name, subscripts, 56cabdff1aSopenharmony_ci bits, value); 57cabdff1aSopenharmony_ci } 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci *write_to = value; 60cabdff1aSopenharmony_ci return 0; 61cabdff1aSopenharmony_ci} 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_cistatic int cbs_vp9_write_s(CodedBitstreamContext *ctx, PutBitContext *pbc, 64cabdff1aSopenharmony_ci int width, const char *name, 65cabdff1aSopenharmony_ci const int *subscripts, int32_t value) 66cabdff1aSopenharmony_ci{ 67cabdff1aSopenharmony_ci uint32_t magnitude; 68cabdff1aSopenharmony_ci int sign; 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci if (put_bits_left(pbc) < width + 1) 71cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci sign = value < 0; 74cabdff1aSopenharmony_ci magnitude = sign ? -value : value; 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci if (ctx->trace_enable) { 77cabdff1aSopenharmony_ci char bits[33]; 78cabdff1aSopenharmony_ci int i; 79cabdff1aSopenharmony_ci for (i = 0; i < width; i++) 80cabdff1aSopenharmony_ci bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0'; 81cabdff1aSopenharmony_ci bits[i] = sign ? '1' : '0'; 82cabdff1aSopenharmony_ci bits[i + 1] = 0; 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), 85cabdff1aSopenharmony_ci name, subscripts, bits, value); 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci put_bits(pbc, width, magnitude); 89cabdff1aSopenharmony_ci put_bits(pbc, 1, sign); 90cabdff1aSopenharmony_ci 91cabdff1aSopenharmony_ci return 0; 92cabdff1aSopenharmony_ci} 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_cistatic int cbs_vp9_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc, 95cabdff1aSopenharmony_ci uint32_t range_min, uint32_t range_max, 96cabdff1aSopenharmony_ci const char *name, uint32_t *write_to) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci uint32_t value; 99cabdff1aSopenharmony_ci int position, i; 100cabdff1aSopenharmony_ci char bits[8]; 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci av_assert0(range_min <= range_max && range_max - range_min < sizeof(bits) - 1); 103cabdff1aSopenharmony_ci if (ctx->trace_enable) 104cabdff1aSopenharmony_ci position = get_bits_count(gbc); 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci for (i = 0, value = range_min; value < range_max;) { 107cabdff1aSopenharmony_ci if (get_bits_left(gbc) < 1) { 108cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid increment value at " 109cabdff1aSopenharmony_ci "%s: bitstream ended.\n", name); 110cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci if (get_bits1(gbc)) { 113cabdff1aSopenharmony_ci bits[i++] = '1'; 114cabdff1aSopenharmony_ci ++value; 115cabdff1aSopenharmony_ci } else { 116cabdff1aSopenharmony_ci bits[i++] = '0'; 117cabdff1aSopenharmony_ci break; 118cabdff1aSopenharmony_ci } 119cabdff1aSopenharmony_ci } 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci if (ctx->trace_enable) { 122cabdff1aSopenharmony_ci bits[i] = 0; 123cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, position, name, NULL, bits, value); 124cabdff1aSopenharmony_ci } 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci *write_to = value; 127cabdff1aSopenharmony_ci return 0; 128cabdff1aSopenharmony_ci} 129cabdff1aSopenharmony_ci 130cabdff1aSopenharmony_cistatic int cbs_vp9_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc, 131cabdff1aSopenharmony_ci uint32_t range_min, uint32_t range_max, 132cabdff1aSopenharmony_ci const char *name, uint32_t value) 133cabdff1aSopenharmony_ci{ 134cabdff1aSopenharmony_ci int len; 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci av_assert0(range_min <= range_max && range_max - range_min < 8); 137cabdff1aSopenharmony_ci if (value < range_min || value > range_max) { 138cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: " 139cabdff1aSopenharmony_ci "%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n", 140cabdff1aSopenharmony_ci name, value, range_min, range_max); 141cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci if (value == range_max) 145cabdff1aSopenharmony_ci len = range_max - range_min; 146cabdff1aSopenharmony_ci else 147cabdff1aSopenharmony_ci len = value - range_min + 1; 148cabdff1aSopenharmony_ci if (put_bits_left(pbc) < len) 149cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci if (ctx->trace_enable) { 152cabdff1aSopenharmony_ci char bits[8]; 153cabdff1aSopenharmony_ci int i; 154cabdff1aSopenharmony_ci for (i = 0; i < len; i++) { 155cabdff1aSopenharmony_ci if (range_min + i == value) 156cabdff1aSopenharmony_ci bits[i] = '0'; 157cabdff1aSopenharmony_ci else 158cabdff1aSopenharmony_ci bits[i] = '1'; 159cabdff1aSopenharmony_ci } 160cabdff1aSopenharmony_ci bits[i] = 0; 161cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), 162cabdff1aSopenharmony_ci name, NULL, bits, value); 163cabdff1aSopenharmony_ci } 164cabdff1aSopenharmony_ci 165cabdff1aSopenharmony_ci if (len > 0) 166cabdff1aSopenharmony_ci put_bits(pbc, len, (1 << len) - 1 - (value != range_max)); 167cabdff1aSopenharmony_ci 168cabdff1aSopenharmony_ci return 0; 169cabdff1aSopenharmony_ci} 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_cistatic int cbs_vp9_read_le(CodedBitstreamContext *ctx, GetBitContext *gbc, 172cabdff1aSopenharmony_ci int width, const char *name, 173cabdff1aSopenharmony_ci const int *subscripts, uint32_t *write_to) 174cabdff1aSopenharmony_ci{ 175cabdff1aSopenharmony_ci uint32_t value; 176cabdff1aSopenharmony_ci int position, b; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci av_assert0(width % 8 == 0); 179cabdff1aSopenharmony_ci 180cabdff1aSopenharmony_ci if (ctx->trace_enable) 181cabdff1aSopenharmony_ci position = get_bits_count(gbc); 182cabdff1aSopenharmony_ci 183cabdff1aSopenharmony_ci if (get_bits_left(gbc) < width) { 184cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid le value at " 185cabdff1aSopenharmony_ci "%s: bitstream ended.\n", name); 186cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci value = 0; 190cabdff1aSopenharmony_ci for (b = 0; b < width; b += 8) 191cabdff1aSopenharmony_ci value |= get_bits(gbc, 8) << b; 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci if (ctx->trace_enable) { 194cabdff1aSopenharmony_ci char bits[33]; 195cabdff1aSopenharmony_ci int i; 196cabdff1aSopenharmony_ci for (b = 0; b < width; b += 8) 197cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) 198cabdff1aSopenharmony_ci bits[b + i] = value >> (b + i) & 1 ? '1' : '0'; 199cabdff1aSopenharmony_ci bits[b] = 0; 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, position, name, subscripts, 202cabdff1aSopenharmony_ci bits, value); 203cabdff1aSopenharmony_ci } 204cabdff1aSopenharmony_ci 205cabdff1aSopenharmony_ci *write_to = value; 206cabdff1aSopenharmony_ci return 0; 207cabdff1aSopenharmony_ci} 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_cistatic int cbs_vp9_write_le(CodedBitstreamContext *ctx, PutBitContext *pbc, 210cabdff1aSopenharmony_ci int width, const char *name, 211cabdff1aSopenharmony_ci const int *subscripts, uint32_t value) 212cabdff1aSopenharmony_ci{ 213cabdff1aSopenharmony_ci int b; 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci av_assert0(width % 8 == 0); 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci if (put_bits_left(pbc) < width) 218cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 219cabdff1aSopenharmony_ci 220cabdff1aSopenharmony_ci if (ctx->trace_enable) { 221cabdff1aSopenharmony_ci char bits[33]; 222cabdff1aSopenharmony_ci int i; 223cabdff1aSopenharmony_ci for (b = 0; b < width; b += 8) 224cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) 225cabdff1aSopenharmony_ci bits[b + i] = value >> (b + i) & 1 ? '1' : '0'; 226cabdff1aSopenharmony_ci bits[b] = 0; 227cabdff1aSopenharmony_ci 228cabdff1aSopenharmony_ci ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), 229cabdff1aSopenharmony_ci name, subscripts, bits, value); 230cabdff1aSopenharmony_ci } 231cabdff1aSopenharmony_ci 232cabdff1aSopenharmony_ci for (b = 0; b < width; b += 8) 233cabdff1aSopenharmony_ci put_bits(pbc, 8, value >> b & 0xff); 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci return 0; 236cabdff1aSopenharmony_ci} 237cabdff1aSopenharmony_ci 238cabdff1aSopenharmony_ci#define HEADER(name) do { \ 239cabdff1aSopenharmony_ci ff_cbs_trace_header(ctx, name); \ 240cabdff1aSopenharmony_ci } while (0) 241cabdff1aSopenharmony_ci 242cabdff1aSopenharmony_ci#define CHECK(call) do { \ 243cabdff1aSopenharmony_ci err = (call); \ 244cabdff1aSopenharmony_ci if (err < 0) \ 245cabdff1aSopenharmony_ci return err; \ 246cabdff1aSopenharmony_ci } while (0) 247cabdff1aSopenharmony_ci 248cabdff1aSopenharmony_ci#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name 249cabdff1aSopenharmony_ci#define FUNC_VP9(rw, name) FUNC_NAME(rw, vp9, name) 250cabdff1aSopenharmony_ci#define FUNC(name) FUNC_VP9(READWRITE, name) 251cabdff1aSopenharmony_ci 252cabdff1aSopenharmony_ci#define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL) 253cabdff1aSopenharmony_ci 254cabdff1aSopenharmony_ci#define f(width, name) \ 255cabdff1aSopenharmony_ci xf(width, name, current->name, 0, ) 256cabdff1aSopenharmony_ci#define s(width, name) \ 257cabdff1aSopenharmony_ci xs(width, name, current->name, 0, ) 258cabdff1aSopenharmony_ci#define fs(width, name, subs, ...) \ 259cabdff1aSopenharmony_ci xf(width, name, current->name, subs, __VA_ARGS__) 260cabdff1aSopenharmony_ci#define ss(width, name, subs, ...) \ 261cabdff1aSopenharmony_ci xs(width, name, current->name, subs, __VA_ARGS__) 262cabdff1aSopenharmony_ci 263cabdff1aSopenharmony_ci#define READ 264cabdff1aSopenharmony_ci#define READWRITE read 265cabdff1aSopenharmony_ci#define RWContext GetBitContext 266cabdff1aSopenharmony_ci 267cabdff1aSopenharmony_ci#define xf(width, name, var, subs, ...) do { \ 268cabdff1aSopenharmony_ci uint32_t value; \ 269cabdff1aSopenharmony_ci CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ 270cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), \ 271cabdff1aSopenharmony_ci &value, 0, (1 << width) - 1)); \ 272cabdff1aSopenharmony_ci var = value; \ 273cabdff1aSopenharmony_ci } while (0) 274cabdff1aSopenharmony_ci#define xs(width, name, var, subs, ...) do { \ 275cabdff1aSopenharmony_ci int32_t value; \ 276cabdff1aSopenharmony_ci CHECK(cbs_vp9_read_s(ctx, rw, width, #name, \ 277cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), &value)); \ 278cabdff1aSopenharmony_ci var = value; \ 279cabdff1aSopenharmony_ci } while (0) 280cabdff1aSopenharmony_ci 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci#define increment(name, min, max) do { \ 283cabdff1aSopenharmony_ci uint32_t value; \ 284cabdff1aSopenharmony_ci CHECK(cbs_vp9_read_increment(ctx, rw, min, max, #name, &value)); \ 285cabdff1aSopenharmony_ci current->name = value; \ 286cabdff1aSopenharmony_ci } while (0) 287cabdff1aSopenharmony_ci 288cabdff1aSopenharmony_ci#define fle(width, name, subs, ...) do { \ 289cabdff1aSopenharmony_ci CHECK(cbs_vp9_read_le(ctx, rw, width, #name, \ 290cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), ¤t->name)); \ 291cabdff1aSopenharmony_ci } while (0) 292cabdff1aSopenharmony_ci 293cabdff1aSopenharmony_ci#define delta_q(name) do { \ 294cabdff1aSopenharmony_ci uint8_t delta_coded; \ 295cabdff1aSopenharmony_ci int8_t delta_q; \ 296cabdff1aSopenharmony_ci xf(1, name.delta_coded, delta_coded, 0, ); \ 297cabdff1aSopenharmony_ci if (delta_coded) \ 298cabdff1aSopenharmony_ci xs(4, name.delta_q, delta_q, 0, ); \ 299cabdff1aSopenharmony_ci else \ 300cabdff1aSopenharmony_ci delta_q = 0; \ 301cabdff1aSopenharmony_ci current->name = delta_q; \ 302cabdff1aSopenharmony_ci } while (0) 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci#define prob(name, subs, ...) do { \ 305cabdff1aSopenharmony_ci uint8_t prob_coded; \ 306cabdff1aSopenharmony_ci uint8_t prob; \ 307cabdff1aSopenharmony_ci xf(1, name.prob_coded, prob_coded, subs, __VA_ARGS__); \ 308cabdff1aSopenharmony_ci if (prob_coded) \ 309cabdff1aSopenharmony_ci xf(8, name.prob, prob, subs, __VA_ARGS__); \ 310cabdff1aSopenharmony_ci else \ 311cabdff1aSopenharmony_ci prob = 255; \ 312cabdff1aSopenharmony_ci current->name = prob; \ 313cabdff1aSopenharmony_ci } while (0) 314cabdff1aSopenharmony_ci 315cabdff1aSopenharmony_ci#define fixed(width, name, value) do { \ 316cabdff1aSopenharmony_ci av_unused uint32_t fixed_value; \ 317cabdff1aSopenharmony_ci CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \ 318cabdff1aSopenharmony_ci 0, &fixed_value, value, value)); \ 319cabdff1aSopenharmony_ci } while (0) 320cabdff1aSopenharmony_ci 321cabdff1aSopenharmony_ci#define infer(name, value) do { \ 322cabdff1aSopenharmony_ci current->name = value; \ 323cabdff1aSopenharmony_ci } while (0) 324cabdff1aSopenharmony_ci 325cabdff1aSopenharmony_ci#define byte_alignment(rw) (get_bits_count(rw) % 8) 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci#include "cbs_vp9_syntax_template.c" 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci#undef READ 330cabdff1aSopenharmony_ci#undef READWRITE 331cabdff1aSopenharmony_ci#undef RWContext 332cabdff1aSopenharmony_ci#undef xf 333cabdff1aSopenharmony_ci#undef xs 334cabdff1aSopenharmony_ci#undef increment 335cabdff1aSopenharmony_ci#undef fle 336cabdff1aSopenharmony_ci#undef delta_q 337cabdff1aSopenharmony_ci#undef prob 338cabdff1aSopenharmony_ci#undef fixed 339cabdff1aSopenharmony_ci#undef infer 340cabdff1aSopenharmony_ci#undef byte_alignment 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci 343cabdff1aSopenharmony_ci#define WRITE 344cabdff1aSopenharmony_ci#define READWRITE write 345cabdff1aSopenharmony_ci#define RWContext PutBitContext 346cabdff1aSopenharmony_ci 347cabdff1aSopenharmony_ci#define xf(width, name, var, subs, ...) do { \ 348cabdff1aSopenharmony_ci CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ 349cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), \ 350cabdff1aSopenharmony_ci var, 0, (1 << width) - 1)); \ 351cabdff1aSopenharmony_ci } while (0) 352cabdff1aSopenharmony_ci#define xs(width, name, var, subs, ...) do { \ 353cabdff1aSopenharmony_ci CHECK(cbs_vp9_write_s(ctx, rw, width, #name, \ 354cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), var)); \ 355cabdff1aSopenharmony_ci } while (0) 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci#define increment(name, min, max) do { \ 358cabdff1aSopenharmony_ci CHECK(cbs_vp9_write_increment(ctx, rw, min, max, #name, current->name)); \ 359cabdff1aSopenharmony_ci } while (0) 360cabdff1aSopenharmony_ci 361cabdff1aSopenharmony_ci#define fle(width, name, subs, ...) do { \ 362cabdff1aSopenharmony_ci CHECK(cbs_vp9_write_le(ctx, rw, width, #name, \ 363cabdff1aSopenharmony_ci SUBSCRIPTS(subs, __VA_ARGS__), current->name)); \ 364cabdff1aSopenharmony_ci } while (0) 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_ci#define delta_q(name) do { \ 367cabdff1aSopenharmony_ci xf(1, name.delta_coded, !!current->name, 0, ); \ 368cabdff1aSopenharmony_ci if (current->name) \ 369cabdff1aSopenharmony_ci xs(4, name.delta_q, current->name, 0, ); \ 370cabdff1aSopenharmony_ci } while (0) 371cabdff1aSopenharmony_ci 372cabdff1aSopenharmony_ci#define prob(name, subs, ...) do { \ 373cabdff1aSopenharmony_ci xf(1, name.prob_coded, current->name != 255, subs, __VA_ARGS__); \ 374cabdff1aSopenharmony_ci if (current->name != 255) \ 375cabdff1aSopenharmony_ci xf(8, name.prob, current->name, subs, __VA_ARGS__); \ 376cabdff1aSopenharmony_ci } while (0) 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_ci#define fixed(width, name, value) do { \ 379cabdff1aSopenharmony_ci CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \ 380cabdff1aSopenharmony_ci 0, value, value, value)); \ 381cabdff1aSopenharmony_ci } while (0) 382cabdff1aSopenharmony_ci 383cabdff1aSopenharmony_ci#define infer(name, value) do { \ 384cabdff1aSopenharmony_ci if (current->name != (value)) { \ 385cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_WARNING, "Warning: " \ 386cabdff1aSopenharmony_ci "%s does not match inferred value: " \ 387cabdff1aSopenharmony_ci "%"PRId64", but should be %"PRId64".\n", \ 388cabdff1aSopenharmony_ci #name, (int64_t)current->name, (int64_t)(value)); \ 389cabdff1aSopenharmony_ci } \ 390cabdff1aSopenharmony_ci } while (0) 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci#define byte_alignment(rw) (put_bits_count(rw) % 8) 393cabdff1aSopenharmony_ci 394cabdff1aSopenharmony_ci#include "cbs_vp9_syntax_template.c" 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci#undef WRITE 397cabdff1aSopenharmony_ci#undef READWRITE 398cabdff1aSopenharmony_ci#undef RWContext 399cabdff1aSopenharmony_ci#undef xf 400cabdff1aSopenharmony_ci#undef xs 401cabdff1aSopenharmony_ci#undef increment 402cabdff1aSopenharmony_ci#undef fle 403cabdff1aSopenharmony_ci#undef delta_q 404cabdff1aSopenharmony_ci#undef prob 405cabdff1aSopenharmony_ci#undef fixed 406cabdff1aSopenharmony_ci#undef infer 407cabdff1aSopenharmony_ci#undef byte_alignment 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci 410cabdff1aSopenharmony_cistatic int cbs_vp9_split_fragment(CodedBitstreamContext *ctx, 411cabdff1aSopenharmony_ci CodedBitstreamFragment *frag, 412cabdff1aSopenharmony_ci int header) 413cabdff1aSopenharmony_ci{ 414cabdff1aSopenharmony_ci uint8_t superframe_header; 415cabdff1aSopenharmony_ci int err; 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci if (frag->data_size == 0) 418cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci // Last byte in the packet. 421cabdff1aSopenharmony_ci superframe_header = frag->data[frag->data_size - 1]; 422cabdff1aSopenharmony_ci 423cabdff1aSopenharmony_ci if ((superframe_header & 0xe0) == 0xc0) { 424cabdff1aSopenharmony_ci VP9RawSuperframeIndex sfi; 425cabdff1aSopenharmony_ci GetBitContext gbc; 426cabdff1aSopenharmony_ci size_t index_size, pos; 427cabdff1aSopenharmony_ci int i; 428cabdff1aSopenharmony_ci 429cabdff1aSopenharmony_ci index_size = 2 + (((superframe_header & 0x18) >> 3) + 1) * 430cabdff1aSopenharmony_ci ((superframe_header & 0x07) + 1); 431cabdff1aSopenharmony_ci 432cabdff1aSopenharmony_ci if (index_size > frag->data_size) 433cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 434cabdff1aSopenharmony_ci 435cabdff1aSopenharmony_ci err = init_get_bits(&gbc, frag->data + frag->data_size - index_size, 436cabdff1aSopenharmony_ci 8 * index_size); 437cabdff1aSopenharmony_ci if (err < 0) 438cabdff1aSopenharmony_ci return err; 439cabdff1aSopenharmony_ci 440cabdff1aSopenharmony_ci err = cbs_vp9_read_superframe_index(ctx, &gbc, &sfi); 441cabdff1aSopenharmony_ci if (err < 0) 442cabdff1aSopenharmony_ci return err; 443cabdff1aSopenharmony_ci 444cabdff1aSopenharmony_ci pos = 0; 445cabdff1aSopenharmony_ci for (i = 0; i <= sfi.frames_in_superframe_minus_1; i++) { 446cabdff1aSopenharmony_ci if (pos + sfi.frame_sizes[i] + index_size > frag->data_size) { 447cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Frame %d too large " 448cabdff1aSopenharmony_ci "in superframe: %"PRIu32" bytes.\n", 449cabdff1aSopenharmony_ci i, sfi.frame_sizes[i]); 450cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 451cabdff1aSopenharmony_ci } 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci err = ff_cbs_append_unit_data(frag, 0, 454cabdff1aSopenharmony_ci frag->data + pos, 455cabdff1aSopenharmony_ci sfi.frame_sizes[i], 456cabdff1aSopenharmony_ci frag->data_ref); 457cabdff1aSopenharmony_ci if (err < 0) 458cabdff1aSopenharmony_ci return err; 459cabdff1aSopenharmony_ci 460cabdff1aSopenharmony_ci pos += sfi.frame_sizes[i]; 461cabdff1aSopenharmony_ci } 462cabdff1aSopenharmony_ci if (pos + index_size != frag->data_size) { 463cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_WARNING, "Extra padding at " 464cabdff1aSopenharmony_ci "end of superframe: %"SIZE_SPECIFIER" bytes.\n", 465cabdff1aSopenharmony_ci frag->data_size - (pos + index_size)); 466cabdff1aSopenharmony_ci } 467cabdff1aSopenharmony_ci 468cabdff1aSopenharmony_ci return 0; 469cabdff1aSopenharmony_ci 470cabdff1aSopenharmony_ci } else { 471cabdff1aSopenharmony_ci err = ff_cbs_append_unit_data(frag, 0, 472cabdff1aSopenharmony_ci frag->data, frag->data_size, 473cabdff1aSopenharmony_ci frag->data_ref); 474cabdff1aSopenharmony_ci if (err < 0) 475cabdff1aSopenharmony_ci return err; 476cabdff1aSopenharmony_ci } 477cabdff1aSopenharmony_ci 478cabdff1aSopenharmony_ci return 0; 479cabdff1aSopenharmony_ci} 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_cistatic int cbs_vp9_read_unit(CodedBitstreamContext *ctx, 482cabdff1aSopenharmony_ci CodedBitstreamUnit *unit) 483cabdff1aSopenharmony_ci{ 484cabdff1aSopenharmony_ci VP9RawFrame *frame; 485cabdff1aSopenharmony_ci GetBitContext gbc; 486cabdff1aSopenharmony_ci int err, pos; 487cabdff1aSopenharmony_ci 488cabdff1aSopenharmony_ci err = init_get_bits(&gbc, unit->data, 8 * unit->data_size); 489cabdff1aSopenharmony_ci if (err < 0) 490cabdff1aSopenharmony_ci return err; 491cabdff1aSopenharmony_ci 492cabdff1aSopenharmony_ci err = ff_cbs_alloc_unit_content2(ctx, unit); 493cabdff1aSopenharmony_ci if (err < 0) 494cabdff1aSopenharmony_ci return err; 495cabdff1aSopenharmony_ci frame = unit->content; 496cabdff1aSopenharmony_ci 497cabdff1aSopenharmony_ci err = cbs_vp9_read_frame(ctx, &gbc, frame); 498cabdff1aSopenharmony_ci if (err < 0) 499cabdff1aSopenharmony_ci return err; 500cabdff1aSopenharmony_ci 501cabdff1aSopenharmony_ci pos = get_bits_count(&gbc); 502cabdff1aSopenharmony_ci av_assert0(pos % 8 == 0); 503cabdff1aSopenharmony_ci pos /= 8; 504cabdff1aSopenharmony_ci av_assert0(pos <= unit->data_size); 505cabdff1aSopenharmony_ci 506cabdff1aSopenharmony_ci if (pos == unit->data_size) { 507cabdff1aSopenharmony_ci // No data (e.g. a show-existing-frame frame). 508cabdff1aSopenharmony_ci } else { 509cabdff1aSopenharmony_ci frame->data_ref = av_buffer_ref(unit->data_ref); 510cabdff1aSopenharmony_ci if (!frame->data_ref) 511cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 512cabdff1aSopenharmony_ci 513cabdff1aSopenharmony_ci frame->data = unit->data + pos; 514cabdff1aSopenharmony_ci frame->data_size = unit->data_size - pos; 515cabdff1aSopenharmony_ci } 516cabdff1aSopenharmony_ci 517cabdff1aSopenharmony_ci return 0; 518cabdff1aSopenharmony_ci} 519cabdff1aSopenharmony_ci 520cabdff1aSopenharmony_cistatic int cbs_vp9_write_unit(CodedBitstreamContext *ctx, 521cabdff1aSopenharmony_ci CodedBitstreamUnit *unit, 522cabdff1aSopenharmony_ci PutBitContext *pbc) 523cabdff1aSopenharmony_ci{ 524cabdff1aSopenharmony_ci VP9RawFrame *frame = unit->content; 525cabdff1aSopenharmony_ci int err; 526cabdff1aSopenharmony_ci 527cabdff1aSopenharmony_ci err = cbs_vp9_write_frame(ctx, pbc, frame); 528cabdff1aSopenharmony_ci if (err < 0) 529cabdff1aSopenharmony_ci return err; 530cabdff1aSopenharmony_ci 531cabdff1aSopenharmony_ci // Frame must be byte-aligned. 532cabdff1aSopenharmony_ci av_assert0(put_bits_count(pbc) % 8 == 0); 533cabdff1aSopenharmony_ci 534cabdff1aSopenharmony_ci if (frame->data) { 535cabdff1aSopenharmony_ci if (frame->data_size > put_bits_left(pbc) / 8) 536cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 537cabdff1aSopenharmony_ci 538cabdff1aSopenharmony_ci flush_put_bits(pbc); 539cabdff1aSopenharmony_ci memcpy(put_bits_ptr(pbc), frame->data, frame->data_size); 540cabdff1aSopenharmony_ci skip_put_bytes(pbc, frame->data_size); 541cabdff1aSopenharmony_ci } 542cabdff1aSopenharmony_ci 543cabdff1aSopenharmony_ci return 0; 544cabdff1aSopenharmony_ci} 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_cistatic int cbs_vp9_assemble_fragment(CodedBitstreamContext *ctx, 547cabdff1aSopenharmony_ci CodedBitstreamFragment *frag) 548cabdff1aSopenharmony_ci{ 549cabdff1aSopenharmony_ci int err; 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_ci if (frag->nb_units == 1) { 552cabdff1aSopenharmony_ci // Output is just the content of the single frame. 553cabdff1aSopenharmony_ci 554cabdff1aSopenharmony_ci CodedBitstreamUnit *frame = &frag->units[0]; 555cabdff1aSopenharmony_ci 556cabdff1aSopenharmony_ci frag->data_ref = av_buffer_ref(frame->data_ref); 557cabdff1aSopenharmony_ci if (!frag->data_ref) 558cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 559cabdff1aSopenharmony_ci 560cabdff1aSopenharmony_ci frag->data = frame->data; 561cabdff1aSopenharmony_ci frag->data_size = frame->data_size; 562cabdff1aSopenharmony_ci 563cabdff1aSopenharmony_ci } else { 564cabdff1aSopenharmony_ci // Build superframe out of frames. 565cabdff1aSopenharmony_ci 566cabdff1aSopenharmony_ci VP9RawSuperframeIndex sfi; 567cabdff1aSopenharmony_ci PutBitContext pbc; 568cabdff1aSopenharmony_ci AVBufferRef *ref; 569cabdff1aSopenharmony_ci uint8_t *data; 570cabdff1aSopenharmony_ci size_t size, max, pos; 571cabdff1aSopenharmony_ci int i, size_len; 572cabdff1aSopenharmony_ci 573cabdff1aSopenharmony_ci if (frag->nb_units > 8) { 574cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many frames to " 575cabdff1aSopenharmony_ci "make superframe: %d.\n", frag->nb_units); 576cabdff1aSopenharmony_ci return AVERROR(EINVAL); 577cabdff1aSopenharmony_ci } 578cabdff1aSopenharmony_ci 579cabdff1aSopenharmony_ci max = 0; 580cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) 581cabdff1aSopenharmony_ci if (max < frag->units[i].data_size) 582cabdff1aSopenharmony_ci max = frag->units[i].data_size; 583cabdff1aSopenharmony_ci 584cabdff1aSopenharmony_ci if (max < 2) 585cabdff1aSopenharmony_ci size_len = 1; 586cabdff1aSopenharmony_ci else 587cabdff1aSopenharmony_ci size_len = av_log2(max) / 8 + 1; 588cabdff1aSopenharmony_ci av_assert0(size_len <= 4); 589cabdff1aSopenharmony_ci 590cabdff1aSopenharmony_ci sfi.superframe_marker = VP9_SUPERFRAME_MARKER; 591cabdff1aSopenharmony_ci sfi.bytes_per_framesize_minus_1 = size_len - 1; 592cabdff1aSopenharmony_ci sfi.frames_in_superframe_minus_1 = frag->nb_units - 1; 593cabdff1aSopenharmony_ci 594cabdff1aSopenharmony_ci size = 2; 595cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) { 596cabdff1aSopenharmony_ci size += size_len + frag->units[i].data_size; 597cabdff1aSopenharmony_ci sfi.frame_sizes[i] = frag->units[i].data_size; 598cabdff1aSopenharmony_ci } 599cabdff1aSopenharmony_ci 600cabdff1aSopenharmony_ci ref = av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE); 601cabdff1aSopenharmony_ci if (!ref) 602cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 603cabdff1aSopenharmony_ci data = ref->data; 604cabdff1aSopenharmony_ci memset(data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE); 605cabdff1aSopenharmony_ci 606cabdff1aSopenharmony_ci pos = 0; 607cabdff1aSopenharmony_ci for (i = 0; i < frag->nb_units; i++) { 608cabdff1aSopenharmony_ci av_assert0(size - pos > frag->units[i].data_size); 609cabdff1aSopenharmony_ci memcpy(data + pos, frag->units[i].data, 610cabdff1aSopenharmony_ci frag->units[i].data_size); 611cabdff1aSopenharmony_ci pos += frag->units[i].data_size; 612cabdff1aSopenharmony_ci } 613cabdff1aSopenharmony_ci av_assert0(size - pos == 2 + frag->nb_units * size_len); 614cabdff1aSopenharmony_ci 615cabdff1aSopenharmony_ci init_put_bits(&pbc, data + pos, size - pos); 616cabdff1aSopenharmony_ci 617cabdff1aSopenharmony_ci err = cbs_vp9_write_superframe_index(ctx, &pbc, &sfi); 618cabdff1aSopenharmony_ci if (err < 0) { 619cabdff1aSopenharmony_ci av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write " 620cabdff1aSopenharmony_ci "superframe index.\n"); 621cabdff1aSopenharmony_ci av_buffer_unref(&ref); 622cabdff1aSopenharmony_ci return err; 623cabdff1aSopenharmony_ci } 624cabdff1aSopenharmony_ci 625cabdff1aSopenharmony_ci av_assert0(put_bits_left(&pbc) == 0); 626cabdff1aSopenharmony_ci flush_put_bits(&pbc); 627cabdff1aSopenharmony_ci 628cabdff1aSopenharmony_ci frag->data_ref = ref; 629cabdff1aSopenharmony_ci frag->data = data; 630cabdff1aSopenharmony_ci frag->data_size = size; 631cabdff1aSopenharmony_ci } 632cabdff1aSopenharmony_ci 633cabdff1aSopenharmony_ci return 0; 634cabdff1aSopenharmony_ci} 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_cistatic void cbs_vp9_flush(CodedBitstreamContext *ctx) 637cabdff1aSopenharmony_ci{ 638cabdff1aSopenharmony_ci CodedBitstreamVP9Context *vp9 = ctx->priv_data; 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci memset(vp9->ref, 0, sizeof(vp9->ref)); 641cabdff1aSopenharmony_ci} 642cabdff1aSopenharmony_ci 643cabdff1aSopenharmony_cistatic const CodedBitstreamUnitTypeDescriptor cbs_vp9_unit_types[] = { 644cabdff1aSopenharmony_ci CBS_UNIT_TYPE_INTERNAL_REF(0, VP9RawFrame, data), 645cabdff1aSopenharmony_ci CBS_UNIT_TYPE_END_OF_LIST 646cabdff1aSopenharmony_ci}; 647cabdff1aSopenharmony_ci 648cabdff1aSopenharmony_ciconst CodedBitstreamType ff_cbs_type_vp9 = { 649cabdff1aSopenharmony_ci .codec_id = AV_CODEC_ID_VP9, 650cabdff1aSopenharmony_ci 651cabdff1aSopenharmony_ci .priv_data_size = sizeof(CodedBitstreamVP9Context), 652cabdff1aSopenharmony_ci 653cabdff1aSopenharmony_ci .unit_types = cbs_vp9_unit_types, 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ci .split_fragment = &cbs_vp9_split_fragment, 656cabdff1aSopenharmony_ci .read_unit = &cbs_vp9_read_unit, 657cabdff1aSopenharmony_ci .write_unit = &cbs_vp9_write_unit, 658cabdff1aSopenharmony_ci 659cabdff1aSopenharmony_ci .flush = &cbs_vp9_flush, 660cabdff1aSopenharmony_ci 661cabdff1aSopenharmony_ci .assemble_fragment = &cbs_vp9_assemble_fragment, 662cabdff1aSopenharmony_ci}; 663