xref: /aosp_15_r20/external/libvpx/vp8/vp8_dx_iface.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
14*fb1b10abSAndroid Build Coastguard Worker #include "./vp8_rtcd.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_scale_rtcd.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_decoder.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vp8dx.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx/internal/vpx_codec_internal.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_version.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "common/alloccommon.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "common/common.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "common/onyxc_int.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "common/onyxd.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "decoder/onyxd_int.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/vpx_dsp_common.h"
27*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
28*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
29*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_ERROR_CONCEALMENT
30*fb1b10abSAndroid Build Coastguard Worker #include "decoder/error_concealment.h"
31*fb1b10abSAndroid Build Coastguard Worker #endif
32*fb1b10abSAndroid Build Coastguard Worker #include "decoder/decoderthreading.h"
33*fb1b10abSAndroid Build Coastguard Worker 
34*fb1b10abSAndroid Build Coastguard Worker #define VP8_CAP_POSTPROC (CONFIG_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
35*fb1b10abSAndroid Build Coastguard Worker #define VP8_CAP_ERROR_CONCEALMENT \
36*fb1b10abSAndroid Build Coastguard Worker   (CONFIG_ERROR_CONCEALMENT ? VPX_CODEC_CAP_ERROR_CONCEALMENT : 0)
37*fb1b10abSAndroid Build Coastguard Worker 
38*fb1b10abSAndroid Build Coastguard Worker typedef vpx_codec_stream_info_t vp8_stream_info_t;
39*fb1b10abSAndroid Build Coastguard Worker 
40*fb1b10abSAndroid Build Coastguard Worker /* Structures for handling memory allocations */
41*fb1b10abSAndroid Build Coastguard Worker typedef enum { VP8_SEG_ALG_PRIV = 256, VP8_SEG_MAX } mem_seg_id_t;
42*fb1b10abSAndroid Build Coastguard Worker #define NELEMENTS(x) ((int)(sizeof(x) / sizeof((x)[0])))
43*fb1b10abSAndroid Build Coastguard Worker 
44*fb1b10abSAndroid Build Coastguard Worker struct vpx_codec_alg_priv {
45*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_priv_t base;
46*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_dec_cfg_t cfg;
47*fb1b10abSAndroid Build Coastguard Worker   vp8_stream_info_t si;
48*fb1b10abSAndroid Build Coastguard Worker   int decoder_init;
49*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
50*fb1b10abSAndroid Build Coastguard Worker   // Restart threads on next frame if set to 1.
51*fb1b10abSAndroid Build Coastguard Worker   // This is set when error happens in multithreaded decoding and all threads
52*fb1b10abSAndroid Build Coastguard Worker   // are shut down.
53*fb1b10abSAndroid Build Coastguard Worker   int restart_threads;
54*fb1b10abSAndroid Build Coastguard Worker #endif
55*fb1b10abSAndroid Build Coastguard Worker   int postproc_cfg_set;
56*fb1b10abSAndroid Build Coastguard Worker   vp8_postproc_cfg_t postproc_cfg;
57*fb1b10abSAndroid Build Coastguard Worker   vpx_decrypt_cb decrypt_cb;
58*fb1b10abSAndroid Build Coastguard Worker   void *decrypt_state;
59*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t img;
60*fb1b10abSAndroid Build Coastguard Worker   int img_setup;
61*fb1b10abSAndroid Build Coastguard Worker   struct frame_buffers yv12_frame_buffers;
62*fb1b10abSAndroid Build Coastguard Worker   void *user_priv;
63*fb1b10abSAndroid Build Coastguard Worker   FRAGMENT_DATA fragments;
64*fb1b10abSAndroid Build Coastguard Worker };
65*fb1b10abSAndroid Build Coastguard Worker 
vp8_init_ctx(vpx_codec_ctx_t * ctx)66*fb1b10abSAndroid Build Coastguard Worker static int vp8_init_ctx(vpx_codec_ctx_t *ctx) {
67*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_alg_priv_t *priv =
68*fb1b10abSAndroid Build Coastguard Worker       (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv));
69*fb1b10abSAndroid Build Coastguard Worker   if (!priv) return 1;
70*fb1b10abSAndroid Build Coastguard Worker 
71*fb1b10abSAndroid Build Coastguard Worker   ctx->priv = (vpx_codec_priv_t *)priv;
72*fb1b10abSAndroid Build Coastguard Worker   ctx->priv->init_flags = ctx->init_flags;
73*fb1b10abSAndroid Build Coastguard Worker 
74*fb1b10abSAndroid Build Coastguard Worker   priv->si.sz = sizeof(priv->si);
75*fb1b10abSAndroid Build Coastguard Worker   priv->decrypt_cb = NULL;
76*fb1b10abSAndroid Build Coastguard Worker   priv->decrypt_state = NULL;
77*fb1b10abSAndroid Build Coastguard Worker 
78*fb1b10abSAndroid Build Coastguard Worker   if (ctx->config.dec) {
79*fb1b10abSAndroid Build Coastguard Worker     /* Update the reference to the config structure to an internal copy. */
80*fb1b10abSAndroid Build Coastguard Worker     priv->cfg = *ctx->config.dec;
81*fb1b10abSAndroid Build Coastguard Worker     ctx->config.dec = &priv->cfg;
82*fb1b10abSAndroid Build Coastguard Worker   }
83*fb1b10abSAndroid Build Coastguard Worker 
84*fb1b10abSAndroid Build Coastguard Worker   return 0;
85*fb1b10abSAndroid Build Coastguard Worker }
86*fb1b10abSAndroid Build Coastguard Worker 
vp8_init(vpx_codec_ctx_t * ctx,vpx_codec_priv_enc_mr_cfg_t * data)87*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx,
88*fb1b10abSAndroid Build Coastguard Worker                                 vpx_codec_priv_enc_mr_cfg_t *data) {
89*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res = VPX_CODEC_OK;
90*fb1b10abSAndroid Build Coastguard Worker   (void)data;
91*fb1b10abSAndroid Build Coastguard Worker 
92*fb1b10abSAndroid Build Coastguard Worker   vp8_rtcd();
93*fb1b10abSAndroid Build Coastguard Worker   vpx_dsp_rtcd();
94*fb1b10abSAndroid Build Coastguard Worker   vpx_scale_rtcd();
95*fb1b10abSAndroid Build Coastguard Worker 
96*fb1b10abSAndroid Build Coastguard Worker   /* This function only allocates space for the vpx_codec_alg_priv_t
97*fb1b10abSAndroid Build Coastguard Worker    * structure. More memory may be required at the time the stream
98*fb1b10abSAndroid Build Coastguard Worker    * information becomes known.
99*fb1b10abSAndroid Build Coastguard Worker    */
100*fb1b10abSAndroid Build Coastguard Worker   if (!ctx->priv) {
101*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_alg_priv_t *priv;
102*fb1b10abSAndroid Build Coastguard Worker 
103*fb1b10abSAndroid Build Coastguard Worker     if (vp8_init_ctx(ctx)) return VPX_CODEC_MEM_ERROR;
104*fb1b10abSAndroid Build Coastguard Worker 
105*fb1b10abSAndroid Build Coastguard Worker     priv = (vpx_codec_alg_priv_t *)ctx->priv;
106*fb1b10abSAndroid Build Coastguard Worker 
107*fb1b10abSAndroid Build Coastguard Worker     /* initialize number of fragments to zero */
108*fb1b10abSAndroid Build Coastguard Worker     priv->fragments.count = 0;
109*fb1b10abSAndroid Build Coastguard Worker     /* is input fragments enabled? */
110*fb1b10abSAndroid Build Coastguard Worker     priv->fragments.enabled =
111*fb1b10abSAndroid Build Coastguard Worker         (priv->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS);
112*fb1b10abSAndroid Build Coastguard Worker 
113*fb1b10abSAndroid Build Coastguard Worker     /*post processing level initialized to do nothing */
114*fb1b10abSAndroid Build Coastguard Worker   }
115*fb1b10abSAndroid Build Coastguard Worker 
116*fb1b10abSAndroid Build Coastguard Worker   return res;
117*fb1b10abSAndroid Build Coastguard Worker }
118*fb1b10abSAndroid Build Coastguard Worker 
vp8_destroy(vpx_codec_alg_priv_t * ctx)119*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) {
120*fb1b10abSAndroid Build Coastguard Worker   vp8_remove_decoder_instances(&ctx->yv12_frame_buffers);
121*fb1b10abSAndroid Build Coastguard Worker 
122*fb1b10abSAndroid Build Coastguard Worker   vpx_free(ctx);
123*fb1b10abSAndroid Build Coastguard Worker 
124*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_OK;
125*fb1b10abSAndroid Build Coastguard Worker }
126*fb1b10abSAndroid Build Coastguard Worker 
vp8_peek_si_internal(const uint8_t * data,unsigned int data_sz,vpx_codec_stream_info_t * si,vpx_decrypt_cb decrypt_cb,void * decrypt_state)127*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data,
128*fb1b10abSAndroid Build Coastguard Worker                                             unsigned int data_sz,
129*fb1b10abSAndroid Build Coastguard Worker                                             vpx_codec_stream_info_t *si,
130*fb1b10abSAndroid Build Coastguard Worker                                             vpx_decrypt_cb decrypt_cb,
131*fb1b10abSAndroid Build Coastguard Worker                                             void *decrypt_state) {
132*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res = VPX_CODEC_OK;
133*fb1b10abSAndroid Build Coastguard Worker 
134*fb1b10abSAndroid Build Coastguard Worker   assert(data != NULL);
135*fb1b10abSAndroid Build Coastguard Worker 
136*fb1b10abSAndroid Build Coastguard Worker   if (data + data_sz <= data) {
137*fb1b10abSAndroid Build Coastguard Worker     res = VPX_CODEC_INVALID_PARAM;
138*fb1b10abSAndroid Build Coastguard Worker   } else {
139*fb1b10abSAndroid Build Coastguard Worker     /* Parse uncompresssed part of key frame header.
140*fb1b10abSAndroid Build Coastguard Worker      * 3 bytes:- including version, frame type and an offset
141*fb1b10abSAndroid Build Coastguard Worker      * 3 bytes:- sync code (0x9d, 0x01, 0x2a)
142*fb1b10abSAndroid Build Coastguard Worker      * 4 bytes:- including image width and height in the lowest 14 bits
143*fb1b10abSAndroid Build Coastguard Worker      *           of each 2-byte value.
144*fb1b10abSAndroid Build Coastguard Worker      */
145*fb1b10abSAndroid Build Coastguard Worker     uint8_t clear_buffer[10];
146*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *clear = data;
147*fb1b10abSAndroid Build Coastguard Worker     if (decrypt_cb) {
148*fb1b10abSAndroid Build Coastguard Worker       int n = VPXMIN(sizeof(clear_buffer), data_sz);
149*fb1b10abSAndroid Build Coastguard Worker       decrypt_cb(decrypt_state, data, clear_buffer, n);
150*fb1b10abSAndroid Build Coastguard Worker       clear = clear_buffer;
151*fb1b10abSAndroid Build Coastguard Worker     }
152*fb1b10abSAndroid Build Coastguard Worker     si->is_kf = 0;
153*fb1b10abSAndroid Build Coastguard Worker 
154*fb1b10abSAndroid Build Coastguard Worker     if (data_sz >= 10 && !(clear[0] & 0x01)) { /* I-Frame */
155*fb1b10abSAndroid Build Coastguard Worker       si->is_kf = 1;
156*fb1b10abSAndroid Build Coastguard Worker 
157*fb1b10abSAndroid Build Coastguard Worker       /* vet via sync code */
158*fb1b10abSAndroid Build Coastguard Worker       if (clear[3] != 0x9d || clear[4] != 0x01 || clear[5] != 0x2a) {
159*fb1b10abSAndroid Build Coastguard Worker         return VPX_CODEC_UNSUP_BITSTREAM;
160*fb1b10abSAndroid Build Coastguard Worker       }
161*fb1b10abSAndroid Build Coastguard Worker 
162*fb1b10abSAndroid Build Coastguard Worker       si->w = (clear[6] | (clear[7] << 8)) & 0x3fff;
163*fb1b10abSAndroid Build Coastguard Worker       si->h = (clear[8] | (clear[9] << 8)) & 0x3fff;
164*fb1b10abSAndroid Build Coastguard Worker 
165*fb1b10abSAndroid Build Coastguard Worker       /*printf("w=%d, h=%d\n", si->w, si->h);*/
166*fb1b10abSAndroid Build Coastguard Worker       if (!(si->h && si->w)) {
167*fb1b10abSAndroid Build Coastguard Worker         si->w = si->h = 0;
168*fb1b10abSAndroid Build Coastguard Worker         res = VPX_CODEC_CORRUPT_FRAME;
169*fb1b10abSAndroid Build Coastguard Worker       }
170*fb1b10abSAndroid Build Coastguard Worker     } else {
171*fb1b10abSAndroid Build Coastguard Worker       res = VPX_CODEC_UNSUP_BITSTREAM;
172*fb1b10abSAndroid Build Coastguard Worker     }
173*fb1b10abSAndroid Build Coastguard Worker   }
174*fb1b10abSAndroid Build Coastguard Worker 
175*fb1b10abSAndroid Build Coastguard Worker   return res;
176*fb1b10abSAndroid Build Coastguard Worker }
177*fb1b10abSAndroid Build Coastguard Worker 
vp8_peek_si(const uint8_t * data,unsigned int data_sz,vpx_codec_stream_info_t * si)178*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_peek_si(const uint8_t *data, unsigned int data_sz,
179*fb1b10abSAndroid Build Coastguard Worker                                    vpx_codec_stream_info_t *si) {
180*fb1b10abSAndroid Build Coastguard Worker   return vp8_peek_si_internal(data, data_sz, si, NULL, NULL);
181*fb1b10abSAndroid Build Coastguard Worker }
182*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_si(vpx_codec_alg_priv_t * ctx,vpx_codec_stream_info_t * si)183*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t *ctx,
184*fb1b10abSAndroid Build Coastguard Worker                                   vpx_codec_stream_info_t *si) {
185*fb1b10abSAndroid Build Coastguard Worker   unsigned int sz;
186*fb1b10abSAndroid Build Coastguard Worker 
187*fb1b10abSAndroid Build Coastguard Worker   if (si->sz >= sizeof(vp8_stream_info_t)) {
188*fb1b10abSAndroid Build Coastguard Worker     sz = sizeof(vp8_stream_info_t);
189*fb1b10abSAndroid Build Coastguard Worker   } else {
190*fb1b10abSAndroid Build Coastguard Worker     sz = sizeof(vpx_codec_stream_info_t);
191*fb1b10abSAndroid Build Coastguard Worker   }
192*fb1b10abSAndroid Build Coastguard Worker 
193*fb1b10abSAndroid Build Coastguard Worker   memcpy(si, &ctx->si, sz);
194*fb1b10abSAndroid Build Coastguard Worker   si->sz = sz;
195*fb1b10abSAndroid Build Coastguard Worker 
196*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_OK;
197*fb1b10abSAndroid Build Coastguard Worker }
198*fb1b10abSAndroid Build Coastguard Worker 
update_error_state(vpx_codec_alg_priv_t * ctx,const struct vpx_internal_error_info * error)199*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t update_error_state(
200*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_alg_priv_t *ctx, const struct vpx_internal_error_info *error) {
201*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res;
202*fb1b10abSAndroid Build Coastguard Worker 
203*fb1b10abSAndroid Build Coastguard Worker   if ((res = error->error_code)) {
204*fb1b10abSAndroid Build Coastguard Worker     ctx->base.err_detail = error->has_detail ? error->detail : NULL;
205*fb1b10abSAndroid Build Coastguard Worker   }
206*fb1b10abSAndroid Build Coastguard Worker 
207*fb1b10abSAndroid Build Coastguard Worker   return res;
208*fb1b10abSAndroid Build Coastguard Worker }
209*fb1b10abSAndroid Build Coastguard Worker 
yuvconfig2image(vpx_image_t * img,const YV12_BUFFER_CONFIG * yv12,void * user_priv)210*fb1b10abSAndroid Build Coastguard Worker static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
211*fb1b10abSAndroid Build Coastguard Worker                             void *user_priv) {
212*fb1b10abSAndroid Build Coastguard Worker   /** vpx_img_wrap() doesn't allow specifying independent strides for
213*fb1b10abSAndroid Build Coastguard Worker    * the Y, U, and V planes, nor other alignment adjustments that
214*fb1b10abSAndroid Build Coastguard Worker    * might be representable by a YV12_BUFFER_CONFIG, so we just
215*fb1b10abSAndroid Build Coastguard Worker    * initialize all the fields.*/
216*fb1b10abSAndroid Build Coastguard Worker   img->fmt = VPX_IMG_FMT_I420;
217*fb1b10abSAndroid Build Coastguard Worker   img->w = yv12->y_stride;
218*fb1b10abSAndroid Build Coastguard Worker   img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15;
219*fb1b10abSAndroid Build Coastguard Worker   img->d_w = img->r_w = yv12->y_width;
220*fb1b10abSAndroid Build Coastguard Worker   img->d_h = img->r_h = yv12->y_height;
221*fb1b10abSAndroid Build Coastguard Worker   img->x_chroma_shift = 1;
222*fb1b10abSAndroid Build Coastguard Worker   img->y_chroma_shift = 1;
223*fb1b10abSAndroid Build Coastguard Worker   img->planes[VPX_PLANE_Y] = yv12->y_buffer;
224*fb1b10abSAndroid Build Coastguard Worker   img->planes[VPX_PLANE_U] = yv12->u_buffer;
225*fb1b10abSAndroid Build Coastguard Worker   img->planes[VPX_PLANE_V] = yv12->v_buffer;
226*fb1b10abSAndroid Build Coastguard Worker   img->planes[VPX_PLANE_ALPHA] = NULL;
227*fb1b10abSAndroid Build Coastguard Worker   img->stride[VPX_PLANE_Y] = yv12->y_stride;
228*fb1b10abSAndroid Build Coastguard Worker   img->stride[VPX_PLANE_U] = yv12->uv_stride;
229*fb1b10abSAndroid Build Coastguard Worker   img->stride[VPX_PLANE_V] = yv12->uv_stride;
230*fb1b10abSAndroid Build Coastguard Worker   img->stride[VPX_PLANE_ALPHA] = yv12->y_stride;
231*fb1b10abSAndroid Build Coastguard Worker   img->bit_depth = 8;
232*fb1b10abSAndroid Build Coastguard Worker   img->bps = 12;
233*fb1b10abSAndroid Build Coastguard Worker   img->user_priv = user_priv;
234*fb1b10abSAndroid Build Coastguard Worker   img->img_data = yv12->buffer_alloc;
235*fb1b10abSAndroid Build Coastguard Worker   img->img_data_owner = 0;
236*fb1b10abSAndroid Build Coastguard Worker   img->self_allocd = 0;
237*fb1b10abSAndroid Build Coastguard Worker }
238*fb1b10abSAndroid Build Coastguard Worker 
update_fragments(vpx_codec_alg_priv_t * ctx,const uint8_t * data,unsigned int data_sz,volatile vpx_codec_err_t * res)239*fb1b10abSAndroid Build Coastguard Worker static int update_fragments(vpx_codec_alg_priv_t *ctx, const uint8_t *data,
240*fb1b10abSAndroid Build Coastguard Worker                             unsigned int data_sz,
241*fb1b10abSAndroid Build Coastguard Worker                             volatile vpx_codec_err_t *res) {
242*fb1b10abSAndroid Build Coastguard Worker   *res = VPX_CODEC_OK;
243*fb1b10abSAndroid Build Coastguard Worker 
244*fb1b10abSAndroid Build Coastguard Worker   if (ctx->fragments.count == 0) {
245*fb1b10abSAndroid Build Coastguard Worker     /* New frame, reset fragment pointers and sizes */
246*fb1b10abSAndroid Build Coastguard Worker     memset((void *)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs));
247*fb1b10abSAndroid Build Coastguard Worker     memset(ctx->fragments.sizes, 0, sizeof(ctx->fragments.sizes));
248*fb1b10abSAndroid Build Coastguard Worker   }
249*fb1b10abSAndroid Build Coastguard Worker   if (ctx->fragments.enabled && !(data == NULL && data_sz == 0)) {
250*fb1b10abSAndroid Build Coastguard Worker     /* Store a pointer to this fragment and return. We haven't
251*fb1b10abSAndroid Build Coastguard Worker      * received the complete frame yet, so we will wait with decoding.
252*fb1b10abSAndroid Build Coastguard Worker      */
253*fb1b10abSAndroid Build Coastguard Worker     if (ctx->fragments.count >= MAX_PARTITIONS) {
254*fb1b10abSAndroid Build Coastguard Worker       ctx->fragments.count = 0;
255*fb1b10abSAndroid Build Coastguard Worker       *res = VPX_CODEC_INVALID_PARAM;
256*fb1b10abSAndroid Build Coastguard Worker       return -1;
257*fb1b10abSAndroid Build Coastguard Worker     }
258*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.ptrs[ctx->fragments.count] = data;
259*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.sizes[ctx->fragments.count] = data_sz;
260*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.count++;
261*fb1b10abSAndroid Build Coastguard Worker     return 0;
262*fb1b10abSAndroid Build Coastguard Worker   }
263*fb1b10abSAndroid Build Coastguard Worker 
264*fb1b10abSAndroid Build Coastguard Worker   if (!ctx->fragments.enabled && (data == NULL && data_sz == 0)) {
265*fb1b10abSAndroid Build Coastguard Worker     return 0;
266*fb1b10abSAndroid Build Coastguard Worker   }
267*fb1b10abSAndroid Build Coastguard Worker 
268*fb1b10abSAndroid Build Coastguard Worker   if (!ctx->fragments.enabled) {
269*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.ptrs[0] = data;
270*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.sizes[0] = data_sz;
271*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.count = 1;
272*fb1b10abSAndroid Build Coastguard Worker   }
273*fb1b10abSAndroid Build Coastguard Worker 
274*fb1b10abSAndroid Build Coastguard Worker   return 1;
275*fb1b10abSAndroid Build Coastguard Worker }
276*fb1b10abSAndroid Build Coastguard Worker 
vp8_decode(vpx_codec_alg_priv_t * ctx,const uint8_t * data,unsigned int data_sz,void * user_priv)277*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
278*fb1b10abSAndroid Build Coastguard Worker                                   const uint8_t *data, unsigned int data_sz,
279*fb1b10abSAndroid Build Coastguard Worker                                   void *user_priv) {
280*fb1b10abSAndroid Build Coastguard Worker   volatile vpx_codec_err_t res;
281*fb1b10abSAndroid Build Coastguard Worker   volatile unsigned int resolution_change = 0;
282*fb1b10abSAndroid Build Coastguard Worker   volatile unsigned int w, h;
283*fb1b10abSAndroid Build Coastguard Worker 
284*fb1b10abSAndroid Build Coastguard Worker   if (!ctx->fragments.enabled && (data == NULL && data_sz == 0)) {
285*fb1b10abSAndroid Build Coastguard Worker     return 0;
286*fb1b10abSAndroid Build Coastguard Worker   }
287*fb1b10abSAndroid Build Coastguard Worker 
288*fb1b10abSAndroid Build Coastguard Worker   /* Update the input fragment data */
289*fb1b10abSAndroid Build Coastguard Worker   if (update_fragments(ctx, data, data_sz, &res) <= 0) return res;
290*fb1b10abSAndroid Build Coastguard Worker 
291*fb1b10abSAndroid Build Coastguard Worker   /* Determine the stream parameters. Note that we rely on peek_si to
292*fb1b10abSAndroid Build Coastguard Worker    * validate that we have a buffer that does not wrap around the top
293*fb1b10abSAndroid Build Coastguard Worker    * of the heap.
294*fb1b10abSAndroid Build Coastguard Worker    */
295*fb1b10abSAndroid Build Coastguard Worker   w = ctx->si.w;
296*fb1b10abSAndroid Build Coastguard Worker   h = ctx->si.h;
297*fb1b10abSAndroid Build Coastguard Worker 
298*fb1b10abSAndroid Build Coastguard Worker   res = vp8_peek_si_internal(ctx->fragments.ptrs[0], ctx->fragments.sizes[0],
299*fb1b10abSAndroid Build Coastguard Worker                              &ctx->si, ctx->decrypt_cb, ctx->decrypt_state);
300*fb1b10abSAndroid Build Coastguard Worker 
301*fb1b10abSAndroid Build Coastguard Worker   if ((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) {
302*fb1b10abSAndroid Build Coastguard Worker     /* the peek function returns an error for non keyframes, however for
303*fb1b10abSAndroid Build Coastguard Worker      * this case, it is not an error */
304*fb1b10abSAndroid Build Coastguard Worker     res = VPX_CODEC_OK;
305*fb1b10abSAndroid Build Coastguard Worker   }
306*fb1b10abSAndroid Build Coastguard Worker 
307*fb1b10abSAndroid Build Coastguard Worker   if (!ctx->decoder_init && !ctx->si.is_kf) res = VPX_CODEC_UNSUP_BITSTREAM;
308*fb1b10abSAndroid Build Coastguard Worker   if (!res && ctx->decoder_init && w == 0 && h == 0 && ctx->si.h == 0 &&
309*fb1b10abSAndroid Build Coastguard Worker       ctx->si.w == 0) {
310*fb1b10abSAndroid Build Coastguard Worker     VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
311*fb1b10abSAndroid Build Coastguard Worker     assert(pbi != NULL);
312*fb1b10abSAndroid Build Coastguard Worker     assert(!pbi->common.error.setjmp);
313*fb1b10abSAndroid Build Coastguard Worker     res = VPX_CODEC_CORRUPT_FRAME;
314*fb1b10abSAndroid Build Coastguard Worker     vpx_internal_error(&pbi->common.error, res,
315*fb1b10abSAndroid Build Coastguard Worker                        "Keyframe / intra-only frame required to reset decoder"
316*fb1b10abSAndroid Build Coastguard Worker                        " state");
317*fb1b10abSAndroid Build Coastguard Worker   }
318*fb1b10abSAndroid Build Coastguard Worker 
319*fb1b10abSAndroid Build Coastguard Worker   if ((ctx->si.h != h) || (ctx->si.w != w)) resolution_change = 1;
320*fb1b10abSAndroid Build Coastguard Worker 
321*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
322*fb1b10abSAndroid Build Coastguard Worker   if (!res && ctx->restart_threads) {
323*fb1b10abSAndroid Build Coastguard Worker     VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
324*fb1b10abSAndroid Build Coastguard Worker     VP8_COMMON *const pc = &pbi->common;
325*fb1b10abSAndroid Build Coastguard Worker     if (setjmp(pbi->common.error.jmp)) {
326*fb1b10abSAndroid Build Coastguard Worker       pbi->common.error.setjmp = 0;
327*fb1b10abSAndroid Build Coastguard Worker       vp8_decoder_remove_threads(pbi);
328*fb1b10abSAndroid Build Coastguard Worker       vpx_clear_system_state();
329*fb1b10abSAndroid Build Coastguard Worker       return VPX_CODEC_ERROR;
330*fb1b10abSAndroid Build Coastguard Worker     }
331*fb1b10abSAndroid Build Coastguard Worker     pbi->common.error.setjmp = 1;
332*fb1b10abSAndroid Build Coastguard Worker     pbi->max_threads = ctx->cfg.threads;
333*fb1b10abSAndroid Build Coastguard Worker     vp8_decoder_create_threads(pbi);
334*fb1b10abSAndroid Build Coastguard Worker     if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd)) {
335*fb1b10abSAndroid Build Coastguard Worker       vp8mt_alloc_temp_buffers(pbi, pc->Width, pc->mb_rows);
336*fb1b10abSAndroid Build Coastguard Worker     }
337*fb1b10abSAndroid Build Coastguard Worker     ctx->restart_threads = 0;
338*fb1b10abSAndroid Build Coastguard Worker     pbi->common.error.setjmp = 0;
339*fb1b10abSAndroid Build Coastguard Worker   }
340*fb1b10abSAndroid Build Coastguard Worker #endif
341*fb1b10abSAndroid Build Coastguard Worker   /* Initialize the decoder instance on the first frame*/
342*fb1b10abSAndroid Build Coastguard Worker   if (!res && !ctx->decoder_init) {
343*fb1b10abSAndroid Build Coastguard Worker     VP8D_CONFIG oxcf;
344*fb1b10abSAndroid Build Coastguard Worker 
345*fb1b10abSAndroid Build Coastguard Worker     oxcf.Width = ctx->si.w;
346*fb1b10abSAndroid Build Coastguard Worker     oxcf.Height = ctx->si.h;
347*fb1b10abSAndroid Build Coastguard Worker     oxcf.Version = 9;
348*fb1b10abSAndroid Build Coastguard Worker     oxcf.postprocess = 0;
349*fb1b10abSAndroid Build Coastguard Worker     oxcf.max_threads = ctx->cfg.threads;
350*fb1b10abSAndroid Build Coastguard Worker     oxcf.error_concealment =
351*fb1b10abSAndroid Build Coastguard Worker         (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT);
352*fb1b10abSAndroid Build Coastguard Worker 
353*fb1b10abSAndroid Build Coastguard Worker     /* If postprocessing was enabled by the application and a
354*fb1b10abSAndroid Build Coastguard Worker      * configuration has not been provided, default it.
355*fb1b10abSAndroid Build Coastguard Worker      */
356*fb1b10abSAndroid Build Coastguard Worker     if (!ctx->postproc_cfg_set &&
357*fb1b10abSAndroid Build Coastguard Worker         (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) {
358*fb1b10abSAndroid Build Coastguard Worker       ctx->postproc_cfg.post_proc_flag =
359*fb1b10abSAndroid Build Coastguard Worker           VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE;
360*fb1b10abSAndroid Build Coastguard Worker       ctx->postproc_cfg.deblocking_level = 4;
361*fb1b10abSAndroid Build Coastguard Worker       ctx->postproc_cfg.noise_level = 0;
362*fb1b10abSAndroid Build Coastguard Worker     }
363*fb1b10abSAndroid Build Coastguard Worker 
364*fb1b10abSAndroid Build Coastguard Worker     res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf);
365*fb1b10abSAndroid Build Coastguard Worker     if (res == VPX_CODEC_OK) {
366*fb1b10abSAndroid Build Coastguard Worker       ctx->decoder_init = 1;
367*fb1b10abSAndroid Build Coastguard Worker     } else {
368*fb1b10abSAndroid Build Coastguard Worker       /* on failure clear the cached resolution to ensure a full
369*fb1b10abSAndroid Build Coastguard Worker        * reallocation is attempted on resync. */
370*fb1b10abSAndroid Build Coastguard Worker       ctx->si.w = 0;
371*fb1b10abSAndroid Build Coastguard Worker       ctx->si.h = 0;
372*fb1b10abSAndroid Build Coastguard Worker     }
373*fb1b10abSAndroid Build Coastguard Worker   }
374*fb1b10abSAndroid Build Coastguard Worker 
375*fb1b10abSAndroid Build Coastguard Worker   /* Set these even if already initialized.  The caller may have changed the
376*fb1b10abSAndroid Build Coastguard Worker    * decrypt config between frames.
377*fb1b10abSAndroid Build Coastguard Worker    */
378*fb1b10abSAndroid Build Coastguard Worker   if (ctx->decoder_init) {
379*fb1b10abSAndroid Build Coastguard Worker     ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb;
380*fb1b10abSAndroid Build Coastguard Worker     ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state;
381*fb1b10abSAndroid Build Coastguard Worker   }
382*fb1b10abSAndroid Build Coastguard Worker 
383*fb1b10abSAndroid Build Coastguard Worker   if (!res) {
384*fb1b10abSAndroid Build Coastguard Worker     VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
385*fb1b10abSAndroid Build Coastguard Worker     VP8_COMMON *const pc = &pbi->common;
386*fb1b10abSAndroid Build Coastguard Worker     if (resolution_change) {
387*fb1b10abSAndroid Build Coastguard Worker       MACROBLOCKD *const xd = &pbi->mb;
388*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
389*fb1b10abSAndroid Build Coastguard Worker       int i;
390*fb1b10abSAndroid Build Coastguard Worker #endif
391*fb1b10abSAndroid Build Coastguard Worker       pc->Width = ctx->si.w;
392*fb1b10abSAndroid Build Coastguard Worker       pc->Height = ctx->si.h;
393*fb1b10abSAndroid Build Coastguard Worker       {
394*fb1b10abSAndroid Build Coastguard Worker         if (setjmp(pbi->common.error.jmp)) {
395*fb1b10abSAndroid Build Coastguard Worker           pbi->common.error.setjmp = 0;
396*fb1b10abSAndroid Build Coastguard Worker           /* on failure clear the cached resolution to ensure a full
397*fb1b10abSAndroid Build Coastguard Worker            * reallocation is attempted on resync. */
398*fb1b10abSAndroid Build Coastguard Worker           ctx->si.w = 0;
399*fb1b10abSAndroid Build Coastguard Worker           ctx->si.h = 0;
400*fb1b10abSAndroid Build Coastguard Worker           vpx_clear_system_state();
401*fb1b10abSAndroid Build Coastguard Worker           /* same return value as used in vp8dx_receive_compressed_data */
402*fb1b10abSAndroid Build Coastguard Worker           return -1;
403*fb1b10abSAndroid Build Coastguard Worker         }
404*fb1b10abSAndroid Build Coastguard Worker 
405*fb1b10abSAndroid Build Coastguard Worker         pbi->common.error.setjmp = 1;
406*fb1b10abSAndroid Build Coastguard Worker 
407*fb1b10abSAndroid Build Coastguard Worker         if (pc->Width <= 0) {
408*fb1b10abSAndroid Build Coastguard Worker           pc->Width = w;
409*fb1b10abSAndroid Build Coastguard Worker           vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
410*fb1b10abSAndroid Build Coastguard Worker                              "Invalid frame width");
411*fb1b10abSAndroid Build Coastguard Worker         }
412*fb1b10abSAndroid Build Coastguard Worker 
413*fb1b10abSAndroid Build Coastguard Worker         if (pc->Height <= 0) {
414*fb1b10abSAndroid Build Coastguard Worker           pc->Height = h;
415*fb1b10abSAndroid Build Coastguard Worker           vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
416*fb1b10abSAndroid Build Coastguard Worker                              "Invalid frame height");
417*fb1b10abSAndroid Build Coastguard Worker         }
418*fb1b10abSAndroid Build Coastguard Worker 
419*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
420*fb1b10abSAndroid Build Coastguard Worker         if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd)) {
421*fb1b10abSAndroid Build Coastguard Worker           vp8mt_de_alloc_temp_buffers(pbi, pc->mb_rows);
422*fb1b10abSAndroid Build Coastguard Worker         }
423*fb1b10abSAndroid Build Coastguard Worker #endif
424*fb1b10abSAndroid Build Coastguard Worker 
425*fb1b10abSAndroid Build Coastguard Worker         if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height)) {
426*fb1b10abSAndroid Build Coastguard Worker           vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
427*fb1b10abSAndroid Build Coastguard Worker                              "Failed to allocate frame buffers");
428*fb1b10abSAndroid Build Coastguard Worker         }
429*fb1b10abSAndroid Build Coastguard Worker 
430*fb1b10abSAndroid Build Coastguard Worker         xd->pre = pc->yv12_fb[pc->lst_fb_idx];
431*fb1b10abSAndroid Build Coastguard Worker         xd->dst = pc->yv12_fb[pc->new_fb_idx];
432*fb1b10abSAndroid Build Coastguard Worker 
433*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
434*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < pbi->allocated_decoding_thread_count; ++i) {
435*fb1b10abSAndroid Build Coastguard Worker           pbi->mb_row_di[i].mbd.dst = pc->yv12_fb[pc->new_fb_idx];
436*fb1b10abSAndroid Build Coastguard Worker           vp8_build_block_doffsets(&pbi->mb_row_di[i].mbd);
437*fb1b10abSAndroid Build Coastguard Worker         }
438*fb1b10abSAndroid Build Coastguard Worker #endif
439*fb1b10abSAndroid Build Coastguard Worker         vp8_build_block_doffsets(&pbi->mb);
440*fb1b10abSAndroid Build Coastguard Worker 
441*fb1b10abSAndroid Build Coastguard Worker /* allocate memory for last frame MODE_INFO array */
442*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_ERROR_CONCEALMENT
443*fb1b10abSAndroid Build Coastguard Worker 
444*fb1b10abSAndroid Build Coastguard Worker         if (pbi->ec_enabled) {
445*fb1b10abSAndroid Build Coastguard Worker           /* old prev_mip was released by vp8_de_alloc_frame_buffers()
446*fb1b10abSAndroid Build Coastguard Worker            * called in vp8_alloc_frame_buffers() */
447*fb1b10abSAndroid Build Coastguard Worker           pc->prev_mip = vpx_calloc((pc->mb_cols + 1) * (pc->mb_rows + 1),
448*fb1b10abSAndroid Build Coastguard Worker                                     sizeof(MODE_INFO));
449*fb1b10abSAndroid Build Coastguard Worker 
450*fb1b10abSAndroid Build Coastguard Worker           if (!pc->prev_mip) {
451*fb1b10abSAndroid Build Coastguard Worker             vp8_de_alloc_frame_buffers(pc);
452*fb1b10abSAndroid Build Coastguard Worker             vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
453*fb1b10abSAndroid Build Coastguard Worker                                "Failed to allocate"
454*fb1b10abSAndroid Build Coastguard Worker                                "last frame MODE_INFO array");
455*fb1b10abSAndroid Build Coastguard Worker           }
456*fb1b10abSAndroid Build Coastguard Worker 
457*fb1b10abSAndroid Build Coastguard Worker           pc->prev_mi = pc->prev_mip + pc->mode_info_stride + 1;
458*fb1b10abSAndroid Build Coastguard Worker 
459*fb1b10abSAndroid Build Coastguard Worker           if (vp8_alloc_overlap_lists(pbi))
460*fb1b10abSAndroid Build Coastguard Worker             vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
461*fb1b10abSAndroid Build Coastguard Worker                                "Failed to allocate overlap lists "
462*fb1b10abSAndroid Build Coastguard Worker                                "for error concealment");
463*fb1b10abSAndroid Build Coastguard Worker         }
464*fb1b10abSAndroid Build Coastguard Worker 
465*fb1b10abSAndroid Build Coastguard Worker #endif
466*fb1b10abSAndroid Build Coastguard Worker 
467*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
468*fb1b10abSAndroid Build Coastguard Worker         if (vpx_atomic_load_acquire(&pbi->b_multithreaded_rd)) {
469*fb1b10abSAndroid Build Coastguard Worker           vp8mt_alloc_temp_buffers(pbi, pc->Width, 0);
470*fb1b10abSAndroid Build Coastguard Worker         }
471*fb1b10abSAndroid Build Coastguard Worker #endif
472*fb1b10abSAndroid Build Coastguard Worker       }
473*fb1b10abSAndroid Build Coastguard Worker 
474*fb1b10abSAndroid Build Coastguard Worker       pbi->common.error.setjmp = 0;
475*fb1b10abSAndroid Build Coastguard Worker 
476*fb1b10abSAndroid Build Coastguard Worker       /* required to get past the first get_free_fb() call */
477*fb1b10abSAndroid Build Coastguard Worker       pbi->common.fb_idx_ref_cnt[0] = 0;
478*fb1b10abSAndroid Build Coastguard Worker     }
479*fb1b10abSAndroid Build Coastguard Worker 
480*fb1b10abSAndroid Build Coastguard Worker     if (setjmp(pbi->common.error.jmp)) {
481*fb1b10abSAndroid Build Coastguard Worker       vpx_clear_system_state();
482*fb1b10abSAndroid Build Coastguard Worker       /* We do not know if the missing frame(s) was supposed to update
483*fb1b10abSAndroid Build Coastguard Worker        * any of the reference buffers, but we act conservative and
484*fb1b10abSAndroid Build Coastguard Worker        * mark only the last buffer as corrupted.
485*fb1b10abSAndroid Build Coastguard Worker        */
486*fb1b10abSAndroid Build Coastguard Worker       pc->yv12_fb[pc->lst_fb_idx].corrupted = 1;
487*fb1b10abSAndroid Build Coastguard Worker 
488*fb1b10abSAndroid Build Coastguard Worker       if (pc->fb_idx_ref_cnt[pc->new_fb_idx] > 0) {
489*fb1b10abSAndroid Build Coastguard Worker         pc->fb_idx_ref_cnt[pc->new_fb_idx]--;
490*fb1b10abSAndroid Build Coastguard Worker       }
491*fb1b10abSAndroid Build Coastguard Worker       pbi->common.error.setjmp = 0;
492*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
493*fb1b10abSAndroid Build Coastguard Worker       if (pbi->restart_threads) {
494*fb1b10abSAndroid Build Coastguard Worker         ctx->si.w = 0;
495*fb1b10abSAndroid Build Coastguard Worker         ctx->si.h = 0;
496*fb1b10abSAndroid Build Coastguard Worker         ctx->restart_threads = 1;
497*fb1b10abSAndroid Build Coastguard Worker       }
498*fb1b10abSAndroid Build Coastguard Worker #endif
499*fb1b10abSAndroid Build Coastguard Worker       res = update_error_state(ctx, &pbi->common.error);
500*fb1b10abSAndroid Build Coastguard Worker       return res;
501*fb1b10abSAndroid Build Coastguard Worker     }
502*fb1b10abSAndroid Build Coastguard Worker 
503*fb1b10abSAndroid Build Coastguard Worker     pbi->common.error.setjmp = 1;
504*fb1b10abSAndroid Build Coastguard Worker 
505*fb1b10abSAndroid Build Coastguard Worker     /* update the pbi fragment data */
506*fb1b10abSAndroid Build Coastguard Worker     pbi->fragments = ctx->fragments;
507*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
508*fb1b10abSAndroid Build Coastguard Worker     pbi->restart_threads = 0;
509*fb1b10abSAndroid Build Coastguard Worker #endif
510*fb1b10abSAndroid Build Coastguard Worker     ctx->user_priv = user_priv;
511*fb1b10abSAndroid Build Coastguard Worker     if (vp8dx_receive_compressed_data(pbi)) {
512*fb1b10abSAndroid Build Coastguard Worker       res = update_error_state(ctx, &pbi->common.error);
513*fb1b10abSAndroid Build Coastguard Worker     }
514*fb1b10abSAndroid Build Coastguard Worker 
515*fb1b10abSAndroid Build Coastguard Worker     /* get ready for the next series of fragments */
516*fb1b10abSAndroid Build Coastguard Worker     ctx->fragments.count = 0;
517*fb1b10abSAndroid Build Coastguard Worker     pbi->common.error.setjmp = 0;
518*fb1b10abSAndroid Build Coastguard Worker   }
519*fb1b10abSAndroid Build Coastguard Worker 
520*fb1b10abSAndroid Build Coastguard Worker   return res;
521*fb1b10abSAndroid Build Coastguard Worker }
522*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_frame(vpx_codec_alg_priv_t * ctx,vpx_codec_iter_t * iter)523*fb1b10abSAndroid Build Coastguard Worker static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx,
524*fb1b10abSAndroid Build Coastguard Worker                                   vpx_codec_iter_t *iter) {
525*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t *img = NULL;
526*fb1b10abSAndroid Build Coastguard Worker 
527*fb1b10abSAndroid Build Coastguard Worker   /* iter acts as a flip flop, so an image is only returned on the first
528*fb1b10abSAndroid Build Coastguard Worker    * call to get_frame.
529*fb1b10abSAndroid Build Coastguard Worker    */
530*fb1b10abSAndroid Build Coastguard Worker   if (!(*iter) && ctx->yv12_frame_buffers.pbi[0]) {
531*fb1b10abSAndroid Build Coastguard Worker     YV12_BUFFER_CONFIG sd;
532*fb1b10abSAndroid Build Coastguard Worker     vp8_ppflags_t flags;
533*fb1b10abSAndroid Build Coastguard Worker     vp8_zero(flags);
534*fb1b10abSAndroid Build Coastguard Worker 
535*fb1b10abSAndroid Build Coastguard Worker     if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
536*fb1b10abSAndroid Build Coastguard Worker       flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag;
537*fb1b10abSAndroid Build Coastguard Worker       flags.deblocking_level = ctx->postproc_cfg.deblocking_level;
538*fb1b10abSAndroid Build Coastguard Worker       flags.noise_level = ctx->postproc_cfg.noise_level;
539*fb1b10abSAndroid Build Coastguard Worker     }
540*fb1b10abSAndroid Build Coastguard Worker 
541*fb1b10abSAndroid Build Coastguard Worker     if (0 == vp8dx_get_raw_frame(ctx->yv12_frame_buffers.pbi[0], &sd, &flags)) {
542*fb1b10abSAndroid Build Coastguard Worker       yuvconfig2image(&ctx->img, &sd, ctx->user_priv);
543*fb1b10abSAndroid Build Coastguard Worker 
544*fb1b10abSAndroid Build Coastguard Worker       img = &ctx->img;
545*fb1b10abSAndroid Build Coastguard Worker       *iter = img;
546*fb1b10abSAndroid Build Coastguard Worker     }
547*fb1b10abSAndroid Build Coastguard Worker   }
548*fb1b10abSAndroid Build Coastguard Worker 
549*fb1b10abSAndroid Build Coastguard Worker   return img;
550*fb1b10abSAndroid Build Coastguard Worker }
551*fb1b10abSAndroid Build Coastguard Worker 
image2yuvconfig(const vpx_image_t * img,YV12_BUFFER_CONFIG * yv12)552*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
553*fb1b10abSAndroid Build Coastguard Worker                                        YV12_BUFFER_CONFIG *yv12) {
554*fb1b10abSAndroid Build Coastguard Worker   const int y_w = img->d_w;
555*fb1b10abSAndroid Build Coastguard Worker   const int y_h = img->d_h;
556*fb1b10abSAndroid Build Coastguard Worker   const int uv_w = (img->d_w + 1) / 2;
557*fb1b10abSAndroid Build Coastguard Worker   const int uv_h = (img->d_h + 1) / 2;
558*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res = VPX_CODEC_OK;
559*fb1b10abSAndroid Build Coastguard Worker   yv12->y_buffer = img->planes[VPX_PLANE_Y];
560*fb1b10abSAndroid Build Coastguard Worker   yv12->u_buffer = img->planes[VPX_PLANE_U];
561*fb1b10abSAndroid Build Coastguard Worker   yv12->v_buffer = img->planes[VPX_PLANE_V];
562*fb1b10abSAndroid Build Coastguard Worker 
563*fb1b10abSAndroid Build Coastguard Worker   yv12->y_crop_width = y_w;
564*fb1b10abSAndroid Build Coastguard Worker   yv12->y_crop_height = y_h;
565*fb1b10abSAndroid Build Coastguard Worker   yv12->y_width = y_w;
566*fb1b10abSAndroid Build Coastguard Worker   yv12->y_height = y_h;
567*fb1b10abSAndroid Build Coastguard Worker   yv12->uv_crop_width = uv_w;
568*fb1b10abSAndroid Build Coastguard Worker   yv12->uv_crop_height = uv_h;
569*fb1b10abSAndroid Build Coastguard Worker   yv12->uv_width = uv_w;
570*fb1b10abSAndroid Build Coastguard Worker   yv12->uv_height = uv_h;
571*fb1b10abSAndroid Build Coastguard Worker 
572*fb1b10abSAndroid Build Coastguard Worker   yv12->y_stride = img->stride[VPX_PLANE_Y];
573*fb1b10abSAndroid Build Coastguard Worker   yv12->uv_stride = img->stride[VPX_PLANE_U];
574*fb1b10abSAndroid Build Coastguard Worker 
575*fb1b10abSAndroid Build Coastguard Worker   yv12->border = (img->stride[VPX_PLANE_Y] - img->d_w) / 2;
576*fb1b10abSAndroid Build Coastguard Worker   return res;
577*fb1b10abSAndroid Build Coastguard Worker }
578*fb1b10abSAndroid Build Coastguard Worker 
vp8_set_reference(vpx_codec_alg_priv_t * ctx,va_list args)579*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx,
580*fb1b10abSAndroid Build Coastguard Worker                                          va_list args) {
581*fb1b10abSAndroid Build Coastguard Worker   vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
582*fb1b10abSAndroid Build Coastguard Worker 
583*fb1b10abSAndroid Build Coastguard Worker   if (data) {
584*fb1b10abSAndroid Build Coastguard Worker     vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
585*fb1b10abSAndroid Build Coastguard Worker     YV12_BUFFER_CONFIG sd;
586*fb1b10abSAndroid Build Coastguard Worker 
587*fb1b10abSAndroid Build Coastguard Worker     image2yuvconfig(&frame->img, &sd);
588*fb1b10abSAndroid Build Coastguard Worker 
589*fb1b10abSAndroid Build Coastguard Worker     return vp8dx_set_reference(ctx->yv12_frame_buffers.pbi[0],
590*fb1b10abSAndroid Build Coastguard Worker                                frame->frame_type, &sd);
591*fb1b10abSAndroid Build Coastguard Worker   } else {
592*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
593*fb1b10abSAndroid Build Coastguard Worker   }
594*fb1b10abSAndroid Build Coastguard Worker }
595*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_reference(vpx_codec_alg_priv_t * ctx,va_list args)596*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx,
597*fb1b10abSAndroid Build Coastguard Worker                                          va_list args) {
598*fb1b10abSAndroid Build Coastguard Worker   vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
599*fb1b10abSAndroid Build Coastguard Worker 
600*fb1b10abSAndroid Build Coastguard Worker   if (data) {
601*fb1b10abSAndroid Build Coastguard Worker     vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data;
602*fb1b10abSAndroid Build Coastguard Worker     YV12_BUFFER_CONFIG sd;
603*fb1b10abSAndroid Build Coastguard Worker 
604*fb1b10abSAndroid Build Coastguard Worker     image2yuvconfig(&frame->img, &sd);
605*fb1b10abSAndroid Build Coastguard Worker 
606*fb1b10abSAndroid Build Coastguard Worker     return vp8dx_get_reference(ctx->yv12_frame_buffers.pbi[0],
607*fb1b10abSAndroid Build Coastguard Worker                                frame->frame_type, &sd);
608*fb1b10abSAndroid Build Coastguard Worker   } else {
609*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
610*fb1b10abSAndroid Build Coastguard Worker   }
611*fb1b10abSAndroid Build Coastguard Worker }
612*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_quantizer(vpx_codec_alg_priv_t * ctx,va_list args)613*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_quantizer(vpx_codec_alg_priv_t *ctx,
614*fb1b10abSAndroid Build Coastguard Worker                                          va_list args) {
615*fb1b10abSAndroid Build Coastguard Worker   int *const arg = va_arg(args, int *);
616*fb1b10abSAndroid Build Coastguard Worker   VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0];
617*fb1b10abSAndroid Build Coastguard Worker   if (arg == NULL) return VPX_CODEC_INVALID_PARAM;
618*fb1b10abSAndroid Build Coastguard Worker   if (pbi == NULL) return VPX_CODEC_CORRUPT_FRAME;
619*fb1b10abSAndroid Build Coastguard Worker   *arg = vp8dx_get_quantizer(pbi);
620*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_OK;
621*fb1b10abSAndroid Build Coastguard Worker }
622*fb1b10abSAndroid Build Coastguard Worker 
vp8_set_postproc(vpx_codec_alg_priv_t * ctx,va_list args)623*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_set_postproc(vpx_codec_alg_priv_t *ctx,
624*fb1b10abSAndroid Build Coastguard Worker                                         va_list args) {
625*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_POSTPROC
626*fb1b10abSAndroid Build Coastguard Worker   vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
627*fb1b10abSAndroid Build Coastguard Worker 
628*fb1b10abSAndroid Build Coastguard Worker   if (data) {
629*fb1b10abSAndroid Build Coastguard Worker     ctx->postproc_cfg_set = 1;
630*fb1b10abSAndroid Build Coastguard Worker     ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
631*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_OK;
632*fb1b10abSAndroid Build Coastguard Worker   } else {
633*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
634*fb1b10abSAndroid Build Coastguard Worker   }
635*fb1b10abSAndroid Build Coastguard Worker 
636*fb1b10abSAndroid Build Coastguard Worker #else
637*fb1b10abSAndroid Build Coastguard Worker   (void)ctx;
638*fb1b10abSAndroid Build Coastguard Worker   (void)args;
639*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_INCAPABLE;
640*fb1b10abSAndroid Build Coastguard Worker #endif
641*fb1b10abSAndroid Build Coastguard Worker }
642*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_last_ref_updates(vpx_codec_alg_priv_t * ctx,va_list args)643*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
644*fb1b10abSAndroid Build Coastguard Worker                                                 va_list args) {
645*fb1b10abSAndroid Build Coastguard Worker   int *update_info = va_arg(args, int *);
646*fb1b10abSAndroid Build Coastguard Worker 
647*fb1b10abSAndroid Build Coastguard Worker   if (update_info) {
648*fb1b10abSAndroid Build Coastguard Worker     VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0];
649*fb1b10abSAndroid Build Coastguard Worker     if (pbi == NULL) return VPX_CODEC_CORRUPT_FRAME;
650*fb1b10abSAndroid Build Coastguard Worker 
651*fb1b10abSAndroid Build Coastguard Worker     *update_info = pbi->common.refresh_alt_ref_frame * (int)VP8_ALTR_FRAME +
652*fb1b10abSAndroid Build Coastguard Worker                    pbi->common.refresh_golden_frame * (int)VP8_GOLD_FRAME +
653*fb1b10abSAndroid Build Coastguard Worker                    pbi->common.refresh_last_frame * (int)VP8_LAST_FRAME;
654*fb1b10abSAndroid Build Coastguard Worker 
655*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_OK;
656*fb1b10abSAndroid Build Coastguard Worker   } else {
657*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
658*fb1b10abSAndroid Build Coastguard Worker   }
659*fb1b10abSAndroid Build Coastguard Worker }
660*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_last_ref_frame(vpx_codec_alg_priv_t * ctx,va_list args)661*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx,
662*fb1b10abSAndroid Build Coastguard Worker                                               va_list args) {
663*fb1b10abSAndroid Build Coastguard Worker   int *ref_info = va_arg(args, int *);
664*fb1b10abSAndroid Build Coastguard Worker 
665*fb1b10abSAndroid Build Coastguard Worker   if (ref_info) {
666*fb1b10abSAndroid Build Coastguard Worker     VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0];
667*fb1b10abSAndroid Build Coastguard Worker     if (pbi) {
668*fb1b10abSAndroid Build Coastguard Worker       VP8_COMMON *oci = &pbi->common;
669*fb1b10abSAndroid Build Coastguard Worker       *ref_info =
670*fb1b10abSAndroid Build Coastguard Worker           (vp8dx_references_buffer(oci, ALTREF_FRAME) ? VP8_ALTR_FRAME : 0) |
671*fb1b10abSAndroid Build Coastguard Worker           (vp8dx_references_buffer(oci, GOLDEN_FRAME) ? VP8_GOLD_FRAME : 0) |
672*fb1b10abSAndroid Build Coastguard Worker           (vp8dx_references_buffer(oci, LAST_FRAME) ? VP8_LAST_FRAME : 0);
673*fb1b10abSAndroid Build Coastguard Worker       return VPX_CODEC_OK;
674*fb1b10abSAndroid Build Coastguard Worker     } else {
675*fb1b10abSAndroid Build Coastguard Worker       return VPX_CODEC_CORRUPT_FRAME;
676*fb1b10abSAndroid Build Coastguard Worker     }
677*fb1b10abSAndroid Build Coastguard Worker   } else {
678*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
679*fb1b10abSAndroid Build Coastguard Worker   }
680*fb1b10abSAndroid Build Coastguard Worker }
681*fb1b10abSAndroid Build Coastguard Worker 
vp8_get_frame_corrupted(vpx_codec_alg_priv_t * ctx,va_list args)682*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
683*fb1b10abSAndroid Build Coastguard Worker                                                va_list args) {
684*fb1b10abSAndroid Build Coastguard Worker   int *corrupted = va_arg(args, int *);
685*fb1b10abSAndroid Build Coastguard Worker   VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0];
686*fb1b10abSAndroid Build Coastguard Worker 
687*fb1b10abSAndroid Build Coastguard Worker   if (corrupted && pbi) {
688*fb1b10abSAndroid Build Coastguard Worker     const YV12_BUFFER_CONFIG *const frame = pbi->common.frame_to_show;
689*fb1b10abSAndroid Build Coastguard Worker     if (frame == NULL) return VPX_CODEC_ERROR;
690*fb1b10abSAndroid Build Coastguard Worker     *corrupted = frame->corrupted;
691*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_OK;
692*fb1b10abSAndroid Build Coastguard Worker   } else {
693*fb1b10abSAndroid Build Coastguard Worker     return VPX_CODEC_INVALID_PARAM;
694*fb1b10abSAndroid Build Coastguard Worker   }
695*fb1b10abSAndroid Build Coastguard Worker }
696*fb1b10abSAndroid Build Coastguard Worker 
vp8_set_decryptor(vpx_codec_alg_priv_t * ctx,va_list args)697*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t vp8_set_decryptor(vpx_codec_alg_priv_t *ctx,
698*fb1b10abSAndroid Build Coastguard Worker                                          va_list args) {
699*fb1b10abSAndroid Build Coastguard Worker   vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
700*fb1b10abSAndroid Build Coastguard Worker 
701*fb1b10abSAndroid Build Coastguard Worker   if (init) {
702*fb1b10abSAndroid Build Coastguard Worker     ctx->decrypt_cb = init->decrypt_cb;
703*fb1b10abSAndroid Build Coastguard Worker     ctx->decrypt_state = init->decrypt_state;
704*fb1b10abSAndroid Build Coastguard Worker   } else {
705*fb1b10abSAndroid Build Coastguard Worker     ctx->decrypt_cb = NULL;
706*fb1b10abSAndroid Build Coastguard Worker     ctx->decrypt_state = NULL;
707*fb1b10abSAndroid Build Coastguard Worker   }
708*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_OK;
709*fb1b10abSAndroid Build Coastguard Worker }
710*fb1b10abSAndroid Build Coastguard Worker 
711*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = {
712*fb1b10abSAndroid Build Coastguard Worker   { VP8_SET_REFERENCE, vp8_set_reference },
713*fb1b10abSAndroid Build Coastguard Worker   { VP8_COPY_REFERENCE, vp8_get_reference },
714*fb1b10abSAndroid Build Coastguard Worker   { VP8_SET_POSTPROC, vp8_set_postproc },
715*fb1b10abSAndroid Build Coastguard Worker   { VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates },
716*fb1b10abSAndroid Build Coastguard Worker   { VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted },
717*fb1b10abSAndroid Build Coastguard Worker   { VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame },
718*fb1b10abSAndroid Build Coastguard Worker   { VPXD_GET_LAST_QUANTIZER, vp8_get_quantizer },
719*fb1b10abSAndroid Build Coastguard Worker   { VPXD_SET_DECRYPTOR, vp8_set_decryptor },
720*fb1b10abSAndroid Build Coastguard Worker   { -1, NULL },
721*fb1b10abSAndroid Build Coastguard Worker };
722*fb1b10abSAndroid Build Coastguard Worker 
723*fb1b10abSAndroid Build Coastguard Worker #ifndef VERSION_STRING
724*fb1b10abSAndroid Build Coastguard Worker #define VERSION_STRING
725*fb1b10abSAndroid Build Coastguard Worker #endif
726*fb1b10abSAndroid Build Coastguard Worker CODEC_INTERFACE(vpx_codec_vp8_dx) = {
727*fb1b10abSAndroid Build Coastguard Worker   "WebM Project VP8 Decoder" VERSION_STRING,
728*fb1b10abSAndroid Build Coastguard Worker   VPX_CODEC_INTERNAL_ABI_VERSION,
729*fb1b10abSAndroid Build Coastguard Worker   VPX_CODEC_CAP_DECODER | VP8_CAP_POSTPROC | VP8_CAP_ERROR_CONCEALMENT |
730*fb1b10abSAndroid Build Coastguard Worker       VPX_CODEC_CAP_INPUT_FRAGMENTS,
731*fb1b10abSAndroid Build Coastguard Worker   /* vpx_codec_caps_t          caps; */
732*fb1b10abSAndroid Build Coastguard Worker   vp8_init,     /* vpx_codec_init_fn_t       init; */
733*fb1b10abSAndroid Build Coastguard Worker   vp8_destroy,  /* vpx_codec_destroy_fn_t    destroy; */
734*fb1b10abSAndroid Build Coastguard Worker   vp8_ctf_maps, /* vpx_codec_ctrl_fn_map_t  *ctrl_maps; */
735*fb1b10abSAndroid Build Coastguard Worker   {
736*fb1b10abSAndroid Build Coastguard Worker       vp8_peek_si,   /* vpx_codec_peek_si_fn_t    peek_si; */
737*fb1b10abSAndroid Build Coastguard Worker       vp8_get_si,    /* vpx_codec_get_si_fn_t     get_si; */
738*fb1b10abSAndroid Build Coastguard Worker       vp8_decode,    /* vpx_codec_decode_fn_t     decode; */
739*fb1b10abSAndroid Build Coastguard Worker       vp8_get_frame, /* vpx_codec_frame_get_fn_t  frame_get; */
740*fb1b10abSAndroid Build Coastguard Worker       NULL,
741*fb1b10abSAndroid Build Coastguard Worker   },
742*fb1b10abSAndroid Build Coastguard Worker   {
743*fb1b10abSAndroid Build Coastguard Worker       /* encoder functions */
744*fb1b10abSAndroid Build Coastguard Worker       0, NULL, /* vpx_codec_enc_cfg_map_t */
745*fb1b10abSAndroid Build Coastguard Worker       NULL,    /* vpx_codec_encode_fn_t */
746*fb1b10abSAndroid Build Coastguard Worker       NULL,    /* vpx_codec_get_cx_data_fn_t */
747*fb1b10abSAndroid Build Coastguard Worker       NULL,    /* vpx_codec_enc_config_set_fn_t */
748*fb1b10abSAndroid Build Coastguard Worker       NULL,    /* vpx_codec_get_global_headers_fn_t */
749*fb1b10abSAndroid Build Coastguard Worker       NULL,    /* vpx_codec_get_preview_frame_fn_t */
750*fb1b10abSAndroid Build Coastguard Worker       NULL     /* vpx_codec_enc_mr_get_mem_loc_fn_t */
751*fb1b10abSAndroid Build Coastguard Worker   }
752*fb1b10abSAndroid Build Coastguard Worker };
753