diff --git a/src/media/media_filter.cpp b/src/media/media_filter.cpp index 64e7b5e8620e1f9ed59d5828f1c52993790af18e..de9995d9ff03b3adff671c4ad8560cd8e3016084 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 b3278ef9b1e0ae9094b811bc1a8ca8ba5f8eff2f..5e99dc73e8d889202a7df495d0c52b828c21f0c6 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 a7a42592bebde9a07059706b448b9bfceb0cbfc3..3953e721714154f76002e537af082496a9d48003 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);