History

vaapi_encode: Maintain a pool of bitstream output buffers

Previously we would allocate a new one for every frame. This instead maintains an AVBufferPool of them to use as-needed. Also makes the maximum size of an output buffer adapt to the frame size - the fixed upper bound was a bit too easy to hit when encoding large pictures at high quality.

Mark Thompson committed 10 years ago

Commit 8a62d2c1 parent bd31c612 files · +75 −19Browse files

Unified · Split

2 files
  1. libavcodec/vaapi_encode.c +72 −18
  2. libavcodec/vaapi_encode.h +3 −1
libavcodec/vaapi_encode.c+72−18
@@ -178,16 +178,12 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 177 unmodified lines
178 pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];178 pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];
179 av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);179 av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);
180 180
181 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,181 pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
182 VAEncCodedBufferType,182 if (!pic->output_buffer_ref) {
183 MAX_OUTPUT_BUFFER_SIZE, 1, 0,
184 &pic->output_buffer);
185 if (vas != VA_STATUS_SUCCESS) {
186 av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
187 "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
188 err = AVERROR(ENOMEM);183 err = AVERROR(ENOMEM);
189 goto fail;184 goto fail;
190 }185 }
186 pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data;
191 av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",187 av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",
192 pic->output_buffer);188 pic->output_buffer);
193 189
@@ -438,7 +434,7 @@ static int vaapi_encode_output(AVCodecContext *avctx, · 244 unmodified lines
438 434
439 err = av_new_packet(pkt, buf->size);435 err = av_new_packet(pkt, buf->size);
440 if (err < 0)436 if (err < 0)
441 goto fail;437 goto fail_mapped;
442 438
443 memcpy(pkt->data, buf->buf, buf->size);439 memcpy(pkt->data, buf->buf, buf->size);
444 }440 }
@@ -456,35 +452,32 @@ static int vaapi_encode_output(AVCodecContext *avctx, · 11 unmodified lines
456 goto fail;452 goto fail;
457 }453 }
458 454
459 vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);455 av_buffer_unref(&pic->output_buffer_ref);
460 pic->output_buffer = VA_INVALID_ID;456 pic->output_buffer = VA_INVALID_ID;
461 457
462 av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",458 av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
463 pic->display_order, pic->encode_order);459 pic->display_order, pic->encode_order);
464 return 0;460 return 0;
465 461
462fail_mapped:
463 vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
466fail:464fail:
467 if (pic->output_buffer != VA_INVALID_ID) {465 av_buffer_unref(&pic->output_buffer_ref);
468 vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);466 pic->output_buffer = VA_INVALID_ID;
469 vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);
470 pic->output_buffer = VA_INVALID_ID;
471 }
472 return err;467 return err;
473}468}
474 469
475static int vaapi_encode_discard(AVCodecContext *avctx,470static int vaapi_encode_discard(AVCodecContext *avctx,
476 VAAPIEncodePicture *pic)471 VAAPIEncodePicture *pic)
477{472{
478 VAAPIEncodeContext *ctx = avctx->priv_data;
479
480 vaapi_encode_wait(avctx, pic);473 vaapi_encode_wait(avctx, pic);
481 474
482 if (pic->output_buffer != VA_INVALID_ID) {475 if (pic->output_buffer_ref) {
483 av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "476 av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
484 "%"PRId64"/%"PRId64".\n",477 "%"PRId64"/%"PRId64".\n",
485 pic->display_order, pic->encode_order);478 pic->display_order, pic->encode_order);
486 479
487 vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer);480 av_buffer_unref(&pic->output_buffer_ref);
488 pic->output_buffer = VA_INVALID_ID;481 pic->output_buffer = VA_INVALID_ID;
489 }482 }
490 483
@@ -1025,6 +1018,57 @@ fail: · 534 unmodified lines
1025 return err;1018 return err;
1026}1019}
1027 1020
1021static void vaapi_encode_free_output_buffer(void *opaque,
1022 uint8_t *data)
1023{
1024 AVCodecContext *avctx = opaque;
1025 VAAPIEncodeContext *ctx = avctx->priv_data;
1026 VABufferID buffer_id;
1027
1028 buffer_id = (VABufferID)(uintptr_t)data;
1029
1030 vaDestroyBuffer(ctx->hwctx->display, buffer_id);
1031
1032 av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id);
1033}
1034
1035static AVBufferRef *vaapi_encode_alloc_output_buffer(void *opaque,
1036 int size)
1037{
1038 AVCodecContext *avctx = opaque;
1039 VAAPIEncodeContext *ctx = avctx->priv_data;
1040 VABufferID buffer_id;
1041 VAStatus vas;
1042 AVBufferRef *ref;
1043
1044 // The output buffer size is fixed, so it needs to be large enough
1045 // to hold the largest possible compressed frame. We assume here
1046 // that the uncompressed frame plus some header data is an upper
1047 // bound on that.
1048 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
1049 VAEncCodedBufferType,
1050 3 * ctx->aligned_width * ctx->aligned_height +
1051 (1 << 16), 1, 0, &buffer_id);
1052 if (vas != VA_STATUS_SUCCESS) {
1053 av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
1054 "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
1055 return NULL;
1056 }
1057
1058 av_log(avctx, AV_LOG_DEBUG, "Allocated output buffer %#x\n", buffer_id);
1059
1060 ref = av_buffer_create((uint8_t*)(uintptr_t)buffer_id,
1061 sizeof(buffer_id),
1062 &vaapi_encode_free_output_buffer,
1063 avctx, AV_BUFFER_FLAG_READONLY);
1064 if (!ref) {
1065 vaDestroyBuffer(ctx->hwctx->display, buffer_id);
1066 return NULL;
1067 }
1068
1069 return ref;
1070}
1071
1028av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,1072av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
1029 const VAAPIEncodeType *type)1073 const VAAPIEncodeType *type)
1030{1074{
@@ -1207,6 +1251,14 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, · 176 unmodified lines
1207 }1251 }
1208 }1252 }
1209 1253
1254 ctx->output_buffer_pool =
1255 av_buffer_pool_init2(sizeof(VABufferID), avctx,
1256 &vaapi_encode_alloc_output_buffer, NULL);
1257 if (!ctx->output_buffer_pool) {
1258 err = AVERROR(ENOMEM);
1259 goto fail;
1260 }
1261
1210 // All I are IDR for now.1262 // All I are IDR for now.
1211 ctx->i_per_idr = 0;1263 ctx->i_per_idr = 0;
1212 ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) /1264 ctx->p_per_i = ((avctx->gop_size + avctx->max_b_frames) /
@@ -1249,6 +1301,8 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) · 36 unmodified lines
1249 if (ctx->codec->close)1301 if (ctx->codec->close)
1250 ctx->codec->close(avctx);1302 ctx->codec->close(avctx);
1251 1303
1304 av_buffer_pool_uninit(&ctx->output_buffer_pool);
1305
1252 av_freep(&ctx->codec_sequence_params);1306 av_freep(&ctx->codec_sequence_params);
1253 av_freep(&ctx->codec_picture_params);1307 av_freep(&ctx->codec_picture_params);
1254 1308
libavcodec/vaapi_encode.h+3−1
@@ -39,7 +39,6 @@ enum { · 38 unmodified lines
39 MAX_PARAM_BUFFERS = 16,39 MAX_PARAM_BUFFERS = 16,
40 MAX_REORDER_DELAY = 16,40 MAX_REORDER_DELAY = 16,
41 MAX_PARAM_BUFFER_SIZE = 1024,41 MAX_PARAM_BUFFER_SIZE = 1024,
42 MAX_OUTPUT_BUFFER_SIZE = 1024 * 1024,
43};42};
44 43
45enum {44enum {
@@ -84,6 +83,7 @@ typedef struct VAAPIEncodePicture { · 38 unmodified lines
84 int nb_param_buffers;83 int nb_param_buffers;
85 VABufferID param_buffers[MAX_PARAM_BUFFERS];84 VABufferID param_buffers[MAX_PARAM_BUFFERS];
86 85
86 AVBufferRef *output_buffer_ref;
87 VABufferID output_buffer;87 VABufferID output_buffer;
88 88
89 void *priv_data;89 void *priv_data;
@@ -130,6 +130,8 @@ typedef struct VAAPIEncodeContext { · 40 unmodified lines
130 AVBufferRef *recon_frames_ref;130 AVBufferRef *recon_frames_ref;
131 AVHWFramesContext *recon_frames;131 AVHWFramesContext *recon_frames;
132 132
133 AVBufferPool *output_buffer_pool;
134
133 VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES];135 VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES];
134 int nb_config_attributes;136 int nb_config_attributes;
135 137

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