| Index: source/libvpx/vp9/decoder/vp9_decoder.c
|
| diff --git a/source/libvpx/vp9/decoder/vp9_decoder.c b/source/libvpx/vp9/decoder/vp9_decoder.c
|
| index 7bef265b851f261ffc7100d81fa30f36e6d524cc..aee46206ae9fd335a81a9e3cb13f9b3225584c87 100644
|
| --- a/source/libvpx/vp9/decoder/vp9_decoder.c
|
| +++ b/source/libvpx/vp9/decoder/vp9_decoder.c
|
| @@ -28,6 +28,7 @@
|
| #include "vp9/common/vp9_quant_common.h"
|
| #include "vp9/common/vp9_reconintra.h"
|
| #include "vp9/common/vp9_systemdependent.h"
|
| +#include "vp9/common/vp9_thread.h"
|
|
|
| #include "vp9/decoder/vp9_decodeframe.h"
|
| #include "vp9/decoder/vp9_decoder.h"
|
| @@ -61,7 +62,7 @@ static void vp9_dec_free_mi(VP9_COMMON *cm) {
|
| cm->mip = NULL;
|
| }
|
|
|
| -VP9Decoder *vp9_decoder_create() {
|
| +VP9Decoder *vp9_decoder_create(BufferPool *const pool) {
|
| VP9Decoder *volatile const pbi = vpx_memalign(32, sizeof(*pbi));
|
| VP9_COMMON *volatile const cm = pbi ? &pbi->common : NULL;
|
|
|
| @@ -89,9 +90,12 @@ VP9Decoder *vp9_decoder_create() {
|
|
|
| // Initialize the references to not point to any frame buffers.
|
| vpx_memset(&cm->ref_frame_map, -1, sizeof(cm->ref_frame_map));
|
| + vpx_memset(&cm->next_ref_frame_map, -1, sizeof(cm->next_ref_frame_map));
|
|
|
| cm->current_video_frame = 0;
|
| pbi->ready_for_new_data = 1;
|
| + pbi->common.buffer_pool = pool;
|
| +
|
| cm->bit_depth = VPX_BITS_8;
|
| cm->dequant_bit_depth = VPX_BITS_8;
|
|
|
| @@ -114,7 +118,6 @@ VP9Decoder *vp9_decoder_create() {
|
| }
|
|
|
| void vp9_decoder_remove(VP9Decoder *pbi) {
|
| - VP9_COMMON *const cm = &pbi->common;
|
| int i;
|
|
|
| vp9_get_worker_interface()->end(&pbi->lf_worker);
|
| @@ -132,7 +135,6 @@ void vp9_decoder_remove(VP9Decoder *pbi) {
|
| vp9_loop_filter_dealloc(&pbi->lf_row_sync);
|
| }
|
|
|
| - vp9_remove_common(cm);
|
| vpx_free(pbi);
|
| }
|
|
|
| @@ -177,6 +179,7 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
| VP9_REFFRAME ref_frame_flag,
|
| YV12_BUFFER_CONFIG *sd) {
|
| RefBuffer *ref_buf = NULL;
|
| + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
|
|
| // TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
|
| // encoder is using the frame buffers for. This is just a stub to keep the
|
| @@ -204,11 +207,11 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
| const int free_fb = get_free_fb(cm);
|
| // Decrease ref_count since it will be increased again in
|
| // ref_cnt_fb() below.
|
| - cm->frame_bufs[free_fb].ref_count--;
|
| + --frame_bufs[free_fb].ref_count;
|
|
|
| // Manage the reference counters and copy image.
|
| - ref_cnt_fb(cm->frame_bufs, ref_fb_ptr, free_fb);
|
| - ref_buf->buf = &cm->frame_bufs[*ref_fb_ptr].buf;
|
| + ref_cnt_fb(frame_bufs, ref_fb_ptr, free_fb);
|
| + ref_buf->buf = &frame_bufs[*ref_fb_ptr].buf;
|
| vp8_yv12_copy_frame(sd, ref_buf->buf);
|
| }
|
|
|
| @@ -219,33 +222,51 @@ vpx_codec_err_t vp9_set_reference_dec(VP9_COMMON *cm,
|
| static void swap_frame_buffers(VP9Decoder *pbi) {
|
| int ref_index = 0, mask;
|
| VP9_COMMON *const cm = &pbi->common;
|
| + BufferPool *const pool = cm->buffer_pool;
|
| + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
|
|
| + lock_buffer_pool(pool);
|
| for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
| - if (mask & 1) {
|
| - const int old_idx = cm->ref_frame_map[ref_index];
|
| - ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index],
|
| - cm->new_fb_idx);
|
| - if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0)
|
| - cm->release_fb_cb(cm->cb_priv,
|
| - &cm->frame_bufs[old_idx].raw_frame_buffer);
|
| + const int old_idx = cm->ref_frame_map[ref_index];
|
| + // Current thread releases the holding of reference frame.
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| +
|
| + // Release the reference frame in reference map.
|
| + if ((mask & 1) && old_idx >= 0) {
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| }
|
| + cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
|
| ++ref_index;
|
| }
|
|
|
| + // Current thread releases the holding of reference frame.
|
| + for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
|
| + const int old_idx = cm->ref_frame_map[ref_index];
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| + cm->ref_frame_map[ref_index] = cm->next_ref_frame_map[ref_index];
|
| + }
|
| + unlock_buffer_pool(pool);
|
| + pbi->hold_ref_buf = 0;
|
| cm->frame_to_show = get_frame_new_buffer(cm);
|
| - cm->frame_bufs[cm->new_fb_idx].ref_count--;
|
| +
|
| + if (!pbi->frame_parallel_decode || !cm->show_frame) {
|
| + lock_buffer_pool(pool);
|
| + --frame_bufs[cm->new_fb_idx].ref_count;
|
| + unlock_buffer_pool(pool);
|
| + }
|
|
|
| // Invalidate these references until the next frame starts.
|
| for (ref_index = 0; ref_index < 3; ref_index++)
|
| - cm->frame_refs[ref_index].idx = -1;
|
| + cm->frame_refs[ref_index].idx = INT_MAX;
|
| }
|
|
|
| int vp9_receive_compressed_data(VP9Decoder *pbi,
|
| size_t size, const uint8_t **psource) {
|
| VP9_COMMON *volatile const cm = &pbi->common;
|
| + BufferPool *const pool = cm->buffer_pool;
|
| + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
| const uint8_t *source = *psource;
|
| int retcode = 0;
|
| -
|
| cm->error.error_code = VPX_CODEC_OK;
|
|
|
| if (size == 0) {
|
| @@ -264,20 +285,38 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
|
| pbi->ready_for_new_data = 0;
|
|
|
| // Check if the previous frame was a frame without any references to it.
|
| - if (cm->new_fb_idx >= 0 && cm->frame_bufs[cm->new_fb_idx].ref_count == 0)
|
| - cm->release_fb_cb(cm->cb_priv,
|
| - &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer);
|
| + // Release frame buffer if not decoding in frame parallel mode.
|
| + if (!pbi->frame_parallel_decode && cm->new_fb_idx >= 0
|
| + && frame_bufs[cm->new_fb_idx].ref_count == 0)
|
| + pool->release_fb_cb(pool->cb_priv,
|
| + &frame_bufs[cm->new_fb_idx].raw_frame_buffer);
|
| cm->new_fb_idx = get_free_fb(cm);
|
|
|
| // Assign a MV array to the frame buffer.
|
| - cm->cur_frame = &cm->frame_bufs[cm->new_fb_idx];
|
| + cm->cur_frame = &pool->frame_bufs[cm->new_fb_idx];
|
| +
|
| + pbi->hold_ref_buf = 0;
|
| + if (pbi->frame_parallel_decode) {
|
| + VP9Worker *const worker = pbi->frame_worker_owner;
|
| + vp9_frameworker_lock_stats(worker);
|
| + frame_bufs[cm->new_fb_idx].frame_worker_owner = worker;
|
| + // Reset decoding progress.
|
| + pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
|
| + pbi->cur_buf->row = -1;
|
| + pbi->cur_buf->col = -1;
|
| + vp9_frameworker_unlock_stats(worker);
|
| + } else {
|
| + pbi->cur_buf = &frame_bufs[cm->new_fb_idx];
|
| + }
|
| +
|
|
|
| if (setjmp(cm->error.jmp)) {
|
| const VP9WorkerInterface *const winterface = vp9_get_worker_interface();
|
| + VP9_COMMON *const cm = &pbi->common;
|
| int i;
|
|
|
| - pbi->need_resync = 1;
|
| cm->error.setjmp = 0;
|
| + pbi->ready_for_new_data = 1;
|
|
|
| // Synchronize all threads immediately as a subsequent decode call may
|
| // cause a resize invalidating some allocations.
|
| @@ -286,32 +325,75 @@ int vp9_receive_compressed_data(VP9Decoder *pbi,
|
| winterface->sync(&pbi->tile_workers[i]);
|
| }
|
|
|
| - vp9_clear_system_state();
|
| + lock_buffer_pool(pool);
|
| + // Release all the reference buffers if worker thread is holding them.
|
| + if (pbi->hold_ref_buf == 1) {
|
| + int ref_index = 0, mask;
|
| + BufferPool *const pool = cm->buffer_pool;
|
| + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
| + for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) {
|
| + const int old_idx = cm->ref_frame_map[ref_index];
|
| + // Current thread releases the holding of reference frame.
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| +
|
| + // Release the reference frame in reference map.
|
| + if ((mask & 1) && old_idx >= 0) {
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| + }
|
| + ++ref_index;
|
| + }
|
|
|
| - if (cm->new_fb_idx > 0 && cm->frame_bufs[cm->new_fb_idx].ref_count > 0)
|
| - cm->frame_bufs[cm->new_fb_idx].ref_count--;
|
| + // Current thread releases the holding of reference frame.
|
| + for (; ref_index < REF_FRAMES && !cm->show_existing_frame; ++ref_index) {
|
| + const int old_idx = cm->ref_frame_map[ref_index];
|
| + decrease_ref_count(old_idx, frame_bufs, pool);
|
| + }
|
| + pbi->hold_ref_buf = 0;
|
| + }
|
| + // Release current frame.
|
| + decrease_ref_count(cm->new_fb_idx, frame_bufs, pool);
|
| + unlock_buffer_pool(pool);
|
|
|
| + vp9_clear_system_state();
|
| return -1;
|
| }
|
|
|
| cm->error.setjmp = 1;
|
| -
|
| vp9_decode_frame(pbi, source, source + size, psource);
|
|
|
| swap_frame_buffers(pbi);
|
|
|
| vp9_clear_system_state();
|
|
|
| - cm->last_width = cm->width;
|
| - cm->last_height = cm->height;
|
| -
|
| if (!cm->show_existing_frame) {
|
| cm->last_show_frame = cm->show_frame;
|
| cm->prev_frame = cm->cur_frame;
|
| + if (cm->seg.enabled && !pbi->frame_parallel_decode)
|
| + vp9_swap_current_and_last_seg_map(cm);
|
| }
|
|
|
| - if (cm->show_frame)
|
| - cm->current_video_frame++;
|
| + // Update progress in frame parallel decode.
|
| + if (pbi->frame_parallel_decode) {
|
| + // Need to lock the mutex here as another thread may
|
| + // be accessing this buffer.
|
| + VP9Worker *const worker = pbi->frame_worker_owner;
|
| + FrameWorkerData *const frame_worker_data = worker->data1;
|
| + vp9_frameworker_lock_stats(worker);
|
| +
|
| + if (cm->show_frame) {
|
| + cm->current_video_frame++;
|
| + }
|
| + frame_worker_data->frame_decoded = 1;
|
| + frame_worker_data->frame_context_ready = 1;
|
| + vp9_frameworker_signal_stats(worker);
|
| + vp9_frameworker_unlock_stats(worker);
|
| + } else {
|
| + cm->last_width = cm->width;
|
| + cm->last_height = cm->height;
|
| + if (cm->show_frame) {
|
| + cm->current_video_frame++;
|
| + }
|
| + }
|
|
|
| cm->error.setjmp = 0;
|
| return retcode;
|
| @@ -334,6 +416,8 @@ int vp9_get_raw_frame(VP9Decoder *pbi, YV12_BUFFER_CONFIG *sd,
|
| if (!cm->show_frame)
|
| return ret;
|
|
|
| + pbi->ready_for_new_data = 1;
|
| +
|
| #if CONFIG_VP9_POSTPROC
|
| if (!cm->show_existing_frame) {
|
| ret = vp9_post_proc_frame(cm, sd, flags);
|
|
|