* commit 'b46a77f19ddc4b2b5fa3187835ceb602a5244e24': lavc: external hardware frame pool initialization Includes the fix from e724bdfffbd3c27aac53d1f32f20f105f37caef0
Unified · Split
| @@ -15,6 +15,9 @@ libavutil: 2017-10-21 · 14 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | API changes, most recent first: |
| 17 | 17 | |
| 18 | +2017-xx-xx - xxxxxxx - lavc 58.3.100 - avcodec.h | |
| 19 | + Add avcodec_get_hw_frames_parameters(). | |
| 20 | + | |
| 18 | 21 | -------- 8< --------- FFmpeg 3.4 was cut here -------- 8< --------- |
| 19 | 22 | |
| 20 | 23 | 2017-09-28 - b6cf66ae1c - lavc 57.106.104 - avcodec.h |
| @@ -3533,6 +3533,16 @@ typedef struct AVHWAccel { · 3532 unmodified lines | ||
| 3533 | 3533 | */ |
| 3534 | 3534 | int caps_internal; |
| 3535 | 3535 | |
| 3536 | + /** | |
| 3537 | + * Fill the given hw_frames context with current codec parameters. Called | |
| 3538 | + * from get_format. Refer to avcodec_get_hw_frames_parameters() for | |
| 3539 | + * details. | |
| 3540 | + * | |
| 3541 | + * This CAN be called before AVHWAccel.init is called, and you must assume | |
| 3542 | + * that avctx->hwaccel_priv_data is invalid. | |
| 3543 | + */ | |
| 3544 | + int (*frame_params)(AVCodecContext *avctx, AVBufferRef *hw_frames_ctx); | |
| 3545 | + | |
| 3536 | 3546 | /** |
| 3537 | 3547 | * Some hwaccels are ambiguous if only the id and pix_fmt fields are used. |
| 3538 | 3548 | * If non-NULL, the associated AVCodec must have |
| @@ -4674,6 +4684,109 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame); · 1135 unmodified lines | ||
| 4674 | 4684 | */ |
| 4675 | 4685 | int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt); |
| 4676 | 4686 | |
| 4687 | +/** | |
| 4688 | + * Create and return a AVHWFramesContext with values adequate for hardware | |
| 4689 | + * decoding. This is meant to get called from the get_format callback, and is | |
| 4690 | + * a helper for preparing a AVHWFramesContext for AVCodecContext.hw_frames_ctx. | |
| 4691 | + * This API is for decoding with certain hardware acceleration modes/APIs only. | |
| 4692 | + * | |
| 4693 | + * The returned AVHWFramesContext is not initialized. The caller must do this | |
| 4694 | + * with av_hwframe_ctx_init(). | |
| 4695 | + * | |
| 4696 | + * Calling this function is not a requirement, but makes it simpler to avoid | |
| 4697 | + * codec or hardware API specific details when manually allocating frames. | |
| 4698 | + * | |
| 4699 | + * Alternatively to this, an API user can set AVCodecContext.hw_device_ctx, | |
| 4700 | + * which sets up AVCodecContext.hw_frames_ctx fully automatically, and makes | |
| 4701 | + * it unnecessary to call this function or having to care about | |
| 4702 | + * AVHWFramesContext initialization at all. | |
| 4703 | + * | |
| 4704 | + * There are a number of requirements for calling this function: | |
| 4705 | + * | |
| 4706 | + * - It must be called from get_format with the same avctx parameter that was | |
| 4707 | + * passed to get_format. Calling it outside of get_format is not allowed, and | |
| 4708 | + * can trigger undefined behavior. | |
| 4709 | + * - The function is not always supported (see description of return values). | |
| 4710 | + * Even if this function returns successfully, hwaccel initialization could | |
| 4711 | + * fail later. (The degree to which implementations check whether the stream | |
| 4712 | + * is actually supported varies. Some do this check only after the user's | |
| 4713 | + * get_format callback returns.) | |
| 4714 | + * - The hw_pix_fmt must be one of the choices suggested by get_format. If the | |
| 4715 | + * user decides to use a AVHWFramesContext prepared with this API function, | |
| 4716 | + * the user must return the same hw_pix_fmt from get_format. | |
| 4717 | + * - The device_ref passed to this function must support the given hw_pix_fmt. | |
| 4718 | + * - After calling this API function, it is the user's responsibility to | |
| 4719 | + * initialize the AVHWFramesContext (returned by the out_frames_ref parameter), | |
| 4720 | + * and to set AVCodecContext.hw_frames_ctx to it. If done, this must be done | |
| 4721 | + * before returning from get_format (this is implied by the normal | |
| 4722 | + * AVCodecContext.hw_frames_ctx API rules). | |
| 4723 | + * - The AVHWFramesContext parameters may change every time time get_format is | |
| 4724 | + * called. Also, AVCodecContext.hw_frames_ctx is reset before get_format. So | |
| 4725 | + * you are inherently required to go through this process again on every | |
| 4726 | + * get_format call. | |
| 4727 | + * - It is perfectly possible to call this function without actually using | |
| 4728 | + * the resulting AVHWFramesContext. One use-case might be trying to reuse a | |
| 4729 | + * previously initialized AVHWFramesContext, and calling this API function | |
| 4730 | + * only to test whether the required frame parameters have changed. | |
| 4731 | + * - Fields that use dynamically allocated values of any kind must not be set | |
| 4732 | + * by the user unless setting them is explicitly allowed by the documentation. | |
| 4733 | + * If the user sets AVHWFramesContext.free and AVHWFramesContext.user_opaque, | |
| 4734 | + * the new free callback must call the potentially set previous free callback. | |
| 4735 | + * This API call may set any dynamically allocated fields, including the free | |
| 4736 | + * callback. | |
| 4737 | + * | |
| 4738 | + * The function will set at least the following fields on AVHWFramesContext | |
| 4739 | + * (potentially more, depending on hwaccel API): | |
| 4740 | + * | |
| 4741 | + * - All fields set by av_hwframe_ctx_alloc(). | |
| 4742 | + * - Set the format field to hw_pix_fmt. | |
| 4743 | + * - Set the sw_format field to the most suited and most versatile format. (An | |
| 4744 | + * implication is that this will prefer generic formats over opaque formats | |
| 4745 | + * with arbitrary restrictions, if possible.) | |
| 4746 | + * - Set the width/height fields to the coded frame size, rounded up to the | |
| 4747 | + * API-specific minimum alignment. | |
| 4748 | + * - Only _if_ the hwaccel requires a pre-allocated pool: set the initial_pool_size | |
| 4749 | + * field to the number of maximum reference surfaces possible with the codec, | |
| 4750 | + * plus 1 surface for the user to work (meaning the user can safely reference | |
| 4751 | + * at most 1 decoded surface at a time), plus additional buffering introduced | |
| 4752 | + * by frame threading. If the hwaccel does not require pre-allocation, the | |
| 4753 | + * field is left to 0, and the decoder will allocate new surfaces on demand | |
| 4754 | + * during decoding. | |
| 4755 | + * - Possibly AVHWFramesContext.hwctx fields, depending on the underlying | |
| 4756 | + * hardware API. | |
| 4757 | + * | |
| 4758 | + * Essentially, out_frames_ref returns the same as av_hwframe_ctx_alloc(), but | |
| 4759 | + * with basic frame parameters set. | |
| 4760 | + * | |
| 4761 | + * The function is stateless, and does not change the AVCodecContext or the | |
| 4762 | + * device_ref AVHWDeviceContext. | |
| 4763 | + * | |
| 4764 | + * @param avctx The context which is currently calling get_format, and which | |
| 4765 | + * implicitly contains all state needed for filling the returned | |
| 4766 | + * AVHWFramesContext properly. | |
| 4767 | + * @param device_ref A reference to the AVHWDeviceContext describing the device | |
| 4768 | + * which will be used by the hardware decoder. | |
| 4769 | + * @param hw_pix_fmt The hwaccel format you are going to return from get_format. | |
| 4770 | + * @param out_frames_ref On success, set to a reference to an _uninitialized_ | |
| 4771 | + * AVHWFramesContext, created from the given device_ref. | |
| 4772 | + * Fields will be set to values required for decoding. | |
| 4773 | + * Not changed if an error is returned. | |
| 4774 | + * @return zero on success, a negative value on error. The following error codes | |
| 4775 | + * have special semantics: | |
| 4776 | + * AVERROR(ENOENT): the decoder does not support this functionality. Setup | |
| 4777 | + * is always manual, or it is a decoder which does not | |
| 4778 | + * support setting AVCodecContext.hw_frames_ctx at all, | |
| 4779 | + * or it is a software format. | |
| 4780 | + * AVERROR(EINVAL): it is known that hardware decoding is not supported for | |
| 4781 | + * this configuration, or the device_ref is not supported | |
| 4782 | + * for the hwaccel referenced by hw_pix_fmt. | |
| 4783 | + */ | |
| 4784 | +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, | |
| 4785 | + AVBufferRef *device_ref, | |
| 4786 | + enum AVPixelFormat hw_pix_fmt, | |
| 4787 | + AVBufferRef **out_frames_ref); | |
| 4788 | + | |
| 4789 | + | |
| 4677 | 4790 | |
| 4678 | 4791 | /** |
| 4679 | 4792 | * @defgroup lavc_parsing Frame parsing |
| @@ -1106,6 +1106,86 @@ static AVHWAccel *find_hwaccel(AVCodecContext *avctx, · 1105 unmodified lines | ||
| 1106 | 1106 | return NULL; |
| 1107 | 1107 | } |
| 1108 | 1108 | |
| 1109 | +int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, | |
| 1110 | + enum AVHWDeviceType dev_type) | |
| 1111 | +{ | |
| 1112 | + AVHWDeviceContext *device_ctx; | |
| 1113 | + AVHWFramesContext *frames_ctx; | |
| 1114 | + int ret; | |
| 1115 | + | |
| 1116 | + if (!avctx->hwaccel) | |
| 1117 | + return AVERROR(ENOSYS); | |
| 1118 | + | |
| 1119 | + if (avctx->hw_frames_ctx) | |
| 1120 | + return 0; | |
| 1121 | + if (!avctx->hw_device_ctx) { | |
| 1122 | + av_log(avctx, AV_LOG_ERROR, "A hardware frames or device context is " | |
| 1123 | + "required for hardware accelerated decoding.\n"); | |
| 1124 | + return AVERROR(EINVAL); | |
| 1125 | + } | |
| 1126 | + | |
| 1127 | + device_ctx = (AVHWDeviceContext *)avctx->hw_device_ctx->data; | |
| 1128 | + if (device_ctx->type != dev_type) { | |
| 1129 | + av_log(avctx, AV_LOG_ERROR, "Device type %s expected for hardware " | |
| 1130 | + "decoding, but got %s.\n", av_hwdevice_get_type_name(dev_type), | |
| 1131 | + av_hwdevice_get_type_name(device_ctx->type)); | |
| 1132 | + return AVERROR(EINVAL); | |
| 1133 | + } | |
| 1134 | + | |
| 1135 | + ret = avcodec_get_hw_frames_parameters(avctx, | |
| 1136 | + avctx->hw_device_ctx, | |
| 1137 | + avctx->hwaccel->pix_fmt, | |
| 1138 | + &avctx->hw_frames_ctx); | |
| 1139 | + if (ret < 0) | |
| 1140 | + return ret; | |
| 1141 | + | |
| 1142 | + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + if (frames_ctx->initial_pool_size) { | |
| 1146 | + // We guarantee 4 base work surfaces. The function above guarantees 1 | |
| 1147 | + // (the absolute minimum), so add the missing count. | |
| 1148 | + frames_ctx->initial_pool_size += 3; | |
| 1149 | + | |
| 1150 | + // Add an additional surface per thread is frame threading is enabled. | |
| 1151 | + if (avctx->active_thread_type & FF_THREAD_FRAME) | |
| 1152 | + frames_ctx->initial_pool_size += avctx->thread_count; | |
| 1153 | + } | |
| 1154 | + | |
| 1155 | + ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); | |
| 1156 | + if (ret < 0) { | |
| 1157 | + av_buffer_unref(&avctx->hw_frames_ctx); | |
| 1158 | + return ret; | |
| 1159 | + } | |
| 1160 | + | |
| 1161 | + return 0; | |
| 1162 | +} | |
| 1163 | + | |
| 1164 | +int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, | |
| 1165 | + AVBufferRef *device_ref, | |
| 1166 | + enum AVPixelFormat hw_pix_fmt, | |
| 1167 | + AVBufferRef **out_frames_ref) | |
| 1168 | +{ | |
| 1169 | + AVBufferRef *frames_ref = NULL; | |
| 1170 | + AVHWAccel *hwa = find_hwaccel(avctx, hw_pix_fmt); | |
| 1171 | + int ret; | |
| 1172 | + | |
| 1173 | + if (!hwa || !hwa->frame_params) | |
| 1174 | + return AVERROR(ENOENT); | |
| 1175 | + | |
| 1176 | + frames_ref = av_hwframe_ctx_alloc(device_ref); | |
| 1177 | + if (!frames_ref) | |
| 1178 | + return AVERROR(ENOMEM); | |
| 1179 | + | |
| 1180 | + ret = hwa->frame_params(avctx, frames_ref); | |
| 1181 | + if (ret >= 0) { | |
| 1182 | + *out_frames_ref = frames_ref; | |
| 1183 | + } else { | |
| 1184 | + av_buffer_unref(&frames_ref); | |
| 1185 | + } | |
| 1186 | + return ret; | |
| 1187 | +} | |
| 1188 | + | |
| 1109 | 1189 | static int setup_hwaccel(AVCodecContext *avctx, |
| 1110 | 1190 | const enum AVPixelFormat fmt, |
| 1111 | 1191 | const char *name) |
| @@ -24,6 +24,10 @@ · 23 unmodified lines | ||
| 24 | 24 | #include "libavutil/buffer.h" |
| 25 | 25 | #include "libavutil/frame.h" |
| 26 | 26 | |
| 27 | +#include "libavutil/buffer.h" | |
| 28 | +#include "libavutil/frame.h" | |
| 29 | +#include "libavutil/hwcontext.h" | |
| 30 | + | |
| 27 | 31 | #include "avcodec.h" |
| 28 | 32 | |
| 29 | 33 | /** |
| @@ -65,6 +69,14 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt); · 35 unmodified lines | ||
| 65 | 69 | |
| 66 | 70 | void ff_decode_bsfs_uninit(AVCodecContext *avctx); |
| 67 | 71 | |
| 72 | +/** | |
| 73 | + * Make sure avctx.hw_frames_ctx is set. If it's not set, the function will | |
| 74 | + * try to allocate it from hw_device_ctx. If that is not possible, an error | |
| 75 | + * message is printed, and an error code is returned. | |
| 76 | + */ | |
| 77 | +int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx, | |
| 78 | + enum AVHWDeviceType dev_type); | |
| 79 | + | |
| 68 | 80 | int ff_attach_decode_data(AVFrame *frame); |
| 69 | 81 | |
| 70 | 82 | #endif /* AVCODEC_DECODE_H */ |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include "libavutil/time.h" |
| 30 | 30 | |
| 31 | 31 | #include "avcodec.h" |
| 32 | +#include "decode.h" | |
| 32 | 33 | #include "dxva2_internal.h" |
| 33 | 34 | |
| 34 | 35 | /* define all the GUIDs used directly here, |
| @@ -576,14 +577,20 @@ static void ff_dxva2_unlock(AVCodecContext *avctx) · 541 unmodified lines | ||
| 576 | 577 | #endif |
| 577 | 578 | } |
| 578 | 579 | |
| 579 | −// This must work before the decoder is created. | |
| 580 | −// This somehow needs to be exported to the user. | |
| 581 | −static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frames_ctx) | |
| 580 | +int ff_dxva2_common_frame_params(AVCodecContext *avctx, | |
| 581 | + AVBufferRef *hw_frames_ctx) | |
| 582 | 582 | { |
| 583 | − FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); | |
| 583 | + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data; | |
| 584 | + AVHWDeviceContext *device_ctx = frames_ctx->device_ctx; | |
| 584 | 585 | int surface_alignment, num_surfaces; |
| 585 | 586 | |
| 586 | − frames_ctx->format = sctx->pix_fmt; | |
| 587 | + if (device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { | |
| 588 | + frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; | |
| 589 | + } else if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { | |
| 590 | + frames_ctx->format = AV_PIX_FMT_D3D11; | |
| 591 | + } else { | |
| 592 | + return AVERROR(EINVAL); | |
| 593 | + } | |
| 587 | 594 | |
| 588 | 595 | /* decoding MPEG-2 requires additional alignment on some Intel GPUs, |
| 589 | 596 | but it causes issues for H.264 on certain AMD GPUs..... */ |
| @@ -596,8 +603,8 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame · 6 unmodified lines | ||
| 596 | 603 | else |
| 597 | 604 | surface_alignment = 16; |
| 598 | 605 | |
| 599 | − /* 4 base work surfaces */ | |
| 600 | − num_surfaces = 4; | |
| 606 | + /* 1 base work surface */ | |
| 607 | + num_surfaces = 1; | |
| 601 | 608 | |
| 602 | 609 | /* add surfaces based on number of possible refs */ |
| 603 | 610 | if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) |
| @@ -633,12 +640,16 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame · 29 unmodified lines | ||
| 633 | 640 | frames_hwctx->BindFlags |= D3D11_BIND_DECODER; |
| 634 | 641 | } |
| 635 | 642 | #endif |
| 643 | + | |
| 644 | + return 0; | |
| 636 | 645 | } |
| 637 | 646 | |
| 638 | 647 | int ff_dxva2_decode_init(AVCodecContext *avctx) |
| 639 | 648 | { |
| 640 | 649 | FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); |
| 641 | − AVHWFramesContext *frames_ctx = NULL; | |
| 650 | + AVHWFramesContext *frames_ctx; | |
| 651 | + enum AVHWDeviceType dev_type = avctx->hwaccel->pix_fmt == AV_PIX_FMT_DXVA2_VLD | |
| 652 | + ? AV_HWDEVICE_TYPE_DXVA2 : AV_HWDEVICE_TYPE_D3D11VA; | |
| 642 | 653 | int ret = 0; |
| 643 | 654 | |
| 644 | 655 | // Old API. |
| @@ -648,32 +659,14 @@ int ff_dxva2_decode_init(AVCodecContext *avctx) · 3 unmodified lines | ||
| 648 | 659 | // (avctx->pix_fmt is not updated yet at this point) |
| 649 | 660 | sctx->pix_fmt = avctx->hwaccel->pix_fmt; |
| 650 | 661 | |
| 651 | − if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) { | |
| 652 | − av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n"); | |
| 653 | − return AVERROR(EINVAL); | |
| 654 | − } | |
| 655 | − | |
| 656 | − if (avctx->hw_frames_ctx) { | |
| 657 | − frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 658 | − } else { | |
| 659 | − avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); | |
| 660 | − if (!avctx->hw_frames_ctx) | |
| 661 | − return AVERROR(ENOMEM); | |
| 662 | − | |
| 663 | − frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 664 | − | |
| 665 | − dxva_adjust_hwframes(avctx, frames_ctx); | |
| 666 | − | |
| 667 | − ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); | |
| 668 | − if (ret < 0) | |
| 669 | − goto fail; | |
| 670 | − } | |
| 662 | + ret = ff_decode_get_hw_frames_ctx(avctx, dev_type); | |
| 663 | + if (ret < 0) | |
| 664 | + return ret; | |
| 671 | 665 | |
| 666 | + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 672 | 667 | sctx->device_ctx = frames_ctx->device_ctx; |
| 673 | 668 | |
| 674 | − if (frames_ctx->format != sctx->pix_fmt || | |
| 675 | − !((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) || | |
| 676 | − (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) { | |
| 669 | + if (frames_ctx->format != sctx->pix_fmt) { | |
| 677 | 670 | av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n"); |
| 678 | 671 | ret = AVERROR(EINVAL); |
| 679 | 672 | goto fail; |
| @@ -528,6 +528,7 @@ AVHWAccel ff_h264_dxva2_hwaccel = { · 527 unmodified lines | ||
| 528 | 528 | .start_frame = dxva2_h264_start_frame, |
| 529 | 529 | .decode_slice = dxva2_h264_decode_slice, |
| 530 | 530 | .end_frame = dxva2_h264_end_frame, |
| 531 | + .frame_params = ff_dxva2_common_frame_params, | |
| 531 | 532 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 532 | 533 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 533 | 534 | }; |
| @@ -544,6 +545,7 @@ AVHWAccel ff_h264_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 544 | 545 | .start_frame = dxva2_h264_start_frame, |
| 545 | 546 | .decode_slice = dxva2_h264_decode_slice, |
| 546 | 547 | .end_frame = dxva2_h264_end_frame, |
| 548 | + .frame_params = ff_dxva2_common_frame_params, | |
| 547 | 549 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 548 | 550 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 549 | 551 | }; |
| @@ -560,6 +562,7 @@ AVHWAccel ff_h264_d3d11va2_hwaccel = { · 10 unmodified lines | ||
| 560 | 562 | .start_frame = dxva2_h264_start_frame, |
| 561 | 563 | .decode_slice = dxva2_h264_decode_slice, |
| 562 | 564 | .end_frame = dxva2_h264_end_frame, |
| 565 | + .frame_params = ff_dxva2_common_frame_params, | |
| 563 | 566 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 564 | 567 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 565 | 568 | }; |
| @@ -432,6 +432,7 @@ AVHWAccel ff_hevc_dxva2_hwaccel = { · 431 unmodified lines | ||
| 432 | 432 | .start_frame = dxva2_hevc_start_frame, |
| 433 | 433 | .decode_slice = dxva2_hevc_decode_slice, |
| 434 | 434 | .end_frame = dxva2_hevc_end_frame, |
| 435 | + .frame_params = ff_dxva2_common_frame_params, | |
| 435 | 436 | .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), |
| 436 | 437 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 437 | 438 | }; |
| @@ -448,6 +449,7 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 448 | 449 | .start_frame = dxva2_hevc_start_frame, |
| 449 | 450 | .decode_slice = dxva2_hevc_decode_slice, |
| 450 | 451 | .end_frame = dxva2_hevc_end_frame, |
| 452 | + .frame_params = ff_dxva2_common_frame_params, | |
| 451 | 453 | .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), |
| 452 | 454 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 453 | 455 | }; |
| @@ -464,6 +466,7 @@ AVHWAccel ff_hevc_d3d11va2_hwaccel = { · 10 unmodified lines | ||
| 464 | 466 | .start_frame = dxva2_hevc_start_frame, |
| 465 | 467 | .decode_slice = dxva2_hevc_decode_slice, |
| 466 | 468 | .end_frame = dxva2_hevc_end_frame, |
| 469 | + .frame_params = ff_dxva2_common_frame_params, | |
| 467 | 470 | .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context), |
| 468 | 471 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 469 | 472 | }; |
| @@ -156,6 +156,9 @@ int ff_dxva2_decode_init(AVCodecContext *avctx); · 155 unmodified lines | ||
| 156 | 156 | |
| 157 | 157 | int ff_dxva2_decode_uninit(AVCodecContext *avctx); |
| 158 | 158 | |
| 159 | +int ff_dxva2_common_frame_params(AVCodecContext *avctx, | |
| 160 | + AVBufferRef *hw_frames_ctx); | |
| 161 | + | |
| 159 | 162 | int ff_dxva2_is_d3d11(const AVCodecContext *avctx); |
| 160 | 163 | |
| 161 | 164 | #endif /* AVCODEC_DXVA2_INTERNAL_H */ |
| @@ -327,6 +327,7 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = { · 326 unmodified lines | ||
| 327 | 327 | .start_frame = dxva2_mpeg2_start_frame, |
| 328 | 328 | .decode_slice = dxva2_mpeg2_decode_slice, |
| 329 | 329 | .end_frame = dxva2_mpeg2_end_frame, |
| 330 | + .frame_params = ff_dxva2_common_frame_params, | |
| 330 | 331 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 331 | 332 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 332 | 333 | }; |
| @@ -343,6 +344,7 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 343 | 344 | .start_frame = dxva2_mpeg2_start_frame, |
| 344 | 345 | .decode_slice = dxva2_mpeg2_decode_slice, |
| 345 | 346 | .end_frame = dxva2_mpeg2_end_frame, |
| 347 | + .frame_params = ff_dxva2_common_frame_params, | |
| 346 | 348 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 347 | 349 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 348 | 350 | }; |
| @@ -359,6 +361,7 @@ AVHWAccel ff_mpeg2_d3d11va2_hwaccel = { · 10 unmodified lines | ||
| 359 | 361 | .start_frame = dxva2_mpeg2_start_frame, |
| 360 | 362 | .decode_slice = dxva2_mpeg2_decode_slice, |
| 361 | 363 | .end_frame = dxva2_mpeg2_end_frame, |
| 364 | + .frame_params = ff_dxva2_common_frame_params, | |
| 362 | 365 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 363 | 366 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 364 | 367 | }; |
| @@ -388,6 +388,7 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = { · 387 unmodified lines | ||
| 388 | 388 | .start_frame = dxva2_vc1_start_frame, |
| 389 | 389 | .decode_slice = dxva2_vc1_decode_slice, |
| 390 | 390 | .end_frame = dxva2_vc1_end_frame, |
| 391 | + .frame_params = ff_dxva2_common_frame_params, | |
| 391 | 392 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 392 | 393 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 393 | 394 | }; |
| @@ -404,6 +405,7 @@ AVHWAccel ff_vc1_dxva2_hwaccel = { · 10 unmodified lines | ||
| 404 | 405 | .start_frame = dxva2_vc1_start_frame, |
| 405 | 406 | .decode_slice = dxva2_vc1_decode_slice, |
| 406 | 407 | .end_frame = dxva2_vc1_end_frame, |
| 408 | + .frame_params = ff_dxva2_common_frame_params, | |
| 407 | 409 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 408 | 410 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 409 | 411 | }; |
| @@ -420,6 +422,7 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 420 | 422 | .start_frame = dxva2_vc1_start_frame, |
| 421 | 423 | .decode_slice = dxva2_vc1_decode_slice, |
| 422 | 424 | .end_frame = dxva2_vc1_end_frame, |
| 425 | + .frame_params = ff_dxva2_common_frame_params, | |
| 423 | 426 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 424 | 427 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 425 | 428 | }; |
| @@ -436,6 +439,7 @@ AVHWAccel ff_wmv3_d3d11va2_hwaccel = { · 10 unmodified lines | ||
| 436 | 439 | .start_frame = dxva2_vc1_start_frame, |
| 437 | 440 | .decode_slice = dxva2_vc1_decode_slice, |
| 438 | 441 | .end_frame = dxva2_vc1_end_frame, |
| 442 | + .frame_params = ff_dxva2_common_frame_params, | |
| 439 | 443 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 440 | 444 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 441 | 445 | }; |
| @@ -452,6 +456,7 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 452 | 456 | .start_frame = dxva2_vc1_start_frame, |
| 453 | 457 | .decode_slice = dxva2_vc1_decode_slice, |
| 454 | 458 | .end_frame = dxva2_vc1_end_frame, |
| 459 | + .frame_params = ff_dxva2_common_frame_params, | |
| 455 | 460 | .frame_priv_data_size = sizeof(struct dxva2_picture_context), |
| 456 | 461 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 457 | 462 | }; |
| @@ -319,6 +319,7 @@ AVHWAccel ff_vp9_dxva2_hwaccel = { · 318 unmodified lines | ||
| 319 | 319 | .start_frame = dxva2_vp9_start_frame, |
| 320 | 320 | .decode_slice = dxva2_vp9_decode_slice, |
| 321 | 321 | .end_frame = dxva2_vp9_end_frame, |
| 322 | + .frame_params = ff_dxva2_common_frame_params, | |
| 322 | 323 | .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context), |
| 323 | 324 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 324 | 325 | }; |
| @@ -335,6 +336,7 @@ AVHWAccel ff_vp9_d3d11va_hwaccel = { · 10 unmodified lines | ||
| 335 | 336 | .start_frame = dxva2_vp9_start_frame, |
| 336 | 337 | .decode_slice = dxva2_vp9_decode_slice, |
| 337 | 338 | .end_frame = dxva2_vp9_end_frame, |
| 339 | + .frame_params = ff_dxva2_common_frame_params, | |
| 338 | 340 | .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context), |
| 339 | 341 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 340 | 342 | }; |
| @@ -351,6 +353,7 @@ AVHWAccel ff_vp9_d3d11va2_hwaccel = { · 10 unmodified lines | ||
| 351 | 353 | .start_frame = dxva2_vp9_start_frame, |
| 352 | 354 | .decode_slice = dxva2_vp9_decode_slice, |
| 353 | 355 | .end_frame = dxva2_vp9_end_frame, |
| 356 | + .frame_params = ff_dxva2_common_frame_params, | |
| 354 | 357 | .frame_priv_data_size = sizeof(struct vp9_dxva2_picture_context), |
| 355 | 358 | .priv_data_size = sizeof(FFDXVASharedContext), |
| 356 | 359 | }; |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | ||
| 21 | 21 | #include "libavutil/pixdesc.h" |
| 22 | 22 | |
| 23 | 23 | #include "avcodec.h" |
| 24 | +#include "decode.h" | |
| 24 | 25 | #include "internal.h" |
| 25 | 26 | #include "vaapi_decode.h" |
| 26 | 27 | |
| @@ -272,10 +273,15 @@ static const struct { · 245 unmodified lines | ||
| 272 | 273 | #undef MAP |
| 273 | 274 | }; |
| 274 | 275 | |
| 275 | −static int vaapi_decode_make_config(AVCodecContext *avctx) | |
| 276 | +/* | |
| 277 | + * Set *va_config and the frames_ref fields from the current codec parameters | |
| 278 | + * in avctx. | |
| 279 | + */ | |
| 280 | +static int vaapi_decode_make_config(AVCodecContext *avctx, | |
| 281 | + AVBufferRef *device_ref, | |
| 282 | + VAConfigID *va_config, | |
| 283 | + AVBufferRef *frames_ref) | |
| 276 | 284 | { |
| 277 | − VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | |
| 278 | − | |
| 279 | 285 | AVVAAPIHWConfig *hwconfig = NULL; |
| 280 | 286 | AVHWFramesConstraints *constraints = NULL; |
| 281 | 287 | VAStatus vas; |
| @@ -285,13 +291,16 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 3 unmodified lines | ||
| 285 | 291 | int profile_count, exact_match, alt_profile; |
| 286 | 292 | const AVPixFmtDescriptor *sw_desc, *desc; |
| 287 | 293 | |
| 294 | + AVHWDeviceContext *device = (AVHWDeviceContext*)device_ref->data; | |
| 295 | + AVVAAPIDeviceContext *hwctx = device->hwctx; | |
| 296 | + | |
| 288 | 297 | codec_desc = avcodec_descriptor_get(avctx->codec_id); |
| 289 | 298 | if (!codec_desc) { |
| 290 | 299 | err = AVERROR(EINVAL); |
| 291 | 300 | goto fail; |
| 292 | 301 | } |
| 293 | 302 | |
| 294 | − profile_count = vaMaxNumProfiles(ctx->hwctx->display); | |
| 303 | + profile_count = vaMaxNumProfiles(hwctx->display); | |
| 295 | 304 | profile_list = av_malloc_array(profile_count, |
| 296 | 305 | sizeof(VAProfile)); |
| 297 | 306 | if (!profile_list) { |
| @@ -299,7 +308,7 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 1 unmodified line | ||
| 299 | 308 | goto fail; |
| 300 | 309 | } |
| 301 | 310 | |
| 302 | − vas = vaQueryConfigProfiles(ctx->hwctx->display, | |
| 311 | + vas = vaQueryConfigProfiles(hwctx->display, | |
| 303 | 312 | profile_list, &profile_count); |
| 304 | 313 | if (vas != VA_STATUS_SUCCESS) { |
| 305 | 314 | av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: " |
| @@ -358,12 +367,9 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 52 unmodified lines | ||
| 358 | 367 | } |
| 359 | 368 | } |
| 360 | 369 | |
| 361 | − ctx->va_profile = profile; | |
| 362 | − ctx->va_entrypoint = VAEntrypointVLD; | |
| 363 | − | |
| 364 | − vas = vaCreateConfig(ctx->hwctx->display, ctx->va_profile, | |
| 365 | − ctx->va_entrypoint, NULL, 0, | |
| 366 | − &ctx->va_config); | |
| 370 | + vas = vaCreateConfig(hwctx->display, profile, | |
| 371 | + VAEntrypointVLD, NULL, 0, | |
| 372 | + va_config); | |
| 367 | 373 | if (vas != VA_STATUS_SUCCESS) { |
| 368 | 374 | av_log(avctx, AV_LOG_ERROR, "Failed to create decode " |
| 369 | 375 | "configuration: %d (%s).\n", vas, vaErrorStr(vas)); |
| @@ -371,20 +377,15 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 1 unmodified line | ||
| 371 | 377 | goto fail; |
| 372 | 378 | } |
| 373 | 379 | |
| 374 | − hwconfig = av_hwdevice_hwconfig_alloc(avctx->hw_device_ctx ? | |
| 375 | − avctx->hw_device_ctx : | |
| 376 | − ctx->frames->device_ref); | |
| 380 | + hwconfig = av_hwdevice_hwconfig_alloc(device_ref); | |
| 377 | 381 | if (!hwconfig) { |
| 378 | 382 | err = AVERROR(ENOMEM); |
| 379 | 383 | goto fail; |
| 380 | 384 | } |
| 381 | − hwconfig->config_id = ctx->va_config; | |
| 385 | + hwconfig->config_id = *va_config; | |
| 382 | 386 | |
| 383 | 387 | constraints = |
| 384 | − av_hwdevice_get_hwframe_constraints(avctx->hw_device_ctx ? | |
| 385 | − avctx->hw_device_ctx : | |
| 386 | − ctx->frames->device_ref, | |
| 387 | − hwconfig); | |
| 388 | + av_hwdevice_get_hwframe_constraints(device_ref, hwconfig); | |
| 388 | 389 | if (!constraints) { |
| 389 | 390 | err = AVERROR(ENOMEM); |
| 390 | 391 | goto fail; |
| @@ -410,48 +411,52 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 19 unmodified lines | ||
| 410 | 411 | goto fail; |
| 411 | 412 | } |
| 412 | 413 | |
| 413 | − // Find the first format in the list which matches the expected | |
| 414 | − // bit depth and subsampling. If none are found (this can happen | |
| 415 | − // when 10-bit streams are decoded to 8-bit surfaces, for example) | |
| 416 | − // then just take the first format on the list. | |
| 417 | − ctx->surface_format = constraints->valid_sw_formats[0]; | |
| 418 | − sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); | |
| 419 | − for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { | |
| 420 | − desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); | |
| 421 | − if (desc->nb_components != sw_desc->nb_components || | |
| 422 | − desc->log2_chroma_w != sw_desc->log2_chroma_w || | |
| 423 | − desc->log2_chroma_h != sw_desc->log2_chroma_h) | |
| 424 | − continue; | |
| 425 | − for (j = 0; j < desc->nb_components; j++) { | |
| 426 | − if (desc->comp[j].depth != sw_desc->comp[j].depth) | |
| 427 | − break; | |
| 414 | + if (frames_ref) { | |
| 415 | + AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; | |
| 416 | + | |
| 417 | + frames->format = AV_PIX_FMT_VAAPI; | |
| 418 | + frames->width = avctx->coded_width; | |
| 419 | + frames->height = avctx->coded_height; | |
| 420 | + | |
| 421 | + // Find the first format in the list which matches the expected | |
| 422 | + // bit depth and subsampling. If none are found (this can happen | |
| 423 | + // when 10-bit streams are decoded to 8-bit surfaces, for example) | |
| 424 | + // then just take the first format on the list. | |
| 425 | + frames->sw_format = constraints->valid_sw_formats[0]; | |
| 426 | + sw_desc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); | |
| 427 | + for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) { | |
| 428 | + desc = av_pix_fmt_desc_get(constraints->valid_sw_formats[i]); | |
| 429 | + if (desc->nb_components != sw_desc->nb_components || | |
| 430 | + desc->log2_chroma_w != sw_desc->log2_chroma_w || | |
| 431 | + desc->log2_chroma_h != sw_desc->log2_chroma_h) | |
| 432 | + continue; | |
| 433 | + for (j = 0; j < desc->nb_components; j++) { | |
| 434 | + if (desc->comp[j].depth != sw_desc->comp[j].depth) | |
| 435 | + break; | |
| 436 | + } | |
| 437 | + if (j < desc->nb_components) | |
| 438 | + continue; | |
| 439 | + frames->sw_format = constraints->valid_sw_formats[i]; | |
| 440 | + break; | |
| 428 | 441 | } |
| 429 | − if (j < desc->nb_components) | |
| 430 | − continue; | |
| 431 | − ctx->surface_format = constraints->valid_sw_formats[i]; | |
| 432 | − break; | |
| 433 | − } | |
| 434 | 442 | |
| 435 | − // Start with at least four surfaces. | |
| 436 | − ctx->surface_count = 4; | |
| 437 | − // Add per-codec number of surfaces used for storing reference frames. | |
| 438 | − switch (avctx->codec_id) { | |
| 439 | − case AV_CODEC_ID_H264: | |
| 440 | − case AV_CODEC_ID_HEVC: | |
| 441 | − ctx->surface_count += 16; | |
| 442 | − break; | |
| 443 | − case AV_CODEC_ID_VP9: | |
| 444 | − ctx->surface_count += 8; | |
| 445 | − break; | |
| 446 | − case AV_CODEC_ID_VP8: | |
| 447 | − ctx->surface_count += 3; | |
| 448 | − break; | |
| 449 | − default: | |
| 450 | − ctx->surface_count += 2; | |
| 443 | + frames->initial_pool_size = 1; | |
| 444 | + // Add per-codec number of surfaces used for storing reference frames. | |
| 445 | + switch (avctx->codec_id) { | |
| 446 | + case AV_CODEC_ID_H264: | |
| 447 | + case AV_CODEC_ID_HEVC: | |
| 448 | + frames->initial_pool_size += 16; | |
| 449 | + break; | |
| 450 | + case AV_CODEC_ID_VP9: | |
| 451 | + frames->initial_pool_size += 8; | |
| 452 | + break; | |
| 453 | + case AV_CODEC_ID_VP8: | |
| 454 | + frames->initial_pool_size += 3; | |
| 455 | + break; | |
| 456 | + default: | |
| 457 | + frames->initial_pool_size += 2; | |
| 458 | + } | |
| 451 | 459 | } |
| 452 | − // Add an additional surface per thread is frame threading is enabled. | |
| 453 | − if (avctx->active_thread_type & FF_THREAD_FRAME) | |
| 454 | − ctx->surface_count += avctx->thread_count; | |
| 455 | 460 | |
| 456 | 461 | av_hwframe_constraints_free(&constraints); |
| 457 | 462 | av_freep(&hwconfig); |
| @@ -461,14 +466,38 @@ static int vaapi_decode_make_config(AVCodecContext *avctx) · 3 unmodified lines | ||
| 461 | 466 | fail: |
| 462 | 467 | av_hwframe_constraints_free(&constraints); |
| 463 | 468 | av_freep(&hwconfig); |
| 464 | − if (ctx->va_config != VA_INVALID_ID) { | |
| 465 | − vaDestroyConfig(ctx->hwctx->display, ctx->va_config); | |
| 466 | − ctx->va_config = VA_INVALID_ID; | |
| 469 | + if (*va_config != VA_INVALID_ID) { | |
| 470 | + vaDestroyConfig(hwctx->display, *va_config); | |
| 471 | + *va_config = VA_INVALID_ID; | |
| 467 | 472 | } |
| 468 | 473 | av_freep(&profile_list); |
| 469 | 474 | return err; |
| 470 | 475 | } |
| 471 | 476 | |
| 477 | +int ff_vaapi_common_frame_params(AVCodecContext *avctx, | |
| 478 | + AVBufferRef *hw_frames_ctx) | |
| 479 | +{ | |
| 480 | + AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data; | |
| 481 | + AVHWDeviceContext *device_ctx = hw_frames->device_ctx; | |
| 482 | + AVVAAPIDeviceContext *hwctx; | |
| 483 | + VAConfigID va_config = VA_INVALID_ID; | |
| 484 | + int err; | |
| 485 | + | |
| 486 | + if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI) | |
| 487 | + return AVERROR(EINVAL); | |
| 488 | + hwctx = device_ctx->hwctx; | |
| 489 | + | |
| 490 | + err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config, | |
| 491 | + hw_frames_ctx); | |
| 492 | + if (err) | |
| 493 | + return err; | |
| 494 | + | |
| 495 | + if (va_config != VA_INVALID_ID) | |
| 496 | + vaDestroyConfig(hwctx->display, va_config); | |
| 497 | + | |
| 498 | + return 0; | |
| 499 | +} | |
| 500 | + | |
| 472 | 501 | int ff_vaapi_decode_init(AVCodecContext *avctx) |
| 473 | 502 | { |
| 474 | 503 | VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; |
| @@ -505,36 +534,8 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) · 30 unmodified lines | ||
| 505 | 534 | ctx->hwctx->driver_quirks = |
| 506 | 535 | AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS; |
| 507 | 536 | |
| 508 | − } else | |
| 509 | −#endif | |
| 510 | − if (avctx->hw_frames_ctx) { | |
| 511 | − // This structure has a shorter lifetime than the enclosing | |
| 512 | − // AVCodecContext, so we inherit the references from there | |
| 513 | − // and do not need to make separate ones. | |
| 514 | − | |
| 515 | − ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 516 | − ctx->hwfc = ctx->frames->hwctx; | |
| 517 | − ctx->device = ctx->frames->device_ctx; | |
| 518 | − ctx->hwctx = ctx->device->hwctx; | |
| 519 | − | |
| 520 | − } else if (avctx->hw_device_ctx) { | |
| 521 | − ctx->device = (AVHWDeviceContext*)avctx->hw_device_ctx->data; | |
| 522 | − ctx->hwctx = ctx->device->hwctx; | |
| 523 | − | |
| 524 | − if (ctx->device->type != AV_HWDEVICE_TYPE_VAAPI) { | |
| 525 | − av_log(avctx, AV_LOG_ERROR, "Device supplied for VAAPI " | |
| 526 | − "decoding must be a VAAPI device (not %d).\n", | |
| 527 | − ctx->device->type); | |
| 528 | − err = AVERROR(EINVAL); | |
| 529 | − goto fail; | |
| 530 | − } | |
| 531 | − | |
| 532 | − } else { | |
| 533 | − av_log(avctx, AV_LOG_ERROR, "A hardware device or frames context " | |
| 534 | − "is required for VAAPI decoding.\n"); | |
| 535 | − err = AVERROR(EINVAL); | |
| 536 | − goto fail; | |
| 537 | 537 | } |
| 538 | +#endif | |
| 538 | 539 | |
| 539 | 540 | #if FF_API_STRUCT_VAAPI_CONTEXT |
| 540 | 541 | if (ctx->have_old_context) { |
| @@ -546,34 +547,19 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) · 5 unmodified lines | ||
| 546 | 547 | } else { |
| 547 | 548 | #endif |
| 548 | 549 | |
| 549 | − err = vaapi_decode_make_config(avctx); | |
| 550 | − if (err) | |
| 550 | + err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); | |
| 551 | + if (err < 0) | |
| 551 | 552 | goto fail; |
| 552 | 553 | |
| 553 | − if (!avctx->hw_frames_ctx) { | |
| 554 | − avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); | |
| 555 | − if (!avctx->hw_frames_ctx) { | |
| 556 | − err = AVERROR(ENOMEM); | |
| 557 | − goto fail; | |
| 558 | − } | |
| 559 | − ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 560 | − | |
| 561 | − ctx->frames->format = AV_PIX_FMT_VAAPI; | |
| 562 | − ctx->frames->width = avctx->coded_width; | |
| 563 | − ctx->frames->height = avctx->coded_height; | |
| 564 | − | |
| 565 | − ctx->frames->sw_format = ctx->surface_format; | |
| 566 | − ctx->frames->initial_pool_size = ctx->surface_count; | |
| 554 | + ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 555 | + ctx->hwfc = ctx->frames->hwctx; | |
| 556 | + ctx->device = ctx->frames->device_ctx; | |
| 557 | + ctx->hwctx = ctx->device->hwctx; | |
| 567 | 558 | |
| 568 | − err = av_hwframe_ctx_init(avctx->hw_frames_ctx); | |
| 569 | − if (err < 0) { | |
| 570 | − av_log(avctx, AV_LOG_ERROR, "Failed to initialise internal " | |
| 571 | − "frames context: %d.\n", err); | |
| 572 | − goto fail; | |
| 573 | − } | |
| 574 | − | |
| 575 | − ctx->hwfc = ctx->frames->hwctx; | |
| 576 | − } | |
| 559 | + err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, | |
| 560 | + &ctx->va_config, avctx->hw_frames_ctx); | |
| 561 | + if (err) | |
| 562 | + goto fail; | |
| 577 | 563 | |
| 578 | 564 | vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, |
| 579 | 565 | avctx->coded_width, avctx->coded_height, |
| @@ -53,8 +53,6 @@ typedef struct VAAPIDecodePicture { · 52 unmodified lines | ||
| 53 | 53 | } VAAPIDecodePicture; |
| 54 | 54 | |
| 55 | 55 | typedef struct VAAPIDecodeContext { |
| 56 | − VAProfile va_profile; | |
| 57 | − VAEntrypoint va_entrypoint; | |
| 58 | 56 | VAConfigID va_config; |
| 59 | 57 | VAContextID va_context; |
| 60 | 58 | |
| @@ -98,4 +96,7 @@ int ff_vaapi_decode_cancel(AVCodecContext *avctx, · 37 unmodified lines | ||
| 98 | 96 | int ff_vaapi_decode_init(AVCodecContext *avctx); |
| 99 | 97 | int ff_vaapi_decode_uninit(AVCodecContext *avctx); |
| 100 | 98 | |
| 99 | +int ff_vaapi_common_frame_params(AVCodecContext *avctx, | |
| 100 | + AVBufferRef *hw_frames_ctx); | |
| 101 | + | |
| 101 | 102 | #endif /* AVCODEC_VAAPI_DECODE_H */ |
| @@ -399,6 +399,7 @@ AVHWAccel ff_h264_vaapi_hwaccel = { · 398 unmodified lines | ||
| 399 | 399 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 400 | 400 | .init = &ff_vaapi_decode_init, |
| 401 | 401 | .uninit = &ff_vaapi_decode_uninit, |
| 402 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 402 | 403 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 403 | 404 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 404 | 405 | }; |
| @@ -434,6 +434,7 @@ AVHWAccel ff_hevc_vaapi_hwaccel = { · 433 unmodified lines | ||
| 434 | 434 | .frame_priv_data_size = sizeof(VAAPIDecodePictureHEVC), |
| 435 | 435 | .init = ff_vaapi_decode_init, |
| 436 | 436 | .uninit = ff_vaapi_decode_uninit, |
| 437 | + .frame_params = ff_vaapi_common_frame_params, | |
| 437 | 438 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 438 | 439 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 439 | 440 | }; |
| @@ -183,6 +183,7 @@ AVHWAccel ff_mpeg2_vaapi_hwaccel = { · 182 unmodified lines | ||
| 183 | 183 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 184 | 184 | .init = &ff_vaapi_decode_init, |
| 185 | 185 | .uninit = &ff_vaapi_decode_uninit, |
| 186 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 186 | 187 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 187 | 188 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 188 | 189 | }; |
| @@ -189,6 +189,7 @@ AVHWAccel ff_mpeg4_vaapi_hwaccel = { · 188 unmodified lines | ||
| 189 | 189 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 190 | 190 | .init = &ff_vaapi_decode_init, |
| 191 | 191 | .uninit = &ff_vaapi_decode_uninit, |
| 192 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 192 | 193 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 193 | 194 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 194 | 195 | }; |
| @@ -206,6 +207,7 @@ AVHWAccel ff_h263_vaapi_hwaccel = { · 11 unmodified lines | ||
| 206 | 207 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 207 | 208 | .init = &ff_vaapi_decode_init, |
| 208 | 209 | .uninit = &ff_vaapi_decode_uninit, |
| 210 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 209 | 211 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 210 | 212 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 211 | 213 | }; |
| @@ -399,6 +399,7 @@ AVHWAccel ff_wmv3_vaapi_hwaccel = { · 398 unmodified lines | ||
| 399 | 399 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 400 | 400 | .init = &ff_vaapi_decode_init, |
| 401 | 401 | .uninit = &ff_vaapi_decode_uninit, |
| 402 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 402 | 403 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 403 | 404 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 404 | 405 | }; |
| @@ -415,6 +416,7 @@ AVHWAccel ff_vc1_vaapi_hwaccel = { · 10 unmodified lines | ||
| 415 | 416 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 416 | 417 | .init = &ff_vaapi_decode_init, |
| 417 | 418 | .uninit = &ff_vaapi_decode_uninit, |
| 419 | + .frame_params = &ff_vaapi_common_frame_params, | |
| 418 | 420 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 419 | 421 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 420 | 422 | }; |
| @@ -179,6 +179,7 @@ AVHWAccel ff_vp9_vaapi_hwaccel = { · 178 unmodified lines | ||
| 179 | 179 | .frame_priv_data_size = sizeof(VAAPIDecodePicture), |
| 180 | 180 | .init = ff_vaapi_decode_init, |
| 181 | 181 | .uninit = ff_vaapi_decode_uninit, |
| 182 | + .frame_params = ff_vaapi_common_frame_params, | |
| 182 | 183 | .priv_data_size = sizeof(VAAPIDecodeContext), |
| 183 | 184 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 184 | 185 | }; |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | #include <limits.h> |
| 25 | 25 | |
| 26 | 26 | #include "avcodec.h" |
| 27 | +#include "decode.h" | |
| 27 | 28 | #include "internal.h" |
| 28 | 29 | #include "h264dec.h" |
| 29 | 30 | #include "vc1.h" |
| @@ -110,6 +111,25 @@ int av_vdpau_get_surface_parameters(AVCodecContext *avctx, · 80 unmodified lines | ||
| 110 | 111 | return 0; |
| 111 | 112 | } |
| 112 | 113 | |
| 114 | +int ff_vdpau_common_frame_params(AVCodecContext *avctx, | |
| 115 | + AVBufferRef *hw_frames_ctx) | |
| 116 | +{ | |
| 117 | + AVHWFramesContext *hw_frames = (AVHWFramesContext*)hw_frames_ctx->data; | |
| 118 | + VdpChromaType type; | |
| 119 | + uint32_t width; | |
| 120 | + uint32_t height; | |
| 121 | + | |
| 122 | + if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height)) | |
| 123 | + return AVERROR(EINVAL); | |
| 124 | + | |
| 125 | + hw_frames->format = AV_PIX_FMT_VDPAU; | |
| 126 | + hw_frames->sw_format = avctx->sw_pix_fmt; | |
| 127 | + hw_frames->width = width; | |
| 128 | + hw_frames->height = height; | |
| 129 | + | |
| 130 | + return 0; | |
| 131 | +} | |
| 132 | + | |
| 113 | 133 | int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, |
| 114 | 134 | int level) |
| 115 | 135 | { |
| @@ -127,6 +147,7 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, · 11 unmodified lines | ||
| 127 | 147 | VdpChromaType type; |
| 128 | 148 | uint32_t width; |
| 129 | 149 | uint32_t height; |
| 150 | + int ret; | |
| 130 | 151 | |
| 131 | 152 | vdctx->width = UINT32_MAX; |
| 132 | 153 | vdctx->height = UINT32_MAX; |
| @@ -154,41 +175,14 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile, · 21 unmodified lines | ||
| 154 | 175 | type != VDP_CHROMA_TYPE_420) |
| 155 | 176 | return AVERROR(ENOSYS); |
| 156 | 177 | } else { |
| 157 | − AVHWFramesContext *frames_ctx = NULL; | |
| 178 | + AVHWFramesContext *frames_ctx; | |
| 158 | 179 | AVVDPAUDeviceContext *dev_ctx; |
| 159 | 180 | |
| 160 | − // We assume the hw_frames_ctx always survives until ff_vdpau_common_uninit | |
| 161 | − // is called. This holds true as the user is not allowed to touch | |
| 162 | − // hw_device_ctx, or hw_frames_ctx after get_format (and ff_get_format | |
| 163 | − // itself also uninits before unreffing hw_frames_ctx). | |
| 164 | − if (avctx->hw_frames_ctx) { | |
| 165 | − frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 166 | − } else if (avctx->hw_device_ctx) { | |
| 167 | − int ret; | |
| 168 | − | |
| 169 | − avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx); | |
| 170 | − if (!avctx->hw_frames_ctx) | |
| 171 | − return AVERROR(ENOMEM); | |
| 172 | − | |
| 173 | − frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 174 | − frames_ctx->format = AV_PIX_FMT_VDPAU; | |
| 175 | − frames_ctx->sw_format = avctx->sw_pix_fmt; | |
| 176 | − frames_ctx->width = avctx->coded_width; | |
| 177 | − frames_ctx->height = avctx->coded_height; | |
| 178 | − | |
| 179 | − ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); | |
| 180 | − if (ret < 0) { | |
| 181 | − av_buffer_unref(&avctx->hw_frames_ctx); | |
| 182 | − return ret; | |
| 183 | − } | |
| 184 | − } | |
| 185 | − | |
| 186 | − if (!frames_ctx) { | |
| 187 | − av_log(avctx, AV_LOG_ERROR, "A hardware frames context is " | |
| 188 | − "required for VDPAU decoding.\n"); | |
| 189 | − return AVERROR(EINVAL); | |
| 190 | − } | |
| 181 | + ret = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VDPAU); | |
| 182 | + if (ret < 0) | |
| 183 | + return ret; | |
| 191 | 184 | |
| 185 | + frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | |
| 192 | 186 | dev_ctx = frames_ctx->device_ctx->hwctx; |
| 193 | 187 | |
| 194 | 188 | vdctx->device = dev_ctx->device; |
| @@ -273,6 +273,7 @@ AVHWAccel ff_h264_vdpau_hwaccel = { · 272 unmodified lines | ||
| 273 | 273 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 274 | 274 | .init = vdpau_h264_init, |
| 275 | 275 | .uninit = ff_vdpau_common_uninit, |
| 276 | + .frame_params = ff_vdpau_common_frame_params, | |
| 276 | 277 | .priv_data_size = sizeof(VDPAUContext), |
| 277 | 278 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 278 | 279 | }; |
| @@ -424,6 +424,7 @@ AVHWAccel ff_hevc_vdpau_hwaccel = { · 423 unmodified lines | ||
| 424 | 424 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 425 | 425 | .init = vdpau_hevc_init, |
| 426 | 426 | .uninit = ff_vdpau_common_uninit, |
| 427 | + .frame_params = ff_vdpau_common_frame_params, | |
| 427 | 428 | .priv_data_size = sizeof(VDPAUContext), |
| 428 | 429 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 429 | 430 | }; |
| @@ -119,5 +119,7 @@ int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame, · 118 unmodified lines | ||
| 119 | 119 | int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx); |
| 120 | 120 | int ff_vdpau_add_buffer(struct vdpau_picture_context *pic, const uint8_t *buf, |
| 121 | 121 | uint32_t buf_size); |
| 122 | +int ff_vdpau_common_frame_params(AVCodecContext *avctx, | |
| 123 | + AVBufferRef *hw_frames_ctx); | |
| 122 | 124 | |
| 123 | 125 | #endif /* AVCODEC_VDPAU_INTERNAL_H */ |
| @@ -149,6 +149,7 @@ AVHWAccel ff_mpeg2_vdpau_hwaccel = { · 148 unmodified lines | ||
| 149 | 149 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 150 | 150 | .init = vdpau_mpeg2_init, |
| 151 | 151 | .uninit = ff_vdpau_common_uninit, |
| 152 | + .frame_params = ff_vdpau_common_frame_params, | |
| 152 | 153 | .priv_data_size = sizeof(VDPAUContext), |
| 153 | 154 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 154 | 155 | }; |
| @@ -121,6 +121,7 @@ AVHWAccel ff_mpeg4_vdpau_hwaccel = { · 120 unmodified lines | ||
| 121 | 121 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 122 | 122 | .init = vdpau_mpeg4_init, |
| 123 | 123 | .uninit = ff_vdpau_common_uninit, |
| 124 | + .frame_params = ff_vdpau_common_frame_params, | |
| 124 | 125 | .priv_data_size = sizeof(VDPAUContext), |
| 125 | 126 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 126 | 127 | }; |
| @@ -147,6 +147,7 @@ AVHWAccel ff_wmv3_vdpau_hwaccel = { · 146 unmodified lines | ||
| 147 | 147 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 148 | 148 | .init = vdpau_vc1_init, |
| 149 | 149 | .uninit = ff_vdpau_common_uninit, |
| 150 | + .frame_params = ff_vdpau_common_frame_params, | |
| 150 | 151 | .priv_data_size = sizeof(VDPAUContext), |
| 151 | 152 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 152 | 153 | }; |
| @@ -163,6 +164,7 @@ AVHWAccel ff_vc1_vdpau_hwaccel = { · 10 unmodified lines | ||
| 163 | 164 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
| 164 | 165 | .init = vdpau_vc1_init, |
| 165 | 166 | .uninit = ff_vdpau_common_uninit, |
| 167 | + .frame_params = ff_vdpau_common_frame_params, | |
| 166 | 168 | .priv_data_size = sizeof(VDPAUContext), |
| 167 | 169 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
| 168 | 170 | }; |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "libavutil/version.h" |
| 29 | 29 | |
| 30 | 30 | #define LIBAVCODEC_VERSION_MAJOR 58 |
| 31 | −#define LIBAVCODEC_VERSION_MINOR 2 | |
| 31 | +#define LIBAVCODEC_VERSION_MINOR 3 | |
| 32 | 32 | #define LIBAVCODEC_VERSION_MICRO 100 |
| 33 | 33 | |
| 34 | 34 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |