From 60305d9224a1c1bfa9aa2f34ac88512b8c8c4752 Mon Sep 17 00:00:00 2001 From: philippegorley Date: Mon, 30 Jul 2018 12:18:40 -0400 Subject: [PATCH] filter: simplify usage and get input params Adds a way to get input parameters. Simplifies usage of simple filters. Adds const where useful. Change-Id: I768d2f3e4e46e791e10530a1c3010607fecc42da --- src/media/media_filter.cpp | 39 ++++++++++++++++++++--- src/media/media_filter.h | 30 ++++++++++++++--- test/unitTest/media/test_media_filter.cpp | 22 ++++++++----- 3 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/media/media_filter.cpp b/src/media/media_filter.cpp index 64e7b5e86..de9995d9f 100644 --- a/src/media/media_filter.cpp +++ b/src/media/media_filter.cpp @@ -125,7 +125,22 @@ MediaFilter::initialize(const std::string& filterDesc, std::vector } MediaStream -MediaFilter::getOutputParams() +MediaFilter::getInputParams() const +{ + return getInputParams("default"); +} + +MediaStream +MediaFilter::getInputParams(const std::string& inputName) const +{ + for (auto ms : inputParams_) + if (ms.name == inputName) + return ms; + return {}; +} + +MediaStream +MediaFilter::getOutputParams() const { MediaStream output; if (!output_ || !initialized_) { @@ -174,7 +189,7 @@ MediaFilter::feedInput(AVFrame* frame, std::string inputName) for (size_t i = 0; i < inputs_.size(); ++i) { auto filterCtx = inputs_[i]; - if (inputNames_[i] != inputName) + if (inputParams_[i].name != inputName) continue; int flags = AV_BUFFERSRC_FLAG_PUSH | AV_BUFFERSRC_FLAG_KEEP_REF; @@ -213,6 +228,19 @@ MediaFilter::readOutput() return nullptr; } +AVFrame* +MediaFilter::apply(AVFrame* frame) +{ + if (inputs_.size() != 1) { + RING_ERR() << "Cannot use apply(AVFrame*) shortcut with a complex filter"; + return nullptr; + } + + if (feedInput(frame) < 0) + return nullptr; + return readOutput(); +} + int MediaFilter::initOutputFilter(AVFilterInOut* out) { @@ -291,14 +319,15 @@ MediaFilter::initInputFilter(AVFilterInOut* in, MediaStream msp, bool simple) inputs_.push_back(buffersrcCtx); if (simple) - inputNames_.push_back("default"); + msp.name = "default"; else - inputNames_.push_back(in->name); + msp.name = in->name; + inputParams_.push_back(msp); return ret; } int -MediaFilter::fail(std::string msg, int err) +MediaFilter::fail(std::string msg, int err) const { if (!msg.empty()) RING_ERR() << msg << ": " << libav_utils::getError(err); diff --git a/src/media/media_filter.h b/src/media/media_filter.h index b3278ef9b..5e99dc73e 100644 --- a/src/media/media_filter.h +++ b/src/media/media_filter.h @@ -78,12 +78,24 @@ class MediaFilter { */ int initialize(const std::string& filterDesc, std::vector msps); + /** + * Returns a MediaStream object describing the input. + * + * NOTE This is a shortcut for simple filters and will fail when called on a complex filter. + */ + MediaStream getInputParams() const; + + /** + * Returns a MediaStream object describing the input specified by @inputName. + */ + MediaStream getInputParams(const std::string& inputName) const; + /** * Returns a MediaStream struct describing the frames that will be output. * * When called in an invalid state, the returned format will be invalid (less than 0). */ - MediaStream getOutputParams(); + MediaStream getOutputParams() const; /** * Give the filter graph an input frame. Caller is responsible for freeing the frame. @@ -109,6 +121,16 @@ class MediaFilter { */ AVFrame* readOutput(); + /** + * Passes a frame through a simple filter (1 input, 1 output). + * + * This is a shortcut for feedInput(AVFrame*)+readOutput(). + * + * NOTE Returns nullptr if the filter graph has multiple inputs/outputs. + * NOTE Caller is responsible for freeing the input and output frames. + */ + AVFrame* apply(AVFrame* frame); + private: NON_COPYABLE(MediaFilter); @@ -127,7 +149,7 @@ class MediaFilter { * * NOTE @msg should not be null. */ - int fail(std::string msg, int err); + int fail(std::string msg, int err) const; /** * Frees resources used by MediaFilter. @@ -150,9 +172,9 @@ class MediaFilter { std::vector inputs_; /** - * List of filter graph input names. Same order as @inputs_. + * List of filter graph input parameters. Same order as @inputs_. */ - std::vector inputNames_; + std::vector inputParams_; /** * Filter graph string. diff --git a/test/unitTest/media/test_media_filter.cpp b/test/unitTest/media/test_media_filter.cpp index a7a42592b..3953e7217 100644 --- a/test/unitTest/media/test_media_filter.cpp +++ b/test/unitTest/media/test_media_filter.cpp @@ -140,8 +140,7 @@ MediaFilterTest::testSimpleVideoFilter() CPPUNIT_ASSERT(filter_->initialize(filterSpec, params) >= 0); // apply filter - CPPUNIT_ASSERT(filter_->feedInput(frame_) >= 0); - frame_ = filter_->readOutput(); + frame_ = filter_->apply(frame_); CPPUNIT_ASSERT(frame_); // check if the filter worked @@ -178,8 +177,7 @@ MediaFilterTest::testSimpleAudioFilter() CPPUNIT_ASSERT(filter_->initialize(filterSpec, params) >= 0); // apply filter - CPPUNIT_ASSERT(filter_->feedInput(frame_) >= 0); - frame_ = filter_->readOutput(); + frame_ = filter_->apply(frame_); CPPUNIT_ASSERT(frame_); // check if the filter worked @@ -259,17 +257,19 @@ MediaFilterTest::testSimpleFilterParams() // prepare filter CPPUNIT_ASSERT(filter_->initialize(filterSpec, params) >= 0); + // check input params + auto msin = filter_->getInputParams(); + CPPUNIT_ASSERT(msin.format == format && msin.width == width && msin.height == height); + // output params should now be valid - auto ms = filter_->getOutputParams(); - CPPUNIT_ASSERT(ms.format >= 0 && ms.width > 0 && ms.height > 0); + auto msout = filter_->getOutputParams(); + CPPUNIT_ASSERT(msout.format >= 0 && msout.width > 0 && msout.height > 0); } void MediaFilterTest::testComplexFilterParams() { std::string filterSpec = "[main] [top] overlay=main_w-overlay_w-10:main_h-overlay_h-10"; - std::string main = "main"; - std::string top = "top"; // constants const constexpr int width1 = 320; @@ -292,6 +292,12 @@ MediaFilterTest::testComplexFilterParams() vec.push_back(params1); CPPUNIT_ASSERT(filter_->initialize(filterSpec, vec) >= 0); + // check input params + auto main = filter_->getInputParams("main"); + CPPUNIT_ASSERT(main.format == format && main.width == width1 && main.height == height1); + auto top = filter_->getInputParams("top"); + CPPUNIT_ASSERT(top.format == format && top.width == width2 && top.height == height2); + // output params should now be valid auto ms = filter_->getOutputParams(); CPPUNIT_ASSERT(ms.format >= 0 && ms.width == width1 && ms.height == height1); -- GitLab