#include "avcodec.h"
#include "internal.h"
+#include "qsv.h"
#include "qsv_internal.h"
#include "qsvdec.h"
}
}
-static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession session)
+int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q)
{
- if (!session) {
- if (!q->internal_qs.session) {
- int ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, NULL);
- if (ret < 0)
- return ret;
- }
-
- q->session = q->internal_qs.session;
- } else {
- q->session = session;
- }
+ mfxVideoParam param = { { 0 } };
+ int ret;
- /* make sure the decoder is uninitialized */
- MFXVideoDECODE_Close(q->session);
+ q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
+ (sizeof(mfxSyncPoint) + sizeof(QSVFrame*)));
+ if (!q->async_fifo)
+ return AVERROR(ENOMEM);
- return 0;
-}
+ q->iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
-int ff_qsv_decode_init(AVCodecContext *avctx, QSVContext *q, mfxSession session)
-{
- mfxVideoParam param = { { 0 } };
- int ret;
+ if (avctx->hwaccel_context) {
+ AVQSVContext *qsv = avctx->hwaccel_context;
- ret = qsv_init_session(avctx, q, session);
- if (ret < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
- return ret;
+ q->session = qsv->session;
+ q->iopattern = qsv->iopattern;
+ q->ext_buffers = qsv->ext_buffers;
+ q->nb_ext_buffers = qsv->nb_ext_buffers;
}
+ if (!q->session) {
+ ret = ff_qsv_init_internal_session(avctx, &q->internal_qs, NULL);
+ if (ret < 0)
+ return ret;
+ q->session = q->internal_qs.session;
+ }
ret = ff_qsv_codec_id_to_mfx(avctx->codec_id);
if (ret < 0)
{
QSVFrame *cur = q->work_frames;
while (cur) {
- if (cur->surface && !cur->surface->Data.Locked) {
+ if (cur->surface && !cur->surface->Data.Locked && !cur->queued) {
cur->surface = NULL;
av_frame_unref(cur->frame);
}
return 0;
}
-static AVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
+static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf)
{
QSVFrame *cur = q->work_frames;
while (cur) {
if (surf == cur->surface)
- return cur->frame;
+ return cur;
cur = cur->next;
}
return NULL;
AVFrame *frame, int *got_frame,
AVPacket *avpkt)
{
+ QSVFrame *out_frame;
mfxFrameSurface1 *insurf;
mfxFrameSurface1 *outsurf;
mfxSyncPoint sync;
}
if (sync) {
- AVFrame *src_frame;
-
- MFXVideoCORE_SyncOperation(q->session, sync, 60000);
+ QSVFrame *out_frame = find_frame(q, outsurf);
- src_frame = find_frame(q, outsurf);
- if (!src_frame) {
+ if (!out_frame) {
av_log(avctx, AV_LOG_ERROR,
"The returned surface does not correspond to any frame\n");
return AVERROR_BUG;
}
+ out_frame->queued = 1;
+ av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
+ av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL);
+ }
+
+ if (!av_fifo_space(q->async_fifo) ||
+ (!avpkt->size && av_fifo_size(q->async_fifo))) {
+ AVFrame *src_frame;
+
+ av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL);
+ av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL);
+ out_frame->queued = 0;
+
+ MFXVideoCORE_SyncOperation(q->session, sync, 60000);
+
+ src_frame = out_frame->frame;
+
ret = av_frame_ref(frame, src_frame);
if (ret < 0)
return ret;
+ outsurf = out_frame->surface;
+
frame->pkt_pts = frame->pts = outsurf->Data.TimeStamp;
frame->repeat_pict =
av_freep(&cur);
cur = q->work_frames;
}
+
+ av_fifo_free(q->async_fifo);
+ q->async_fifo = NULL;
+
+ MFXVideoDECODE_Close(q->session);
+ q->session = NULL;
+
ff_qsv_close_internal_session(&q->internal_qs);
return 0;