Message ID | 81c67c62-d7e7-badd-1c52-02317b858ad7@jkqxz.net |
---|---|
State | New |
Headers | show |
On Tue, 17 Jan 2017 22:30:44 +0000 Mark Thompson <sw@jkqxz.net> wrote: > --- > libavcodec/qsvdec.c | 25 +++++++++++++++++++++++-- > libavcodec/qsvdec.h | 2 ++ > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c > index 258042d..5a42fd7 100644 > --- a/libavcodec/qsvdec.c > +++ b/libavcodec/qsvdec.c > @@ -42,7 +42,7 @@ > #include "qsvdec.h" > > static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, > - AVBufferRef *hw_frames_ref) > + AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) > { > int ret; > > @@ -68,6 +68,25 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses > } > > q->session = q->internal_session; > + } else if (hw_device_ref) { > + if (q->internal_session) { > + MFXClose(q->internal_session); > + q->internal_session = NULL; > + } > + av_buffer_unref(&q->hw_device_ctx); > + > + q->hw_device_ctx = av_buffer_ref(hw_device_ref); > + if (!q->hw_device_ctx) > + return AVERROR(ENOMEM); > + > + ret = ff_qsv_init_session_device(avctx, &q->internal_session, > + q->hw_device_ctx, q->load_plugins); > + if (ret < 0) { > + av_buffer_unref(&q->hw_device_ctx); > + return ret; > + } > + > + q->session = q->internal_session; > } else { > if (!q->internal_session) { > ret = ff_qsv_init_internal_session(avctx, &q->internal_session, > @@ -133,7 +152,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) > iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; > q->iopattern = iopattern; > > - ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx); > + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); > if (ret < 0) { > av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); > return ret; > @@ -431,6 +450,8 @@ int ff_qsv_decode_close(QSVContext *q) > av_freep(&q->frames_ctx.mids); > q->frames_ctx.nb_mids = 0; > > + av_buffer_unref(&q->hw_device_ctx); > + > return 0; > } > > diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h > index 41fb716..5fb02aa 100644 > --- a/libavcodec/qsvdec.h > +++ b/libavcodec/qsvdec.h > @@ -43,6 +43,8 @@ typedef struct QSVContext { > // one > mfxSession internal_session; > > + AVBufferRef *hw_device_ctx; > + > QSVFramesContext frames_ctx; > > /** Seems fine. Looks like with this decoder, attempting to change the device in get_format (by using a frames context with another device) is undefined behavior.
On 18/01/17 07:57, wm4 wrote: > On Tue, 17 Jan 2017 22:30:44 +0000 > Mark Thompson <sw@jkqxz.net> wrote: > >> --- >> libavcodec/qsvdec.c | 25 +++++++++++++++++++++++-- >> libavcodec/qsvdec.h | 2 ++ >> 2 files changed, 25 insertions(+), 2 deletions(-) >> >> diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c >> index 258042d..5a42fd7 100644 >> --- a/libavcodec/qsvdec.c >> +++ b/libavcodec/qsvdec.c >> @@ -42,7 +42,7 @@ >> #include "qsvdec.h" >> >> static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, >> - AVBufferRef *hw_frames_ref) >> + AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) >> { >> int ret; >> >> @@ -68,6 +68,25 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses >> } >> >> q->session = q->internal_session; >> + } else if (hw_device_ref) { >> + if (q->internal_session) { >> + MFXClose(q->internal_session); >> + q->internal_session = NULL; >> + } >> + av_buffer_unref(&q->hw_device_ctx); >> + >> + q->hw_device_ctx = av_buffer_ref(hw_device_ref); >> + if (!q->hw_device_ctx) >> + return AVERROR(ENOMEM); >> + >> + ret = ff_qsv_init_session_device(avctx, &q->internal_session, >> + q->hw_device_ctx, q->load_plugins); >> + if (ret < 0) { >> + av_buffer_unref(&q->hw_device_ctx); >> + return ret; >> + } >> + >> + q->session = q->internal_session; >> } else { >> if (!q->internal_session) { >> ret = ff_qsv_init_internal_session(avctx, &q->internal_session, >> @@ -133,7 +152,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) >> iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; >> q->iopattern = iopattern; >> >> - ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx); >> + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); >> if (ret < 0) { >> av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); >> return ret; >> @@ -431,6 +450,8 @@ int ff_qsv_decode_close(QSVContext *q) >> av_freep(&q->frames_ctx.mids); >> q->frames_ctx.nb_mids = 0; >> >> + av_buffer_unref(&q->hw_device_ctx); >> + >> return 0; >> } >> >> diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h >> index 41fb716..5fb02aa 100644 >> --- a/libavcodec/qsvdec.h >> +++ b/libavcodec/qsvdec.h >> @@ -43,6 +43,8 @@ typedef struct QSVContext { >> // one >> mfxSession internal_session; >> >> + AVBufferRef *hw_device_ctx; >> + >> QSVFramesContext frames_ctx; >> >> /** > > Seems fine. > > Looks like with this decoder, attempting to change the device in > get_format (by using a frames context with another device) is undefined > behavior. Yes. I'm deliberately supporting only the first operation mode of AVCodecContext.hw_device_ctx (see the device thread) because it's simpler and there can only be one device with Intel.
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 258042d..5a42fd7 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -42,7 +42,7 @@ #include "qsvdec.h" static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session, - AVBufferRef *hw_frames_ref) + AVBufferRef *hw_frames_ref, AVBufferRef *hw_device_ref) { int ret; @@ -68,6 +68,25 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses } q->session = q->internal_session; + } else if (hw_device_ref) { + if (q->internal_session) { + MFXClose(q->internal_session); + q->internal_session = NULL; + } + av_buffer_unref(&q->hw_device_ctx); + + q->hw_device_ctx = av_buffer_ref(hw_device_ref); + if (!q->hw_device_ctx) + return AVERROR(ENOMEM); + + ret = ff_qsv_init_session_device(avctx, &q->internal_session, + q->hw_device_ctx, q->load_plugins); + if (ret < 0) { + av_buffer_unref(&q->hw_device_ctx); + return ret; + } + + q->session = q->internal_session; } else { if (!q->internal_session) { ret = ff_qsv_init_internal_session(avctx, &q->internal_session, @@ -133,7 +152,7 @@ static int qsv_decode_init(AVCodecContext *avctx, QSVContext *q) iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; q->iopattern = iopattern; - ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx); + ret = qsv_init_session(avctx, q, session, avctx->hw_frames_ctx, avctx->hw_device_ctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n"); return ret; @@ -431,6 +450,8 @@ int ff_qsv_decode_close(QSVContext *q) av_freep(&q->frames_ctx.mids); q->frames_ctx.nb_mids = 0; + av_buffer_unref(&q->hw_device_ctx); + return 0; } diff --git a/libavcodec/qsvdec.h b/libavcodec/qsvdec.h index 41fb716..5fb02aa 100644 --- a/libavcodec/qsvdec.h +++ b/libavcodec/qsvdec.h @@ -43,6 +43,8 @@ typedef struct QSVContext { // one mfxSession internal_session; + AVBufferRef *hw_device_ctx; + QSVFramesContext frames_ctx; /**