| Index: source/libvpx/vp9/common/vp9_onyxc_int.h
|
| diff --git a/source/libvpx/vp9/common/vp9_onyxc_int.h b/source/libvpx/vp9/common/vp9_onyxc_int.h
|
| index 1a957bc99baf4ae5c8eb54fc6cd02e7d50212b3e..cfb0a98e5c51ff71bcbb1be92c19b5539ac74fd9 100644
|
| --- a/source/libvpx/vp9/common/vp9_onyxc_int.h
|
| +++ b/source/libvpx/vp9/common/vp9_onyxc_int.h
|
| @@ -20,6 +20,7 @@
|
| #include "vp9/common/vp9_entropymode.h"
|
| #include "vp9/common/vp9_frame_buffers.h"
|
| #include "vp9/common/vp9_quant_common.h"
|
| +#include "vp9/common/vp9_thread.h"
|
| #include "vp9/common/vp9_tile_common.h"
|
|
|
| #if CONFIG_VP9_POSTPROC
|
| @@ -35,14 +36,19 @@ extern "C" {
|
| #define REF_FRAMES_LOG2 3
|
| #define REF_FRAMES (1 << REF_FRAMES_LOG2)
|
|
|
| -// 1 scratch frame for the new frame, 3 for scaled references on the encoder
|
| +// 4 scratch frames for the new frames to support a maximum of 4 cores decoding
|
| +// in parallel, 3 for scaled references on the encoder.
|
| +// TODO(hkuang): Add ondemand frame buffers instead of hardcoding the number
|
| +// of framebuffers.
|
| // TODO(jkoleszar): These 3 extra references could probably come from the
|
| // normal reference pool.
|
| -#define FRAME_BUFFERS (REF_FRAMES + 4)
|
| +#define FRAME_BUFFERS (REF_FRAMES + 7)
|
|
|
| #define FRAME_CONTEXTS_LOG2 2
|
| #define FRAME_CONTEXTS (1 << FRAME_CONTEXTS_LOG2)
|
|
|
| +#define NUM_PING_PONG_BUFFERS 2
|
| +
|
| extern const struct {
|
| PARTITION_CONTEXT above;
|
| PARTITION_CONTEXT left;
|
| @@ -68,8 +74,40 @@ typedef struct {
|
| int mi_cols;
|
| vpx_codec_frame_buffer_t raw_frame_buffer;
|
| YV12_BUFFER_CONFIG buf;
|
| +
|
| + // The Following variables will only be used in frame parallel decode.
|
| +
|
| + // frame_worker_owner indicates which FrameWorker owns this buffer. NULL means
|
| + // that no FrameWorker owns, or is decoding, this buffer.
|
| + VP9Worker *frame_worker_owner;
|
| +
|
| + // row and col indicate which position frame has been decoded to in real
|
| + // pixel unit. They are reset to -1 when decoding begins and set to INT_MAX
|
| + // when the frame is fully decoded.
|
| + int row;
|
| + int col;
|
| } RefCntBuffer;
|
|
|
| +typedef struct {
|
| + // Protect BufferPool from being accessed by several FrameWorkers at
|
| + // the same time during frame parallel decode.
|
| + // TODO(hkuang): Try to use atomic variable instead of locking the whole pool.
|
| +#if CONFIG_MULTITHREAD
|
| + pthread_mutex_t pool_mutex;
|
| +#endif
|
| +
|
| + // Private data associated with the frame buffer callbacks.
|
| + void *cb_priv;
|
| +
|
| + vpx_get_frame_buffer_cb_fn_t get_fb_cb;
|
| + vpx_release_frame_buffer_cb_fn_t release_fb_cb;
|
| +
|
| + RefCntBuffer frame_bufs[FRAME_BUFFERS];
|
| +
|
| + // Frame buffers allocated internally by the codec.
|
| + InternalFrameBufferList int_frame_buffers;
|
| +} BufferPool;
|
| +
|
| typedef struct VP9Common {
|
| struct vpx_internal_error_info error;
|
|
|
| @@ -96,7 +134,6 @@ typedef struct VP9Common {
|
| #endif
|
|
|
| YV12_BUFFER_CONFIG *frame_to_show;
|
| - RefCntBuffer frame_bufs[FRAME_BUFFERS];
|
| RefCntBuffer *prev_frame;
|
|
|
| // TODO(hkuang): Combine this with cur_buf in macroblockd.
|
| @@ -104,6 +141,10 @@ typedef struct VP9Common {
|
|
|
| int ref_frame_map[REF_FRAMES]; /* maps fb_idx to reference slot */
|
|
|
| + // Prepare ref_frame_map for the next frame.
|
| + // Only used in frame parallel decode.
|
| + int next_ref_frame_map[REF_FRAMES];
|
| +
|
| // TODO(jkoleszar): could expand active_ref_idx to 4, with 0 as intra, and
|
| // roll new_fb_idx into it.
|
|
|
| @@ -170,7 +211,12 @@ typedef struct VP9Common {
|
| int use_prev_frame_mvs;
|
|
|
| // Persistent mb segment id map used in prediction.
|
| - unsigned char *last_frame_seg_map;
|
| + int seg_map_idx;
|
| + int prev_seg_map_idx;
|
| +
|
| + uint8_t *seg_map_array[NUM_PING_PONG_BUFFERS];
|
| + uint8_t *last_frame_seg_map;
|
| + uint8_t *current_frame_seg_map;
|
|
|
| INTERP_FILTER interp_filter;
|
|
|
| @@ -183,6 +229,10 @@ typedef struct VP9Common {
|
| struct loopfilter lf;
|
| struct segmentation seg;
|
|
|
| + // TODO(hkuang): Remove this as it is the same as frame_parallel_decode
|
| + // in pbi.
|
| + int frame_parallel_decode; // frame-based threading.
|
| +
|
| // Context probabilities for reference frame prediction
|
| MV_REFERENCE_FRAME comp_fixed_ref;
|
| MV_REFERENCE_FRAME comp_var_ref[2];
|
| @@ -218,31 +268,43 @@ typedef struct VP9Common {
|
| // Handles memory for the codec.
|
| InternalFrameBufferList int_frame_buffers;
|
|
|
| + // External BufferPool passed from outside.
|
| + BufferPool *buffer_pool;
|
| +
|
| PARTITION_CONTEXT *above_seg_context;
|
| ENTROPY_CONTEXT *above_context;
|
| } VP9_COMMON;
|
|
|
| +// TODO(hkuang): Don't need to lock the whole pool after implementing atomic
|
| +// frame reference count.
|
| +void lock_buffer_pool(BufferPool *const pool);
|
| +void unlock_buffer_pool(BufferPool *const pool);
|
| +
|
| static INLINE YV12_BUFFER_CONFIG *get_ref_frame(VP9_COMMON *cm, int index) {
|
| if (index < 0 || index >= REF_FRAMES)
|
| return NULL;
|
| if (cm->ref_frame_map[index] < 0)
|
| return NULL;
|
| assert(cm->ref_frame_map[index] < FRAME_BUFFERS);
|
| - return &cm->frame_bufs[cm->ref_frame_map[index]].buf;
|
| + return &cm->buffer_pool->frame_bufs[cm->ref_frame_map[index]].buf;
|
| }
|
|
|
| static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
|
| - return &cm->frame_bufs[cm->new_fb_idx].buf;
|
| + return &cm->buffer_pool->frame_bufs[cm->new_fb_idx].buf;
|
| }
|
|
|
| static INLINE int get_free_fb(VP9_COMMON *cm) {
|
| + RefCntBuffer *const frame_bufs = cm->buffer_pool->frame_bufs;
|
| int i;
|
| - for (i = 0; i < FRAME_BUFFERS; i++)
|
| - if (cm->frame_bufs[i].ref_count == 0)
|
| +
|
| + lock_buffer_pool(cm->buffer_pool);
|
| + for (i = 0; i < FRAME_BUFFERS; ++i)
|
| + if (frame_bufs[i].ref_count == 0)
|
| break;
|
|
|
| assert(i < FRAME_BUFFERS);
|
| - cm->frame_bufs[i].ref_count = 1;
|
| + frame_bufs[i].ref_count = 1;
|
| + unlock_buffer_pool(cm->buffer_pool);
|
| return i;
|
| }
|
|
|
|
|