|
|
|
@ -35,9 +35,9 @@ |
|
|
|
|
#include "hwaccel_internal.h" |
|
|
|
|
#include "hwconfig.h" |
|
|
|
|
#include "mathops.h" |
|
|
|
|
#include "progressframe.h" |
|
|
|
|
#include "refstruct.h" |
|
|
|
|
#include "thread.h" |
|
|
|
|
#include "threadframe.h" |
|
|
|
|
#include "vp8.h" |
|
|
|
|
#include "vp89_rac.h" |
|
|
|
|
#include "vp8data.h" |
|
|
|
@ -103,9 +103,9 @@ static void free_buffers(VP8Context *s) |
|
|
|
|
|
|
|
|
|
static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
if ((ret = ff_thread_get_ext_buffer(s->avctx, &f->tf, |
|
|
|
|
ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) |
|
|
|
|
int ret = ff_progress_frame_get_buffer(s->avctx, &f->tf, |
|
|
|
|
ref ? AV_GET_BUFFER_FLAG_REF : 0); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
if (!(f->seg_map = ff_refstruct_allocz(s->mb_width * s->mb_height))) |
|
|
|
|
goto fail; |
|
|
|
@ -117,7 +117,7 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
ff_refstruct_unref(&f->seg_map); |
|
|
|
|
ff_thread_release_ext_buffer(&f->tf); |
|
|
|
|
ff_progress_frame_unref(&f->tf); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -125,26 +125,9 @@ static void vp8_release_frame(VP8Frame *f) |
|
|
|
|
{ |
|
|
|
|
ff_refstruct_unref(&f->seg_map); |
|
|
|
|
ff_refstruct_unref(&f->hwaccel_picture_private); |
|
|
|
|
ff_thread_release_ext_buffer(&f->tf); |
|
|
|
|
ff_progress_frame_unref(&f->tf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if CONFIG_VP8_DECODER |
|
|
|
|
static int vp8_ref_frame(VP8Frame *dst, const VP8Frame *src) |
|
|
|
|
{ |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
vp8_release_frame(dst); |
|
|
|
|
|
|
|
|
|
if ((ret = ff_thread_ref_frame(&dst->tf, &src->tf)) < 0) |
|
|
|
|
return ret; |
|
|
|
|
ff_refstruct_replace(&dst->seg_map, src->seg_map); |
|
|
|
|
ff_refstruct_replace(&dst->hwaccel_picture_private, |
|
|
|
|
src->hwaccel_picture_private); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
#endif /* CONFIG_VP8_DECODER */ |
|
|
|
|
|
|
|
|
|
static void vp8_decode_flush_impl(AVCodecContext *avctx, int free_mem) |
|
|
|
|
{ |
|
|
|
|
VP8Context *s = avctx->priv_data; |
|
|
|
@ -184,7 +167,7 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s) |
|
|
|
|
av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); |
|
|
|
|
abort(); |
|
|
|
|
} |
|
|
|
|
if (frame->tf.f->buf[0]) |
|
|
|
|
if (frame->tf.f) |
|
|
|
|
vp8_release_frame(frame); |
|
|
|
|
|
|
|
|
|
return frame; |
|
|
|
@ -1830,7 +1813,7 @@ static const uint8_t subpel_idx[3][8] = { |
|
|
|
|
*/ |
|
|
|
|
static av_always_inline |
|
|
|
|
void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, |
|
|
|
|
const ThreadFrame *ref, const VP8mv *mv, |
|
|
|
|
const ProgressFrame *ref, const VP8mv *mv, |
|
|
|
|
int x_off, int y_off, int block_w, int block_h, |
|
|
|
|
int width, int height, ptrdiff_t linesize, |
|
|
|
|
vp8_mc_func mc_func[3][3]) |
|
|
|
@ -1847,7 +1830,7 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, |
|
|
|
|
y_off += mv->y >> 2; |
|
|
|
|
|
|
|
|
|
// edge emulation
|
|
|
|
|
ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 4, 0); |
|
|
|
|
ff_progress_frame_await(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 4); |
|
|
|
|
src += y_off * linesize + x_off; |
|
|
|
|
if (x_off < mx_idx || x_off >= width - block_w - subpel_idx[2][mx] || |
|
|
|
|
y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) { |
|
|
|
@ -1863,7 +1846,7 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, |
|
|
|
|
} |
|
|
|
|
mc_func[my_idx][mx_idx](dst, linesize, src, src_linesize, block_h, mx, my); |
|
|
|
|
} else { |
|
|
|
|
ff_thread_await_progress(ref, (3 + y_off + block_h) >> 4, 0); |
|
|
|
|
ff_progress_frame_await(ref, (3 + y_off + block_h) >> 4); |
|
|
|
|
mc_func[0][0](dst, linesize, src + y_off * linesize + x_off, |
|
|
|
|
linesize, block_h, 0, 0); |
|
|
|
|
} |
|
|
|
@ -1888,7 +1871,7 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst, |
|
|
|
|
*/ |
|
|
|
|
static av_always_inline |
|
|
|
|
void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, |
|
|
|
|
uint8_t *dst2, const ThreadFrame *ref, const VP8mv *mv, |
|
|
|
|
uint8_t *dst2, const ProgressFrame *ref, const VP8mv *mv, |
|
|
|
|
int x_off, int y_off, int block_w, int block_h, |
|
|
|
|
int width, int height, ptrdiff_t linesize, |
|
|
|
|
vp8_mc_func mc_func[3][3]) |
|
|
|
@ -1905,7 +1888,7 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, |
|
|
|
|
// edge emulation
|
|
|
|
|
src1 += y_off * linesize + x_off; |
|
|
|
|
src2 += y_off * linesize + x_off; |
|
|
|
|
ff_thread_await_progress(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 3, 0); |
|
|
|
|
ff_progress_frame_await(ref, (3 + y_off + block_h + subpel_idx[2][my]) >> 3); |
|
|
|
|
if (x_off < mx_idx || x_off >= width - block_w - subpel_idx[2][mx] || |
|
|
|
|
y_off < my_idx || y_off >= height - block_h - subpel_idx[2][my]) { |
|
|
|
|
s->vdsp.emulated_edge_mc(td->edge_emu_buffer, |
|
|
|
@ -1930,7 +1913,7 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, |
|
|
|
|
mc_func[my_idx][mx_idx](dst2, linesize, src2, linesize, block_h, mx, my); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
ff_thread_await_progress(ref, (3 + y_off + block_h) >> 3, 0); |
|
|
|
|
ff_progress_frame_await(ref, (3 + y_off + block_h) >> 3); |
|
|
|
|
mc_func[0][0](dst1, linesize, src1 + y_off * linesize + x_off, linesize, block_h, 0, 0); |
|
|
|
|
mc_func[0][0](dst2, linesize, src2 + y_off * linesize + x_off, linesize, block_h, 0, 0); |
|
|
|
|
} |
|
|
|
@ -1938,7 +1921,7 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1, |
|
|
|
|
|
|
|
|
|
static av_always_inline |
|
|
|
|
void vp8_mc_part(VP8Context *s, VP8ThreadData *td, uint8_t *const dst[3], |
|
|
|
|
const ThreadFrame *ref_frame, int x_off, int y_off, |
|
|
|
|
const ProgressFrame *ref_frame, int x_off, int y_off, |
|
|
|
|
int bx_off, int by_off, int block_w, int block_h, |
|
|
|
|
int width, int height, const VP8mv *mv) |
|
|
|
|
{ |
|
|
|
@ -2003,7 +1986,7 @@ void inter_predict(VP8Context *s, VP8ThreadData *td, uint8_t *const dst[3], |
|
|
|
|
{ |
|
|
|
|
int x_off = mb_x << 4, y_off = mb_y << 4; |
|
|
|
|
int width = 16 * s->mb_width, height = 16 * s->mb_height; |
|
|
|
|
const ThreadFrame *ref = &s->framep[mb->ref_frame]->tf; |
|
|
|
|
const ProgressFrame *ref = &s->framep[mb->ref_frame]->tf; |
|
|
|
|
const VP8mv *bmv = mb->bmv; |
|
|
|
|
|
|
|
|
|
switch (mb->partitioning) { |
|
|
|
@ -2423,7 +2406,7 @@ static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void |
|
|
|
|
// if we re-use the same map.
|
|
|
|
|
if (prev_frame && s->segmentation.enabled && |
|
|
|
|
!s->segmentation.update_map) |
|
|
|
|
ff_thread_await_progress(&prev_frame->tf, mb_y, 0); |
|
|
|
|
ff_progress_frame_await(&prev_frame->tf, mb_y); |
|
|
|
|
mb = s->macroblocks + (s->mb_height - mb_y - 1) * 2; |
|
|
|
|
memset(mb - 1, 0, sizeof(*mb)); // zero left macroblock
|
|
|
|
|
AV_WN32A(s->intra4x4_pred_mode_left, DC_PRED * 0x01010101); |
|
|
|
@ -2631,7 +2614,7 @@ int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr, |
|
|
|
|
td->mv_bounds.mv_max.y -= 64 * num_jobs; |
|
|
|
|
|
|
|
|
|
if (avctx->active_thread_type == FF_THREAD_FRAME) |
|
|
|
|
ff_thread_report_progress(&curframe->tf, mb_y, 0); |
|
|
|
|
ff_progress_frame_report(&curframe->tf, mb_y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
@ -2699,7 +2682,7 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, |
|
|
|
|
|
|
|
|
|
// release no longer referenced frames
|
|
|
|
|
for (i = 0; i < 5; i++) |
|
|
|
|
if (s->frames[i].tf.f->buf[0] && |
|
|
|
|
if (s->frames[i].tf.f && |
|
|
|
|
&s->frames[i] != prev_frame && |
|
|
|
|
&s->frames[i] != s->framep[VP8_FRAME_PREVIOUS] && |
|
|
|
|
&s->frames[i] != s->framep[VP8_FRAME_GOLDEN] && |
|
|
|
@ -2728,14 +2711,14 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, |
|
|
|
|
goto err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0) |
|
|
|
|
goto err; |
|
|
|
|
if (s->keyframe) |
|
|
|
|
curframe->tf.f->flags |= AV_FRAME_FLAG_KEY; |
|
|
|
|
else |
|
|
|
|
curframe->tf.f->flags &= ~AV_FRAME_FLAG_KEY; |
|
|
|
|
curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I |
|
|
|
|
: AV_PICTURE_TYPE_P; |
|
|
|
|
if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0) |
|
|
|
|
goto err; |
|
|
|
|
|
|
|
|
|
// check if golden and altref are swapped
|
|
|
|
|
if (s->update_altref != VP8_FRAME_NONE) |
|
|
|
@ -2792,7 +2775,7 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, |
|
|
|
|
// if we re-use the same map.
|
|
|
|
|
if (prev_frame && s->segmentation.enabled && |
|
|
|
|
!s->segmentation.update_map) |
|
|
|
|
ff_thread_await_progress(&prev_frame->tf, 1, 0); |
|
|
|
|
ff_progress_frame_await(&prev_frame->tf, 1); |
|
|
|
|
if (is_vp7) |
|
|
|
|
ret = vp7_decode_mv_mb_modes(avctx, curframe, prev_frame); |
|
|
|
|
else |
|
|
|
@ -2823,7 +2806,7 @@ int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, |
|
|
|
|
num_jobs); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ff_thread_report_progress(&curframe->tf, INT_MAX, 0); |
|
|
|
|
ff_progress_frame_report(&curframe->tf, INT_MAX); |
|
|
|
|
memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4); |
|
|
|
|
|
|
|
|
|
skip_decode: |
|
|
|
@ -2860,24 +2843,8 @@ static int vp7_decode_frame(AVCodecContext *avctx, AVFrame *frame, |
|
|
|
|
|
|
|
|
|
av_cold int ff_vp8_decode_free(AVCodecContext *avctx) |
|
|
|
|
{ |
|
|
|
|
VP8Context *s = avctx->priv_data; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
vp8_decode_flush_impl(avctx, 1); |
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) |
|
|
|
|
av_frame_free(&s->frames[i].tf.f); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static av_cold int vp8_init_frames(VP8Context *s) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { |
|
|
|
|
s->frames[i].tf.f = av_frame_alloc(); |
|
|
|
|
if (!s->frames[i].tf.f) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2885,7 +2852,6 @@ static av_always_inline |
|
|
|
|
int vp78_decode_init(AVCodecContext *avctx, int is_vp7) |
|
|
|
|
{ |
|
|
|
|
VP8Context *s = avctx->priv_data; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
s->avctx = avctx; |
|
|
|
|
s->pix_fmt = AV_PIX_FMT_NONE; |
|
|
|
@ -2909,11 +2875,6 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7) |
|
|
|
|
/* does not change for VP8 */ |
|
|
|
|
memcpy(s->prob[0].scan, ff_zigzag_scan, sizeof(s->prob[0].scan)); |
|
|
|
|
|
|
|
|
|
if ((ret = vp8_init_frames(s)) < 0) { |
|
|
|
|
ff_vp8_decode_free(avctx); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2931,13 +2892,20 @@ av_cold int ff_vp8_decode_init(AVCodecContext *avctx) |
|
|
|
|
|
|
|
|
|
#if CONFIG_VP8_DECODER |
|
|
|
|
#if HAVE_THREADS |
|
|
|
|
static void vp8_replace_frame(VP8Frame *dst, const VP8Frame *src) |
|
|
|
|
{ |
|
|
|
|
ff_progress_frame_replace(&dst->tf, &src->tf); |
|
|
|
|
ff_refstruct_replace(&dst->seg_map, src->seg_map); |
|
|
|
|
ff_refstruct_replace(&dst->hwaccel_picture_private, |
|
|
|
|
src->hwaccel_picture_private); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define REBASE(pic) ((pic) ? (pic) - &s_src->frames[0] + &s->frames[0] : NULL) |
|
|
|
|
|
|
|
|
|
static int vp8_decode_update_thread_context(AVCodecContext *dst, |
|
|
|
|
const AVCodecContext *src) |
|
|
|
|
{ |
|
|
|
|
VP8Context *s = dst->priv_data, *s_src = src->priv_data; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (s->macroblocks_base && |
|
|
|
|
(s_src->mb_width != s->mb_width || s_src->mb_height != s->mb_height)) { |
|
|
|
@ -2952,13 +2920,8 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, |
|
|
|
|
s->lf_delta = s_src->lf_delta; |
|
|
|
|
memcpy(s->sign_bias, s_src->sign_bias, sizeof(s->sign_bias)); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) { |
|
|
|
|
if (s_src->frames[i].tf.f->buf[0]) { |
|
|
|
|
int ret = vp8_ref_frame(&s->frames[i], &s_src->frames[i]); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (int i = 0; i < FF_ARRAY_ELEMS(s_src->frames); i++) |
|
|
|
|
vp8_replace_frame(&s->frames[i], &s_src->frames[i]); |
|
|
|
|
|
|
|
|
|
s->framep[0] = REBASE(s_src->next_framep[0]); |
|
|
|
|
s->framep[1] = REBASE(s_src->next_framep[1]); |
|
|
|
@ -2982,6 +2945,7 @@ const FFCodec ff_vp7_decoder = { |
|
|
|
|
FF_CODEC_DECODE_CB(vp7_decode_frame), |
|
|
|
|
.p.capabilities = AV_CODEC_CAP_DR1, |
|
|
|
|
.flush = vp8_decode_flush, |
|
|
|
|
.caps_internal = FF_CODEC_CAP_USES_PROGRESSFRAMES, |
|
|
|
|
}; |
|
|
|
|
#endif /* CONFIG_VP7_DECODER */ |
|
|
|
|
|
|
|
|
@ -2997,7 +2961,7 @@ const FFCodec ff_vp8_decoder = { |
|
|
|
|
FF_CODEC_DECODE_CB(ff_vp8_decode_frame), |
|
|
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | |
|
|
|
|
AV_CODEC_CAP_SLICE_THREADS, |
|
|
|
|
.caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, |
|
|
|
|
.caps_internal = FF_CODEC_CAP_USES_PROGRESSFRAMES, |
|
|
|
|
.flush = vp8_decode_flush, |
|
|
|
|
UPDATE_THREAD_CONTEXT(vp8_decode_update_thread_context), |
|
|
|
|
.hw_configs = (const AVCodecHWConfigInternal *const []) { |
|
|
|
|