* commit '8a62d2c28fbacd1ae20c35887a1eecba2be14371': vaapi_encode: Maintain a pool of bitstream output buffers
Unified · Split
| @@ -178,16 +178,12 @@ static int vaapi_encode_issue(AVCodecContext *avctx, · 177 unmodified lines | ||
| 178 | 178 | pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3]; |
| 179 | 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, | |
| 182 | − VAEncCodedBufferType, | |
| 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)); | |
| 181 | + pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool); | |
| 182 | + if (!pic->output_buffer_ref) { | |
| 188 | 183 | err = AVERROR(ENOMEM); |
| 189 | 184 | goto fail; |
| 190 | 185 | } |
| 186 | + pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data; | |
| 191 | 187 | av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n", |
| 192 | 188 | pic->output_buffer); |
| 193 | 189 | |
| @@ -438,7 +434,7 @@ static int vaapi_encode_output(AVCodecContext *avctx, · 244 unmodified lines | ||
| 438 | 434 | |
| 439 | 435 | err = av_new_packet(pkt, buf->size); |
| 440 | 436 | if (err < 0) |
| 441 | − goto fail; | |
| 437 | + goto fail_mapped; | |
| 442 | 438 | |
| 443 | 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 | 452 | goto fail; |
| 457 | 453 | } |
| 458 | 454 | |
| 459 | − vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer); | |
| 455 | + av_buffer_unref(&pic->output_buffer_ref); | |
| 460 | 456 | pic->output_buffer = VA_INVALID_ID; |
| 461 | 457 | |
| 462 | 458 | av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n", |
| 463 | 459 | pic->display_order, pic->encode_order); |
| 464 | 460 | return 0; |
| 465 | 461 | |
| 462 | +fail_mapped: | |
| 463 | + vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); | |
| 466 | 464 | fail: |
| 467 | − if (pic->output_buffer != VA_INVALID_ID) { | |
| 468 | − vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); | |
| 469 | − vaDestroyBuffer(ctx->hwctx->display, pic->output_buffer); | |
| 470 | − pic->output_buffer = VA_INVALID_ID; | |
| 471 | − } | |
| 465 | + av_buffer_unref(&pic->output_buffer_ref); | |
| 466 | + pic->output_buffer = VA_INVALID_ID; | |
| 472 | 467 | return err; |
| 473 | 468 | } |
| 474 | 469 | |
| 475 | 470 | static int vaapi_encode_discard(AVCodecContext *avctx, |
| 476 | 471 | VAAPIEncodePicture *pic) |
| 477 | 472 | { |
| 478 | − VAAPIEncodeContext *ctx = avctx->priv_data; | |
| 479 | − | |
| 480 | 473 | vaapi_encode_wait(avctx, pic); |
| 481 | 474 | |
| 482 | − if (pic->output_buffer != VA_INVALID_ID) { | |
| 475 | + if (pic->output_buffer_ref) { | |
| 483 | 476 | av_log(avctx, AV_LOG_DEBUG, "Discard output for pic " |
| 484 | 477 | "%"PRId64"/%"PRId64".\n", |
| 485 | 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 | 481 | pic->output_buffer = VA_INVALID_ID; |
| 489 | 482 | } |
| 490 | 483 | |
| @@ -1025,6 +1018,57 @@ fail: · 534 unmodified lines | ||
| 1025 | 1018 | return err; |
| 1026 | 1019 | } |
| 1027 | 1020 | |
| 1021 | +static 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 | + | |
| 1035 | +static 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 | + | |
| 1028 | 1072 | av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, |
| 1029 | 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 | 1262 | // All I are IDR for now. |
| 1211 | 1263 | ctx->i_per_idr = 0; |
| 1212 | 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 | 1301 | if (ctx->codec->close) |
| 1250 | 1302 | ctx->codec->close(avctx); |
| 1251 | 1303 | |
| 1304 | + av_buffer_pool_uninit(&ctx->output_buffer_pool); | |
| 1305 | + | |
| 1252 | 1306 | av_freep(&ctx->codec_sequence_params); |
| 1253 | 1307 | av_freep(&ctx->codec_picture_params); |
| 1254 | 1308 | |
| @@ -39,7 +39,6 @@ enum { · 38 unmodified lines | ||
| 39 | 39 | MAX_PARAM_BUFFERS = 16, |
| 40 | 40 | MAX_REORDER_DELAY = 16, |
| 41 | 41 | MAX_PARAM_BUFFER_SIZE = 1024, |
| 42 | − MAX_OUTPUT_BUFFER_SIZE = 1024 * 1024, | |
| 43 | 42 | }; |
| 44 | 43 | |
| 45 | 44 | enum { |
| @@ -84,6 +83,7 @@ typedef struct VAAPIEncodePicture { · 38 unmodified lines | ||
| 84 | 83 | int nb_param_buffers; |
| 85 | 84 | VABufferID param_buffers[MAX_PARAM_BUFFERS]; |
| 86 | 85 | |
| 86 | + AVBufferRef *output_buffer_ref; | |
| 87 | 87 | VABufferID output_buffer; |
| 88 | 88 | |
| 89 | 89 | void *priv_data; |
| @@ -130,6 +130,8 @@ typedef struct VAAPIEncodeContext { · 40 unmodified lines | ||
| 130 | 130 | AVBufferRef *recon_frames_ref; |
| 131 | 131 | AVHWFramesContext *recon_frames; |
| 132 | 132 | |
| 133 | + AVBufferPool *output_buffer_pool; | |
| 134 | + | |
| 133 | 135 | VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES]; |
| 134 | 136 | int nb_config_attributes; |
| 135 | 137 | |