* 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 | 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 | ||
| 462 | fail_mapped: | ||
| 463 | vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer); | ||
| 466 | fail: | 464 | fail: |
| 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 | ||
| 475 | static int vaapi_encode_discard(AVCodecContext *avctx, | 470 | static 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 | ||
| 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 | av_cold int ff_vaapi_encode_init(AVCodecContext *avctx, | 1072 | av_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 | ||
| @@ -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 | ||
| 45 | enum { | 44 | enum { |
| @@ -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 | ||