History

vp8: Add hwaccel hooks

Also adds some extra fields to the main context structure that may be needed by a hwaccel decoder.

Mark Thompson committed 10 years ago

Commit 4e528201 parent 131a85a2 files · +157 −60Browse files

Unified · Split

2 files
  1. libavcodec/vp8.c +125 −60
  2. libavcodec/vp8.h +32 −0
libavcodec/vp8.c+125−60
@@ -64,16 +64,30 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) · 63 unmodified lines
64 if ((ret = ff_thread_get_buffer(s->avctx, &f->tf,64 if ((ret = ff_thread_get_buffer(s->avctx, &f->tf,
65 ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)65 ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
66 return ret;66 return ret;
67 if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) {67 if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height)))
68 ff_thread_release_buffer(s->avctx, &f->tf);68 goto fail;
69 return AVERROR(ENOMEM);69 if (s->avctx->hwaccel) {
70 const AVHWAccel *hwaccel = s->avctx->hwaccel;
71 if (hwaccel->frame_priv_data_size) {
72 f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
73 if (!f->hwaccel_priv_buf)
74 goto fail;
75 f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
76 }
70 }77 }
71 return 0;78 return 0;
79
80fail:
81 av_buffer_unref(&f->seg_map);
82 ff_thread_release_buffer(s->avctx, &f->tf);
83 return AVERROR(ENOMEM);
72}84}
73 85
74static void vp8_release_frame(VP8Context *s, VP8Frame *f)86static void vp8_release_frame(VP8Context *s, VP8Frame *f)
75{87{
76 av_buffer_unref(&f->seg_map);88 av_buffer_unref(&f->seg_map);
89 av_buffer_unref(&f->hwaccel_priv_buf);
90 f->hwaccel_picture_private = NULL;
77 ff_thread_release_buffer(s->avctx, &f->tf);91 ff_thread_release_buffer(s->avctx, &f->tf);
78}92}
79 93
@@ -91,6 +105,12 @@ static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src) · 11 unmodified lines
91 vp8_release_frame(s, dst);105 vp8_release_frame(s, dst);
92 return AVERROR(ENOMEM);106 return AVERROR(ENOMEM);
93 }107 }
108 if (src->hwaccel_picture_private) {
109 dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
110 if (!dst->hwaccel_priv_buf)
111 return AVERROR(ENOMEM);
112 dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
113 }
94 114
95 return 0;115 return 0;
96}116}
@@ -132,7 +152,7 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s) · 35 unmodified lines
132 av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");152 av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
133 abort();153 abort();
134 }154 }
135 if (frame->tf.f->data[0])155 if (frame->tf.f->buf[0])
136 vp8_release_frame(s, frame);156 vp8_release_frame(s, frame);
137 157
138 return frame;158 return frame;
@@ -209,8 +229,9 @@ static void parse_segment_info(VP8Context *s) · 70 unmodified lines
209 int i;229 int i;
210 230
211 s->segmentation.update_map = vp8_rac_get(c);231 s->segmentation.update_map = vp8_rac_get(c);
232 s->segmentation.update_feature_data = vp8_rac_get(c);
212 233
213 if (vp8_rac_get(c)) { // update segment feature data234 if (s->segmentation.update_feature_data) {
214 s->segmentation.absolute_vals = vp8_rac_get(c);235 s->segmentation.absolute_vals = vp8_rac_get(c);
215 236
216 for (i = 0; i < 4; i++)237 for (i = 0; i < 4; i++)
@@ -264,11 +285,14 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size) · 47 unmodified lines
264 int size = AV_RL24(sizes + 3 * i);285 int size = AV_RL24(sizes + 3 * i);
265 if (buf_size - size < 0)286 if (buf_size - size < 0)
266 return -1;287 return -1;
288 s->coeff_partition_size[i] = size;
267 289
268 ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);290 ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
269 buf += size;291 buf += size;
270 buf_size -= size;292 buf_size -= size;
271 }293 }
294
295 s->coeff_partition_size[i] = buf_size;
272 ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);296 ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
273 297
274 return 0;298 return 0;
@@ -298,28 +322,28 @@ static void get_quants(VP8Context *s) · 23 unmodified lines
298 VP56RangeCoder *c = &s->c;322 VP56RangeCoder *c = &s->c;
299 int i, base_qi;323 int i, base_qi;
300 324
301 int yac_qi = vp8_rac_get_uint(c, 7);325 s->quant.yac_qi = vp8_rac_get_uint(c, 7);
302 int ydc_delta = vp8_rac_get_sint(c, 4);326 s->quant.ydc_delta = vp8_rac_get_sint(c, 4);
303 int y2dc_delta = vp8_rac_get_sint(c, 4);327 s->quant.y2dc_delta = vp8_rac_get_sint(c, 4);
304 int y2ac_delta = vp8_rac_get_sint(c, 4);328 s->quant.y2ac_delta = vp8_rac_get_sint(c, 4);
305 int uvdc_delta = vp8_rac_get_sint(c, 4);329 s->quant.uvdc_delta = vp8_rac_get_sint(c, 4);
306 int uvac_delta = vp8_rac_get_sint(c, 4);330 s->quant.uvac_delta = vp8_rac_get_sint(c, 4);
307 331
308 for (i = 0; i < 4; i++) {332 for (i = 0; i < 4; i++) {
309 if (s->segmentation.enabled) {333 if (s->segmentation.enabled) {
310 base_qi = s->segmentation.base_quant[i];334 base_qi = s->segmentation.base_quant[i];
311 if (!s->segmentation.absolute_vals)335 if (!s->segmentation.absolute_vals)
312 base_qi += yac_qi;336 base_qi += s->quant.yac_qi;
313 } else337 } else
314 base_qi = yac_qi;338 base_qi = s->quant.yac_qi;
315 339
316 s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta, 7)];340 s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.ydc_delta, 7)];
317 s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)];341 s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)];
318 s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)] * 2;342 s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7)] * 2;
319 /* 101581>>16 is equivalent to 155/100 */343 /* 101581>>16 is equivalent to 155/100 */
320 s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)] * 101581 >> 16;344 s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7)] * 101581 >> 16;
321 s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)];345 s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7)];
322 s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)];346 s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.uvac_delta, 7)];
323 347
324 s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8);348 s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8);
325 s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132);349 s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132);
@@ -637,6 +661,8 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si · 311 unmodified lines
637 buf += 3;661 buf += 3;
638 buf_size -= 3;662 buf_size -= 3;
639 663
664 s->header_partition_size = header_size;
665
640 if (s->profile > 3)666 if (s->profile > 3)
641 av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);667 av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);
642 668
@@ -700,9 +726,11 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si · 57 unmodified lines
700 s->filter.level = vp8_rac_get_uint(c, 6);726 s->filter.level = vp8_rac_get_uint(c, 6);
701 s->filter.sharpness = vp8_rac_get_uint(c, 3);727 s->filter.sharpness = vp8_rac_get_uint(c, 3);
702 728
703 if ((s->lf_delta.enabled = vp8_rac_get(c)))729 if ((s->lf_delta.enabled = vp8_rac_get(c))) {
704 if (vp8_rac_get(c))730 s->lf_delta.update = vp8_rac_get(c);
731 if (s->lf_delta.update)
705 update_lf_deltas(s);732 update_lf_deltas(s);
733 }
706 734
707 if (setup_partitions(s, buf, buf_size)) {735 if (setup_partitions(s, buf, buf_size)) {
708 av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");736 av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");
@@ -741,6 +769,13 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si · 32 unmodified lines
741 vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE);769 vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE);
742 }770 }
743 771
772 // Record the entropy coder state here so that hwaccels can use it.
773 s->c.code_word = vp56_rac_renorm(&s->c);
774 s->coder_state_at_header_end.input = s->c.buffer - (-s->c.bits / 8);
775 s->coder_state_at_header_end.range = s->c.high;
776 s->coder_state_at_header_end.value = s->c.code_word >> 16;
777 s->coder_state_at_header_end.bit_count = -s->c.bits % 8;
778
744 return 0;779 return 0;
745}780}
746 781
@@ -2462,7 +2497,6 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, · 1715 unmodified lines
2462 return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8);2497 return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8);
2463}2498}
2464 2499
2465
2466static av_always_inline2500static av_always_inline
2467int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,2501int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
2468 AVPacket *avpkt, int is_vp7)2502 AVPacket *avpkt, int is_vp7)
@@ -2480,6 +2514,20 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, · 11 unmodified lines
2480 if (ret < 0)2514 if (ret < 0)
2481 goto err;2515 goto err;
2482 2516
2517 if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) {
2518 enum AVPixelFormat pix_fmts[] = {
2519 AV_PIX_FMT_YUV420P,
2520 AV_PIX_FMT_NONE,
2521 };
2522
2523 s->pix_fmt = ff_get_format(s->avctx, pix_fmts);
2524 if (s->pix_fmt < 0) {
2525 ret = AVERROR(EINVAL);
2526 goto err;
2527 }
2528 avctx->pix_fmt = s->pix_fmt;
2529 }
2530
2483 prev_frame = s->framep[VP56_FRAME_CURRENT];2531 prev_frame = s->framep[VP56_FRAME_CURRENT];
2484 2532
2485 referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT ||2533 referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT ||
@@ -2555,51 +2603,67 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, · 69 unmodified lines
2555 2603
2556 ff_thread_finish_setup(avctx);2604 ff_thread_finish_setup(avctx);
2557 2605
2558 s->linesize = curframe->tf.f->linesize[0];2606 if (avctx->hwaccel) {
2559 s->uvlinesize = curframe->tf.f->linesize[1];2607 ret = avctx->hwaccel->start_frame(avctx, avpkt->data, avpkt->size);
2608 if (ret < 0)
2609 goto err;
2560 2610
2561 memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz));2611 ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size);
2562 /* Zero macroblock structures for top/top-left prediction2612 if (ret < 0)
2563 * from outside the frame. */2613 goto err;
2564 if (!s->mb_layout)
2565 memset(s->macroblocks + s->mb_height * 2 - 1, 0,
2566 (s->mb_width + 1) * sizeof(*s->macroblocks));
2567 if (!s->mb_layout && s->keyframe)
2568 memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4);
2569 2614
2570 memset(s->ref_count, 0, sizeof(s->ref_count));2615 ret = avctx->hwaccel->end_frame(avctx);
2616 if (ret < 0)
2617 goto err;
2571 2618
2572 if (s->mb_layout == 1) {2619 } else {
2573 // Make sure the previous frame has read its segmentation map,2620 s->linesize = curframe->tf.f->linesize[0];
2574 // if we re-use the same map.2621 s->uvlinesize = curframe->tf.f->linesize[1];
2575 if (prev_frame && s->segmentation.enabled &&2622
2576 !s->segmentation.update_map)2623 memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz));
2577 ff_thread_await_progress(&prev_frame->tf, 1, 0);2624 /* Zero macroblock structures for top/top-left prediction
2578 if (is_vp7)2625 * from outside the frame. */
2579 vp7_decode_mv_mb_modes(avctx, curframe, prev_frame);2626 if (!s->mb_layout)
2627 memset(s->macroblocks + s->mb_height * 2 - 1, 0,
2628 (s->mb_width + 1) * sizeof(*s->macroblocks));
2629 if (!s->mb_layout && s->keyframe)
2630 memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4);
2631
2632 memset(s->ref_count, 0, sizeof(s->ref_count));
2633
2634 if (s->mb_layout == 1) {
2635 // Make sure the previous frame has read its segmentation map,
2636 // if we re-use the same map.
2637 if (prev_frame && s->segmentation.enabled &&
2638 !s->segmentation.update_map)
2639 ff_thread_await_progress(&prev_frame->tf, 1, 0);
2640 if (is_vp7)
2641 vp7_decode_mv_mb_modes(avctx, curframe, prev_frame);
2642 else
2643 vp8_decode_mv_mb_modes(avctx, curframe, prev_frame);
2644 }
2645
2646 if (avctx->active_thread_type == FF_THREAD_FRAME)
2647 num_jobs = 1;
2580 else2648 else
2581 vp8_decode_mv_mb_modes(avctx, curframe, prev_frame);2649 num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count);
2582 }2650 s->num_jobs = num_jobs;
2651 s->curframe = curframe;
2652 s->prev_frame = prev_frame;
2653 s->mv_min.y = -MARGIN;
2654 s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
2655 for (i = 0; i < MAX_THREADS; i++) {
2656 s->thread_data[i].thread_mb_pos = 0;
2657 s->thread_data[i].wait_mb_pos = INT_MAX;
2658 }
2583 2659
2584 if (avctx->active_thread_type == FF_THREAD_FRAME)2660 if (is_vp7)
2585 num_jobs = 1;2661 avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
2586 else2662 num_jobs);
2587 num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count);2663 else
2588 s->num_jobs = num_jobs;2664 avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL,
2589 s->curframe = curframe;2665 num_jobs);
2590 s->prev_frame = prev_frame;
2591 s->mv_min.y = -MARGIN;
2592 s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
2593 for (i = 0; i < MAX_THREADS; i++) {
2594 s->thread_data[i].thread_mb_pos = 0;
2595 s->thread_data[i].wait_mb_pos = INT_MAX;
2596 }2666 }
2597 if (is_vp7)
2598 avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
2599 num_jobs);
2600 else
2601 avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL,
2602 num_jobs);
2603 2667
2604 ff_thread_report_progress(&curframe->tf, INT_MAX, 0);2668 ff_thread_report_progress(&curframe->tf, INT_MAX, 0);
2605 memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);2669 memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);
@@ -2666,6 +2730,7 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7) · 60 unmodified lines
2666 int ret;2730 int ret;
2667 2731
2668 s->avctx = avctx;2732 s->avctx = avctx;
2733 s->pix_fmt = AV_PIX_FMT_NONE;
2669 avctx->pix_fmt = AV_PIX_FMT_YUV420P;2734 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
2670 avctx->internal->allocate_progress = 1;2735 avctx->internal->allocate_progress = 1;
2671 2736
libavcodec/vp8.h+32−0
@@ -130,12 +130,17 @@ typedef struct VP8ThreadData { · 129 unmodified lines
130typedef struct VP8Frame {130typedef struct VP8Frame {
131 ThreadFrame tf;131 ThreadFrame tf;
132 AVBufferRef *seg_map;132 AVBufferRef *seg_map;
133
134 AVBufferRef *hwaccel_priv_buf;
135 void *hwaccel_picture_private;
133} VP8Frame;136} VP8Frame;
134 137
135#define MAX_THREADS 8138#define MAX_THREADS 8
136typedef struct VP8Context {139typedef struct VP8Context {
137 VP8ThreadData *thread_data;140 VP8ThreadData *thread_data;
138 AVCodecContext *avctx;141 AVCodecContext *avctx;
142 enum AVPixelFormat pix_fmt;
143
139 VP8Frame *framep[4];144 VP8Frame *framep[4];
140 VP8Frame *next_framep[4];145 VP8Frame *next_framep[4];
141 VP8Frame *curframe;146 VP8Frame *curframe;
@@ -165,6 +170,7 @@ typedef struct VP8Context { · 23 unmodified lines
165 uint8_t enabled;170 uint8_t enabled;
166 uint8_t absolute_vals;171 uint8_t absolute_vals;
167 uint8_t update_map;172 uint8_t update_map;
173 uint8_t update_feature_data;
168 int8_t base_quant[4];174 int8_t base_quant[4];
169 int8_t filter_level[4]; ///< base loop filter level175 int8_t filter_level[4]; ///< base loop filter level
170 } segmentation;176 } segmentation;
@@ -192,8 +198,19 @@ typedef struct VP8Context { · 21 unmodified lines
192 int16_t chroma_qmul[2];198 int16_t chroma_qmul[2];
193 } qmat[4];199 } qmat[4];
194 200
201 // Raw quantisation values, which may be needed by hwaccel decode.
202 struct {
203 int yac_qi;
204 int ydc_delta;
205 int y2dc_delta;
206 int y2ac_delta;
207 int uvdc_delta;
208 int uvac_delta;
209 } quant;
210
195 struct {211 struct {
196 uint8_t enabled; ///< whether each mb can have a different strength based on mode/ref212 uint8_t enabled; ///< whether each mb can have a different strength based on mode/ref
213 uint8_t update;
197 214
198 /**215 /**
199 * filter strength adjustment for the following macroblock modes:216 * filter strength adjustment for the following macroblock modes:
@@ -221,6 +238,20 @@ typedef struct VP8Context { · 21 unmodified lines
221 238
222 VP56RangeCoder c; ///< header context, includes mb modes and motion vectors239 VP56RangeCoder c; ///< header context, includes mb modes and motion vectors
223 240
241 /* This contains the entropy coder state at the end of the header
242 * block, in the form specified by the standard. For use by
243 * hwaccels, so that a hardware decoder has the information to
244 * start decoding at the macroblock layer.
245 */
246 struct {
247 const uint8_t *input;
248 uint32_t range;
249 uint32_t value;
250 int bit_count;
251 } coder_state_at_header_end;
252
253 int header_partition_size;
254
224 /**255 /**
225 * These are all of the updatable probabilities for binary decisions.256 * These are all of the updatable probabilities for binary decisions.
226 * They are only implicitly reset on keyframes, making it quite likely257 * They are only implicitly reset on keyframes, making it quite likely
@@ -258,6 +289,7 @@ typedef struct VP8Context { · 31 unmodified lines
258 */289 */
259 int num_coeff_partitions;290 int num_coeff_partitions;
260 VP56RangeCoder coeff_partition[8];291 VP56RangeCoder coeff_partition[8];
292 int coeff_partition_size[8];
261 VideoDSPContext vdsp;293 VideoDSPContext vdsp;
262 VP8DSPContext vp8dsp;294 VP8DSPContext vp8dsp;
263 H264PredContext hpc;295 H264PredContext hpc;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t