Skip to content

Commit 35a6177

Browse files
committed
vp9: add hwaccel hooks
1 parent 103159a commit 35a6177

File tree

2 files changed

+78
-15
lines changed

2 files changed

+78
-15
lines changed

libavcodec/vp9.c

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,15 @@ static const uint8_t bwh_tab[2][N_BS_SIZES][2] = {
167167
}
168168
};
169169

170+
static void vp9_unref_frame(AVCodecContext *ctx, VP9Frame *f)
171+
{
172+
ff_thread_release_buffer(ctx, &f->tf);
173+
av_buffer_unref(&f->extradata);
174+
av_buffer_unref(&f->hwaccel_priv_buf);
175+
f->segmentation_map = NULL;
176+
f->hwaccel_picture_private = NULL;
177+
}
178+
170179
static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f)
171180
{
172181
VP9Context *s = ctx->priv_data;
@@ -176,21 +185,28 @@ static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f)
176185
return ret;
177186
sz = 64 * s->sb_cols * s->sb_rows;
178187
if (!(f->extradata = av_buffer_allocz(sz * (1 + sizeof(struct VP9mvrefPair))))) {
179-
ff_thread_release_buffer(ctx, &f->tf);
180-
return AVERROR(ENOMEM);
188+
goto fail;
181189
}
182190

183191
f->segmentation_map = f->extradata->data;
184192
f->mv = (struct VP9mvrefPair *) (f->extradata->data + sz);
185193

194+
if (ctx->hwaccel) {
195+
const AVHWAccel *hwaccel = ctx->hwaccel;
196+
av_assert0(!f->hwaccel_picture_private);
197+
if (hwaccel->frame_priv_data_size) {
198+
f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
199+
if (!f->hwaccel_priv_buf)
200+
goto fail;
201+
f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
202+
}
203+
}
204+
186205
return 0;
187-
}
188206

189-
static void vp9_unref_frame(AVCodecContext *ctx, VP9Frame *f)
190-
{
191-
ff_thread_release_buffer(ctx, &f->tf);
192-
av_buffer_unref(&f->extradata);
193-
f->segmentation_map = NULL;
207+
fail:
208+
vp9_unref_frame(ctx, f);
209+
return AVERROR(ENOMEM);
194210
}
195211

196212
static int vp9_ref_frame(AVCodecContext *ctx, VP9Frame *dst, VP9Frame *src)
@@ -200,30 +216,59 @@ static int vp9_ref_frame(AVCodecContext *ctx, VP9Frame *dst, VP9Frame *src)
200216
if ((res = ff_thread_ref_frame(&dst->tf, &src->tf)) < 0) {
201217
return res;
202218
} else if (!(dst->extradata = av_buffer_ref(src->extradata))) {
203-
vp9_unref_frame(ctx, dst);
204-
return AVERROR(ENOMEM);
219+
goto fail;
205220
}
206221

207222
dst->segmentation_map = src->segmentation_map;
208223
dst->mv = src->mv;
209224
dst->uses_2pass = src->uses_2pass;
210225

226+
if (src->hwaccel_picture_private) {
227+
dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
228+
if (!dst->hwaccel_priv_buf)
229+
goto fail;
230+
dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
231+
}
232+
211233
return 0;
234+
235+
fail:
236+
vp9_unref_frame(ctx, dst);
237+
return AVERROR(ENOMEM);
212238
}
213239

