From a207a9f003ba9231a9ffa1e12b341a697ad6d764 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Wed, 18 May 2011 01:37:33 +0200 Subject: [PATCH] adapt Media-Access (+Mock) to include an overall Duration --- src/backend/mediaaccessfacade.cpp | 14 +- src/backend/mediaaccessfacade.hpp | 55 ++++++-- src/lib/singleton-preconfigure.hpp | 6 +- src/proc/asset/media.cpp | 14 +- tests/48proc-operate.tests | 14 +- tests/components/backend/mediaaccessmock.cpp | 87 +++++++++---- tests/components/backend/mediaaccessmock.hpp | 9 +- .../backend/mediaaccessmocktest.cpp | 123 ++++++++---------- .../proc/mobject/session/testclip.cpp | 5 +- .../proc/mobject/session/testclip.hpp | 2 +- 10 files changed, 195 insertions(+), 134 deletions(-) diff --git a/src/backend/mediaaccessfacade.cpp b/src/backend/mediaaccessfacade.cpp index e9feab29f..50daf47c1 100644 --- a/src/backend/mediaaccessfacade.cpp +++ b/src/backend/mediaaccessfacade.cpp @@ -28,30 +28,26 @@ using util::isnil; using lumiera::error::Invalid; -namespace backend_interface - { +namespace backend { /** storage for the SingletonFactory * (actually a lumiera::test::MockInjector) */ Singleton MediaAccessFacade::instance; - typedef MediaAccessFacade::FileHandle FileHandle; - typedef MediaAccessFacade::ChanHandle ChanHandle; - FileHandle - MediaAccessFacade::queryFile (const char* name) throw(Invalid) + MediaDesc& + MediaAccessFacade::queryFile (string const& name) const { if (isnil (name)) throw Invalid ("empty filename passed to MediaAccessFacade."); UNIMPLEMENTED ("delegate to backend: query accessability of file"); - return 0; } ChanDesc - MediaAccessFacade::queryChannel (FileHandle fhandle, uint chanNo) throw() + MediaAccessFacade::queryChannel (MediaDesc& mHandle, uint chanNo) const { UNIMPLEMENTED ("delegate to backend: query channel information"); ChanDesc nix; @@ -60,4 +56,4 @@ namespace backend_interface -} // namespace backend_interface +} // namespace backend diff --git a/src/backend/mediaaccessfacade.hpp b/src/backend/mediaaccessfacade.hpp index 261e84a61..241143985 100644 --- a/src/backend/mediaaccessfacade.hpp +++ b/src/backend/mediaaccessfacade.hpp @@ -25,13 +25,20 @@ #define BACKEND_INTERFACE_MEDIAACCESSFACADE_H -#include "lib/singleton.hpp" #include "lib/error.hpp" +#include "lib/singleton.hpp" +#include "lib/time/timevalue.hpp" + +#include -namespace backend_interface { +namespace backend { + using lib::time::Duration; + using std::string; + + struct MediaDesc; struct ChanDesc; @@ -42,24 +49,26 @@ namespace backend_interface { * Implementation delegating to the actual backend functions. * * convention: data passed by pointer is owned by the originator; - * it should be copied if needed byond the control flow + * it should be copied if needed beyond the control flow * of the invoked function. */ - struct MediaAccessFacade + class MediaAccessFacade { - typedef void* FileHandle; + public: typedef void* ChanHandle; static Singleton instance; /** request for testing the denoted files accessibility * @param name path and filename of the media file. - * @throw invalid when passing empty filename + * @throw error::Invalid when passing empty filename, + * or in case the media file is inaccessible + * or otherwise inappropriate. * @return opaque handle usable for querying channel * information from this file, NULL if the * file is not accessible. */ - virtual FileHandle queryFile (const char* name) throw(lumiera::error::Invalid); + virtual MediaDesc& queryFile (string const& name) const; /** request for information about the n-th channel * of the file referred by FileHandle. @@ -67,12 +76,31 @@ namespace backend_interface { * the file doesn't contain this much channels. * @todo throw or return NULL-ChanDesc if Filehandle is invalid? */ - virtual ChanDesc queryChannel (FileHandle, uint chanNo) throw(); + virtual ChanDesc queryChannel (MediaDesc&, uint chanNo) const; virtual ~MediaAccessFacade () {} }; - + + /** + * Descriptor holding the global informations, + * needed for further handling this media within Lumiera. + */ + struct MediaDesc + { + /** effectively usable duration. + * A clip created from this media will have this + * maximum duration. We expect to get media stream data + * from all channels within this limit. + */ + Duration length; + + MediaDesc() : length(Duration::NIL) { } + }; + + + + /** * Description of one channel found in a * media file; result of querying the channel. @@ -105,8 +133,15 @@ namespace backend_interface { handle(h) { } }; - +} // namespace backend + + +namespace backend_interface { + + using backend::MediaAccessFacade; + using backend::MediaDesc; + using backend::ChanDesc; } // namespace backend_interface #endif diff --git a/src/lib/singleton-preconfigure.hpp b/src/lib/singleton-preconfigure.hpp index 5101c634e..70c911a52 100644 --- a/src/lib/singleton-preconfigure.hpp +++ b/src/lib/singleton-preconfigure.hpp @@ -71,7 +71,7 @@ namespace lib { } // namespace test } // namespace lumiera -namespace backend_interface { +namespace backend { class MediaAccessFacade; using lib::Singleton; @@ -97,8 +97,8 @@ namespace lib { template<> - class Singleton - : public MockInjector + class Singleton + : public MockInjector { }; } // namespace lib diff --git a/src/proc/asset/media.cpp b/src/proc/asset/media.cpp index d67231e89..c357338e5 100644 --- a/src/proc/asset/media.cpp +++ b/src/proc/asset/media.cpp @@ -22,12 +22,14 @@ #include "pre.hpp" +#include "lib/error.hpp" #include "proc/assetmanager.hpp" #include "proc/asset/media.hpp" #include "proc/asset/clip.hpp" #include "proc/asset/unknown.hpp" #include "proc/mobject/session/clip.hpp" #include "proc/mobject/session/mobjectfactory.hpp" +#include "backend/mediaaccessfacade.hpp" #include "lib/time/timevalue.hpp" #include "lib/util.hpp" #include "include/logging.h" @@ -39,6 +41,8 @@ using util::isnil; using lib::time::FSecs; using lib::time::Duration; +using backend_interface::MediaDesc; +using backend_interface::MediaAccessFacade; using boost::format; using boost::regex; @@ -46,6 +50,7 @@ using boost::smatch; using boost::regex_search; using std::tr1::dynamic_pointer_cast; +namespace error = lumiera::error; namespace asset { @@ -134,6 +139,7 @@ namespace asset { * either a asset::Media object or an "Unknown" placeholder will be provided. If * the given Category already contains an "Unkown", we just get the * corresponding smart-ptr. Otherwise a new asset::Unknown is created. + * @throw error::Invalid when media file is inaccessible or inappropriate * @return an Media smart ptr linked to the internally registered smart ptr * created as a side effect of calling the concrete Media subclass ctor. */ @@ -157,9 +163,11 @@ namespace asset { else { if (isnil (key.name)) key.name=extractName(file); - TODO ("file exists?"); - TODO ("extract media file properties"); - Duration length(FSecs(5)); + + MediaAccessFacade& maf = MediaAccessFacade::instance(); + MediaDesc& handle = maf.queryFile(file); + Duration length = handle.length; + TODO ("detecting and wiring multichannel compound media!"); pM = new Media (key,file,length); } diff --git a/tests/48proc-operate.tests b/tests/48proc-operate.tests index e36aa3066..1889a8c49 100644 --- a/tests/48proc-operate.tests +++ b/tests/48proc-operate.tests @@ -2,13 +2,13 @@ TESTING "Proc Layer combined operations Test Suite" ./test-components --group=op -TEST "MediaAccessMock_test" MediaAccessMock_test < #include #include using lumiera::error::Invalid; +using lib::time::Mutation; +using lib::time::Duration; +using lib::Literal; using util::for_each; using util::isnil; using std::cout; @@ -51,29 +57,56 @@ using std::vector; using std::map; -namespace backend_interface { +namespace backend { namespace test { - typedef MediaAccessFacade::FileHandle FileHandle; typedef MediaAccessFacade::ChanHandle ChanHandle; namespace { // implementation details - - typedef vector Response; + + struct Response + { + MediaDesc globalDesc; + vector channels; + + Response& + globalLength (Duration length) + { + globalDesc.length.accept (Mutation::changeDuration(length)); + return *this; + } + + Response& + channel (Literal name, Literal id) + { + channels.push_back (ChanDesc (name, id, genH())); + return *this; + } + + private: + static int _i_; + ChanHandle genH() + { + return reinterpret_cast (++_i_); + } + }; + int Response::_i_(0); const ChanDesc NULLResponse; + using mobject::session::test::LENGTH_TestClip; + struct TestCases : map { TestCases () { - // ------------------------------------------------------------------TESTCASES - (*this)["test-1"].push_back (ChanDesc ("video","ID", genH())); + // ----------------------------------------------------------------------TESTCASES + (*this)["test-1"].globalLength(LENGTH_TestClip).channel("video","ID"); - (*this)["test-2"].push_back (ChanDesc ("video","H264", genH())); - (*this)["test-2"].push_back (ChanDesc ("audio-L","PCM", genH())); - (*this)["test-2"].push_back (ChanDesc ("audio-R","PCM", genH())); - // ------------------------------------------------------------------TESTCASES + (*this)["test-2"].globalLength(LENGTH_TestClip).channel("video","H264") + .channel("audio-L","PCM") + .channel("audio-R","PCM"); + // ----------------------------------------------------------------------TESTCASES } bool known (string key) @@ -81,12 +114,6 @@ namespace test { const_iterator i = find (key); return (i != end()); } - private: - int _i_; - ChanHandle genH() - { - return reinterpret_cast (++_i_); - } }; // instantiate TestCasses table @@ -95,28 +122,32 @@ namespace test { } // (end) implementation namespace - FileHandle - MediaAccessMock::queryFile (const char* name) throw(Invalid) + + MediaDesc& + MediaAccessMock::queryFile (string const& name) const { - if (isnil (name)) - throw Invalid ("empty filename passed to MediaAccessFacade."); + if (isnil (name)) + throw Invalid ("empty filename passed to MediaAccessFacade."); if (!testCases.known(name)) - return 0; - else - return reinterpret_cast (&testCases[name]); + throw Invalid ("unable to use media file \""+name+"\"." + "Hint: you're using a test-mock file access, " + "which responds only to some magical names."); + + return testCases[name].globalDesc; } + ChanDesc - MediaAccessMock::queryChannel (FileHandle h, uint chanNo) throw() + MediaAccessMock::queryChannel (MediaDesc& h, uint chanNo) const { - const Response* res (reinterpret_cast (h)); + Response const& res (*reinterpret_cast (&h)); - if (!res || res->size() <= chanNo) + if (res.channels.size() <= chanNo) return NULLResponse; else - return (*res)[chanNo]; + return res.channels[chanNo]; } -}} // namespace backend_interface::test +}} // namespace backend::test diff --git a/tests/components/backend/mediaaccessmock.hpp b/tests/components/backend/mediaaccessmock.hpp index e48733bc1..dce886aa9 100644 --- a/tests/components/backend/mediaaccessmock.hpp +++ b/tests/components/backend/mediaaccessmock.hpp @@ -30,7 +30,7 @@ -namespace backend_interface { +namespace backend { namespace test { /** @@ -39,11 +39,10 @@ namespace test { */ class MediaAccessMock : public MediaAccessFacade { - public: - FileHandle queryFile (const char* name) throw(lumiera::error::Invalid); - ChanDesc queryChannel (FileHandle, uint chanNo) throw(); + MediaDesc& queryFile (string const& name) const; + ChanDesc queryChannel (MediaDesc&, uint chanNo) const; }; -}} // namespace backend_interface::test +}} // namespace backend::test #endif diff --git a/tests/components/backend/mediaaccessmocktest.cpp b/tests/components/backend/mediaaccessmocktest.cpp index 60d770b89..8bd3ae026 100644 --- a/tests/components/backend/mediaaccessmocktest.cpp +++ b/tests/components/backend/mediaaccessmocktest.cpp @@ -25,78 +25,69 @@ #include "backend/mediaaccessmock.hpp" #include "lib/test/run.hpp" -//#include "lib/util.hpp" +#include "lib/time/diagnostics.hpp" +#include "lib/symbol.hpp" -//#include #include -//using boost::format; -//using util::isnil; +using lib::Literal; using std::string; using std::cout; -namespace backend_interface - { - namespace test +namespace backend { +namespace test { + + + + + + /******************************************************************************** + * @test inject a Mock object replacing the backend_interface::MediaAccessFacade. + * Verify if the Mock object behaves as expected when calling the Facade. + */ + class MediaAccessMock_test : public Test { - - - - - - /******************************************************************************** - * @test inject a Mock object replacing the backend_interface::MediaAccessFacade. - * Verify if the Mock object behaves as expected when calling the Facade. - */ - class MediaAccessMock_test : public Test - { - typedef MediaAccessFacade MAF; - - virtual void run(Arg) - { - MAF::instance.injectSubclass (new MediaAccessMock); - - queryScenario ("test-1"); - queryScenario ("test-2"); - - MAF::instance.injectSubclass (0); - } - - - /** perform the test: query for an (alledged) file - * and retrieve the mock answer. - */ - void queryScenario (string filename) - { - MAF& maf (MAF::instance()); - MAF::FileHandle fhandle = maf.queryFile (filename.c_str()); - if (!fhandle) - cout << "File \""< PM; typedef backend_interface::MediaAccessFacade MAF; - using backend_interface::test::MediaAccessMock; + using backend::test::MediaAccessMock; using asset::VIDEO; @@ -86,7 +87,7 @@ namespace test { /* == define some data for verification in unit tests == */ - const Time LENGTH_TestClip(0,25,0,0); //////TODO hard wired as of (1/10). See MediaFactory::operator() in media.cpp + const Duration LENGTH_TestClip(Time(0,25,0,0)); //////TODO hard wired as of (1/10). See MediaFactory::operator() in media.cpp / mediaaccessmock.cpp }}} // namespace mobject::session::test diff --git a/tests/components/proc/mobject/session/testclip.hpp b/tests/components/proc/mobject/session/testclip.hpp index 97c6b8554..c62034250 100644 --- a/tests/components/proc/mobject/session/testclip.hpp +++ b/tests/components/proc/mobject/session/testclip.hpp @@ -78,7 +78,7 @@ namespace test { /* == some test data to check == */ - extern const lib::time::Time LENGTH_TestClip; + extern const lib::time::Duration LENGTH_TestClip; }}} // namespace mobject::session::test