2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
14 #include "./vpx_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
{
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
;
50 vp8_postproc_cfg_t postproc_cfg
;
51 vpx_decrypt_cb decrypt_cb
;
56 int invert_tile_order
;
57 int last_show_frame
; // Index of last output frame.
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
;
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.
91 vpx_codec_alg_priv_t
*const priv
=
92 (vpx_codec_alg_priv_t
*)vpx_calloc(1, sizeof(*priv
));
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
);
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
;
113 static vpx_codec_err_t
decoder_destroy(vpx_codec_alg_priv_t
*ctx
) {
114 if (ctx
->frame_workers
!= NULL
) {
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
);
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
);
131 vpx_free(frame_worker_data
);
133 #if CONFIG_MULTITHREAD
134 pthread_mutex_destroy(&ctx
->buffer_pool
->pool_mutex
);
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
);
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.
162 if (profile
== PROFILE_1
|| profile
== PROFILE_3
) {
163 rb
->bit_offset
+= 1; // unused
165 // RGB is only available in version 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
,
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
;
188 data_sz
= VPXMIN(sizeof(clear_buffer
), data_sz
);
189 decrypt_cb(decrypt_state
, data
, clear_buffer
, data_sz
);
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.
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
);
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
);
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
;
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
;
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
) {
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
;
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
;
330 frame_worker_data
->result
=
331 vp10_receive_compressed_data(frame_worker_data
->pbi
,
332 frame_worker_data
->data_size
,
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
);
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
) {
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
;
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
;
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
;
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
);
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();
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
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
)
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
);
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
);
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
;
590 uint32_t frame_sizes
[8];
593 if (data
== NULL
&& data_sz
== 0) {
598 // Reset flushed when receiving a valid frame.
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
)
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
)
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) {
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
);
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
,
644 if (res
!= VPX_CODEC_OK
)
646 data_start
+= frame_size
;
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
);
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
)
666 // Decode in serial mode.
667 if (frame_count
> 0) {
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
];
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
,
682 if (res
!= VPX_CODEC_OK
)
685 data_start
+= frame_size
;
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
)
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
);
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 &&
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
)
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
;
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
) {
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
)
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
;
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)
787 } while (ctx
->next_output_worker_id
!= ctx
->next_submit_worker_id
);
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
;
807 return VPX_CODEC_ERROR
;
810 static vpx_codec_err_t
ctrl_set_reference(vpx_codec_alg_priv_t
*ctx
,
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
;
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
);
829 return VPX_CODEC_INVALID_PARAM
;
833 static vpx_codec_err_t
ctrl_copy_reference(vpx_codec_alg_priv_t
*ctx
,
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
;
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
);
852 return VPX_CODEC_INVALID_PARAM
;
856 static vpx_codec_err_t
ctrl_get_reference(vpx_codec_alg_priv_t
*ctx
,
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
;
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
);
875 return VPX_CODEC_INVALID_PARAM
;
879 static vpx_codec_err_t
ctrl_set_postproc(vpx_codec_alg_priv_t
*ctx
,
881 #if CONFIG_VP9_POSTPROC
882 vp8_postproc_cfg_t
*data
= va_arg(args
, vp8_postproc_cfg_t
*);
885 ctx
->postproc_cfg_set
= 1;
886 ctx
->postproc_cfg
= *((vp8_postproc_cfg_t
*)data
);
889 return VPX_CODEC_INVALID_PARAM
;
894 return VPX_CODEC_INCAPABLE
;
898 static vpx_codec_err_t
ctrl_set_dbg_options(vpx_codec_alg_priv_t
*ctx
,
902 return VPX_CODEC_INCAPABLE
;
905 static vpx_codec_err_t
ctrl_get_last_ref_updates(vpx_codec_alg_priv_t
*ctx
,
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
;
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
;
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
,
932 int *corrupted
= va_arg(args
, int *);
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
;
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
,
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
;
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
;
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
,
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
;
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
;
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
,
1010 unsigned int *const bit_depth
= va_arg(args
, unsigned int *);
1011 VPxWorker
*const worker
= &ctx
->frame_workers
[ctx
->next_output_worker_id
];
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
;
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
,
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
,
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
,
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
,
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
},
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
},
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
},
1104 #ifndef VERSION_STRING
1105 #define VERSION_STRING
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
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
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