diff --git a/configure.ac b/configure.ac index a53a77dc1aab386ec3d3f3cd391425f7f49b398b..7a76c52b7b907c4c1d6ea5b308684f148be0a178 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ dnl Ring - configure.ac for automake 1.9 and autoconf 2.59 dnl Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([Ring Daemon],[6.0.0],[ring@gnu.org],[ring]) +AC_INIT([Ring Daemon],[6.1.0],[ring@gnu.org],[ring]) AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2018]]) AC_REVISION([$Revision$]) diff --git a/doc/doxygen/core-doc.cfg.in b/doc/doxygen/core-doc.cfg.in index abff1802e775068640c7cc3ca673cdec7ec834e9..f8122b134d41c2a059a1d16497da8815d046d58a 100644 --- a/doc/doxygen/core-doc.cfg.in +++ b/doc/doxygen/core-doc.cfg.in @@ -31,7 +31,7 @@ PROJECT_NAME = "Ring Daemon" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 6.0.0 +PROJECT_NUMBER = 6.1.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer diff --git a/src/client/videomanager.cpp b/src/client/videomanager.cpp index f6ae2328658d3d3be40b9986e7e2470d2bb8b5ae..2c33fd6b1a5cdb38ab068591b73864aef2701b98 100644 --- a/src/client/videomanager.cpp +++ b/src/client/videomanager.cpp @@ -52,6 +52,13 @@ MediaFrame::MediaFrame() throw std::bad_alloc(); } +void +MediaFrame::copyFrom(MediaFrame& o) +{ + reset(); + av_frame_ref(frame_.get(), o.frame_.get()); +} + void MediaFrame::reset() noexcept { @@ -72,6 +79,14 @@ VideoFrame::reset() noexcept releaseBufferCb_ = {}; } +void +VideoFrame::copyFrom(VideoFrame& o) +{ + MediaFrame::copyFrom(o); + ptr_ = o.ptr_; + allocated_ = o.allocated_; +} + size_t VideoFrame::size() const noexcept { @@ -154,7 +169,6 @@ VideoFrame::setReleaseCb(std::function<void(uint8_t*)> cb) noexcept } } - void VideoFrame::noise() { @@ -166,17 +180,6 @@ VideoFrame::noise() } } -VideoFrame& -VideoFrame::operator =(const VideoFrame& src) -{ - reserve(src.format(), src.width(), src.height()); - auto source = src.pointer(); - av_image_copy(frame_->data, frame_->linesize, (const uint8_t **)source->data, - source->linesize, (AVPixelFormat)frame_->format, - frame_->width, frame_->height); - return *this; -} - VideoFrame* getNewFrame() { if (auto input = ring::Manager::instance().getVideoManager().videoInput.lock()) diff --git a/src/dring/videomanager_interface.h b/src/dring/videomanager_interface.h index 95160e4a79c527d65ac6c63eb9c90c5845b2162c..0993072f3bda16dfe1f0eff0f48ddfc4dd57ab32 100644 --- a/src/dring/videomanager_interface.h +++ b/src/dring/videomanager_interface.h @@ -64,16 +64,23 @@ struct DRING_PUBLIC SinkTarget { std::function<void(FrameBufferPtr)> push; }; -class MediaFrame { +class DRING_PUBLIC MediaFrame { public: // Construct an empty MediaFrame MediaFrame(); + MediaFrame(const MediaFrame&) = delete; + MediaFrame& operator =(const MediaFrame& o) = delete; + MediaFrame(MediaFrame&& o) = delete; + MediaFrame& operator =(MediaFrame&& o) = delete; virtual ~MediaFrame() = default; // Return a pointer on underlaying buffer AVFrame* pointer() const noexcept { return frame_.get(); } + // Fill this MediaFrame with data from o + void copyFrom(MediaFrame& o); + // Reset internal buffers (return to an empty MediaFrame) virtual void reset() noexcept; @@ -81,17 +88,20 @@ protected: std::unique_ptr<AVFrame, void(*)(AVFrame*)> frame_; }; -struct AudioFrame: MediaFrame {}; +class DRING_PUBLIC AudioFrame : public MediaFrame {}; -class VideoFrame: public MediaFrame { +class DRING_PUBLIC VideoFrame : public MediaFrame { public: // Construct an empty VideoFrame - VideoFrame() = default; + VideoFrame() : MediaFrame() {} ~VideoFrame(); // Reset internal buffers (return to an empty VideoFrame) void reset() noexcept override; + // Fill this VideoFrame with data from o + void copyFrom(VideoFrame& o); + // Return frame size in bytes std::size_t size() const noexcept; @@ -115,9 +125,6 @@ public: void noise(); - // Copy-Assignement - VideoFrame& operator =(const VideoFrame& src); - private: std::function<void(uint8_t*)> releaseBufferCb_ {}; uint8_t* ptr_ {nullptr}; diff --git a/src/media/video/video_mixer.cpp b/src/media/video/video_mixer.cpp index f864d9c849f6550fe375a0331dca71e3be825f1f..6757bf4c28de9baced0b0f1114a6b253e83e6ccc 100644 --- a/src/media/video/video_mixer.cpp +++ b/src/media/video/video_mixer.cpp @@ -111,7 +111,7 @@ VideoMixer::update(Observable<std::shared_ptr<VideoFrame>>* ob, x->update_frame.reset(new VideoFrame); else x->update_frame->reset(); - *x->update_frame = *frame_p; // copy frame content, it will be destroyed after return + x->update_frame->copyFrom(*frame_p); // copy frame content, it will be destroyed after return x->atomic_swap_render(x->update_frame); return; } diff --git a/test/unitTest/Makefile.am b/test/unitTest/Makefile.am index 7275096abedf46ce6a22f6650e44295f534e0cff..a17a541633d3e792542c4901334f697084869b36 100644 --- a/test/unitTest/Makefile.am +++ b/test/unitTest/Makefile.am @@ -92,4 +92,10 @@ ut_media_filter_SOURCES = media/test_media_filter.cpp check_PROGRAMS += ut_resampler ut_resampler_SOURCES = media/audio/test_resampler.cpp +# +# media_frame +# +check_PROGRAMS += ut_media_frame +ut_media_frame_SOURCES = media/test_media_frame.cpp + TESTS = $(check_PROGRAMS) diff --git a/test/unitTest/media/test_media_frame.cpp b/test/unitTest/media/test_media_frame.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a3c2a1948f6e2ee61cc35277805b9c2a329ed7a --- /dev/null +++ b/test/unitTest/media/test_media_frame.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2018 Savoir-faire Linux Inc. + * + * Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> + +extern "C" { +#include <libavutil/frame.h> +#include <libavutil/pixfmt.h> +} + +#include "dring.h" +#include "videomanager_interface.h" + +#include "../../test_runner.h" + +namespace ring { namespace test { + +class MediaFrameTest : public CppUnit::TestFixture { +public: + static std::string name() { return "media_frame"; } + + void setUp(); + void tearDown(); + +private: + void testCopy(); + + CPPUNIT_TEST_SUITE(MediaFrameTest); + CPPUNIT_TEST(testCopy); + CPPUNIT_TEST_SUITE_END(); +}; + + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MediaFrameTest, MediaFrameTest::name()); + +void +MediaFrameTest::setUp() +{ + DRing::init(DRing::InitFlag(DRing::DRING_FLAG_DEBUG | DRing::DRING_FLAG_CONSOLE_LOG)); +} + +void +MediaFrameTest::tearDown() +{ + DRing::fini(); +} + +void +MediaFrameTest::testCopy() +{ + // test allocation + DRing::VideoFrame v1; + v1.reserve(AV_PIX_FMT_YUV420P, 100, 100); + v1.pointer()->data[0][0] = 42; + CPPUNIT_ASSERT(v1.pointer()); + + // test frame referencing (different pointers, but same data) + DRing::VideoFrame v2; + v2.copyFrom(v1); + CPPUNIT_ASSERT(v1.format() == v2.format()); + CPPUNIT_ASSERT(v1.width() == v2.width()); + CPPUNIT_ASSERT(v1.height() == v2.height()); + CPPUNIT_ASSERT(v1.pointer() != v2.pointer()); + CPPUNIT_ASSERT(v1.pointer()->data[0][0] == 42); + CPPUNIT_ASSERT(v2.pointer()->data[0][0] == 42); +} + +}} // namespace ring::test + +RING_TEST_RUNNER(ring::test::MediaFrameTest::name());