Exemple #1
0
static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
{
    uint8_t sps_buf[128];
    uint8_t pps_buf[128];

    mfxExtCodingOptionSPSPPS extradata = {
        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
        .Header.BufferSz = sizeof(extradata),
        .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
        .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
    };

    mfxExtBuffer *ext_buffers[] = {
        (mfxExtBuffer*)&extradata,
    };

    int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
    int ret;

    q->param.ExtParam    = ext_buffers;
    q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);

    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
    if (ret < 0)
        return ff_qsv_error(ret);

    q->packet_size = q->param.mfx.BufferSizeInKB * 1000;

    if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) {
        av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
        return AVERROR_UNKNOWN;
    }

    avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize +
                                 AV_INPUT_BUFFER_PADDING_SIZE);
    if (!avctx->extradata)
        return AVERROR(ENOMEM);

    memcpy(avctx->extradata,                        sps_buf, extradata.SPSBufSize);
    if (need_pps)
        memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
    avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
    memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);

    return 0;
}

int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
{
    int ret;

    q->param.IOPattern  = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
    q->param.AsyncDepth = q->async_depth;

    q->async_fifo = av_fifo_alloc((1 + q->async_depth) *
                                  (sizeof(AVPacket) + sizeof(mfxSyncPoint) + sizeof(mfxBitstream*)));
    if (!q->async_fifo)
        return AVERROR(ENOMEM);

    if (avctx->hwaccel_context) {
        AVQSVContext *qsv = avctx->hwaccel_context;

        q->session         = qsv->session;
        q->param.IOPattern = qsv->iopattern;
    }

    if (!q->session) {
        ret = ff_qsv_init_internal_session(avctx, &q->internal_qs,
                                           q->load_plugins);
        if (ret < 0)
            return ret;

        q->session = q->internal_qs.session;
    }

    ret = init_video_param(avctx, q);
    if (ret < 0)
        return ret;

    ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
        return ff_qsv_error(ret);
    }

    ret = MFXVideoENCODE_Init(q->session, &q->param);
    if (MFX_WRN_PARTIAL_ACCELERATION==ret) {
        av_log(avctx, AV_LOG_WARNING, "Encoder will work with partial HW acceleration\n");
    } else if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
        return ff_qsv_error(ret);
    }

    ret = qsv_retrieve_enc_params(avctx, q);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
        return ret;
    }

    q->avctx = avctx;

    return 0;
}
Exemple #2
0
static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
{
    uint8_t sps_buf[128];
    uint8_t pps_buf[128];

    mfxExtCodingOptionSPSPPS extradata = {
        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
        .Header.BufferSz = sizeof(extradata),
        .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
        .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
    };

    mfxExtBuffer *ext_buffers[] = {
        (mfxExtBuffer*)&extradata,
    };

    int ret;

    q->param.ExtParam    = ext_buffers;
    q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);

    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
    if (ret < 0)
        return ff_qsv_error(ret);

    q->packet_size = q->param.mfx.BufferSizeInKB * 1000;

    if (!extradata.SPSBufSize || !extradata.PPSBufSize) {
        av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
        return AVERROR_UNKNOWN;
    }

    avctx->extradata = av_malloc(extradata.SPSBufSize + extradata.PPSBufSize +
                                 FF_INPUT_BUFFER_PADDING_SIZE);
    if (!avctx->extradata)
        return AVERROR(ENOMEM);

    memcpy(avctx->extradata,                        sps_buf, extradata.SPSBufSize);
    memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
    avctx->extradata_size = extradata.SPSBufSize + extradata.PPSBufSize;
    memset(avctx->extradata + avctx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);

    return 0;
}

int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q)
{
    int ret;

    q->param.IOPattern  = MFX_IOPATTERN_IN_SYSTEM_MEMORY;
    q->param.AsyncDepth = q->async_depth;

    if (avctx->hwaccel_context) {
        AVQSVContext *qsv = avctx->hwaccel_context;

        q->session         = qsv->session;
        q->param.IOPattern = qsv->iopattern;
    }

    if (!q->session) {
        ret = ff_qsv_init_internal_session(avctx, &q->internal_session);
        if (ret < 0)
            return ret;

        q->session = q->internal_session;
    }

    ret = init_video_param(avctx, q);
    if (ret < 0)
        return ret;

    ret = MFXVideoENCODE_QueryIOSurf(q->session, &q->param, &q->req);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error querying the encoding parameters\n");
        return ff_qsv_error(ret);
    }

    ret = MFXVideoENCODE_Init(q->session, &q->param);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error initializing the encoder\n");
        return ff_qsv_error(ret);
    }

    ret = qsv_retrieve_enc_params(avctx, q);
    if (ret < 0) {
        av_log(avctx, AV_LOG_ERROR, "Error retrieving encoding parameters.\n");
        return ret;
    }

    avctx->coded_frame = av_frame_alloc();
    if (!avctx->coded_frame)
        return AVERROR(ENOMEM);

    q->avctx = avctx;

    return 0;
}
Exemple #3
0
static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q)
{
    uint8_t sps_buf[128];
    uint8_t pps_buf[128];

    mfxExtCodingOptionSPSPPS extradata = {
        .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_SPSPPS,
        .Header.BufferSz = sizeof(extradata),
        .SPSBuffer = sps_buf, .SPSBufSize = sizeof(sps_buf),
        .PPSBuffer = pps_buf, .PPSBufSize = sizeof(pps_buf)
    };

    mfxExtBuffer *ext_buffers[] = {
        (mfxExtBuffer*)&extradata,
    };

    int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO;
    int ret;

    q->param.ExtParam    = ext_buffers;
    q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers);

    ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param);
    if (ret < 0)
        return ff_qsv_error(ret);

    q->packet_size = q->param.mfx.BufferSizeInKB * 1000;

    if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize)) {
        av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n");
        return AVERROR_UNKNOWN;
    }

    avctx->extradata = av_malloc(extradata.SPSBufSize + need_pps * extradata.PPSBufSize +
                                 AV_INPUT_BUFFER_PADDING_SIZE);
    if (!avctx->extradata)
        return AVERROR(ENOMEM);

    memcpy(avctx->extradata,                        sps_buf, extradata.SPSBufSize);
    if (need_pps)
        memcpy(avctx->extradata + extradata.SPSBufSize, pps_buf, extradata.PPSBufSize);
    avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize;
    memset(avctx->extradata + avctx->extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);

    return 0;
}

