2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 #include "./vpx_version.h"
16 #include "vpx/internal/vpx_codec_internal.h"
17 #include "vpx/vp8dx.h"
18 #include "vpx/vpx_decoder.h"
20 #include "vp9/common/vp9_frame_buffers.h"
22 #include "vp9/decoder/vp9_decoder.h"
23 #include "vp9/decoder/vp9_read_bit_buffer.h"
25 #include "vp9/vp9_iface_common.h"
27 #define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
29 typedef vpx_codec_stream_info_t vp9_stream_info_t;
31 struct vpx_codec_alg_priv {
32 vpx_codec_priv_t base;
33 vpx_codec_dec_cfg_t cfg;
35 struct VP9Decoder *pbi;
37 vp8_postproc_cfg_t postproc_cfg;
38 vpx_decrypt_cb decrypt_cb;
41 int invert_tile_order;
43 // External frame buffer info to save for VP9 common.
44 void *ext_priv; // Private data associated with the external frame buffers.
45 vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
46 vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
49 static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
50 vpx_codec_priv_enc_mr_cfg_t *data) {
51 // This function only allocates space for the vpx_codec_alg_priv_t
52 // structure. More memory may be required at the time the stream
53 // information becomes known.
57 vpx_codec_alg_priv_t *alg_priv = vpx_memalign(32, sizeof(*alg_priv));
59 return VPX_CODEC_MEM_ERROR;
63 ctx->priv = (vpx_codec_priv_t *)alg_priv;
64 ctx->priv->sz = sizeof(*ctx->priv);
65 ctx->priv->iface = ctx->iface;
66 ctx->priv->alg_priv = alg_priv;
67 ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si);
68 ctx->priv->init_flags = ctx->init_flags;
70 if (ctx->config.dec) {
71 // Update the reference to the config structure to an internal copy.
72 ctx->priv->alg_priv->cfg = *ctx->config.dec;
73 ctx->config.dec = &ctx->priv->alg_priv->cfg;
80 static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
82 vp9_decoder_remove(ctx->pbi);
91 static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
93 vpx_codec_stream_info_t *si,
94 vpx_decrypt_cb decrypt_cb,
95 void *decrypt_state) {
96 uint8_t clear_buffer[9];
99 return VPX_CODEC_UNSUP_BITSTREAM;
101 if (data + data_sz <= data)
102 return VPX_CODEC_INVALID_PARAM;
108 data_sz = MIN(sizeof(clear_buffer), data_sz);
109 decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
114 struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
115 const int frame_marker = vp9_rb_read_literal(&rb, 2);
116 const int version = vp9_rb_read_bit(&rb);
117 (void) vp9_rb_read_bit(&rb); // unused version bit
119 if (frame_marker != VP9_FRAME_MARKER)
120 return VPX_CODEC_UNSUP_BITSTREAM;
121 if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
123 if (vp9_rb_read_bit(&rb)) { // show an existing frame
127 si->is_kf = !vp9_rb_read_bit(&rb);
132 rb.bit_offset += 1; // show frame
133 rb.bit_offset += 1; // error resilient
135 if (vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_0 ||
136 vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_1 ||
137 vp9_rb_read_literal(&rb, 8) != VP9_SYNC_CODE_2) {
138 return VPX_CODEC_UNSUP_BITSTREAM;
141 colorspace = vp9_rb_read_literal(&rb, 3);
142 if (colorspace != sRGB) {
143 rb.bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range
145 rb.bit_offset += 2; // subsampling x/y
146 rb.bit_offset += 1; // has extra plane
150 rb.bit_offset += 1; // has extra plane
152 // RGB is only available in version 1
153 return VPX_CODEC_UNSUP_BITSTREAM;
157 // TODO(jzern): these are available on non-keyframes in intra only mode.
158 si->w = vp9_rb_read_literal(&rb, 16) + 1;
159 si->h = vp9_rb_read_literal(&rb, 16) + 1;
166 static vpx_codec_err_t decoder_peek_si(const uint8_t *data,
167 unsigned int data_sz,
168 vpx_codec_stream_info_t *si) {
169 return decoder_peek_si_internal(data, data_sz, si, NULL, NULL);
172 static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
173 vpx_codec_stream_info_t *si) {
174 const size_t sz = (si->sz >= sizeof(vp9_stream_info_t))
175 ? sizeof(vp9_stream_info_t)
176 : sizeof(vpx_codec_stream_info_t);
177 memcpy(si, &ctx->si, sz);
178 si->sz = (unsigned int)sz;
183 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
184 const struct vpx_internal_error_info *error) {
185 if (error->error_code)
186 ctx->base.err_detail = error->has_detail ? error->detail : NULL;
188 return error->error_code;
191 static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
192 VP9_COMMON *const cm = &ctx->pbi->common;
196 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
197 cm->get_fb_cb = ctx->get_ext_fb_cb;
198 cm->release_fb_cb = ctx->release_ext_fb_cb;
199 cm->cb_priv = ctx->ext_priv;
201 cm->get_fb_cb = vp9_get_frame_buffer;
202 cm->release_fb_cb = vp9_release_frame_buffer;
204 if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers))
205 vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
206 "Failed to initialize internal frame buffers");
208 cm->cb_priv = &cm->int_frame_buffers;
212 static void set_default_ppflags(vp8_postproc_cfg_t *cfg) {
213 cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
214 cfg->deblocking_level = 4;
215 cfg->noise_level = 0;
218 static void set_ppflags(const vpx_codec_alg_priv_t *ctx,
219 vp9_ppflags_t *flags) {
220 flags->post_proc_flag =
221 ctx->postproc_cfg.post_proc_flag;
223 flags->deblocking_level = ctx->postproc_cfg.deblocking_level;
224 flags->noise_level = ctx->postproc_cfg.noise_level;
227 static void init_decoder(vpx_codec_alg_priv_t *ctx) {
228 ctx->pbi = vp9_decoder_create();
229 if (ctx->pbi == NULL)
232 ctx->pbi->max_threads = ctx->cfg.threads;
233 ctx->pbi->inv_tile_order = ctx->invert_tile_order;
235 // If postprocessing was enabled by the application and a
236 // configuration has not been provided, default it.
237 if (!ctx->postproc_cfg_set &&
238 (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
239 set_default_ppflags(&ctx->postproc_cfg);
241 init_buffer_callbacks(ctx);
244 static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
245 const uint8_t **data, unsigned int data_sz,
246 void *user_priv, int64_t deadline) {
247 vp9_ppflags_t flags = {0};
248 VP9_COMMON *cm = NULL;
252 // Determine the stream parameters. Note that we rely on peek_si to
253 // validate that we have a buffer that does not wrap around the top
256 const vpx_codec_err_t res =
257 decoder_peek_si_internal(*data, data_sz, &ctx->si, ctx->decrypt_cb,
259 if (res != VPX_CODEC_OK)
263 return VPX_CODEC_ERROR;
266 // Initialize the decoder instance on the first frame
267 if (ctx->pbi == NULL) {
269 if (ctx->pbi == NULL)
270 return VPX_CODEC_ERROR;
273 // Set these even if already initialized. The caller may have changed the
274 // decrypt config between frames.
275 ctx->pbi->decrypt_cb = ctx->decrypt_cb;
276 ctx->pbi->decrypt_state = ctx->decrypt_state;
278 cm = &ctx->pbi->common;
280 if (vp9_receive_compressed_data(ctx->pbi, data_sz, data))
281 return update_error_state(ctx, &cm->error);
283 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
284 set_ppflags(ctx, &flags);
289 static INLINE uint8_t read_marker(vpx_decrypt_cb decrypt_cb,
291 const uint8_t *data) {
294 decrypt_cb(decrypt_state, data, &marker, 1);
300 static void parse_superframe_index(const uint8_t *data, size_t data_sz,
301 uint32_t sizes[8], int *count,
302 vpx_decrypt_cb decrypt_cb,
303 void *decrypt_state) {
307 marker = read_marker(decrypt_cb, decrypt_state, data + data_sz - 1);
310 if ((marker & 0xe0) == 0xc0) {
311 const uint32_t frames = (marker & 0x7) + 1;
312 const uint32_t mag = ((marker >> 3) & 0x3) + 1;
313 const size_t index_sz = 2 + mag * frames;
315 uint8_t marker2 = read_marker(decrypt_cb, decrypt_state,
316 data + data_sz - index_sz);
318 if (data_sz >= index_sz && marker2 == marker) {
319 // found a valid superframe index
321 const uint8_t *x = &data[data_sz - index_sz + 1];
323 // frames has a maximum of 8 and mag has a maximum of 4.
324 uint8_t clear_buffer[32];
325 assert(sizeof(clear_buffer) >= frames * mag);
327 decrypt_cb(decrypt_state, x, clear_buffer, frames * mag);
331 for (i = 0; i < frames; i++) {
332 uint32_t this_sz = 0;
334 for (j = 0; j < mag; j++)
335 this_sz |= (*x++) << (j * 8);
344 static vpx_codec_err_t decode_one_iter(vpx_codec_alg_priv_t *ctx,
345 const uint8_t **data_start_ptr,
346 const uint8_t *data_end,
347 uint32_t frame_size, void *user_priv,
349 const vpx_codec_err_t res = decode_one(ctx, data_start_ptr, frame_size,
350 user_priv, deadline);
351 if (res != VPX_CODEC_OK)
354 // Account for suboptimal termination by the encoder.
355 while (*data_start_ptr < data_end) {
356 const uint8_t marker = read_marker(ctx->decrypt_cb, ctx->decrypt_state,
366 static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
367 const uint8_t *data, unsigned int data_sz,
368 void *user_priv, long deadline) {
369 const uint8_t *data_start = data;
370 const uint8_t *const data_end = data + data_sz;
372 uint32_t frame_sizes[8];
375 if (data == NULL || data_sz == 0)
376 return VPX_CODEC_INVALID_PARAM;
378 parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
379 ctx->decrypt_cb, ctx->decrypt_state);
381 if (frame_count > 0) {
384 for (i = 0; i < frame_count; ++i) {
385 const uint32_t frame_size = frame_sizes[i];
386 if (data_start < data ||
387 frame_size > (uint32_t)(data_end - data_start)) {
388 ctx->base.err_detail = "Invalid frame size in index";
389 return VPX_CODEC_CORRUPT_FRAME;
392 res = decode_one_iter(ctx, &data_start, data_end, frame_size,
393 user_priv, deadline);
394 if (res != VPX_CODEC_OK)
398 while (data_start < data_end) {
399 res = decode_one_iter(ctx, &data_start, data_end,
400 (uint32_t)(data_end - data_start),
401 user_priv, deadline);
402 if (res != VPX_CODEC_OK)
410 static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
411 vpx_codec_iter_t *iter) {
412 vpx_image_t *img = NULL;
414 // iter acts as a flip flop, so an image is only returned on the first
415 // call to get_frame.
416 if (*iter == NULL && ctx->pbi != NULL) {
417 YV12_BUFFER_CONFIG sd;
418 vp9_ppflags_t flags = {0, 0, 0};
420 if (vp9_get_raw_frame(ctx->pbi, &sd, &flags) == 0) {
421 VP9_COMMON *cm = &ctx->pbi->common;
422 yuvconfig2image(&ctx->img, &sd, NULL);
423 ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
432 static vpx_codec_err_t decoder_set_fb_fn(
433 vpx_codec_alg_priv_t *ctx,
434 vpx_get_frame_buffer_cb_fn_t cb_get,
435 vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
436 if (cb_get == NULL || cb_release == NULL) {
437 return VPX_CODEC_INVALID_PARAM;
438 } else if (ctx->pbi == NULL) {
439 // If the decoder has already been initialized, do not accept changes to
440 // the frame buffer functions.
441 ctx->get_ext_fb_cb = cb_get;
442 ctx->release_ext_fb_cb = cb_release;
443 ctx->ext_priv = cb_priv;
447 return VPX_CODEC_ERROR;
450 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
452 vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
455 vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
456 YV12_BUFFER_CONFIG sd;
458 image2yuvconfig(&frame->img, &sd);
459 return vp9_set_reference_dec(&ctx->pbi->common,
460 (VP9_REFFRAME)frame->frame_type, &sd);
462 return VPX_CODEC_INVALID_PARAM;
466 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
468 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
471 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
472 YV12_BUFFER_CONFIG sd;
474 image2yuvconfig(&frame->img, &sd);
476 return vp9_copy_reference_dec(ctx->pbi,
477 (VP9_REFFRAME)frame->frame_type, &sd);
479 return VPX_CODEC_INVALID_PARAM;
483 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
485 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
488 YV12_BUFFER_CONFIG* fb;
490 vp9_get_reference_dec(ctx->pbi, data->idx, &fb);
491 yuvconfig2image(&data->img, fb, NULL);
494 return VPX_CODEC_INVALID_PARAM;
498 static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
500 #if CONFIG_VP9_POSTPROC
501 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
504 ctx->postproc_cfg_set = 1;
505 ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
508 return VPX_CODEC_INVALID_PARAM;
513 return VPX_CODEC_INCAPABLE;
517 static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
521 return VPX_CODEC_INCAPABLE;
524 static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
526 int *const update_info = va_arg(args, int *);
530 *update_info = ctx->pbi->refresh_frame_flags;
532 return VPX_CODEC_ERROR;
535 return VPX_CODEC_INVALID_PARAM;
540 static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
542 int *corrupted = va_arg(args, int *);
546 *corrupted = ctx->pbi->common.frame_to_show->corrupted;
548 return VPX_CODEC_ERROR;
551 return VPX_CODEC_INVALID_PARAM;
555 static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx,
557 int *const display_size = va_arg(args, int *);
561 const VP9_COMMON *const cm = &ctx->pbi->common;
562 display_size[0] = cm->display_width;
563 display_size[1] = cm->display_height;
565 return VPX_CODEC_ERROR;
569 return VPX_CODEC_INVALID_PARAM;
573 static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
575 ctx->invert_tile_order = va_arg(args, int);
579 static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
581 vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
582 ctx->decrypt_cb = init ? init->decrypt_cb : NULL;
583 ctx->decrypt_state = init ? init->decrypt_state : NULL;
587 static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
588 {VP8_COPY_REFERENCE, ctrl_copy_reference},
591 {VP8_SET_REFERENCE, ctrl_set_reference},
592 {VP8_SET_POSTPROC, ctrl_set_postproc},
593 {VP8_SET_DBG_COLOR_REF_FRAME, ctrl_set_dbg_options},
594 {VP8_SET_DBG_COLOR_MB_MODES, ctrl_set_dbg_options},
595 {VP8_SET_DBG_COLOR_B_MODES, ctrl_set_dbg_options},
596 {VP8_SET_DBG_DISPLAY_MV, ctrl_set_dbg_options},
597 {VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order},
598 {VPXD_SET_DECRYPTOR, ctrl_set_decryptor},
601 {VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates},
602 {VP8D_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted},
603 {VP9_GET_REFERENCE, ctrl_get_reference},
604 {VP9D_GET_DISPLAY_SIZE, ctrl_get_display_size},
609 #ifndef VERSION_STRING
610 #define VERSION_STRING
612 CODEC_INTERFACE(vpx_codec_vp9_dx) = {
613 "WebM Project VP9 Decoder" VERSION_STRING,
614 VPX_CODEC_INTERNAL_ABI_VERSION,
615 VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
616 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER, // vpx_codec_caps_t
617 decoder_init, // vpx_codec_init_fn_t
618 decoder_destroy, // vpx_codec_destroy_fn_t
619 decoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
620 NOT_IMPLEMENTED, // vpx_codec_get_mmap_fn_t
621 NOT_IMPLEMENTED, // vpx_codec_set_mmap_fn_t
623 decoder_peek_si, // vpx_codec_peek_si_fn_t
624 decoder_get_si, // vpx_codec_get_si_fn_t
625 decoder_decode, // vpx_codec_decode_fn_t
626 decoder_get_frame, // vpx_codec_frame_get_fn_t
627 decoder_set_fb_fn, // vpx_codec_set_fb_fn_t
630 NOT_IMPLEMENTED, // vpx_codec_enc_cfg_map_t
631 NOT_IMPLEMENTED, // vpx_codec_encode_fn_t
632 NOT_IMPLEMENTED, // vpx_codec_get_cx_data_fn_t
633 NOT_IMPLEMENTED, // vpx_codec_enc_config_set_fn_t
634 NOT_IMPLEMENTED, // vpx_codec_get_global_headers_fn_t
635 NOT_IMPLEMENTED, // vpx_codec_get_preview_frame_fn_t
636 NOT_IMPLEMENTED // vpx_codec_enc_mr_get_mem_loc_fn_t