Commit 60305d92 authored by Philippe Gorley's avatar Philippe Gorley

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
parent d7fee9ca
......@@ -125,7 +125,22 @@ MediaFilter::initialize(const std::string& filterDesc, std::vector<MediaStream>
}
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);
......
......@@ -78,12 +78,24 @@ class MediaFilter {
*/
int initialize(const std::string& filterDesc, std::vector<MediaStream> 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<AVFilterContext*> inputs_;
/**
* List of filter graph input names. Same order as @inputs_.
* List of filter graph input parameters. Same order as @inputs_.
*/
std::vector<std::string> inputNames_;
std::vector<MediaStream> inputParams_;
/**
* Filter graph string.
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment