Merge "VPX: refactor vpx_idct16x16_1_add_sse2()"
[aom.git] / vp10 / vp10_dx_iface.c
blob33337a4bd2a92c19cf7ae8cd01ea083480d1d4d6
1 /*
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.
9 */
11 #include <stdlib.h>
12 #include <string.h>
14 #include "./vpx_config.h"
15 #include "./vpx_version.h"
17 #include "vpx/internal/vpx_codec_internal.h"
18 #include "vpx/vp8dx.h"
19 #include "vpx/vpx_decoder.h"
20 #include "vpx_dsp/bitreader_buffer.h"
21 #include "vpx_dsp/vpx_dsp_common.h"
22 #include "vpx_util/vpx_thread.h"
24 #include "vp10/common/alloccommon.h"
25 #include "vp10/common/frame_buffers.h"
27 #include "vp10/decoder/decoder.h"
28 #include "vp10/decoder/decodeframe.h"
30 #include "vp10/vp10_iface_common.h"
32 #define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0)
34 typedef vpx_codec_stream_info_t vp10_stream_info_t;
36 // This limit is due to framebuffer numbers.
37 // TODO(hkuang): Remove this limit after implementing ondemand framebuffers.
38 #define FRAME_CACHE_SIZE 6 // Cache maximum 6 decoded frames.
40 typedef struct cache_frame {
41 int fb_idx;
42 vpx_image_t img;
43 } cache_frame;
45 struct vpx_codec_alg_priv {
46 vpx_codec_priv_t base;
47 vpx_codec_dec_cfg_t cfg;
48 vp10_stream_info_t si;
49 int postproc_cfg_set;
50 vp8_postproc_cfg_t postproc_cfg;
51 vpx_decrypt_cb decrypt_cb;
52 void *decrypt_state;
53 vpx_image_t img;
54 int img_avail;
55 int flushed;
56 int invert_tile_order;
57 int last_show_frame; // Index of last output frame.
58 int byte_alignment;
59 int skip_loop_filter;
61 // Frame parallel related.
62 int frame_parallel_decode; // frame-based threading.
63 VPxWorker *frame_workers;
64 int num_frame_workers;
65 int next_submit_worker_id;
66 int last_submit_worker_id;
67 int next_output_worker_id;
68 int available_threads;
69 cache_frame frame_cache[FRAME_CACHE_SIZE];
70 int frame_cache_write;
71 int frame_cache_read;
72 int num_cache_frames;
73 int need_resync; // wait for key/intra-only frame
74 // BufferPool that holds all reference frames. Shared by all the FrameWorkers.
75 BufferPool *buffer_pool;
77 // External frame buffer info to save for VP9 common.
78 void *ext_priv; // Private data associated with the external frame buffers.
79 vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
80 vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
83 static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx,
84 vpx_codec_priv_enc_mr_cfg_t *data) {
85 // This function only allocates space for the vpx_codec_alg_priv_t
86 // structure. More memory may be required at the time the stream
87 // information becomes known.
88 (void)data;
90 if (!ctx->priv) {
91 vpx_codec_alg_priv_t *const priv =
92 (vpx_codec_alg_priv_t *)vpx_calloc(1, sizeof(*priv));
93 if (priv == NULL)
94 return VPX_CODEC_MEM_ERROR;
96 ctx->priv = (vpx_codec_priv_t *)priv;
97 ctx->priv->init_flags = ctx->init_flags;
98 priv->si.sz = sizeof(priv->si);
99 priv->flushed = 0;
100 // Only do frame parallel decode when threads > 1.
101 priv->frame_parallel_decode =
102 (ctx->config.dec && (ctx->config.dec->threads > 1) &&
103 (ctx->init_flags & VPX_CODEC_USE_FRAME_THREADING)) ? 1 : 0;
104 if (ctx->config.dec) {
105 priv->cfg = *ctx->config.dec;
106 ctx->config.dec = &priv->cfg;
110 return VPX_CODEC_OK;
113 static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
114 if (ctx->frame_workers != NULL) {
115 int i;
116 for (i = 0; i < ctx->num_frame_workers; ++i) {
117 VPxWorker *const worker = &ctx->frame_workers[i];
118 FrameWorkerData *const frame_worker_data =
119 (FrameWorkerData *)worker->data1;
120 vpx_get_worker_interface()->end(worker);
121 vp10_remove_common(&frame_worker_data->pbi->common);
122 #if CONFIG_VP9_POSTPROC
123 vp10_free_postproc_buffers(&frame_worker_data->pbi->common);
124 #endif
125 vp10_decoder_remove(frame_worker_data->pbi);
126 vpx_free(frame_worker_data->scratch_buffer);
127 #if CONFIG_MULTITHREAD
128 pthread_mutex_destroy(&frame_worker_data->stats_mutex);
129 pthread_cond_destroy(&frame_worker_data->stats_cond);
130 #endif
131 vpx_free(frame_worker_data);
133 #if CONFIG_MULTITHREAD
134 pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex);
135 #endif
138 if (ctx->buffer_pool) {
139 vp10_free_ref_frame_buffers(ctx->buffer_pool);
140 vp10_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers);
143 vpx_free(ctx->frame_workers);
144 vpx_free(ctx->buffer_pool);
145 vpx_free(ctx);
146 return VPX_CODEC_OK;
149 static int parse_bitdepth_colorspace_sampling(
150 BITSTREAM_PROFILE profile, struct vpx_read_bit_buffer *rb) {
151 vpx_color_space_t color_space;
152 if (profile >= PROFILE_2)
153 rb->bit_offset += 1; // Bit-depth 10 or 12.
154 color_space = (vpx_color_space_t)vpx_rb_read_literal(rb, 3);
155 if (color_space != VPX_CS_SRGB) {
156 rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range.
157 if (profile == PROFILE_1 || profile == PROFILE_3) {
158 rb->bit_offset += 2; // subsampling x/y.
159 rb->bit_offset += 1; // unused.
161 } else {
162 if (profile == PROFILE_1 || profile == PROFILE_3) {
163 rb->bit_offset += 1; // unused
164 } else {
165 // RGB is only available in version 1.
166 return 0;
169 return 1;
172 static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
173 unsigned int data_sz,
174 vpx_codec_stream_info_t *si,
175 int *is_intra_only,
176 vpx_decrypt_cb decrypt_cb,
177 void *decrypt_state) {
178 int intra_only_flag = 0;
179 uint8_t clear_buffer[9];
181 if (data + data_sz <= data)
182 return VPX_CODEC_INVALID_PARAM;
184 si->is_kf = 0;
185 si->w = si->h = 0;
187 if (decrypt_cb) {
188 data_sz = VPXMIN(sizeof(clear_buffer), data_sz);
189 decrypt_cb(decrypt_state, data, clear_buffer, data_sz);
190 data = clear_buffer;
194 int show_frame;
195 int error_resilient;
196 struct vpx_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
197 const int frame_marker = vpx_rb_read_literal(&rb, 2);
198 const BITSTREAM_PROFILE profile = vp10_read_profile(&rb);
200 if (frame_marker != VP9_FRAME_MARKER)
201 return VPX_CODEC_UNSUP_BITSTREAM;
203 if (profile >= MAX_PROFILES)
204 return VPX_CODEC_UNSUP_BITSTREAM;
206 if ((profile >= 2 && data_sz <= 1) || data_sz < 1)
207 return VPX_CODEC_UNSUP_BITSTREAM;
209 if (vpx_rb_read_bit(&rb)) { // show an existing frame
210 vpx_rb_read_literal(&rb, 3); // Frame buffer to show.
211 return VPX_CODEC_OK;
214 if (data_sz <= 8)
215 return VPX_CODEC_UNSUP_BITSTREAM;
217 si->is_kf = !vpx_rb_read_bit(&rb);
218 show_frame = vpx_rb_read_bit(&rb);
219 error_resilient = vpx_rb_read_bit(&rb);
221 if (si->is_kf) {
222 if (!vp10_read_sync_code(&rb))
223 return VPX_CODEC_UNSUP_BITSTREAM;
225 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
226 return VPX_CODEC_UNSUP_BITSTREAM;
227 vp10_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
228 } else {
229 intra_only_flag = show_frame ? 0 : vpx_rb_read_bit(&rb);
231 rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context
233 if (intra_only_flag) {
234 if (!vp10_read_sync_code(&rb))
235 return VPX_CODEC_UNSUP_BITSTREAM;
236 if (profile > PROFILE_0) {
237 if (!parse_bitdepth_colorspace_sampling(profile, &rb))
238 return VPX_CODEC_UNSUP_BITSTREAM;
240 rb.bit_offset += REF_FRAMES; // refresh_frame_flags
241 vp10_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
245 if (is_intra_only != NULL)
246 *is_intra_only = intra_only_flag;
247 return VPX_CODEC_OK;
250 static vpx_codec_err_t decoder_peek_si(const uint8_t *data,
251 unsigned int data_sz,
252 vpx_codec_stream_info_t *si) {
253 return decoder_peek_si_internal(data, data_sz, si, NULL, NULL, NULL);
256 static vpx_codec_err_t decoder_get_si(vpx_codec_alg_priv_t *ctx,
257 vpx_codec_stream_info_t *si) {
258 const size_t sz = (si->sz >= sizeof(vp10_stream_info_t))
259 ? sizeof(vp10_stream_info_t)
260 : sizeof(vpx_codec_stream_info_t);
261 memcpy(si, &ctx->si, sz);
262 si->sz = (unsigned int)sz;
264 return VPX_CODEC_OK;
267 static void set_error_detail(vpx_codec_alg_priv_t *ctx,
268 const char *const error) {
269 ctx->base.err_detail = error;
272 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
273 const struct vpx_internal_error_info *error) {
274 if (error->error_code)
275 set_error_detail(ctx, error->has_detail ? error->detail : NULL);
277 return error->error_code;
280 static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) {
281 int i;
283 for (i = 0; i < ctx->num_frame_workers; ++i) {
284 VPxWorker *const worker = &ctx->frame_workers[i];
285 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
286 VP10_COMMON *const cm = &frame_worker_data->pbi->common;
287 BufferPool *const pool = cm->buffer_pool;
289 cm->new_fb_idx = INVALID_IDX;
290 cm->byte_alignment = ctx->byte_alignment;
291 cm->skip_loop_filter = ctx->skip_loop_filter;
293 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
294 pool->get_fb_cb = ctx->get_ext_fb_cb;
295 pool->release_fb_cb = ctx->release_ext_fb_cb;
296 pool->cb_priv = ctx->ext_priv;
297 } else {
298 pool->get_fb_cb = vp10_get_frame_buffer;
299 pool->release_fb_cb = vp10_release_frame_buffer;
301 if (vp10_alloc_internal_frame_buffers(&pool->int_frame_buffers))
302 vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
303 "Failed to initialize internal frame buffers");
305 pool->cb_priv = &pool->int_frame_buffers;
310 static void set_default_ppflags(vp8_postproc_cfg_t *cfg) {
311 cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
312 cfg->deblocking_level = 4;
313 cfg->noise_level = 0;
316 static void set_ppflags(const vpx_codec_alg_priv_t *ctx,
317 vp10_ppflags_t *flags) {
318 flags->post_proc_flag =
319 ctx->postproc_cfg.post_proc_flag;
321 flags->deblocking_level = ctx->postproc_cfg.deblocking_level;
322 flags->noise_level = ctx->postproc_cfg.noise_level;
325 static int frame_worker_hook(void *arg1, void *arg2) {
326 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)arg1;
327 const uint8_t *data = frame_worker_data->data;
328 (void)arg2;
330 frame_worker_data->result =
331 vp10_receive_compressed_data(frame_worker_data->pbi,
332 frame_worker_data->data_size,
333 &data);
334 frame_worker_data->data_end = data;
336 if (frame_worker_data->pbi->common.frame_parallel_decode) {
337 // In frame parallel decoding, a worker thread must successfully decode all
338 // the compressed data.
339 if (frame_worker_data->result != 0 ||
340 frame_worker_data->data + frame_worker_data->data_size - 1 > data) {
341 VPxWorker *const worker = frame_worker_data->pbi->frame_worker_owner;
342 BufferPool *const pool = frame_worker_data->pbi->common.buffer_pool;
343 // Signal all the other threads that are waiting for this frame.
344 vp10_frameworker_lock_stats(worker);
345 frame_worker_data->frame_context_ready = 1;
346 lock_buffer_pool(pool);
347 frame_worker_data->pbi->cur_buf->buf.corrupted = 1;
348 unlock_buffer_pool(pool);
349 frame_worker_data->pbi->need_resync = 1;
350 vp10_frameworker_signal_stats(worker);
351 vp10_frameworker_unlock_stats(worker);
352 return 0;
354 } else if (frame_worker_data->result != 0) {
355 // Check decode result in serial decode.
356 frame_worker_data->pbi->cur_buf->buf.corrupted = 1;
357 frame_worker_data->pbi->need_resync = 1;
359 return !frame_worker_data->result;
362 static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) {
363 int i;
364 const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
366 ctx->last_show_frame = -1;
367 ctx->next_submit_worker_id = 0;
368 ctx->last_submit_worker_id = 0;
369 ctx->next_output_worker_id = 0;
370 ctx->frame_cache_read = 0;
371 ctx->frame_cache_write = 0;
372 ctx->num_cache_frames = 0;
373 ctx->need_resync = 1;
374 ctx->num_frame_workers =
375 (ctx->frame_parallel_decode == 1) ? ctx->cfg.threads: 1;
376 if (ctx->num_frame_workers > MAX_DECODE_THREADS)
377 ctx->num_frame_workers = MAX_DECODE_THREADS;
378 ctx->available_threads = ctx->num_frame_workers;
379 ctx->flushed = 0;
381 ctx->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool));
382 if (ctx->buffer_pool == NULL)
383 return VPX_CODEC_MEM_ERROR;
385 #if CONFIG_MULTITHREAD
386 if (pthread_mutex_init(&ctx->buffer_pool->pool_mutex, NULL)) {
387 set_error_detail(ctx, "Failed to allocate buffer pool mutex");
388 return VPX_CODEC_MEM_ERROR;
390 #endif
392 ctx->frame_workers = (VPxWorker *)
393 vpx_malloc(ctx->num_frame_workers * sizeof(*ctx->frame_workers));
394 if (ctx->frame_workers == NULL) {
395 set_error_detail(ctx, "Failed to allocate frame_workers");
396 return VPX_CODEC_MEM_ERROR;
399 for (i = 0; i < ctx->num_frame_workers; ++i) {
400 VPxWorker *const worker = &ctx->frame_workers[i];
401 FrameWorkerData *frame_worker_data = NULL;
402 winterface->init(worker);
403 worker->data1 = vpx_memalign(32, sizeof(FrameWorkerData));
404 if (worker->data1 == NULL) {
405 set_error_detail(ctx, "Failed to allocate frame_worker_data");
406 return VPX_CODEC_MEM_ERROR;
408 frame_worker_data = (FrameWorkerData *)worker->data1;
409 frame_worker_data->pbi = vp10_decoder_create(ctx->buffer_pool);
410 if (frame_worker_data->pbi == NULL) {
411 set_error_detail(ctx, "Failed to allocate frame_worker_data");
412 return VPX_CODEC_MEM_ERROR;
414 frame_worker_data->pbi->frame_worker_owner = worker;
415 frame_worker_data->worker_id = i;
416 frame_worker_data->scratch_buffer = NULL;
417 frame_worker_data->scratch_buffer_size = 0;
418 frame_worker_data->frame_context_ready = 0;
419 frame_worker_data->received_frame = 0;
420 #if CONFIG_MULTITHREAD
421 if (pthread_mutex_init(&frame_worker_data->stats_mutex, NULL)) {
422 set_error_detail(ctx, "Failed to allocate frame_worker_data mutex");
423 return VPX_CODEC_MEM_ERROR;
426 if (pthread_cond_init(&frame_worker_data->stats_cond, NULL)) {
427 set_error_detail(ctx, "Failed to allocate frame_worker_data cond");
428 return VPX_CODEC_MEM_ERROR;
430 #endif
431 // If decoding in serial mode, FrameWorker thread could create tile worker
432 // thread or loopfilter thread.
433 frame_worker_data->pbi->max_threads =
434 (ctx->frame_parallel_decode == 0) ? ctx->cfg.threads : 0;
436 frame_worker_data->pbi->inv_tile_order = ctx->invert_tile_order;
437 frame_worker_data->pbi->common.frame_parallel_decode =
438 ctx->frame_parallel_decode;
439 worker->hook = (VPxWorkerHook)frame_worker_hook;
440 if (!winterface->reset(worker)) {
441 set_error_detail(ctx, "Frame Worker thread creation failed");
442 return VPX_CODEC_MEM_ERROR;
446 // If postprocessing was enabled by the application and a
447 // configuration has not been provided, default it.
448 if (!ctx->postproc_cfg_set &&
449 (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC))
450 set_default_ppflags(&ctx->postproc_cfg);
452 init_buffer_callbacks(ctx);
454 return VPX_CODEC_OK;
457 static INLINE void check_resync(vpx_codec_alg_priv_t *const ctx,
458 const VP10Decoder *const pbi) {
459 // Clear resync flag if worker got a key frame or intra only frame.
460 if (ctx->need_resync == 1 && pbi->need_resync == 0 &&
461 (pbi->common.intra_only || pbi->common.frame_type == KEY_FRAME))
462 ctx->need_resync = 0;
465 static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
466 const uint8_t **data, unsigned int data_sz,
467 void *user_priv, int64_t deadline) {
468 const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
469 (void)deadline;
471 // Determine the stream parameters. Note that we rely on peek_si to
472 // validate that we have a buffer that does not wrap around the top
473 // of the heap.
474 if (!ctx->si.h) {
475 int is_intra_only = 0;
476 const vpx_codec_err_t res =
477 decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only,
478 ctx->decrypt_cb, ctx->decrypt_state);
479 if (res != VPX_CODEC_OK)
480 return res;
482 if (!ctx->si.is_kf && !is_intra_only)
483 return VPX_CODEC_ERROR;
486 if (!ctx->frame_parallel_decode) {
487 VPxWorker *const worker = ctx->frame_workers;
488 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
489 frame_worker_data->data = *data;
490 frame_worker_data->data_size = data_sz;
491 frame_worker_data->user_priv = user_priv;
492 frame_worker_data->received_frame = 1;
494 // Set these even if already initialized. The caller may have changed the
495 // decrypt config between frames.
496 frame_worker_data->pbi->decrypt_cb = ctx->decrypt_cb;
497 frame_worker_data->pbi->decrypt_state = ctx->decrypt_state;
499 worker->had_error = 0;
500 winterface->execute(worker);
502 // Update data pointer after decode.
503 *data = frame_worker_data->data_end;
505 if (worker->had_error)
506 return update_error_state(ctx, &frame_worker_data->pbi->common.error);
508 check_resync(ctx, frame_worker_data->pbi);
509 } else {
510 VPxWorker *const worker = &ctx->frame_workers[ctx->next_submit_worker_id];
511 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
512 // Copy context from last worker thread to next worker thread.
513 if (ctx->next_submit_worker_id != ctx->last_submit_worker_id)
514 vp10_frameworker_copy_context(
515 &ctx->frame_workers[ctx->next_submit_worker_id],
516 &ctx->frame_workers[ctx->last_submit_worker_id]);
518 frame_worker_data->pbi->ready_for_new_data = 0;
519 // Copy the compressed data into worker's internal buffer.
520 // TODO(hkuang): Will all the workers allocate the same size
521 // as the size of the first intra frame be better? This will
522 // avoid too many deallocate and allocate.
523 if (frame_worker_data->scratch_buffer_size < data_sz) {
524 frame_worker_data->scratch_buffer =
525 (uint8_t *)vpx_realloc(frame_worker_data->scratch_buffer, data_sz);
526 if (frame_worker_data->scratch_buffer == NULL) {
527 set_error_detail(ctx, "Failed to reallocate scratch buffer");
528 return VPX_CODEC_MEM_ERROR;
530 frame_worker_data->scratch_buffer_size = data_sz;
532 frame_worker_data->data_size = data_sz;
533 memcpy(frame_worker_data->scratch_buffer, *data, data_sz);
535 frame_worker_data->frame_decoded = 0;
536 frame_worker_data->frame_context_ready = 0;
537 frame_worker_data->received_frame = 1;
538 frame_worker_data->data = frame_worker_data->scratch_buffer;
539 frame_worker_data->user_priv = user_priv;
541 if (ctx->next_submit_worker_id != ctx->last_submit_worker_id)
542 ctx->last_submit_worker_id =
543 (ctx->last_submit_worker_id + 1) % ctx->num_frame_workers;
545 ctx->next_submit_worker_id =
546 (ctx->next_submit_worker_id + 1) % ctx->num_frame_workers;
547 --ctx->available_threads;
548 worker->had_error = 0;
549 winterface->launch(worker);
552 return VPX_CODEC_OK;
555 static void wait_worker_and_cache_frame(vpx_codec_alg_priv_t *ctx) {
556 YV12_BUFFER_CONFIG sd;
557 vp10_ppflags_t flags = {0, 0, 0};
558 const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
559 VPxWorker *const worker = &ctx->frame_workers[ctx->next_output_worker_id];
560 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
561 ctx->next_output_worker_id =
562 (ctx->next_output_worker_id + 1) % ctx->num_frame_workers;
563 // TODO(hkuang): Add worker error handling here.
564 winterface->sync(worker);
565 frame_worker_data->received_frame = 0;
566 ++ctx->available_threads;
568 check_resync(ctx, frame_worker_data->pbi);
570 if (vp10_get_raw_frame(frame_worker_data->pbi, &sd, &flags) == 0) {
571 VP10_COMMON *const cm = &frame_worker_data->pbi->common;
572 RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
573 ctx->frame_cache[ctx->frame_cache_write].fb_idx = cm->new_fb_idx;
574 yuvconfig2image(&ctx->frame_cache[ctx->frame_cache_write].img, &sd,
575 frame_worker_data->user_priv);
576 ctx->frame_cache[ctx->frame_cache_write].img.fb_priv =
577 frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
578 ctx->frame_cache_write =
579 (ctx->frame_cache_write + 1) % FRAME_CACHE_SIZE;
580 ++ctx->num_cache_frames;
584 static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx,
585 const uint8_t *data, unsigned int data_sz,
586 void *user_priv, long deadline) {
587 const uint8_t *data_start = data;
588 const uint8_t * const data_end = data + data_sz;
589 vpx_codec_err_t res;
590 uint32_t frame_sizes[8];
591 int frame_count;
593 if (data == NULL && data_sz == 0) {
594 ctx->flushed = 1;
595 return VPX_CODEC_OK;
598 // Reset flushed when receiving a valid frame.
599 ctx->flushed = 0;
601 // Initialize the decoder workers on the first frame.
602 if (ctx->frame_workers == NULL) {
603 const vpx_codec_err_t res = init_decoder(ctx);
604 if (res != VPX_CODEC_OK)
605 return res;
608 res = vp10_parse_superframe_index(data, data_sz, frame_sizes, &frame_count,
609 ctx->decrypt_cb, ctx->decrypt_state);
610 if (res != VPX_CODEC_OK)
611 return res;
613 if (ctx->frame_parallel_decode) {
614 // Decode in frame parallel mode. When decoding in this mode, the frame
615 // passed to the decoder must be either a normal frame or a superframe with
616 // superframe index so the decoder could get each frame's start position
617 // in the superframe.
618 if (frame_count > 0) {
619 int i;
621 for (i = 0; i < frame_count; ++i) {
622 const uint8_t *data_start_copy = data_start;
623 const uint32_t frame_size = frame_sizes[i];
624 if (data_start < data
625 || frame_size > (uint32_t) (data_end - data_start)) {
626 set_error_detail(ctx, "Invalid frame size in index");
627 return VPX_CODEC_CORRUPT_FRAME;
630 if (ctx->available_threads == 0) {
631 // No more threads for decoding. Wait until the next output worker
632 // finishes decoding. Then copy the decoded frame into cache.
633 if (ctx->num_cache_frames < FRAME_CACHE_SIZE) {
634 wait_worker_and_cache_frame(ctx);
635 } else {
636 // TODO(hkuang): Add unit test to test this path.
637 set_error_detail(ctx, "Frame output cache is full.");
638 return VPX_CODEC_ERROR;
642 res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
643 deadline);
644 if (res != VPX_CODEC_OK)
645 return res;
646 data_start += frame_size;
648 } else {
649 if (ctx->available_threads == 0) {
650 // No more threads for decoding. Wait until the next output worker
651 // finishes decoding. Then copy the decoded frame into cache.
652 if (ctx->num_cache_frames < FRAME_CACHE_SIZE) {
653 wait_worker_and_cache_frame(ctx);
654 } else {
655 // TODO(hkuang): Add unit test to test this path.
656 set_error_detail(ctx, "Frame output cache is full.");
657 return VPX_CODEC_ERROR;
661 res = decode_one(ctx, &data, data_sz, user_priv, deadline);
662 if (res != VPX_CODEC_OK)
663 return res;
665 } else {
666 // Decode in serial mode.
667 if (frame_count > 0) {
668 int i;
670 for (i = 0; i < frame_count; ++i) {
671 const uint8_t *data_start_copy = data_start;
672 const uint32_t frame_size = frame_sizes[i];
673 vpx_codec_err_t res;
674 if (data_start < data
675 || frame_size > (uint32_t) (data_end - data_start)) {
676 set_error_detail(ctx, "Invalid frame size in index");
677 return VPX_CODEC_CORRUPT_FRAME;
680 res = decode_one(ctx, &data_start_copy, frame_size, user_priv,
681 deadline);
682 if (res != VPX_CODEC_OK)
683 return res;
685 data_start += frame_size;
687 } else {
688 while (data_start < data_end) {
689 const uint32_t frame_size = (uint32_t) (data_end - data_start);
690 const vpx_codec_err_t res = decode_one(ctx, &data_start, frame_size,
691 user_priv, deadline);
692 if (res != VPX_CODEC_OK)
693 return res;
695 // Account for suboptimal termination by the encoder.
696 while (data_start < data_end) {
697 const uint8_t marker = read_marker(ctx->decrypt_cb,
698 ctx->decrypt_state, data_start);
699 if (marker)
700 break;
701 ++data_start;
707 return res;
710 static void release_last_output_frame(vpx_codec_alg_priv_t *ctx) {
711 RefCntBuffer *const frame_bufs = ctx->buffer_pool->frame_bufs;
712 // Decrease reference count of last output frame in frame parallel mode.
713 if (ctx->frame_parallel_decode && ctx->last_show_frame >= 0) {
714 BufferPool *const pool = ctx->buffer_pool;
715 lock_buffer_pool(pool);
716 decrease_ref_count(ctx->last_show_frame, frame_bufs, pool);
717 unlock_buffer_pool(pool);
721 static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx,
722 vpx_codec_iter_t *iter) {
723 vpx_image_t *img = NULL;
725 // Only return frame when all the cpu are busy or
726 // application fluhsed the decoder in frame parallel decode.
727 if (ctx->frame_parallel_decode && ctx->available_threads > 0 &&
728 !ctx->flushed) {
729 return NULL;
732 // Output the frames in the cache first.
733 if (ctx->num_cache_frames > 0) {
734 release_last_output_frame(ctx);
735 ctx->last_show_frame = ctx->frame_cache[ctx->frame_cache_read].fb_idx;
736 if (ctx->need_resync)
737 return NULL;
738 img = &ctx->frame_cache[ctx->frame_cache_read].img;
739 ctx->frame_cache_read = (ctx->frame_cache_read + 1) % FRAME_CACHE_SIZE;
740 --ctx->num_cache_frames;
741 return img;
744 // iter acts as a flip flop, so an image is only returned on the first
745 // call to get_frame.
746 if (*iter == NULL && ctx->frame_workers != NULL) {
747 do {
748 YV12_BUFFER_CONFIG sd;
749 vp10_ppflags_t flags = {0, 0, 0};
750 const VPxWorkerInterface *const winterface = vpx_get_worker_interface();
751 VPxWorker *const worker =
752 &ctx->frame_workers[ctx->next_output_worker_id];
753 FrameWorkerData *const frame_worker_data =
754 (FrameWorkerData *)worker->data1;
755 ctx->next_output_worker_id =
756 (ctx->next_output_worker_id + 1) % ctx->num_frame_workers;
757 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)
758 set_ppflags(ctx, &flags);
759 // Wait for the frame from worker thread.
760 if (winterface->sync(worker)) {
761 // Check if worker has received any frames.
762 if (frame_worker_data->received_frame == 1) {
763 ++ctx->available_threads;
764 frame_worker_data->received_frame = 0;
765 check_resync(ctx, frame_worker_data->pbi);
767 if (vp10_get_raw_frame(frame_worker_data->pbi, &sd, &flags) == 0) {
768 VP10_COMMON *const cm = &frame_worker_data->pbi->common;
769 RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
770 release_last_output_frame(ctx);
771 ctx->last_show_frame = frame_worker_data->pbi->common.new_fb_idx;
772 if (ctx->need_resync)
773 return NULL;
774 yuvconfig2image(&ctx->img, &sd, frame_worker_data->user_priv);
775 ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
776 img = &ctx->img;
777 return img;
779 } else {
780 // Decoding failed. Release the worker thread.
781 frame_worker_data->received_frame = 0;
782 ++ctx->available_threads;
783 ctx->need_resync = 1;
784 if (ctx->flushed != 1)
785 return NULL;
787 } while (ctx->next_output_worker_id != ctx->next_submit_worker_id);
789 return NULL;
792 static vpx_codec_err_t decoder_set_fb_fn(
793 vpx_codec_alg_priv_t *ctx,
794 vpx_get_frame_buffer_cb_fn_t cb_get,
795 vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
796 if (cb_get == NULL || cb_release == NULL) {
797 return VPX_CODEC_INVALID_PARAM;
798 } else if (ctx->frame_workers == NULL) {
799 // If the decoder has already been initialized, do not accept changes to
800 // the frame buffer functions.
801 ctx->get_ext_fb_cb = cb_get;
802 ctx->release_ext_fb_cb = cb_release;
803 ctx->ext_priv = cb_priv;
804 return VPX_CODEC_OK;
807 return VPX_CODEC_ERROR;
810 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx,
811 va_list args) {
812 vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *);
814 // Only support this function in serial decode.
815 if (ctx->frame_parallel_decode) {
816 set_error_detail(ctx, "Not supported in frame parallel decode");
817 return VPX_CODEC_INCAPABLE;
820 if (data) {
821 vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data;
822 YV12_BUFFER_CONFIG sd;
823 VPxWorker *const worker = ctx->frame_workers;
824 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
825 image2yuvconfig(&frame->img, &sd);
826 return vp10_set_reference_dec(&frame_worker_data->pbi->common,
827 (VP9_REFFRAME)frame->frame_type, &sd);
828 } else {
829 return VPX_CODEC_INVALID_PARAM;
833 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx,
834 va_list args) {
835 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
837 // Only support this function in serial decode.
838 if (ctx->frame_parallel_decode) {
839 set_error_detail(ctx, "Not supported in frame parallel decode");
840 return VPX_CODEC_INCAPABLE;
843 if (data) {
844 vpx_ref_frame_t *frame = (vpx_ref_frame_t *) data;
845 YV12_BUFFER_CONFIG sd;
846 VPxWorker *const worker = ctx->frame_workers;
847 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
848 image2yuvconfig(&frame->img, &sd);
849 return vp10_copy_reference_dec(frame_worker_data->pbi,
850 (VP9_REFFRAME)frame->frame_type, &sd);
851 } else {
852 return VPX_CODEC_INVALID_PARAM;
856 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx,
857 va_list args) {
858 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
860 // Only support this function in serial decode.
861 if (ctx->frame_parallel_decode) {
862 set_error_detail(ctx, "Not supported in frame parallel decode");
863 return VPX_CODEC_INCAPABLE;
866 if (data) {
867 YV12_BUFFER_CONFIG* fb;
868 VPxWorker *const worker = ctx->frame_workers;
869 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
870 fb = get_ref_frame(&frame_worker_data->pbi->common, data->idx);
871 if (fb == NULL) return VPX_CODEC_ERROR;
872 yuvconfig2image(&data->img, fb, NULL);
873 return VPX_CODEC_OK;
874 } else {
875 return VPX_CODEC_INVALID_PARAM;
879 static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx,
880 va_list args) {
881 #if CONFIG_VP9_POSTPROC
882 vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
884 if (data) {
885 ctx->postproc_cfg_set = 1;
886 ctx->postproc_cfg = *((vp8_postproc_cfg_t *)data);
887 return VPX_CODEC_OK;
888 } else {
889 return VPX_CODEC_INVALID_PARAM;
891 #else
892 (void)ctx;
893 (void)args;
894 return VPX_CODEC_INCAPABLE;
895 #endif
898 static vpx_codec_err_t ctrl_set_dbg_options(vpx_codec_alg_priv_t *ctx,
899 va_list args) {
900 (void)ctx;
901 (void)args;
902 return VPX_CODEC_INCAPABLE;
905 static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
906 va_list args) {
907 int *const update_info = va_arg(args, int *);
909 // Only support this function in serial decode.
910 if (ctx->frame_parallel_decode) {
911 set_error_detail(ctx, "Not supported in frame parallel decode");
912 return VPX_CODEC_INCAPABLE;
915 if (update_info) {
916 if (ctx->frame_workers) {
917 VPxWorker *const worker = ctx->frame_workers;
918 FrameWorkerData *const frame_worker_data =
919 (FrameWorkerData *)worker->data1;
920 *update_info = frame_worker_data->pbi->refresh_frame_flags;
921 return VPX_CODEC_OK;
922 } else {
923 return VPX_CODEC_ERROR;
927 return VPX_CODEC_INVALID_PARAM;
930 static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
931 va_list args) {
932 int *corrupted = va_arg(args, int *);
934 if (corrupted) {
935 if (ctx->frame_workers) {
936 VPxWorker *const worker = ctx->frame_workers;
937 FrameWorkerData *const frame_worker_data =
938 (FrameWorkerData *)worker->data1;
939 RefCntBuffer *const frame_bufs =
940 frame_worker_data->pbi->common.buffer_pool->frame_bufs;
941 if (frame_worker_data->pbi->common.frame_to_show == NULL)
942 return VPX_CODEC_ERROR;
943 if (ctx->last_show_frame >= 0)
944 *corrupted = frame_bufs[ctx->last_show_frame].buf.corrupted;
945 return VPX_CODEC_OK;
946 } else {
947 return VPX_CODEC_ERROR;
951 return VPX_CODEC_INVALID_PARAM;
954 static vpx_codec_err_t ctrl_get_frame_size(vpx_codec_alg_priv_t *ctx,
955 va_list args) {
956 int *const frame_size = va_arg(args, int *);
958 // Only support this function in serial decode.
959 if (ctx->frame_parallel_decode) {
960 set_error_detail(ctx, "Not supported in frame parallel decode");
961 return VPX_CODEC_INCAPABLE;
964 if (frame_size) {
965 if (ctx->frame_workers) {
966 VPxWorker *const worker = ctx->frame_workers;
967 FrameWorkerData *const frame_worker_data =
968 (FrameWorkerData *)worker->data1;
969 const VP10_COMMON *const cm = &frame_worker_data->pbi->common;
970 frame_size[0] = cm->width;
971 frame_size[1] = cm->height;
972 return VPX_CODEC_OK;
973 } else {
974 return VPX_CODEC_ERROR;
978 return VPX_CODEC_INVALID_PARAM;
981 static vpx_codec_err_t ctrl_get_render_size(vpx_codec_alg_priv_t *ctx,
982 va_list args) {
983 int *const render_size = va_arg(args, int *);
985 // Only support this function in serial decode.
986 if (ctx->frame_parallel_decode) {
987 set_error_detail(ctx, "Not supported in frame parallel decode");
988 return VPX_CODEC_INCAPABLE;
991 if (render_size) {
992 if (ctx->frame_workers) {
993 VPxWorker *const worker = ctx->frame_workers;
994 FrameWorkerData *const frame_worker_data =
995 (FrameWorkerData *)worker->data1;
996 const VP10_COMMON *const cm = &frame_worker_data->pbi->common;
997 render_size[0] = cm->render_width;
998 render_size[1] = cm->render_height;
999 return VPX_CODEC_OK;
1000 } else {
1001 return VPX_CODEC_ERROR;
1005 return VPX_CODEC_INVALID_PARAM;
1008 static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx,
1009 va_list args) {
1010 unsigned int *const bit_depth = va_arg(args, unsigned int *);
1011 VPxWorker *const worker = &ctx->frame_workers[ctx->next_output_worker_id];
1013 if (bit_depth) {
1014 if (worker) {
1015 FrameWorkerData *const frame_worker_data =
1016 (FrameWorkerData *)worker->data1;
1017 const VP10_COMMON *const cm = &frame_worker_data->pbi->common;
1018 *bit_depth = cm->bit_depth;
1019 return VPX_CODEC_OK;
1020 } else {
1021 return VPX_CODEC_ERROR;
1025 return VPX_CODEC_INVALID_PARAM;
1028 static vpx_codec_err_t ctrl_set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
1029 va_list args) {
1030 ctx->invert_tile_order = va_arg(args, int);
1031 return VPX_CODEC_OK;
1034 static vpx_codec_err_t ctrl_set_decryptor(vpx_codec_alg_priv_t *ctx,
1035 va_list args) {
1036 vpx_decrypt_init *init = va_arg(args, vpx_decrypt_init *);
1037 ctx->decrypt_cb = init ? init->decrypt_cb : NULL;
1038 ctx->decrypt_state = init ? init->decrypt_state : NULL;
1039 return VPX_CODEC_OK;
1042 static vpx_codec_err_t ctrl_set_byte_alignment(vpx_codec_alg_priv_t *ctx,
1043 va_list args) {
1044 const int legacy_byte_alignment = 0;
1045 const int min_byte_alignment = 32;
1046 const int max_byte_alignment = 1024;
1047 const int byte_alignment = va_arg(args, int);
1049 if (byte_alignment != legacy_byte_alignment &&
1050 (byte_alignment < min_byte_alignment ||
1051 byte_alignment > max_byte_alignment ||
1052 (byte_alignment & (byte_alignment - 1)) != 0))
1053 return VPX_CODEC_INVALID_PARAM;
1055 ctx->byte_alignment = byte_alignment;
1056 if (ctx->frame_workers) {
1057 VPxWorker *const worker = ctx->frame_workers;
1058 FrameWorkerData *const frame_worker_data =
1059 (FrameWorkerData *)worker->data1;
1060 frame_worker_data->pbi->common.byte_alignment = byte_alignment;
1062 return VPX_CODEC_OK;
1065 static vpx_codec_err_t ctrl_set_skip_loop_filter(vpx_codec_alg_priv_t *ctx,
1066 va_list args) {
1067 ctx->skip_loop_filter = va_arg(args, int);
1069 if (ctx->frame_workers) {
1070 VPxWorker *const worker = ctx->frame_workers;
1071 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1;
1072 frame_worker_data->pbi->common.skip_loop_filter = ctx->skip_loop_filter;
1075 return VPX_CODEC_OK;
1078 static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = {
1079 {VP8_COPY_REFERENCE, ctrl_copy_reference},
1081 // Setters
1082 {VP8_SET_REFERENCE, ctrl_set_reference},
1083 {VP8_SET_POSTPROC, ctrl_set_postproc},
1084 {VP8_SET_DBG_COLOR_REF_FRAME, ctrl_set_dbg_options},
1085 {VP8_SET_DBG_COLOR_MB_MODES, ctrl_set_dbg_options},
1086 {VP8_SET_DBG_COLOR_B_MODES, ctrl_set_dbg_options},
1087 {VP8_SET_DBG_DISPLAY_MV, ctrl_set_dbg_options},
1088 {VP9_INVERT_TILE_DECODE_ORDER, ctrl_set_invert_tile_order},
1089 {VPXD_SET_DECRYPTOR, ctrl_set_decryptor},
1090 {VP9_SET_BYTE_ALIGNMENT, ctrl_set_byte_alignment},
1091 {VP9_SET_SKIP_LOOP_FILTER, ctrl_set_skip_loop_filter},
1093 // Getters
1094 {VP8D_GET_LAST_REF_UPDATES, ctrl_get_last_ref_updates},
1095 {VP8D_GET_FRAME_CORRUPTED, ctrl_get_frame_corrupted},
1096 {VP9_GET_REFERENCE, ctrl_get_reference},
1097 {VP9D_GET_DISPLAY_SIZE, ctrl_get_render_size},
1098 {VP9D_GET_BIT_DEPTH, ctrl_get_bit_depth},
1099 {VP9D_GET_FRAME_SIZE, ctrl_get_frame_size},
1101 { -1, NULL},
1104 #ifndef VERSION_STRING
1105 #define VERSION_STRING
1106 #endif
1107 CODEC_INTERFACE(vpx_codec_vp10_dx) = {
1108 "WebM Project VP10 Decoder" VERSION_STRING,
1109 VPX_CODEC_INTERNAL_ABI_VERSION,
1110 VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
1111 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER, // vpx_codec_caps_t
1112 decoder_init, // vpx_codec_init_fn_t
1113 decoder_destroy, // vpx_codec_destroy_fn_t
1114 decoder_ctrl_maps, // vpx_codec_ctrl_fn_map_t
1115 { // NOLINT
1116 decoder_peek_si, // vpx_codec_peek_si_fn_t
1117 decoder_get_si, // vpx_codec_get_si_fn_t
1118 decoder_decode, // vpx_codec_decode_fn_t
1119 decoder_get_frame, // vpx_codec_frame_get_fn_t
1120 decoder_set_fb_fn, // vpx_codec_set_fb_fn_t
1122 { // NOLINT
1124 NULL, // vpx_codec_enc_cfg_map_t
1125 NULL, // vpx_codec_encode_fn_t
1126 NULL, // vpx_codec_get_cx_data_fn_t
1127 NULL, // vpx_codec_enc_config_set_fn_t
1128 NULL, // vpx_codec_get_global_headers_fn_t
1129 NULL, // vpx_codec_get_preview_frame_fn_t
1130 NULL // vpx_codec_enc_mr_get_mem_loc_fn_t