OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 | 13 |
14 #include "./vpx_config.h" | 14 #include "./vpx_config.h" |
15 #include "./vpx_version.h" | 15 #include "./vpx_version.h" |
16 | 16 |
17 #include "vpx/internal/vpx_codec_internal.h" | 17 #include "vpx/internal/vpx_codec_internal.h" |
18 #include "vpx/vp8dx.h" | 18 #include "vpx/vp8dx.h" |
19 #include "vpx/vpx_decoder.h" | 19 #include "vpx/vpx_decoder.h" |
20 | 20 |
21 #include "vp9/common/vp9_alloccommon.h" | |
22 #include "vp9/common/vp9_frame_buffers.h" | 21 #include "vp9/common/vp9_frame_buffers.h" |
23 #include "vp9/common/vp9_thread.h" | |
24 | 22 |
25 #include "vp9/decoder/vp9_decoder.h" | 23 #include "vp9/decoder/vp9_decoder.h" |
26 #include "vp9/decoder/vp9_decodeframe.h" | 24 #include "vp9/decoder/vp9_decodeframe.h" |
27 #include "vp9/decoder/vp9_read_bit_buffer.h" | 25 #include "vp9/decoder/vp9_read_bit_buffer.h" |
28 | 26 |
29 #include "vp9/vp9_iface_common.h" | 27 #include "vp9/vp9_iface_common.h" |
30 | 28 |
31 #define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) | 29 #define VP9_CAP_POSTPROC (CONFIG_VP9_POSTPROC ? VPX_CODEC_CAP_POSTPROC : 0) |
32 | 30 |
33 typedef vpx_codec_stream_info_t vp9_stream_info_t; | 31 typedef vpx_codec_stream_info_t vp9_stream_info_t; |
34 | 32 |
35 // This limit is due to framebuffer numbers. | |
36 // TODO(hkuang): Remove this limit after implementing ondemand framebuffers. | |
37 #define FRAME_CACHE_SIZE 6 // Cache maximum 6 decoded frames. | |
38 | |
39 typedef struct cache_frame { | |
40 int fb_idx; | |
41 vpx_image_t img; | |
42 } cache_frame; | |
43 | |
44 struct vpx_codec_alg_priv { | 33 struct vpx_codec_alg_priv { |
45 vpx_codec_priv_t base; | 34 vpx_codec_priv_t base; |
46 vpx_codec_dec_cfg_t cfg; | 35 vpx_codec_dec_cfg_t cfg; |
47 vp9_stream_info_t si; | 36 vp9_stream_info_t si; |
| 37 struct VP9Decoder *pbi; |
48 int postproc_cfg_set; | 38 int postproc_cfg_set; |
49 vp8_postproc_cfg_t postproc_cfg; | 39 vp8_postproc_cfg_t postproc_cfg; |
50 vpx_decrypt_cb decrypt_cb; | 40 vpx_decrypt_cb decrypt_cb; |
51 void *decrypt_state; | 41 void *decrypt_state; |
52 vpx_image_t img; | 42 vpx_image_t img; |
53 int img_avail; | 43 int img_avail; |
54 int flushed; | 44 int flushed; |
55 int invert_tile_order; | 45 int invert_tile_order; |
56 int last_show_frame; // Index of last output frame. | |
57 | |
58 // Frame parallel related. | |
59 int frame_parallel_decode; // frame-based threading. | 46 int frame_parallel_decode; // frame-based threading. |
60 int byte_alignment; | 47 int byte_alignment; |
61 VP9Worker *frame_workers; | |
62 int num_frame_workers; | |
63 int next_submit_worker_id; | |
64 int last_submit_worker_id; | |
65 int next_output_worker_id; | |
66 int available_threads; | |
67 cache_frame frame_cache[FRAME_CACHE_SIZE]; | |
68 int frame_cache_write; | |
69 int frame_cache_read; | |
70 int num_cache_frames; | |
71 | |
72 // BufferPool that holds all reference frames. Shared by all the FrameWorkers. | |
73 BufferPool *buffer_pool; | |
74 | 48 |
75 // External frame buffer info to save for VP9 common. | 49 // External frame buffer info to save for VP9 common. |
76 void *ext_priv; // Private data associated with the external frame buffers. | 50 void *ext_priv; // Private data associated with the external frame buffers. |
77 vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb; | 51 vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb; |
78 vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb; | 52 vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb; |
79 }; | 53 }; |
80 | 54 |
81 static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx, | 55 static vpx_codec_err_t decoder_init(vpx_codec_ctx_t *ctx, |
82 vpx_codec_priv_enc_mr_cfg_t *data) { | 56 vpx_codec_priv_enc_mr_cfg_t *data) { |
83 // This function only allocates space for the vpx_codec_alg_priv_t | 57 // This function only allocates space for the vpx_codec_alg_priv_t |
84 // structure. More memory may be required at the time the stream | 58 // structure. More memory may be required at the time the stream |
85 // information becomes known. | 59 // information becomes known. |
86 (void)data; | 60 (void)data; |
87 | 61 |
88 if (!ctx->priv) { | 62 if (!ctx->priv) { |
89 vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv)); | 63 vpx_codec_alg_priv_t *const priv = vpx_calloc(1, sizeof(*priv)); |
90 if (priv == NULL) | 64 if (priv == NULL) |
91 return VPX_CODEC_MEM_ERROR; | 65 return VPX_CODEC_MEM_ERROR; |
92 | 66 |
93 ctx->priv = (vpx_codec_priv_t *)priv; | 67 ctx->priv = (vpx_codec_priv_t *)priv; |
94 ctx->priv->init_flags = ctx->init_flags; | 68 ctx->priv->init_flags = ctx->init_flags; |
| 69 |
95 priv->si.sz = sizeof(priv->si); | 70 priv->si.sz = sizeof(priv->si); |
96 priv->flushed = 0; | 71 priv->flushed = 0; |
97 // Only do frame parallel decode when threads > 1. | |
98 priv->frame_parallel_decode = | 72 priv->frame_parallel_decode = |
99 (ctx->config.dec && (ctx->config.dec->threads > 1) && | 73 (ctx->init_flags & VPX_CODEC_USE_FRAME_THREADING); |
100 (ctx->init_flags & VPX_CODEC_USE_FRAME_THREADING)) ? 1 : 0; | 74 priv->frame_parallel_decode = 0; // Disable for now |
| 75 |
101 if (ctx->config.dec) { | 76 if (ctx->config.dec) { |
102 priv->cfg = *ctx->config.dec; | 77 priv->cfg = *ctx->config.dec; |
103 ctx->config.dec = &priv->cfg; | 78 ctx->config.dec = &priv->cfg; |
104 } | 79 } |
105 } | 80 } |
106 | 81 |
107 return VPX_CODEC_OK; | 82 return VPX_CODEC_OK; |
108 } | 83 } |
109 | 84 |
110 static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) { | 85 static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) { |
111 if (ctx->frame_workers != NULL) { | 86 if (ctx->pbi) { |
112 int i; | 87 vp9_decoder_remove(ctx->pbi); |
113 for (i = 0; i < ctx->num_frame_workers; ++i) { | 88 ctx->pbi = NULL; |
114 VP9Worker *const worker = &ctx->frame_workers[i]; | |
115 FrameWorkerData *const frame_worker_data = | |
116 (FrameWorkerData *)worker->data1; | |
117 vp9_get_worker_interface()->end(worker); | |
118 vp9_remove_common(&frame_worker_data->pbi->common); | |
119 vp9_decoder_remove(frame_worker_data->pbi); | |
120 vpx_free(frame_worker_data->scratch_buffer); | |
121 #if CONFIG_MULTITHREAD | |
122 pthread_mutex_destroy(&frame_worker_data->stats_mutex); | |
123 pthread_cond_destroy(&frame_worker_data->stats_cond); | |
124 #endif | |
125 vpx_free(frame_worker_data); | |
126 } | |
127 #if CONFIG_MULTITHREAD | |
128 pthread_mutex_destroy(&ctx->buffer_pool->pool_mutex); | |
129 #endif | |
130 } | 89 } |
131 | 90 |
132 if (ctx->buffer_pool) | 91 vpx_free(ctx); |
133 vp9_free_internal_frame_buffers(&ctx->buffer_pool->int_frame_buffers); | |
134 | 92 |
135 vpx_free(ctx->frame_workers); | |
136 vpx_free(ctx->buffer_pool); | |
137 vpx_free(ctx); | |
138 return VPX_CODEC_OK; | 93 return VPX_CODEC_OK; |
139 } | 94 } |
140 | 95 |
141 static int parse_bitdepth_colorspace_sampling( | 96 static int parse_bitdepth_colorspace_sampling( |
142 BITSTREAM_PROFILE profile, struct vp9_read_bit_buffer *rb) { | 97 BITSTREAM_PROFILE profile, struct vp9_read_bit_buffer *rb) { |
143 vpx_color_space_t color_space; | 98 const int sRGB = 7; |
| 99 int colorspace; |
144 if (profile >= PROFILE_2) | 100 if (profile >= PROFILE_2) |
145 rb->bit_offset += 1; // Bit-depth 10 or 12. | 101 rb->bit_offset += 1; // Bit-depth 10 or 12. |
146 color_space = (vpx_color_space_t)vp9_rb_read_literal(rb, 3); | 102 colorspace = vp9_rb_read_literal(rb, 3); |
147 if (color_space != VPX_CS_SRGB) { | 103 if (colorspace != sRGB) { |
148 rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range. | 104 rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range. |
149 if (profile == PROFILE_1 || profile == PROFILE_3) { | 105 if (profile == PROFILE_1 || profile == PROFILE_3) { |
150 rb->bit_offset += 2; // subsampling x/y. | 106 rb->bit_offset += 2; // subsampling x/y. |
151 rb->bit_offset += 1; // unused. | 107 rb->bit_offset += 1; // unused. |
152 } | 108 } |
153 } else { | 109 } else { |
154 if (profile == PROFILE_1 || profile == PROFILE_3) { | 110 if (profile == PROFILE_1 || profile == PROFILE_3) { |
155 rb->bit_offset += 1; // unused | 111 rb->bit_offset += 1; // unused |
156 } else { | 112 } else { |
157 // RGB is only available in version 1. | 113 // RGB is only available in version 1. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 vpx_codec_stream_info_t *si) { | 205 vpx_codec_stream_info_t *si) { |
250 const size_t sz = (si->sz >= sizeof(vp9_stream_info_t)) | 206 const size_t sz = (si->sz >= sizeof(vp9_stream_info_t)) |
251 ? sizeof(vp9_stream_info_t) | 207 ? sizeof(vp9_stream_info_t) |
252 : sizeof(vpx_codec_stream_info_t); | 208 : sizeof(vpx_codec_stream_info_t); |
253 memcpy(si, &ctx->si, sz); | 209 memcpy(si, &ctx->si, sz); |
254 si->sz = (unsigned int)sz; | 210 si->sz = (unsigned int)sz; |
255 | 211 |
256 return VPX_CODEC_OK; | 212 return VPX_CODEC_OK; |
257 } | 213 } |
258 | 214 |
259 static void set_error_detail(vpx_codec_alg_priv_t *ctx, | |
260 const char *const error) { | |
261 ctx->base.err_detail = error; | |
262 } | |
263 | |
264 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx, | 215 static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx, |
265 const struct vpx_internal_error_info *error) { | 216 const struct vpx_internal_error_info *error) { |
266 if (error->error_code) | 217 if (error->error_code) |
267 set_error_detail(ctx, error->has_detail ? error->detail : NULL); | 218 ctx->base.err_detail = error->has_detail ? error->detail : NULL; |
268 | 219 |
269 return error->error_code; | 220 return error->error_code; |
270 } | 221 } |
271 | 222 |
272 static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) { | 223 static void init_buffer_callbacks(vpx_codec_alg_priv_t *ctx) { |
273 int i; | 224 VP9_COMMON *const cm = &ctx->pbi->common; |
274 | 225 |
275 for (i = 0; i < ctx->num_frame_workers; ++i) { | 226 cm->new_fb_idx = -1; |
276 VP9Worker *const worker = &ctx->frame_workers[i]; | 227 cm->byte_alignment = ctx->byte_alignment; |
277 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
278 VP9_COMMON *const cm = &frame_worker_data->pbi->common; | |
279 BufferPool *const pool = cm->buffer_pool; | |
280 | 228 |
281 cm->new_fb_idx = -1; | 229 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) { |
282 cm->byte_alignment = ctx->byte_alignment; | 230 cm->get_fb_cb = ctx->get_ext_fb_cb; |
| 231 cm->release_fb_cb = ctx->release_ext_fb_cb; |
| 232 cm->cb_priv = ctx->ext_priv; |
| 233 } else { |
| 234 cm->get_fb_cb = vp9_get_frame_buffer; |
| 235 cm->release_fb_cb = vp9_release_frame_buffer; |
283 | 236 |
284 if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) { | 237 if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers)) |
285 pool->get_fb_cb = ctx->get_ext_fb_cb; | 238 vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, |
286 pool->release_fb_cb = ctx->release_ext_fb_cb; | 239 "Failed to initialize internal frame buffers"); |
287 pool->cb_priv = ctx->ext_priv; | |
288 } else { | |
289 pool->get_fb_cb = vp9_get_frame_buffer; | |
290 pool->release_fb_cb = vp9_release_frame_buffer; | |
291 | 240 |
292 if (vp9_alloc_internal_frame_buffers(&pool->int_frame_buffers)) | 241 cm->cb_priv = &cm->int_frame_buffers; |
293 vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, | |
294 "Failed to initialize internal frame buffers"); | |
295 | |
296 pool->cb_priv = &pool->int_frame_buffers; | |
297 } | |
298 } | 242 } |
299 } | 243 } |
300 | 244 |
301 static void set_default_ppflags(vp8_postproc_cfg_t *cfg) { | 245 static void set_default_ppflags(vp8_postproc_cfg_t *cfg) { |
302 cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK; | 246 cfg->post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK; |
303 cfg->deblocking_level = 4; | 247 cfg->deblocking_level = 4; |
304 cfg->noise_level = 0; | 248 cfg->noise_level = 0; |
305 } | 249 } |
306 | 250 |
307 static void set_ppflags(const vpx_codec_alg_priv_t *ctx, | 251 static void set_ppflags(const vpx_codec_alg_priv_t *ctx, |
308 vp9_ppflags_t *flags) { | 252 vp9_ppflags_t *flags) { |
309 flags->post_proc_flag = | 253 flags->post_proc_flag = |
310 ctx->postproc_cfg.post_proc_flag; | 254 ctx->postproc_cfg.post_proc_flag; |
311 | 255 |
312 flags->deblocking_level = ctx->postproc_cfg.deblocking_level; | 256 flags->deblocking_level = ctx->postproc_cfg.deblocking_level; |
313 flags->noise_level = ctx->postproc_cfg.noise_level; | 257 flags->noise_level = ctx->postproc_cfg.noise_level; |
314 } | 258 } |
315 | 259 |
316 static int frame_worker_hook(void *arg1, void *arg2) { | 260 static void init_decoder(vpx_codec_alg_priv_t *ctx) { |
317 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)arg1; | 261 ctx->pbi = vp9_decoder_create(); |
318 const uint8_t *data = frame_worker_data->data; | 262 if (ctx->pbi == NULL) |
319 (void)arg2; | 263 return; |
320 | 264 |
321 frame_worker_data->result = | 265 ctx->pbi->max_threads = ctx->cfg.threads; |
322 vp9_receive_compressed_data(frame_worker_data->pbi, | 266 ctx->pbi->inv_tile_order = ctx->invert_tile_order; |
323 frame_worker_data->data_size, | 267 ctx->pbi->frame_parallel_decode = ctx->frame_parallel_decode; |
324 &data); | |
325 frame_worker_data->data_end = data; | |
326 | |
327 if (frame_worker_data->pbi->frame_parallel_decode) { | |
328 // In frame parallel decoding, a worker thread must successfully decode all | |
329 // the compressed data. | |
330 if (frame_worker_data->result != 0 || | |
331 frame_worker_data->data + frame_worker_data->data_size - 1 > data) { | |
332 VP9Worker *const worker = frame_worker_data->pbi->frame_worker_owner; | |
333 BufferPool *const pool = frame_worker_data->pbi->common.buffer_pool; | |
334 // Signal all the other threads that are waiting for this frame. | |
335 vp9_frameworker_lock_stats(worker); | |
336 frame_worker_data->frame_context_ready = 1; | |
337 lock_buffer_pool(pool); | |
338 frame_worker_data->pbi->cur_buf->buf.corrupted = 1; | |
339 unlock_buffer_pool(pool); | |
340 frame_worker_data->pbi->need_resync = 1; | |
341 vp9_frameworker_signal_stats(worker); | |
342 vp9_frameworker_unlock_stats(worker); | |
343 return 0; | |
344 } | |
345 } else if (frame_worker_data->result != 0) { | |
346 // Check decode result in serial decode. | |
347 frame_worker_data->pbi->cur_buf->buf.corrupted = 1; | |
348 frame_worker_data->pbi->need_resync = 1; | |
349 } | |
350 return !frame_worker_data->result; | |
351 } | |
352 | |
353 static vpx_codec_err_t init_decoder(vpx_codec_alg_priv_t *ctx) { | |
354 int i; | |
355 const VP9WorkerInterface *const winterface = vp9_get_worker_interface(); | |
356 | |
357 ctx->last_show_frame = -1; | |
358 ctx->next_submit_worker_id = 0; | |
359 ctx->last_submit_worker_id = 0; | |
360 ctx->next_output_worker_id = 0; | |
361 ctx->frame_cache_read = 0; | |
362 ctx->frame_cache_write = 0; | |
363 ctx->num_cache_frames = 0; | |
364 ctx->num_frame_workers = | |
365 (ctx->frame_parallel_decode == 1) ? ctx->cfg.threads: 1; | |
366 ctx->available_threads = ctx->num_frame_workers; | |
367 ctx->flushed = 0; | |
368 | |
369 ctx->buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(BufferPool)); | |
370 if (ctx->buffer_pool == NULL) | |
371 return VPX_CODEC_MEM_ERROR; | |
372 | |
373 #if CONFIG_MULTITHREAD | |
374 if (pthread_mutex_init(&ctx->buffer_pool->pool_mutex, NULL)) { | |
375 set_error_detail(ctx, "Failed to allocate buffer pool mutex"); | |
376 return VPX_CODEC_MEM_ERROR; | |
377 } | |
378 #endif | |
379 | |
380 ctx->frame_workers = (VP9Worker *) | |
381 vpx_malloc(ctx->num_frame_workers * sizeof(*ctx->frame_workers)); | |
382 if (ctx->frame_workers == NULL) { | |
383 set_error_detail(ctx, "Failed to allocate frame_workers"); | |
384 return VPX_CODEC_MEM_ERROR; | |
385 } | |
386 | |
387 for (i = 0; i < ctx->num_frame_workers; ++i) { | |
388 VP9Worker *const worker = &ctx->frame_workers[i]; | |
389 FrameWorkerData *frame_worker_data = NULL; | |
390 winterface->init(worker); | |
391 worker->data1 = vpx_memalign(32, sizeof(FrameWorkerData)); | |
392 if (worker->data1 == NULL) { | |
393 set_error_detail(ctx, "Failed to allocate frame_worker_data"); | |
394 return VPX_CODEC_MEM_ERROR; | |
395 } | |
396 frame_worker_data = (FrameWorkerData *)worker->data1; | |
397 frame_worker_data->pbi = vp9_decoder_create(ctx->buffer_pool); | |
398 if (frame_worker_data->pbi == NULL) { | |
399 set_error_detail(ctx, "Failed to allocate frame_worker_data"); | |
400 return VPX_CODEC_MEM_ERROR; | |
401 } | |
402 frame_worker_data->pbi->frame_worker_owner = worker; | |
403 frame_worker_data->worker_id = i; | |
404 frame_worker_data->scratch_buffer = NULL; | |
405 frame_worker_data->scratch_buffer_size = 0; | |
406 frame_worker_data->frame_context_ready = 0; | |
407 #if CONFIG_MULTITHREAD | |
408 if (pthread_mutex_init(&frame_worker_data->stats_mutex, NULL)) { | |
409 set_error_detail(ctx, "Failed to allocate frame_worker_data mutex"); | |
410 return VPX_CODEC_MEM_ERROR; | |
411 } | |
412 | |
413 if (pthread_cond_init(&frame_worker_data->stats_cond, NULL)) { | |
414 set_error_detail(ctx, "Failed to allocate frame_worker_data cond"); | |
415 return VPX_CODEC_MEM_ERROR; | |
416 } | |
417 #endif | |
418 // If decoding in serial mode, FrameWorker thread could create tile worker | |
419 // thread or loopfilter thread. | |
420 frame_worker_data->pbi->max_threads = | |
421 (ctx->frame_parallel_decode == 0) ? ctx->cfg.threads : 0; | |
422 | |
423 frame_worker_data->pbi->inv_tile_order = ctx->invert_tile_order; | |
424 frame_worker_data->pbi->frame_parallel_decode = ctx->frame_parallel_decode; | |
425 frame_worker_data->pbi->common.frame_parallel_decode = | |
426 ctx->frame_parallel_decode; | |
427 worker->hook = (VP9WorkerHook)frame_worker_hook; | |
428 if (!winterface->reset(worker)) { | |
429 set_error_detail(ctx, "Frame Worker thread creation failed"); | |
430 return VPX_CODEC_MEM_ERROR; | |
431 } | |
432 } | |
433 | 268 |
434 // If postprocessing was enabled by the application and a | 269 // If postprocessing was enabled by the application and a |
435 // configuration has not been provided, default it. | 270 // configuration has not been provided, default it. |
436 if (!ctx->postproc_cfg_set && | 271 if (!ctx->postproc_cfg_set && |
437 (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) | 272 (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) |
438 set_default_ppflags(&ctx->postproc_cfg); | 273 set_default_ppflags(&ctx->postproc_cfg); |
439 | 274 |
440 init_buffer_callbacks(ctx); | 275 init_buffer_callbacks(ctx); |
441 | |
442 return VPX_CODEC_OK; | |
443 } | 276 } |
444 | 277 |
445 static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, | 278 static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, |
446 const uint8_t **data, unsigned int data_sz, | 279 const uint8_t **data, unsigned int data_sz, |
447 void *user_priv, int64_t deadline) { | 280 void *user_priv, int64_t deadline) { |
| 281 YV12_BUFFER_CONFIG sd; |
448 vp9_ppflags_t flags = {0, 0, 0}; | 282 vp9_ppflags_t flags = {0, 0, 0}; |
449 const VP9WorkerInterface *const winterface = vp9_get_worker_interface(); | 283 VP9_COMMON *cm = NULL; |
| 284 |
450 (void)deadline; | 285 (void)deadline; |
451 | 286 |
| 287 vp9_zero(sd); |
| 288 ctx->img_avail = 0; |
| 289 |
452 // Determine the stream parameters. Note that we rely on peek_si to | 290 // Determine the stream parameters. Note that we rely on peek_si to |
453 // validate that we have a buffer that does not wrap around the top | 291 // validate that we have a buffer that does not wrap around the top |
454 // of the heap. | 292 // of the heap. |
455 if (!ctx->si.h) { | 293 if (!ctx->si.h) { |
456 int is_intra_only = 0; | 294 int is_intra_only = 0; |
457 const vpx_codec_err_t res = | 295 const vpx_codec_err_t res = |
458 decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only, | 296 decoder_peek_si_internal(*data, data_sz, &ctx->si, &is_intra_only, |
459 ctx->decrypt_cb, ctx->decrypt_state); | 297 ctx->decrypt_cb, ctx->decrypt_state); |
460 if (res != VPX_CODEC_OK) | 298 if (res != VPX_CODEC_OK) |
461 return res; | 299 return res; |
462 | 300 |
463 if (!ctx->si.is_kf && !is_intra_only) | 301 if (!ctx->si.is_kf && !is_intra_only) |
464 return VPX_CODEC_ERROR; | 302 return VPX_CODEC_ERROR; |
465 } | 303 } |
466 | 304 |
467 if (!ctx->frame_parallel_decode) { | 305 // Initialize the decoder instance on the first frame |
468 VP9Worker *const worker = ctx->frame_workers; | 306 if (ctx->pbi == NULL) { |
469 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | 307 init_decoder(ctx); |
470 frame_worker_data->data = *data; | 308 if (ctx->pbi == NULL) |
471 frame_worker_data->data_size = data_sz; | 309 return VPX_CODEC_ERROR; |
472 frame_worker_data->user_priv = user_priv; | 310 } |
473 | 311 |
474 // Set these even if already initialized. The caller may have changed the | 312 // Set these even if already initialized. The caller may have changed the |
475 // decrypt config between frames. | 313 // decrypt config between frames. |
476 frame_worker_data->pbi->decrypt_cb = ctx->decrypt_cb; | 314 ctx->pbi->decrypt_cb = ctx->decrypt_cb; |
477 frame_worker_data->pbi->decrypt_state = ctx->decrypt_state; | 315 ctx->pbi->decrypt_state = ctx->decrypt_state; |
478 | 316 |
479 worker->had_error = 0; | 317 cm = &ctx->pbi->common; |
480 winterface->execute(worker); | |
481 | 318 |
482 // Update data pointer after decode. | 319 if (vp9_receive_compressed_data(ctx->pbi, data_sz, data)) |
483 *data = frame_worker_data->data_end; | 320 return update_error_state(ctx, &cm->error); |
484 | |
485 if (worker->had_error) | |
486 return update_error_state(ctx, &frame_worker_data->pbi->common.error); | |
487 } else { | |
488 const VP9WorkerInterface *const winterface = vp9_get_worker_interface(); | |
489 VP9Worker *const worker = &ctx->frame_workers[ctx->next_submit_worker_id]; | |
490 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
491 // Copy context from last worker thread to next worker thread. | |
492 if (ctx->next_submit_worker_id != ctx->last_submit_worker_id) | |
493 vp9_frameworker_copy_context( | |
494 &ctx->frame_workers[ctx->next_submit_worker_id], | |
495 &ctx->frame_workers[ctx->last_submit_worker_id]); | |
496 | |
497 frame_worker_data->pbi->ready_for_new_data = 0; | |
498 // Copy the compressed data into worker's internal buffer. | |
499 // TODO(hkuang): Will all the workers allocate the same size | |
500 // as the size of the first intra frame be better? This will | |
501 // avoid too many deallocate and allocate. | |
502 if (frame_worker_data->scratch_buffer_size < data_sz) { | |
503 frame_worker_data->scratch_buffer = | |
504 (uint8_t *)vpx_realloc(frame_worker_data->scratch_buffer, data_sz); | |
505 if (frame_worker_data->scratch_buffer == NULL) { | |
506 set_error_detail(ctx, "Failed to reallocate scratch buffer"); | |
507 return VPX_CODEC_MEM_ERROR; | |
508 } | |
509 frame_worker_data->scratch_buffer_size = data_sz; | |
510 } | |
511 frame_worker_data->data_size = data_sz; | |
512 vpx_memcpy(frame_worker_data->scratch_buffer, *data, data_sz); | |
513 | |
514 frame_worker_data->frame_decoded = 0; | |
515 frame_worker_data->frame_context_ready = 0; | |
516 frame_worker_data->data = frame_worker_data->scratch_buffer; | |
517 frame_worker_data->user_priv = user_priv; | |
518 | |
519 if (ctx->next_submit_worker_id != ctx->last_submit_worker_id) | |
520 ctx->last_submit_worker_id = | |
521 (ctx->last_submit_worker_id + 1) % ctx->num_frame_workers; | |
522 | |
523 ctx->next_submit_worker_id = | |
524 (ctx->next_submit_worker_id + 1) % ctx->num_frame_workers; | |
525 --ctx->available_threads; | |
526 worker->had_error = 0; | |
527 winterface->launch(worker); | |
528 } | |
529 | 321 |
530 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) | 322 if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) |
531 set_ppflags(ctx, &flags); | 323 set_ppflags(ctx, &flags); |
532 | 324 |
| 325 if (vp9_get_raw_frame(ctx->pbi, &sd, &flags)) |
| 326 return update_error_state(ctx, &cm->error); |
| 327 |
| 328 yuvconfig2image(&ctx->img, &sd, user_priv); |
| 329 ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv; |
| 330 ctx->img_avail = 1; |
| 331 |
533 return VPX_CODEC_OK; | 332 return VPX_CODEC_OK; |
534 } | 333 } |
535 | 334 |
536 static void wait_worker_and_cache_frame(vpx_codec_alg_priv_t *ctx) { | |
537 YV12_BUFFER_CONFIG sd; | |
538 vp9_ppflags_t flags = {0, 0, 0}; | |
539 const VP9WorkerInterface *const winterface = vp9_get_worker_interface(); | |
540 VP9Worker *const worker = &ctx->frame_workers[ctx->next_output_worker_id]; | |
541 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
542 ctx->next_output_worker_id = | |
543 (ctx->next_output_worker_id + 1) % ctx->num_frame_workers; | |
544 winterface->sync(worker); | |
545 ++ctx->available_threads; | |
546 if (vp9_get_raw_frame(frame_worker_data->pbi, &sd, &flags) == 0) { | |
547 VP9_COMMON *const cm = &frame_worker_data->pbi->common; | |
548 RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; | |
549 ctx->frame_cache[ctx->frame_cache_write].fb_idx = cm->new_fb_idx; | |
550 yuvconfig2image(&ctx->frame_cache[ctx->frame_cache_write].img, &sd, | |
551 frame_worker_data->user_priv); | |
552 ctx->frame_cache[ctx->frame_cache_write].img.fb_priv = | |
553 frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv; | |
554 ctx->frame_cache_write = | |
555 (ctx->frame_cache_write + 1) % FRAME_CACHE_SIZE; | |
556 ++ctx->num_cache_frames; | |
557 } | |
558 } | |
559 | |
560 static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, | 335 static vpx_codec_err_t decoder_decode(vpx_codec_alg_priv_t *ctx, |
561 const uint8_t *data, unsigned int data_sz, | 336 const uint8_t *data, unsigned int data_sz, |
562 void *user_priv, long deadline) { | 337 void *user_priv, long deadline) { |
563 const uint8_t *data_start = data; | 338 const uint8_t *data_start = data; |
564 const uint8_t * const data_end = data + data_sz; | 339 const uint8_t * const data_end = data + data_sz; |
565 vpx_codec_err_t res; | 340 vpx_codec_err_t res; |
566 uint32_t frame_sizes[8]; | 341 uint32_t frame_sizes[8]; |
567 int frame_count; | 342 int frame_count; |
568 | 343 |
569 if (data == NULL && data_sz == 0) { | 344 if (data == NULL && data_sz == 0) { |
570 ctx->flushed = 1; | 345 ctx->flushed = 1; |
571 return VPX_CODEC_OK; | 346 return VPX_CODEC_OK; |
572 } | 347 } |
573 | 348 |
574 // Reset flushed when receiving a valid frame. | 349 // Reset flushed when receiving a valid frame. |
575 ctx->flushed = 0; | 350 ctx->flushed = 0; |
576 | 351 |
577 // Initialize the decoder workers on the first frame. | |
578 if (ctx->frame_workers == NULL) { | |
579 const vpx_codec_err_t res = init_decoder(ctx); | |
580 if (res != VPX_CODEC_OK) | |
581 return res; | |
582 } | |
583 | |
584 res = vp9_parse_superframe_index(data, data_sz, frame_sizes, &frame_count, | 352 res = vp9_parse_superframe_index(data, data_sz, frame_sizes, &frame_count, |
585 ctx->decrypt_cb, ctx->decrypt_state); | 353 ctx->decrypt_cb, ctx->decrypt_state); |
586 if (res != VPX_CODEC_OK) | 354 if (res != VPX_CODEC_OK) |
587 return res; | 355 return res; |
588 | 356 |
589 if (ctx->frame_parallel_decode) { | 357 if (ctx->frame_parallel_decode) { |
590 // Decode in frame parallel mode. When decoding in this mode, the frame | 358 // Decode in frame parallel mode. When decoding in this mode, the frame |
591 // passed to the decoder must be either a normal frame or a superframe with | 359 // passed to the decoder must be either a normal frame or a superframe with |
592 // superframe index so the decoder could get each frame's start position | 360 // superframe index so the decoder could get each frame's start position |
593 // in the superframe. | 361 // in the superframe. |
594 if (frame_count > 0) { | 362 if (frame_count > 0) { |
595 int i; | 363 int i; |
596 | 364 |
597 for (i = 0; i < frame_count; ++i) { | 365 for (i = 0; i < frame_count; ++i) { |
598 const uint8_t *data_start_copy = data_start; | 366 const uint8_t *data_start_copy = data_start; |
599 const uint32_t frame_size = frame_sizes[i]; | 367 const uint32_t frame_size = frame_sizes[i]; |
| 368 vpx_codec_err_t res; |
600 if (data_start < data | 369 if (data_start < data |
601 || frame_size > (uint32_t) (data_end - data_start)) { | 370 || frame_size > (uint32_t) (data_end - data_start)) { |
602 set_error_detail(ctx, "Invalid frame size in index"); | 371 ctx->base.err_detail = "Invalid frame size in index"; |
603 return VPX_CODEC_CORRUPT_FRAME; | 372 return VPX_CODEC_CORRUPT_FRAME; |
604 } | 373 } |
605 | 374 |
606 if (ctx->available_threads == 0) { | |
607 // No more threads for decoding. Wait until the next output worker | |
608 // finishes decoding. Then copy the decoded frame into cache. | |
609 if (ctx->num_cache_frames < FRAME_CACHE_SIZE) { | |
610 wait_worker_and_cache_frame(ctx); | |
611 } else { | |
612 // TODO(hkuang): Add unit test to test this path. | |
613 set_error_detail(ctx, "Frame output cache is full."); | |
614 return VPX_CODEC_ERROR; | |
615 } | |
616 } | |
617 | |
618 res = decode_one(ctx, &data_start_copy, frame_size, user_priv, | 375 res = decode_one(ctx, &data_start_copy, frame_size, user_priv, |
619 deadline); | 376 deadline); |
620 if (res != VPX_CODEC_OK) | 377 if (res != VPX_CODEC_OK) |
621 return res; | 378 return res; |
| 379 |
622 data_start += frame_size; | 380 data_start += frame_size; |
623 } | 381 } |
624 } else { | 382 } else { |
625 if (ctx->available_threads == 0) { | 383 res = decode_one(ctx, &data_start, data_sz, user_priv, deadline); |
626 // No more threads for decoding. Wait until the next output worker | |
627 // finishes decoding. Then copy the decoded frame into cache. | |
628 if (ctx->num_cache_frames < FRAME_CACHE_SIZE) { | |
629 wait_worker_and_cache_frame(ctx); | |
630 } else { | |
631 // TODO(hkuang): Add unit test to test this path. | |
632 set_error_detail(ctx, "Frame output cache is full."); | |
633 return VPX_CODEC_ERROR; | |
634 } | |
635 } | |
636 | |
637 res = decode_one(ctx, &data, data_sz, user_priv, deadline); | |
638 if (res != VPX_CODEC_OK) | 384 if (res != VPX_CODEC_OK) |
639 return res; | 385 return res; |
| 386 |
| 387 // Extra data detected after the frame. |
| 388 if (data_start < data_end - 1) { |
| 389 ctx->base.err_detail = "Fail to decode frame in parallel mode"; |
| 390 return VPX_CODEC_INCAPABLE; |
| 391 } |
640 } | 392 } |
641 } else { | 393 } else { |
642 // Decode in serial mode. | 394 // Decode in serial mode. |
643 if (frame_count > 0) { | 395 if (frame_count > 0) { |
644 int i; | 396 int i; |
645 | 397 |
646 for (i = 0; i < frame_count; ++i) { | 398 for (i = 0; i < frame_count; ++i) { |
647 const uint8_t *data_start_copy = data_start; | 399 const uint8_t *data_start_copy = data_start; |
648 const uint32_t frame_size = frame_sizes[i]; | 400 const uint32_t frame_size = frame_sizes[i]; |
649 vpx_codec_err_t res; | 401 vpx_codec_err_t res; |
650 if (data_start < data | 402 if (data_start < data |
651 || frame_size > (uint32_t) (data_end - data_start)) { | 403 || frame_size > (uint32_t) (data_end - data_start)) { |
652 set_error_detail(ctx, "Invalid frame size in index"); | 404 ctx->base.err_detail = "Invalid frame size in index"; |
653 return VPX_CODEC_CORRUPT_FRAME; | 405 return VPX_CODEC_CORRUPT_FRAME; |
654 } | 406 } |
655 | 407 |
656 res = decode_one(ctx, &data_start_copy, frame_size, user_priv, | 408 res = decode_one(ctx, &data_start_copy, frame_size, user_priv, |
657 deadline); | 409 deadline); |
658 if (res != VPX_CODEC_OK) | 410 if (res != VPX_CODEC_OK) |
659 return res; | 411 return res; |
660 | 412 |
661 data_start += frame_size; | 413 data_start += frame_size; |
662 } | 414 } |
(...skipping 10 matching lines...) Expand all Loading... |
673 const uint8_t marker = read_marker(ctx->decrypt_cb, | 425 const uint8_t marker = read_marker(ctx->decrypt_cb, |
674 ctx->decrypt_state, data_start); | 426 ctx->decrypt_state, data_start); |
675 if (marker) | 427 if (marker) |
676 break; | 428 break; |
677 ++data_start; | 429 ++data_start; |
678 } | 430 } |
679 } | 431 } |
680 } | 432 } |
681 } | 433 } |
682 | 434 |
683 return res; | 435 return VPX_CODEC_OK; |
684 } | |
685 | |
686 static void release_last_output_frame(vpx_codec_alg_priv_t *ctx) { | |
687 RefCntBuffer *const frame_bufs = ctx->buffer_pool->frame_bufs; | |
688 // Decrease reference count of last output frame in frame parallel mode. | |
689 if (ctx->frame_parallel_decode && ctx->last_show_frame >= 0) { | |
690 BufferPool *const pool = ctx->buffer_pool; | |
691 lock_buffer_pool(pool); | |
692 decrease_ref_count(ctx->last_show_frame, frame_bufs, pool); | |
693 unlock_buffer_pool(pool); | |
694 } | |
695 } | 436 } |
696 | 437 |
697 static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx, | 438 static vpx_image_t *decoder_get_frame(vpx_codec_alg_priv_t *ctx, |
698 vpx_codec_iter_t *iter) { | 439 vpx_codec_iter_t *iter) { |
699 vpx_image_t *img = NULL; | 440 vpx_image_t *img = NULL; |
700 | 441 |
701 // Only return frame when all the cpu are busy or | 442 if (ctx->img_avail) { |
702 // application fluhsed the decoder in frame parallel decode. | 443 // iter acts as a flip flop, so an image is only returned on the first |
703 if (ctx->frame_parallel_decode && ctx->available_threads > 0 && | 444 // call to get_frame. |
704 !ctx->flushed) { | 445 if (!(*iter)) { |
705 return img; | 446 img = &ctx->img; |
| 447 *iter = img; |
| 448 } |
706 } | 449 } |
| 450 ctx->img_avail = 0; |
707 | 451 |
708 // Output the frames in the cache first. | |
709 if (ctx->num_cache_frames > 0) { | |
710 release_last_output_frame(ctx); | |
711 ctx->last_show_frame = ctx->frame_cache[ctx->frame_cache_read].fb_idx; | |
712 img = &ctx->frame_cache[ctx->frame_cache_read].img; | |
713 ctx->frame_cache_read = (ctx->frame_cache_read + 1) % FRAME_CACHE_SIZE; | |
714 --ctx->num_cache_frames; | |
715 return img; | |
716 } | |
717 | |
718 // iter acts as a flip flop, so an image is only returned on the first | |
719 // call to get_frame. | |
720 if (*iter == NULL && ctx->frame_workers != NULL) { | |
721 do { | |
722 YV12_BUFFER_CONFIG sd; | |
723 vp9_ppflags_t flags = {0, 0, 0}; | |
724 const VP9WorkerInterface *const winterface = vp9_get_worker_interface(); | |
725 VP9Worker *const worker = | |
726 &ctx->frame_workers[ctx->next_output_worker_id]; | |
727 FrameWorkerData *const frame_worker_data = | |
728 (FrameWorkerData *)worker->data1; | |
729 ctx->next_output_worker_id = | |
730 (ctx->next_output_worker_id + 1) % ctx->num_frame_workers; | |
731 // Wait for the frame from worker thread. | |
732 if (!winterface->sync(worker)) { | |
733 // Decoding failed. Release the worker thread. | |
734 ++ctx->available_threads; | |
735 if (ctx->flushed != 1) | |
736 return img; | |
737 } else if (vp9_get_raw_frame(frame_worker_data->pbi, &sd, &flags) == 0) { | |
738 VP9_COMMON *const cm = &frame_worker_data->pbi->common; | |
739 RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs; | |
740 ++ctx->available_threads; | |
741 release_last_output_frame(ctx); | |
742 ctx->last_show_frame = frame_worker_data->pbi->common.new_fb_idx; | |
743 yuvconfig2image(&ctx->img, &sd, frame_worker_data->user_priv); | |
744 ctx->img.fb_priv = frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv; | |
745 img = &ctx->img; | |
746 return img; | |
747 } | |
748 } while (ctx->next_output_worker_id != ctx->next_submit_worker_id); | |
749 } | |
750 return img; | 452 return img; |
751 } | 453 } |
752 | 454 |
753 static vpx_codec_err_t decoder_set_fb_fn( | 455 static vpx_codec_err_t decoder_set_fb_fn( |
754 vpx_codec_alg_priv_t *ctx, | 456 vpx_codec_alg_priv_t *ctx, |
755 vpx_get_frame_buffer_cb_fn_t cb_get, | 457 vpx_get_frame_buffer_cb_fn_t cb_get, |
756 vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) { | 458 vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) { |
757 if (cb_get == NULL || cb_release == NULL) { | 459 if (cb_get == NULL || cb_release == NULL) { |
758 return VPX_CODEC_INVALID_PARAM; | 460 return VPX_CODEC_INVALID_PARAM; |
759 } else if (ctx->frame_workers == NULL) { | 461 } else if (ctx->pbi == NULL) { |
760 // If the decoder has already been initialized, do not accept changes to | 462 // If the decoder has already been initialized, do not accept changes to |
761 // the frame buffer functions. | 463 // the frame buffer functions. |
762 ctx->get_ext_fb_cb = cb_get; | 464 ctx->get_ext_fb_cb = cb_get; |
763 ctx->release_ext_fb_cb = cb_release; | 465 ctx->release_ext_fb_cb = cb_release; |
764 ctx->ext_priv = cb_priv; | 466 ctx->ext_priv = cb_priv; |
765 return VPX_CODEC_OK; | 467 return VPX_CODEC_OK; |
766 } | 468 } |
767 | 469 |
768 return VPX_CODEC_ERROR; | 470 return VPX_CODEC_ERROR; |
769 } | 471 } |
770 | 472 |
771 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx, | 473 static vpx_codec_err_t ctrl_set_reference(vpx_codec_alg_priv_t *ctx, |
772 va_list args) { | 474 va_list args) { |
773 vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *); | 475 vpx_ref_frame_t *const data = va_arg(args, vpx_ref_frame_t *); |
774 | 476 |
775 // Only support this function in serial decode. | |
776 if (ctx->frame_parallel_decode) { | |
777 set_error_detail(ctx, "Not supported in frame parallel decode"); | |
778 return VPX_CODEC_INCAPABLE; | |
779 } | |
780 | |
781 if (data) { | 477 if (data) { |
782 vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data; | 478 vpx_ref_frame_t *const frame = (vpx_ref_frame_t *)data; |
783 YV12_BUFFER_CONFIG sd; | 479 YV12_BUFFER_CONFIG sd; |
784 VP9Worker *const worker = ctx->frame_workers; | 480 |
785 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
786 image2yuvconfig(&frame->img, &sd); | 481 image2yuvconfig(&frame->img, &sd); |
787 return vp9_set_reference_dec(&frame_worker_data->pbi->common, | 482 return vp9_set_reference_dec(&ctx->pbi->common, |
788 (VP9_REFFRAME)frame->frame_type, &sd); | 483 (VP9_REFFRAME)frame->frame_type, &sd); |
789 } else { | 484 } else { |
790 return VPX_CODEC_INVALID_PARAM; | 485 return VPX_CODEC_INVALID_PARAM; |
791 } | 486 } |
792 } | 487 } |
793 | 488 |
794 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx, | 489 static vpx_codec_err_t ctrl_copy_reference(vpx_codec_alg_priv_t *ctx, |
795 va_list args) { | 490 va_list args) { |
796 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); | 491 vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); |
797 | 492 |
798 // Only support this function in serial decode. | 493 if (data) { |
799 if (ctx->frame_parallel_decode) { | 494 vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; |
800 set_error_detail(ctx, "Not supported in frame parallel decode"); | 495 YV12_BUFFER_CONFIG sd; |
801 return VPX_CODEC_INCAPABLE; | |
802 } | |
803 | 496 |
804 if (data) { | |
805 vpx_ref_frame_t *frame = (vpx_ref_frame_t *) data; | |
806 YV12_BUFFER_CONFIG sd; | |
807 VP9Worker *const worker = ctx->frame_workers; | |
808 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
809 image2yuvconfig(&frame->img, &sd); | 497 image2yuvconfig(&frame->img, &sd); |
810 return vp9_copy_reference_dec(frame_worker_data->pbi, | 498 |
| 499 return vp9_copy_reference_dec(ctx->pbi, |
811 (VP9_REFFRAME)frame->frame_type, &sd); | 500 (VP9_REFFRAME)frame->frame_type, &sd); |
812 } else { | 501 } else { |
813 return VPX_CODEC_INVALID_PARAM; | 502 return VPX_CODEC_INVALID_PARAM; |
814 } | 503 } |
815 } | 504 } |
816 | 505 |
817 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx, | 506 static vpx_codec_err_t ctrl_get_reference(vpx_codec_alg_priv_t *ctx, |
818 va_list args) { | 507 va_list args) { |
819 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); | 508 vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *); |
820 | 509 |
821 // Only support this function in serial decode. | 510 if (data) { |
822 if (ctx->frame_parallel_decode) { | 511 YV12_BUFFER_CONFIG* fb = get_ref_frame(&ctx->pbi->common, data->idx); |
823 set_error_detail(ctx, "Not supported in frame parallel decode"); | 512 if (fb == NULL) return VPX_CODEC_ERROR; |
824 return VPX_CODEC_INCAPABLE; | |
825 } | |
826 | 513 |
827 if (data) { | |
828 YV12_BUFFER_CONFIG* fb; | |
829 VP9Worker *const worker = ctx->frame_workers; | |
830 FrameWorkerData *const frame_worker_data = (FrameWorkerData *)worker->data1; | |
831 fb = get_ref_frame(&frame_worker_data->pbi->common, data->idx); | |
832 if (fb == NULL) return VPX_CODEC_ERROR; | |
833 yuvconfig2image(&data->img, fb, NULL); | 514 yuvconfig2image(&data->img, fb, NULL); |
834 return VPX_CODEC_OK; | 515 return VPX_CODEC_OK; |
835 } else { | 516 } else { |
836 return VPX_CODEC_INVALID_PARAM; | 517 return VPX_CODEC_INVALID_PARAM; |
837 } | 518 } |
838 } | 519 } |
839 | 520 |
840 static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx, | 521 static vpx_codec_err_t ctrl_set_postproc(vpx_codec_alg_priv_t *ctx, |
841 va_list args) { | 522 va_list args) { |
842 #if CONFIG_VP9_POSTPROC | 523 #if CONFIG_VP9_POSTPROC |
(...skipping 17 matching lines...) Expand all Loading... |
860 va_list args) { | 541 va_list args) { |
861 (void)ctx; | 542 (void)ctx; |
862 (void)args; | 543 (void)args; |
863 return VPX_CODEC_INCAPABLE; | 544 return VPX_CODEC_INCAPABLE; |
864 } | 545 } |
865 | 546 |
866 static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, | 547 static vpx_codec_err_t ctrl_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, |
867 va_list args) { | 548 va_list args) { |
868 int *const update_info = va_arg(args, int *); | 549 int *const update_info = va_arg(args, int *); |
869 | 550 |
870 // Only support this function in serial decode. | |
871 if (ctx->frame_parallel_decode) { | |
872 set_error_detail(ctx, "Not supported in frame parallel decode"); | |
873 return VPX_CODEC_INCAPABLE; | |
874 } | |
875 | |
876 if (update_info) { | 551 if (update_info) { |
877 if (ctx->frame_workers) { | 552 if (ctx->pbi) |
878 VP9Worker *const worker = ctx->frame_workers; | 553 *update_info = ctx->pbi->refresh_frame_flags; |
879 FrameWorkerData *const frame_worker_data = | 554 else |
880 (FrameWorkerData *)worker->data1; | |
881 *update_info = frame_worker_data->pbi->refresh_frame_flags; | |
882 } else { | |
883 return VPX_CODEC_ERROR; | 555 return VPX_CODEC_ERROR; |
884 } | |
885 return VPX_CODEC_OK; | 556 return VPX_CODEC_OK; |
886 } else { | 557 } else { |
887 return VPX_CODEC_INVALID_PARAM; | 558 return VPX_CODEC_INVALID_PARAM; |
888 } | 559 } |
889 } | 560 } |
890 | 561 |
| 562 |
891 static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, | 563 static vpx_codec_err_t ctrl_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, |
892 va_list args) { | 564 va_list args) { |
893 int *corrupted = va_arg(args, int *); | 565 int *corrupted = va_arg(args, int *); |
894 | 566 |
895 if (corrupted) { | 567 if (corrupted != NULL && ctx->pbi != NULL) { |
896 if (ctx->frame_workers) { | 568 const YV12_BUFFER_CONFIG *const frame = ctx->pbi->common.frame_to_show; |
897 VP9Worker *const worker = ctx->frame_workers; | 569 if (frame == NULL) return VPX_CODEC_ERROR; |
898 FrameWorkerData *const frame_worker_data = | 570 *corrupted = frame->corrupted; |
899 (FrameWorkerData *)worker->data1; | |
900 RefCntBuffer *const frame_bufs = | |
901 frame_worker_data->pbi->common.buffer_pool->frame_bufs; | |
902 if (frame_worker_data->pbi->common.frame_to_show == NULL) | |
903 return VPX_CODEC_ERROR; | |
904 *corrupted = frame_bufs[ctx->last_show_frame].buf.corrupted; | |
905 } else { | |
906 return VPX_CODEC_ERROR; | |
907 } | |
908 return VPX_CODEC_OK; | 571 return VPX_CODEC_OK; |
909 } else { | 572 } else { |
910 return VPX_CODEC_INVALID_PARAM; | 573 return VPX_CODEC_INVALID_PARAM; |
911 } | 574 } |
912 } | 575 } |
913 | 576 |
914 static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx, | 577 static vpx_codec_err_t ctrl_get_display_size(vpx_codec_alg_priv_t *ctx, |
915 va_list args) { | 578 va_list args) { |
916 int *const display_size = va_arg(args, int *); | 579 int *const display_size = va_arg(args, int *); |
917 | 580 |
918 // Only support this function in serial decode. | |
919 if (ctx->frame_parallel_decode) { | |
920 set_error_detail(ctx, "Not supported in frame parallel decode"); | |
921 return VPX_CODEC_INCAPABLE; | |
922 } | |
923 | |
924 if (display_size) { | 581 if (display_size) { |
925 if (ctx->frame_workers) { | 582 if (ctx->pbi) { |
926 VP9Worker *const worker = ctx->frame_workers; | 583 const VP9_COMMON *const cm = &ctx->pbi->common; |
927 FrameWorkerData *const frame_worker_data = | |
928 (FrameWorkerData *)worker->data1; | |
929 const VP9_COMMON *const cm = &frame_worker_data->pbi->common; | |
930 display_size[0] = cm->display_width; | 584 display_size[0] = cm->display_width; |
931 display_size[1] = cm->display_height; | 585 display_size[1] = cm->display_height; |
932 } else { | 586 } else { |
933 return VPX_CODEC_ERROR; | 587 return VPX_CODEC_ERROR; |
934 } | 588 } |
935 return VPX_CODEC_OK; | 589 return VPX_CODEC_OK; |
936 } else { | 590 } else { |
937 return VPX_CODEC_INVALID_PARAM; | 591 return VPX_CODEC_INVALID_PARAM; |
938 } | 592 } |
939 } | 593 } |
940 | 594 |
941 static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx, | 595 static vpx_codec_err_t ctrl_get_bit_depth(vpx_codec_alg_priv_t *ctx, |
942 va_list args) { | 596 va_list args) { |
943 unsigned int *const bit_depth = va_arg(args, unsigned int *); | 597 unsigned int *const bit_depth = va_arg(args, unsigned int *); |
944 VP9Worker *const worker = &ctx->frame_workers[ctx->next_output_worker_id]; | |
945 | 598 |
946 if (bit_depth) { | 599 if (bit_depth) { |
947 if (worker) { | 600 if (ctx->pbi) { |
948 FrameWorkerData *const frame_worker_data = | 601 const VP9_COMMON *const cm = &ctx->pbi->common; |
949 (FrameWorkerData *)worker->data1; | |
950 const VP9_COMMON *const cm = &frame_worker_data->pbi->common; | |
951 *bit_depth = cm->bit_depth; | 602 *bit_depth = cm->bit_depth; |
952 return VPX_CODEC_OK; | 603 return VPX_CODEC_OK; |
953 } else { | 604 } else { |
954 return VPX_CODEC_ERROR; | 605 return VPX_CODEC_ERROR; |
955 } | 606 } |
956 } else { | 607 } else { |
957 return VPX_CODEC_INVALID_PARAM; | 608 return VPX_CODEC_INVALID_PARAM; |
958 } | 609 } |
959 } | 610 } |
960 | 611 |
(...skipping 18 matching lines...) Expand all Loading... |
979 const int max_byte_alignment = 1024; | 630 const int max_byte_alignment = 1024; |
980 const int byte_alignment = va_arg(args, int); | 631 const int byte_alignment = va_arg(args, int); |
981 | 632 |
982 if (byte_alignment != legacy_byte_alignment && | 633 if (byte_alignment != legacy_byte_alignment && |
983 (byte_alignment < min_byte_alignment || | 634 (byte_alignment < min_byte_alignment || |
984 byte_alignment > max_byte_alignment || | 635 byte_alignment > max_byte_alignment || |
985 (byte_alignment & (byte_alignment - 1)) != 0)) | 636 (byte_alignment & (byte_alignment - 1)) != 0)) |
986 return VPX_CODEC_INVALID_PARAM; | 637 return VPX_CODEC_INVALID_PARAM; |
987 | 638 |
988 ctx->byte_alignment = byte_alignment; | 639 ctx->byte_alignment = byte_alignment; |
989 if (ctx->frame_workers) { | 640 if (ctx->pbi != NULL) { |
990 VP9Worker *const worker = ctx->frame_workers; | 641 VP9_COMMON *const cm = &ctx->pbi->common; |
991 FrameWorkerData *const frame_worker_data = | 642 cm->byte_alignment = byte_alignment; |
992 (FrameWorkerData *)worker->data1; | |
993 frame_worker_data->pbi->common.byte_alignment = byte_alignment; | |
994 } | 643 } |
995 return VPX_CODEC_OK; | 644 return VPX_CODEC_OK; |
996 } | 645 } |
997 | 646 |
998 static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { | 647 static vpx_codec_ctrl_fn_map_t decoder_ctrl_maps[] = { |
999 {VP8_COPY_REFERENCE, ctrl_copy_reference}, | 648 {VP8_COPY_REFERENCE, ctrl_copy_reference}, |
1000 | 649 |
1001 // Setters | 650 // Setters |
1002 {VP8_SET_REFERENCE, ctrl_set_reference}, | 651 {VP8_SET_REFERENCE, ctrl_set_reference}, |
1003 {VP8_SET_POSTPROC, ctrl_set_postproc}, | 652 {VP8_SET_POSTPROC, ctrl_set_postproc}, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1041 0, | 690 0, |
1042 NULL, // vpx_codec_enc_cfg_map_t | 691 NULL, // vpx_codec_enc_cfg_map_t |
1043 NULL, // vpx_codec_encode_fn_t | 692 NULL, // vpx_codec_encode_fn_t |
1044 NULL, // vpx_codec_get_cx_data_fn_t | 693 NULL, // vpx_codec_get_cx_data_fn_t |
1045 NULL, // vpx_codec_enc_config_set_fn_t | 694 NULL, // vpx_codec_enc_config_set_fn_t |
1046 NULL, // vpx_codec_get_global_headers_fn_t | 695 NULL, // vpx_codec_get_global_headers_fn_t |
1047 NULL, // vpx_codec_get_preview_frame_fn_t | 696 NULL, // vpx_codec_get_preview_frame_fn_t |
1048 NULL // vpx_codec_enc_mr_get_mem_loc_fn_t | 697 NULL // vpx_codec_enc_mr_get_mem_loc_fn_t |
1049 } | 698 } |
1050 }; | 699 }; |
OLD | NEW |