From 454cb1717fbd4b909dc88480e86d28d246993938 Mon Sep 17 00:00:00 2001 From: philippegorley <philippe.gorley@savoirfairelinux.com> Date: Tue, 29 May 2018 10:11:23 -0400 Subject: [PATCH] filter: get output stream properties Change-Id: I6f1ebfc9d967452fe7d7c7e72e32cf795ae2d85a Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com> --- src/media/media_filter.cpp | 35 +++++++++++++ src/media/media_filter.h | 11 +++- test/unitTest/media/test_media_filter.cpp | 62 +++++++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) diff --git a/src/media/media_filter.cpp b/src/media/media_filter.cpp index 9d49018a94..57c3b734a5 100644 --- a/src/media/media_filter.cpp +++ b/src/media/media_filter.cpp @@ -121,6 +121,41 @@ MediaFilter::initialize(const std::string& filterDesc, std::vector<MediaStream> return 0; } +MediaStream +MediaFilter::getOutputParams() +{ + MediaStream output; + if (!output_ || !initialized_) { + fail("Filter not initialized", -1); + return output; + } + + switch (av_buffersink_get_type(output_)) { + case AVMEDIA_TYPE_VIDEO: + output.name = "videoOutput"; + output.format = av_buffersink_get_format(output_); + output.isVideo = true; + output.timeBase = av_buffersink_get_time_base(output_); + output.width = av_buffersink_get_w(output_); + output.height = av_buffersink_get_h(output_); + output.aspectRatio = av_buffersink_get_sample_aspect_ratio(output_); + output.frameRate = av_buffersink_get_frame_rate(output_); + break; + case AVMEDIA_TYPE_AUDIO: + output.name = "audioOutput"; + output.format = av_buffersink_get_format(output_); + output.isVideo = false; + output.timeBase = av_buffersink_get_time_base(output_); + output.sampleRate = av_buffersink_get_sample_rate(output_); + output.nbChannels = av_buffersink_get_channels(output_); + break; + default: + output.format = -1; + break; + } + return output; +} + int MediaFilter::feedInput(AVFrame* frame) { diff --git a/src/media/media_filter.h b/src/media/media_filter.h index aa51a43fed..518a791224 100644 --- a/src/media/media_filter.h +++ b/src/media/media_filter.h @@ -78,6 +78,13 @@ class MediaFilter { */ int initialize(const std::string& filterDesc, std::vector<MediaStream> msps); + /** + * 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(); + /** * Give the filter graph an input frame. Caller is responsible for freeing the frame. * @@ -97,8 +104,10 @@ class MediaFilter { * Pull a frame from the filter graph. Caller owns the frame reference. * * Returns AVERROR(EAGAIN) if filter graph requires more input. + * + * NOTE Frame reference belongs to the caller */ - AVFrame* readOutput(); // frame reference belongs to caller + AVFrame* readOutput(); private: NON_COPYABLE(MediaFilter); diff --git a/test/unitTest/media/test_media_filter.cpp b/test/unitTest/media/test_media_filter.cpp index 82d5f87f19..a7a42592be 100644 --- a/test/unitTest/media/test_media_filter.cpp +++ b/test/unitTest/media/test_media_filter.cpp @@ -41,11 +41,15 @@ private: void testSimpleVideoFilter(); void testSimpleAudioFilter(); void testComplexVideoFilter(); + void testSimpleFilterParams(); + void testComplexFilterParams(); CPPUNIT_TEST_SUITE(MediaFilterTest); CPPUNIT_TEST(testSimpleVideoFilter); CPPUNIT_TEST(testSimpleAudioFilter); CPPUNIT_TEST(testComplexVideoFilter); + CPPUNIT_TEST(testSimpleFilterParams); + CPPUNIT_TEST(testComplexFilterParams); CPPUNIT_TEST_SUITE_END(); std::unique_ptr<MediaFilter> filter_; @@ -235,6 +239,64 @@ MediaFilterTest::testComplexVideoFilter() CPPUNIT_ASSERT(frame_->width == width1 && frame_->height == height1); } +void +MediaFilterTest::testSimpleFilterParams() +{ + std::string filterSpec = "scale=200x100"; + + // constants + const constexpr int width = 320; + const constexpr int height = 240; + const constexpr AVPixelFormat format = AV_PIX_FMT_YUV420P; + + // construct the filter parameters + rational<int> one = rational<int>(1); + auto params = MediaStream("vf", format, one, width, height, one, one); + + // returned params should be invalid + CPPUNIT_ASSERT(filter_->getOutputParams().format < 0); + + // prepare filter + CPPUNIT_ASSERT(filter_->initialize(filterSpec, params) >= 0); + + // output params should now be valid + auto ms = filter_->getOutputParams(); + CPPUNIT_ASSERT(ms.format >= 0 && ms.width > 0 && ms.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; + const constexpr int height1 = 240; + const constexpr int width2 = 30; + const constexpr int height2 = 30; + const constexpr AVPixelFormat format = AV_PIX_FMT_YUV420P; + + // construct the filter parameters + rational<int> one = rational<int>(1); + auto params1 = MediaStream("main", format, one, width1, height1, one, one); + auto params2 = MediaStream("top", format, one, width2, height2, one, one); + + // returned params should be invalid + CPPUNIT_ASSERT(filter_->getOutputParams().format < 0); + + // prepare filter + auto vec = std::vector<MediaStream>(); + vec.push_back(params2); // order does not matter, as long as names match + vec.push_back(params1); + CPPUNIT_ASSERT(filter_->initialize(filterSpec, vec) >= 0); + + // output params should now be valid + auto ms = filter_->getOutputParams(); + CPPUNIT_ASSERT(ms.format >= 0 && ms.width == width1 && ms.height == height1); +} + }} // namespace ring::test RING_TEST_RUNNER(ring::test::MediaFilterTest::name()); -- GitLab