static int qsv_init_opaque_alloc(AVCodecContext *avctx, QSVEncContext *q)
{
    AVQSVContext *qsv = avctx->hwaccel_context;
    mfxFrameSurface1 *surfaces;
    int nb_surfaces, i;

    nb_surfaces = qsv->nb_opaque_surfaces + q->req.NumFrameSuggested + q->async_depth;

    q->opaque_alloc_buf = av_buffer_allocz(sizeof(*surfaces) * nb_surfaces);
    if (!q->opaque_alloc_buf)
        return AVERROR(ENOMEM);

    q->opaque_surfaces = av_malloc_array(nb_surfaces, sizeof(*q->opaque_surfaces));
    if (!q->opaque_surfaces)
        return AVERROR(ENOMEM);

    surfaces = (mfxFrameSurface1*)q->opaque_alloc_buf->data;
    for (i = 0; i < nb_surfaces; i++) {
        surfaces[i].Info      = q->req.Info;
        q->opaque_surfaces[i] = surfaces + i;
    }

    q->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
    q->opaque_alloc.Header.BufferSz = sizeof(q->opaque_alloc);
    q->opaque_alloc.In.Surfaces     = q->opaque_surfaces;
    q->opaque_alloc.In.NumSurface   = nb_surfaces;
    q->opaque_alloc.In.Type         = q->req.Type;

    q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->opaque_alloc;

    qsv->nb_opaque_surfaces = nb_surfaces;
    qsv->opaque_surfaces    = q->opaque_alloc_buf;
    qsv->opaque_alloc_type  = q->req.Type;

    return 0;
}
Exemple #4
0
extern "C" __declspec(dllexport) void *openEncoder(int *pErrorCode, int width, int height, int bitRate, int gop)
{
	*pErrorCode = 0;

	IntelEncoderHandle *pHandle = (IntelEncoderHandle *) malloc(sizeof(IntelEncoderHandle));

	mfxStatus sts = MFX_ERR_NONE;

	mfxIMPL impl = MFX_IMPL_AUTO_ANY;

	mfxVersion ver;
	ver.Major = 1;
	ver.Minor = 0;

	sts = MFXInit(impl, &ver, &pHandle->session);
	if (MFX_ERR_NONE != sts) {
		// TODO:
		*pErrorCode = -1;
	}

	MFXQueryIMPL(pHandle->session, &impl);

	mfxVersion verTemp;
	MFXQueryVersion(pHandle->session, &verTemp);

	mfxVideoParam mfxEncParams;
	memset(&mfxEncParams, 0, sizeof(mfxEncParams));
	mfxEncParams.mfx.CodecId = MFX_CODEC_AVC;
	//  mfxEncParams.mfx.CodecProfile = MFX_PROFILE_AVC_CONSTRAINED_BASELINE;
	mfxEncParams.mfx.TargetUsage = MFX_TARGETUSAGE_BALANCED;

	if (0 == bitRate) bitRate = 128 * 8;
	mfxEncParams.mfx.TargetKbps = bitRate; 

	mfxEncParams.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
	mfxEncParams.mfx.FrameInfo.FrameRateExtN = 30;
	mfxEncParams.mfx.FrameInfo.FrameRateExtD = 1;
	mfxEncParams.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
	mfxEncParams.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
	mfxEncParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
	mfxEncParams.mfx.FrameInfo.CropX = 0;
	mfxEncParams.mfx.FrameInfo.CropY = 0;
	mfxEncParams.mfx.FrameInfo.CropW = width;
	mfxEncParams.mfx.FrameInfo.CropH = height;

	// Width must be a multiple of 16
	// Height must be a multiple of 16 in case of frame picture and a multiple of 32 in case of field picture
	mfxEncParams.mfx.FrameInfo.Width = MSDK_ALIGN16(width);
	mfxEncParams.mfx.FrameInfo.Height =
		(MFX_PICSTRUCT_PROGRESSIVE == mfxEncParams.mfx.FrameInfo.PicStruct) ? MSDK_ALIGN16(width) : MSDK_ALIGN32(height);

	mfxEncParams.IOPattern = MFX_IOPATTERN_IN_SYSTEM_MEMORY;

	sts = MFXVideoENCODE_Query(pHandle->session, &mfxEncParams, &mfxEncParams);
	if (MFX_ERR_NONE != sts) {
		// TODO:
		*pErrorCode = -2;
	}

	mfxFrameAllocRequest EncRequest;
	memset(&EncRequest, 0, sizeof(EncRequest));
	sts = MFXVideoENCODE_QueryIOSurf(pHandle->session, &mfxEncParams, &EncRequest);
	if (MFX_ERR_NONE != sts) {
		// TODO:
		*pErrorCode = -3;
	}

	pHandle->nEncSurfNum = EncRequest.NumFrameSuggested;

	mfxU16 w = (mfxU16)MSDK_ALIGN32(EncRequest.Info.Width);
	mfxU16 h = (mfxU16)MSDK_ALIGN32(EncRequest.Info.Height);
	mfxU8  bitsPerPixel = 12;  // NV12 format is a 12 bits per pixel format
	mfxU32 surfaceSize = w * h * bitsPerPixel / 8;
	pHandle->pSurfaceBuffers = (mfxU8 *)malloc(surfaceSize * pHandle->nEncSurfNum * sizeof(mfxU8));
	pHandle->ppEncSurfaces = (mfxFrameSurface1 **)malloc(sizeof(mfxFrameSurface1*)* pHandle->nEncSurfNum);

	for (int i = 0; i < pHandle->nEncSurfNum; i++)
	{
		pHandle->ppEncSurfaces[i] = (mfxFrameSurface1 *)malloc(sizeof(mfxFrameSurface1));
		memset(pHandle->ppEncSurfaces[i], 0, sizeof(mfxFrameSurface1));
		memcpy(&(pHandle->ppEncSurfaces[i]->Info), &(mfxEncParams.mfx.FrameInfo), sizeof(mfxFrameInfo));
		pHandle->ppEncSurfaces[i]->Data.Y = &pHandle->pSurfaceBuffers[surfaceSize * i];
		pHandle->ppEncSurfaces[i]->Data.U = pHandle->ppEncSurfaces[i]->Data.Y + w * h;
		pHandle->ppEncSurfaces[i]->Data.V = pHandle->ppEncSurfaces[i]->Data.U + 1;
		pHandle->ppEncSurfaces[i]->Data.Pitch = w;

		// In case simulating direct access to frames we initialize the allocated surfaces with default pattern
		// - For true benchmark comparisons to async workloads all surfaces must have the same data
		memset(pHandle->ppEncSurfaces[i]->Data.Y, 100, w * h);  // Y plane
		memset(pHandle->ppEncSurfaces[i]->Data.U, 50, (w * h) / 2);  // UV plane
	}

	sts = MFXVideoENCODE_Init(pHandle->session, &mfxEncParams);
	MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION);
	if (MFX_ERR_NONE != sts) {
		// TODO:
		*pErrorCode = -4;
	}

	mfxVideoParam par;
	memset(&par, 0, sizeof(par));
	sts = MFXVideoENCODE_GetVideoParam(pHandle->session, &par);
	if (MFX_ERR_NONE != sts) {
		// TODO:
		*pErrorCode = -5;
	}

	memset(&pHandle->mfxBS, 0, sizeof(pHandle->mfxBS));
	pHandle->mfxBS.MaxLength = par.mfx.BufferSizeInKB * 1024;
	pHandle->mfxBS.Data = (mfxU8 *)malloc(sizeof(mfxU8)* pHandle->mfxBS.MaxLength);

	return pHandle;
}