Path: blob/master/modules/videoio/src/cap_mfx_reader.cpp
16354 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html34#include "cap_mfx_reader.hpp"5#include "opencv2/core/base.hpp"6#include "cap_mfx_common.hpp"7#include "opencv2/imgproc/hal/hal.hpp"89using namespace cv;10using namespace std;1112inline bool hasExtension(const String &filename, const String &ext)13{14if (filename.size() <= ext.size())15return false;16const size_t diff = filename.size() - ext.size();17const size_t found_at = filename.rfind(ext);18return found_at == diff;19}2021inline mfxU32 determineCodecId(const String &filename)22{23if (hasExtension(filename, ".h264") || hasExtension(filename, ".264"))24return MFX_CODEC_AVC;25else if (hasExtension(filename, ".mp2") || hasExtension(filename, ".mpeg2"))26return MFX_CODEC_MPEG2;27else if (hasExtension(filename, ".265") || hasExtension(filename, ".hevc"))28return MFX_CODEC_HEVC;29else30return (mfxU32)-1;31}3233//==========================================================================3435VideoCapture_IntelMFX::VideoCapture_IntelMFX(const cv::String &filename)36: session(0), plugin(0), deviceHandler(0), bs(0), decoder(0), pool(0), outSurface(0), good(false)37{38mfxStatus res = MFX_ERR_NONE;3940// Init device and session41deviceHandler = createDeviceHandler();42session = new MFXVideoSession();43if (!deviceHandler->init(*session))44{45MSG(cerr << "MFX: Can't initialize session" << endl);46return;47}4849// Load appropriate plugin5051mfxU32 codecId = determineCodecId(filename);52if (codecId == (mfxU32)-1)53{54MSG(cerr << "MFX: Unsupported extension: " << filename << endl);55return;56}57plugin = Plugin::loadDecoderPlugin(*session, codecId);58if (plugin && !plugin->isGood())59{60MSG(cerr << "MFX: LoadPlugin failed for codec: " << codecId << " (" << filename << ")" << endl);61return;62}6364// Read some content from file6566bs = new ReadBitstream(filename.c_str());67if (!bs->read())68{69MSG(cerr << "MFX: Failed to read bitstream" << endl);70return;71}7273// Create decoder and decode stream header7475decoder = new MFXVideoDECODE(*session);76mfxVideoParam params;77memset(¶ms, 0, sizeof(params));78params.mfx.CodecId = codecId;79params.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;80res = decoder->DecodeHeader(&bs->stream, ¶ms);81DBG(cout << "DecodeHeader: " << res << endl << params.mfx << params.mfx.FrameInfo << endl);82if (res < MFX_ERR_NONE)83{84MSG(cerr << "MFX: Failed to decode stream header: " << res << endl);85return;86}8788// Adjust parameters8990res = decoder->Query(¶ms, ¶ms);91DBG(cout << "MFX Query: " << res << endl << params.mfx << params.mfx.FrameInfo);92CV_Assert(res >= MFX_ERR_NONE);9394// Init surface pool9596pool = SurfacePool::create(decoder, params);97if (!pool)98{99MSG(cerr << "MFX: Failed to create surface pool" << endl);100return;101}102103// Init decoder104105res = decoder->Init(¶ms);106DBG(cout << "MFX Init: " << res << endl << params.mfx.FrameInfo);107if (res < MFX_ERR_NONE)108{109MSG(cerr << "MFX: Failed to init decoder: " << res << endl);110return;111}112113good = true;114}115116117VideoCapture_IntelMFX::~VideoCapture_IntelMFX()118{119cleanup(plugin);120cleanup(bs);121cleanup(decoder);122cleanup(pool);123session->Close();124cleanup(session);125cleanup(deviceHandler);126}127128double VideoCapture_IntelMFX::getProperty(int) const129{130MSG(cerr << "MFX: getProperty() is not implemented" << endl);131return 0;132}133134bool VideoCapture_IntelMFX::setProperty(int, double)135{136MSG(cerr << "MFX: setProperty() is not implemented" << endl);137return false;138}139140bool VideoCapture_IntelMFX::grabFrame()141{142mfxStatus res;143mfxFrameSurface1 *workSurface = 0;144mfxSyncPoint sync;145146workSurface = pool->getFreeSurface();147148while (true)149{150if (!workSurface)151{152// not enough surfaces153MSG(cerr << "MFX: Failed to get free surface" << endl);154return false;155}156157outSurface = 0;158res = decoder->DecodeFrameAsync(bs->drain ? 0 : &bs->stream, workSurface, (mfxFrameSurface1**)&outSurface, &sync);159if (res == MFX_ERR_NONE)160{161res = session->SyncOperation(sync, 1000); // 1 sec, TODO: provide interface to modify timeout162if (res == MFX_ERR_NONE)163{164// ready to retrieve165DBG(cout << "Frame ready to retrieve" << endl);166return true;167}168else169{170MSG(cerr << "MFX: Sync error: " << res << endl);171return false;172}173}174else if (res == MFX_ERR_MORE_DATA)175{176if (bs->isDone())177{178if (bs->drain)179{180// finish181DBG(cout << "Drain finished" << endl);182return false;183}184else185{186DBG(cout << "Bitstream finished - Drain started" << endl);187bs->drain = true;188continue;189}190}191else192{193bool read_res = bs->read();194if (!read_res)195{196// failed to read197MSG(cerr << "MFX: Bitstream read failure" << endl);198return false;199}200else201{202DBG(cout << "Bitstream read success" << endl);203continue;204}205}206}207else if (res == MFX_ERR_MORE_SURFACE)208{209DBG(cout << "Getting another surface" << endl);210workSurface = pool->getFreeSurface();211continue;212}213else if (res == MFX_WRN_DEVICE_BUSY)214{215DBG(cout << "Waiting for device" << endl);216sleep(1);217continue;218}219else if (res == MFX_WRN_VIDEO_PARAM_CHANGED)220{221DBG(cout << "Video param changed" << endl);222continue;223}224else225{226MSG(cerr << "MFX: Bad status: " << res << endl);227return false;228}229}230}231232233bool VideoCapture_IntelMFX::retrieveFrame(int, OutputArray out)234{235if (!outSurface)236{237MSG(cerr << "MFX: No frame ready to retrieve" << endl);238return false;239}240mfxFrameSurface1 * s = (mfxFrameSurface1*)outSurface;241mfxFrameInfo &info = s->Info;242mfxFrameData &data = s->Data;243244const int cols = info.CropW;245const int rows = info.CropH;246247out.create(rows, cols, CV_8UC3);248Mat res = out.getMat();249250hal::cvtTwoPlaneYUVtoBGR(data.Y, data.UV, data.Pitch, res.data, res.step, cols, rows, 3, false, 0);251252return true;253}254255bool VideoCapture_IntelMFX::isOpened() const256{257return good;258}259260int VideoCapture_IntelMFX::getCaptureDomain()261{262return CAP_INTEL_MFX;263}264265//==================================================================================================266267268