aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRĂ©mi Denis-Courmont <remi@remlab.net>2014-10-04 16:55:06 +0300
committerAnton Khirnov <anton@khirnov.net>2014-10-06 06:18:56 +0000
commit502cde409ca5ee97ef70c2cdede88b9101746ff6 (patch)
tree5c8318d141d7d8d73b462f88369704f88bca3817
parent89ac99ba5f2dc9f69ad3bc294753930eb0b3e4a4 (diff)
downloadffmpeg-502cde409ca5ee97ef70c2cdede88b9101746ff6.tar.gz
vdpau: force reinitialization when output resolution changes
This is necessary to recreate the decoder with the correct parameters, as not all codecs invoke get_format() in this case. Signed-off-by: Anton Khirnov <anton@khirnov.net>
-rw-r--r--libavcodec/vdpau.c29
-rw-r--r--libavcodec/vdpau_internal.h3
2 files changed, 32 insertions, 0 deletions
diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
index ed8fd7f0e7..c3a8a850ae 100644
--- a/libavcodec/vdpau.c
+++ b/libavcodec/vdpau.c
@@ -76,6 +76,9 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
uint32_t width = (avctx->coded_width + 1) & ~1;
uint32_t height = (avctx->coded_height + 3) & ~3;
+ vdctx->width = UINT32_MAX;
+ vdctx->height = UINT32_MAX;
+
if (hwctx->context.decoder != VDP_INVALID_HANDLE) {
vdctx->decoder = hwctx->context.decoder;
vdctx->render = hwctx->context.render;
@@ -102,6 +105,11 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
status = create(vdctx->device, profile, width, height, avctx->refs,
&vdctx->decoder);
+ if (status == VDP_STATUS_OK) {
+ vdctx->width = avctx->coded_width;
+ vdctx->height = avctx->coded_height;
+ }
+
return vdpau_error(status);
}
@@ -114,6 +122,8 @@ int ff_vdpau_common_uninit(AVCodecContext *avctx)
if (vdctx->device == VDP_INVALID_HANDLE)
return 0; /* Decoder created and destroyed by user */
+ if (vdctx->width == UINT32_MAX && vdctx->height == UINT32_MAX)
+ return 0;
status = vdctx->get_proc_address(vdctx->device,
VDP_FUNC_ID_DECODER_DESTROY, &func);
@@ -126,6 +136,20 @@ int ff_vdpau_common_uninit(AVCodecContext *avctx)
return vdpau_error(status);
}
+static int ff_vdpau_common_reinit(AVCodecContext *avctx)
+{
+ VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
+
+ if (vdctx->device == VDP_INVALID_HANDLE)
+ return 0; /* Decoder created by user */
+ if (avctx->coded_width == vdctx->width &&
+ avctx->coded_height == vdctx->height)
+ return 0;
+
+ avctx->hwaccel->uninit(avctx);
+ return avctx->hwaccel->init(avctx);
+}
+
int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx,
av_unused const uint8_t *buffer,
av_unused uint32_t size)
@@ -142,6 +166,11 @@ int ff_vdpau_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
VDPAUContext *vdctx = avctx->internal->hwaccel_priv_data;
VdpVideoSurface surf = ff_vdpau_get_surface_id(frame);
VdpStatus status;
+ int val;
+
+ val = ff_vdpau_common_reinit(avctx);
+ if (val < 0)
+ return val;
status = vdctx->render(vdctx->decoder, surf, (void *)&pic_ctx->info,
pic_ctx->bitstream_buffers_used,
diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h
index 94fa9aae89..3e74d46963 100644
--- a/libavcodec/vdpau_internal.h
+++ b/libavcodec/vdpau_internal.h
@@ -74,6 +74,9 @@ typedef struct VDPAUContext {
* VDPAU decoder render callback
*/
VdpDecoderRender *render;
+
+ uint32_t width;
+ uint32_t height;
} VDPAUContext;
struct vdpau_picture_context {