diff --git a/src/QtAV/private/VideoDecoderFFmpegHW_p.h b/src/QtAV/private/VideoDecoderFFmpegHW_p.h index e46bfd7c..0fd82454 100644 --- a/src/QtAV/private/VideoDecoderFFmpegHW_p.h +++ b/src/QtAV/private/VideoDecoderFFmpegHW_p.h @@ -33,10 +33,27 @@ public: : VideoDecoderFFmpegPrivate() , va_pixfmt(QTAV_PIX_FMT_C(NONE)) { + get_format = 0; + get_buffer = 0; + release_buffer = 0; + reget_buffer = 0; + //get_buffer2 = 0; // subclass setup va_pixfmt here } - virtual ~VideoDecoderFFmpegHWPrivate() {} + virtual ~VideoDecoderFFmpegHWPrivate() { + restore(); + } + void restore() { + codec_ctx->pix_fmt = pixfmt; + codec_ctx->opaque = 0; + codec_ctx->get_format = get_format; + codec_ctx->get_buffer = get_buffer; + codec_ctx->release_buffer = release_buffer; + codec_ctx->reget_buffer = reget_buffer; + //codec_ctx->get_buffer2 = get_buffer2; + } + virtual bool setup(void **hwctx, AVPixelFormat *chroma, int w, int h) = 0; AVPixelFormat getFormat(struct AVCodecContext *p_context, const AVPixelFormat *pi_fmt); @@ -44,6 +61,14 @@ public: virtual void releaseBuffer(void *opaque, uint8_t *data) = 0; AVPixelFormat va_pixfmt; + AVPixelFormat pixfmt; //store old one + //store old values because it does not own AVCodecContext + AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt); + int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic); + void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic); + int (*reget_buffer)(struct AVCodecContext *c, AVFrame *pic); + //int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags); + QString description; }; diff --git a/src/VideoDecoderDXVA.cpp b/src/VideoDecoderDXVA.cpp index f1ade7c2..ce1d30a0 100644 --- a/src/VideoDecoderDXVA.cpp +++ b/src/VideoDecoderDXVA.cpp @@ -366,12 +366,13 @@ VideoDecoderDXVA::VideoDecoderDXVA() VideoDecoderDXVA::~VideoDecoderDXVA() { - setCodecContext(0); } VideoFrame VideoDecoderDXVA::frame() { DPTR_D(VideoDecoderDXVA); + if (!d.frame->opaque || !d.frame->data[0]) + return VideoFrame(); if (d.width <= 0 || d.height <= 0 || !d.codec_ctx) return VideoFrame(); Q_ASSERT(d.output == MAKEFOURCC('Y','V','1','2')); diff --git a/src/VideoDecoderFFmpegHW.cpp b/src/VideoDecoderFFmpegHW.cpp index 535314da..b258e5b4 100644 --- a/src/VideoDecoderFFmpegHW.cpp +++ b/src/VideoDecoderFFmpegHW.cpp @@ -121,7 +121,6 @@ AVPixelFormat VideoDecoderFFmpegHWPrivate::getFormat(struct AVCodecContext *p_co close(); //vlc_va_Delete(p_va); - end: qWarning("acceleration not available" ); /* Fallback to default behaviour */ @@ -152,6 +151,14 @@ bool VideoDecoderFFmpegHW::prepare() } #endif d.codec_ctx->opaque = &d; //is it ok? + + d.pixfmt = d.codec_ctx->pix_fmt; + //d.get_buffer2 = d.codec_ctx->get_buffer2; + d.get_buffer = d.codec_ctx->get_buffer; + d.reget_buffer = d.codec_ctx->reget_buffer; + d.release_buffer = d.codec_ctx->release_buffer; + d.get_format = d.codec_ctx->get_format; + d.codec_ctx->get_format = ffmpeg_get_va_format; //#if LIBAVCODEC_VERSION_MAJOR >= 55 //d.codec_ctx->get_buffer2 = ffmpeg_get_va_frame; @@ -169,7 +176,7 @@ bool VideoDecoderFFmpegHW::decode(const QByteArray &encoded) { if (!isAvailable()) return false; - DPTR_D(VideoDecoder); + DPTR_D(VideoDecoderFFmpegHW); AVPacket packet; av_new_packet(&packet, encoded.size()); memcpy(packet.data, encoded.data(), encoded.size()); @@ -191,8 +198,10 @@ bool VideoDecoderFFmpegHW::decode(const QByteArray &encoded) // TODO: wait key frame? if (!d.codec_ctx->width || !d.codec_ctx->height) return false; + // avcodec_align_dimensions2 d.width = d.codec_ctx->width; d.height = d.codec_ctx->height; + //avcodec_align_dimensions2(d.codec_ctx, &d.width_align, &d.height_align, aligns); return true; } diff --git a/src/VideoDecoderVAAPI.cpp b/src/VideoDecoderVAAPI.cpp index 720cbc19..b59e3dc9 100644 --- a/src/VideoDecoderVAAPI.cpp +++ b/src/VideoDecoderVAAPI.cpp @@ -154,12 +154,13 @@ VideoDecoderVAAPI::VideoDecoderVAAPI() VideoDecoderVAAPI::~VideoDecoderVAAPI() { - setCodecContext(0); } VideoFrame VideoDecoderVAAPI::frame() { DPTR_D(VideoDecoderVAAPI); + if (!d.frame->opaque || !d.frame->data[0]) + return VideoFrame(); VASurfaceID surface_id = (VASurfaceID)(uintptr_t)d.frame->data[3]; #if VA_CHECK_VERSION(0,31,0) if (vaSyncSurface(d.display, surface_id))