214240
static int update_size(AVCodecContext *ctx, int w, int h, enum AVPixelFormat fmt)
215241
{
242+
#define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + CONFIG_VP9_D3D11VA_HWACCEL)
243+
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts;
216244
VP9Context *s = ctx->priv_data;
217245
uint8_t *p;
218246
int bytesperpixel = s->bytesperpixel;
219247

220248
av_assert0(w > 0 && h > 0);
221249

222-
if (s->intra_pred_data[0] && w == ctx->width && h == ctx->height && ctx->pix_fmt == fmt)
250+
if (s->intra_pred_data[0] && w == ctx->width && h == ctx->height && (ctx->pix_fmt == fmt || (ctx->hwaccel && ctx->sw_pix_fmt == fmt)))
223251
return 0;
224252

225-
ctx->width = w;
226-
ctx->height = h;
253+
ctx->coded_width = ctx->width = w;
254+
ctx->coded_height = ctx->height = h;
255+
256+
if (fmt == AV_PIX_FMT_YUV420P) {
257+
#if CONFIG_VP9_DXVA2_HWACCEL
258+
*fmtp++ = AV_PIX_FMT_DXVA2_VLD;
259+
#endif
260+
#if CONFIG_VP9_D3D11VA_HWACCEL
261+
*fmtp++ = AV_PIX_FMT_D3D11VA_VLD;
262+
#endif
263+
264+
*fmtp++ = fmt;
265+
*fmtp = AV_PIX_FMT_NONE;
266+
267+
fmt = ff_thread_get_format(ctx, pix_fmts);
268+
if (fmt < 0)
269+
return fmt;
270+
}
271+
227272
ctx->pix_fmt = fmt;
228273
s->sb_cols = (w + 63) >> 6;
229274
s->sb_rows = (h + 63) >> 6;
@@ -450,7 +495,7 @@ static int decode_frame_header(AVCodecContext *ctx,
450495
{
451496
VP9Context *s = ctx->priv_data;
452497
int c, i, j, k, l, m, n, w, h, max, size2, res, sharp;
453-
enum AVPixelFormat fmt = ctx->pix_fmt;
498+
enum AVPixelFormat fmt = ctx->sw_pix_fmt;
454499
int last_invisible;
455500
const uint8_t *data2;
456501

@@ -577,8 +622,9 @@ static int decode_frame_header(AVCodecContext *ctx,
577622
for (i = 0; i < 3; i++) {
578623
AVFrame *ref = s->s.refs[s->s.h.refidx[i]].f;
579624
int refw = ref->width, refh = ref->height;
625+
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(ref->format);
580626

581-
if (ref->format != fmt) {
627+
if (ref->format != fmt && (!desc || !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) || fmt != AV_PIX_FMT_YUV420P)) {
582628
av_log(ctx, AV_LOG_ERROR,
583629
"Ref pixfmt (%s) did not match current frame (%s)",
584630
av_get_pix_fmt_name(ref->format),
@@ -3978,6 +4024,19 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
39784024
return res;
39794025
}
39804026

4027+
if (ctx->hwaccel) {
4028+
res = ctx->hwaccel->start_frame(ctx, NULL, 0);
4029+
if (res < 0)
4030+
return res;
4031+
res = ctx->hwaccel->decode_slice(ctx, pkt->data, pkt->size);
4032+
if (res < 0)
4033+
return res;
4034+
res = ctx->hwaccel->end_frame(ctx);
4035+
if (res < 0)
4036+
return res;
4037+
goto finish;
4038+
}
4039+
39814040
// main tile decode loop
39824041
bytesperpixel = s->bytesperpixel;
39834042
memset(s->above_partition_ctx, 0, s->cols);
@@ -4147,6 +4206,7 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
41474206
} while (s->pass++ == 1);
41484207
ff_thread_report_progress(&s->s.frames[CUR_FRAME].tf, INT_MAX, 0);
41494208

4209+
finish:
41504210
// ref frame setup
41514211
for (i = 0; i < 8; i++) {
41524212
if (s->s.refs[i].f->buf[0])

libavcodec/vp9.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ typedef struct VP9Frame {
129129
uint8_t *segmentation_map;
130130
struct VP9mvrefPair *mv;
131131
int uses_2pass;
132+
133+
AVBufferRef *hwaccel_priv_buf;
134+
void *hwaccel_picture_private;
132135
} VP9Frame;
133136

134137
typedef struct VP9BitstreamHeader {

0 commit comments

Comments
 (0)