Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: eldesh/Jefuty
base: master
...
head fork: eldesh/Jefuty
compare: media
Checking mergeability… Don’t worry, you can still create the pull request.
  • 6 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
48 include/jefuty/type_traits.hpp
@@ -0,0 +1,48 @@
+#if !defined JEFUTY_TYPE_TRAITS_INCLUDED
+#define JEFUTY_TYPE_TRAITS_INCLUDED
+
+#include <utility>
+#include <type_traits>
+#include <boost/mpl/bool.hpp>
+
+namespace jefuty { namespace type_traits {
+
+namespace detail {
+
+// workaround for MSVC2010
+template<typename T> T && declval ();
+
+template<typename T>
+struct has_width_impl {
+ template<typename U>
+ static auto check (U u) -> decltype(u.width(), std::true_type());
+ static std::false_type check (...) ;
+
+ static bool const value = std::identity<decltype(check(declval<T>()))>::type::value;
+};
+
+template<typename T>
+struct has_height_impl {
+ template<typename U>
+ static auto check (U u) -> decltype(u.height(), std::true_type());
+ static std::false_type check (...) ;
+
+ static bool const value = std::identity<decltype(check(declval<T>()))>::type::value;
+};
+
+} // namespace detail
+
+template<typename T>
+struct has_width : boost::mpl::bool_<detail::has_width_impl<T>::value>
+{};
+
+template<typename T>
+struct has_height : boost::mpl::bool_<detail::has_height_impl<T>::value>
+{};
+
+
+} // namespace type_traits
+} // namespace jefuty
+
+#endif /* JEFUTY_TYPE_TRAITS_INCLUDED */
+
View
47 include/jefuty/win32/media/stream_identifier.hpp
@@ -0,0 +1,47 @@
+#if !defined JEFUTY_MF_STREAM_IDENTIFIER_INCLUDED
+#define JEFUTY_MF_STREAM_IDENTIFIER_INCLUDED
+
+#include <iostream>
+#include <WinDef.h>
+
+namespace jefuty { namespace win32 { namespace media {
+
+// http://msdn.microsoft.com/en-us/library/windows/desktop/ms703852%28v=vs.85%29.aspx
+// The stream identifier uniquely identifies a stream within a presentation.
+// It does not change throughout the lifetime of the stream.
+// stream identifier *IS NOT* the index number of stream.s
+class stream_identifier {
+private:
+ DWORD id_m;
+ stream_identifier ();
+ stream_identifier (DWORD id) : id_m(id) // construct only from stream-descriptor
+ {
+ }
+ friend class stream_descriptor;
+ friend bool operator< (stream_identifier const & lhs, stream_identifier const & rhs);
+};
+
+bool operator< (stream_identifier const & lhs, stream_identifier const & rhs) {
+ return lhs.id_m < rhs.id_m;
+}
+bool operator> (stream_identifier const & lhs, stream_identifier const & rhs) {
+ return rhs < lhs;
+}
+bool operator<=(stream_identifier const & lhs, stream_identifier const & rhs) {
+ return !(lhs > rhs);
+}
+bool operator>=(stream_identifier const & lhs, stream_identifier const & rhs) {
+ return !(lhs < rhs);
+}
+bool operator==(stream_identifier const & lhs, stream_identifier const & rhs) {
+ return !(lhs < rhs) && !(rhs < lhs);
+}
+bool operator!=(stream_identifier const & lhs, stream_identifier const & rhs) {
+ return !(lhs == rhs);
+}
+
+} // namespace media
+} // namespace win32
+} // namespace jefuty
+
+#endif /* JEFUTY_MF_STREAM_IDENTIFIER_INCLUDED */
View
337 include/jefuty/win32/media_foundation.hpp
@@ -0,0 +1,337 @@
+/****
+ *
+ * Wrapper library for audio/video operations on Windows (Vista or later)
+ *
+ *
+ * Microsoft Media Foundation
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms694197%28v=vs.85%29.aspx
+ *
+ ****/
+
+#if !defined JEFUTY_MEDIAFOUNDATION_INCLUDED
+#define JEFUTY_MEDIAFOUNDATION_INCLUDED
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <windows.h>
+#include <shobjidl.h>
+#include <shlwapi.h>
+#include <assert.h>
+#include <strsafe.h>
+
+// Media Foundation headers
+#include <mfapi.h>
+#include <mfidl.h>
+#include <mferror.h>
+#include <evr.h>
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <jefuty/type_traits.hpp>
+#include "media/stream_identifier.hpp"
+
+namespace {
+ // used for managing reference count of COM object by boost/intrusive_ptr
+ void intrusive_ptr_add_ref(IUnknown * p) { p->AddRef() ; }
+ void intrusive_ptr_release(IUnknown * p) { p->Release(); }
+} // namespace `anonymouse`
+
+namespace std {
+ template<>
+ struct default_delete<IUnknown>
+ {
+ void operator() (IUnknown * p) const {
+ if (p) p->Release();
+ }
+ };
+} // namespace std
+
+namespace jefuty { namespace win32 {
+
+class prop_variant {
+public:
+ PROPVARIANT var_m;
+ prop_variant () {
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/aa380293%28v=vs.85%29.aspx
+ ::PropVariantInit(&var_m); // Initializes a PROPVARIANT structure, and sets its type to VT_EMPTY
+ }
+ ~prop_variant () {
+ ::PropVariantClear(&var_m);
+ }
+};
+
+
+namespace media {
+
+struct MF : private boost::noncopyable {
+private:
+ MF() {
+ // Start up Media Foundation platform.
+ if (FAILED(::MFStartup(MF_VERSION)))
+ throw std::runtime_error("initialize media foundation failed");
+ }
+ ~MF() {
+ MFShutdown();
+ }
+ static MF mf;
+public:
+ static MF & getInstance() {
+ static MF mf;
+ return mf;
+ }
+};
+MF MF::mf; // = MF::getInstance();
+
+template<typename T>
+class mf_wrapper {
+public:
+ typedef T wrapped_type;
+protected:
+ boost::intrusive_ptr<wrapped_type> impl_m; // don't publish from derived class
+ mf_wrapper (wrapped_type * p) : impl_m(p)
+ {
+ }
+public:
+ // publish the raw pointer for interoperability
+ wrapped_type const * get () const { return impl_m.get(); }
+ wrapped_type * get () { return impl_m.get(); }
+};
+
+class stream_descriptor ;
+
+// http://msdn.microsoft.com/en-us/library/windows/desktop/ms698961%28v=vs.85%29.aspx
+class presentation_descriptor : public mf_wrapper<IMFPresentationDescriptor> {
+public:
+ typedef mf_wrapper<IMFPresentationDescriptor> base_type;
+ presentation_descriptor (wrapped_type * p) : base_type(p)
+ {
+ }
+ DWORD stream_count () const {
+ DWORD n;
+ wrapped_type * p = const_cast<wrapped_type*>(get());
+ if (FAILED(p->GetStreamDescriptorCount(&n)))
+ throw std::runtime_error(__FUNCTION__ " fail");
+ return n;
+ }
+ // REVISIT: how to get selected or not
+ //stream_descriptor operator[] (DWORD idx) const { }
+};
+
+class media_type_handler : public mf_wrapper<IMFMediaTypeHandler> {
+public:
+ typedef mf_wrapper<IMFMediaTypeHandler> base_type;
+
+ GUID major_type () const {
+ GUID t;
+ if (FAILED(const_cast<wrapped_type*>(get())->GetMajorType(&t)))
+ throw std::runtime_error("get major type fail");
+ return t;
+ }
+private:
+ media_type_handler (wrapped_type * handler) : base_type(handler)
+ {
+ }
+ friend stream_descriptor; // only allow stream_desc to construct
+};
+
+class source_resolver : public mf_wrapper<IMFSourceResolver> {
+public:
+ typedef mf_wrapper<IMFSourceResolver> base_type;
+ source_resolver() : base_type(nullptr) {
+ wrapped_type * p = nullptr;
+ if (FAILED(::MFCreateSourceResolver(&p)))
+ throw std::runtime_error("create source resolver fail");
+ impl_m.reset(p);
+ }
+};
+
+class source : public mf_wrapper<IMFMediaSource> {
+public:
+ typedef mf_wrapper<IMFMediaSource> base_type;
+private:
+ source (wrapped_type * p) : base_type(p)
+ {
+ }
+public:
+ presentation_descriptor create_presentation_descriptor () {
+ IMFPresentationDescriptor * desc=nullptr;
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ms702261%28v=vs.85%29.aspx
+ // ...The caller must release the interface.
+ get()->CreatePresentationDescriptor(&desc);
+ return presentation_descriptor(desc);
+ }
+ static boost::optional<source> create(PCWSTR path) {
+ source_resolver res;
+ MF_OBJECT_TYPE type = MF_OBJECT_INVALID;
+ IUnknown * src_ = nullptr;
+ if (SUCCEEDED(res.get()->CreateObjectFromURL(path, MF_RESOLUTION_MEDIASOURCE, NULL, &type, &src_))) {
+ std::unique_ptr<IUnknown> src(src_);
+ IMFMediaSource * p = nullptr;
+ if (SUCCEEDED(src->QueryInterface(IID_PPV_ARGS(&p))))
+ return boost::optional<source>(source(p));
+ }
+ return boost::none;
+ }
+};
+
+class stream_descriptor : public mf_wrapper<IMFStreamDescriptor> {
+public:
+ typedef mf_wrapper<IMFStreamDescriptor> base_type;
+ stream_descriptor (wrapped_type * desc) : base_type(desc)
+ { }
+ media_type_handler get_media_type_handler () const {
+ IMFMediaTypeHandler * handler;
+ if (FAILED(const_cast<wrapped_type*>(get())->GetMediaTypeHandler(&handler)))
+ throw std::runtime_error(__FUNCTION__ " fail");
+ return media_type_handler(handler);
+ }
+ stream_identifier id () const {
+ DWORD id_;
+ impl_m->GetStreamIdentifier(&id_);
+ return stream_identifier(id_);
+ }
+};
+
+
+class activate : public mf_wrapper<IMFActivate> {
+public:
+ typedef mf_wrapper<IMFActivate> base_type;
+ activate (wrapped_type * act) : base_type(act)
+ {
+ }
+ static activate create_audio_renderer() {
+ wrapped_type * p(nullptr);
+ ::MFCreateAudioRendererActivate(&p);
+ return activate(p);
+ }
+ static activate create_video_renderer(HWND hwnd) { // TODO: take wrapped handler
+ wrapped_type * p(nullptr);
+ ::MFCreateVideoRendererActivate(hwnd, &p);
+ return activate(p);
+ }
+};
+
+class topology_node : public mf_wrapper<IMFTopologyNode> {
+public:
+ typedef mf_wrapper<IMFTopologyNode> base_type;
+ topology_node(wrapped_type * node) : base_type(node)
+ {
+ }
+ topology_node(MF_TOPOLOGY_TYPE type) : base_type(nullptr)
+ {
+ IMFTopologyNode * p=nullptr;
+ if (FAILED(::MFCreateTopologyNode(type, &p)))
+ throw std::runtime_error("create topology fail");
+ impl_m.reset(p);
+ }
+ // Creating Source Nodes
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb250373%28v=vs.85%29.aspx
+ static topology_node make_src_node(source & src, presentation_descriptor & pd, stream_descriptor & sd)
+ {
+ topology_node node = topology_node(MF_TOPOLOGY_SOURCESTREAM_NODE);
+ /// set nodes with attributes
+ node.get()->SetUnknown(MF_TOPONODE_SOURCE , src.get());
+ node.get()->SetUnknown(MF_TOPONODE_PRESENTATION_DESCRIPTOR, pd.get());
+ node.get()->SetUnknown(MF_TOPONODE_STREAM_DESCRIPTOR , sd.get());
+ return node;
+ }
+ // Creating Output Nodes
+ // - Creating an Output Node from an Activation Object
+ // you must use this way to load the topology inside the PMP
+ // where
+ // PMP = Protected Media Path(=encrypted)
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb250377%28v=vs.85%29.aspx
+ static topology_node make_out_node(activate & act, DWORD id) {
+ topology_node tnode(MF_TOPOLOGY_OUTPUT_NODE);
+ tnode.get()->SetObject(act.get());
+ tnode.get()->SetUINT32(MF_TOPONODE_STREAMID, id);
+ tnode.get()->SetUINT32(MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, FALSE);
+ return tnode;
+ }
+};
+
+// http://msdn.microsoft.com/en-us/library/windows/desktop/ms695284%28v=vs.85%29.aspx
+// connect source topology-node to output topology-node (use output/input streams specified index 0)
+HRESULT operator>> (topology_node & src, topology_node & out) {
+ return src.get()->ConnectOutput(0, out.get(), 0);
+}
+
+// http://msdn.microsoft.com/en-us/library/windows/desktop/ms698943%28v=vs.85%29.aspx
+// A topology is an object that represents how data flows in the pipeline.
+class topology : public mf_wrapper<IMFTopology> {
+public:
+ typedef mf_wrapper<IMFTopology> base_type;
+ topology() : base_type(nullptr) {
+ IMFTopology * p=nullptr;
+ if (FAILED(::MFCreateTopology(&p)))
+ throw std::runtime_error("create topology fail");
+ impl_m.reset(p);
+ }
+ bool add_node(topology_node && node) {
+ return SUCCEEDED(get()->AddNode(node.get()));
+ }
+};
+
+// Media Foundation Attributes
+// http://msdn.microsoft.com/en-us/library/windows/desktop/ms696989%28v=vs.85%29.aspx
+class attributes : public mf_wrapper<IMFAttributes> {
+public:
+ typedef mf_wrapper<IMFAttributes> base_type;
+ attributes (wrapped_type * p) : base_type(p)
+ { }
+};
+
+class session : public mf_wrapper<IMFMediaSession> {
+ session () ;
+public:
+ typedef mf_wrapper<IMFMediaSession> base_type;
+ session (topology & topo, attributes const & conf) : base_type(nullptr) {
+ IMFMediaSession * p=nullptr;
+ if (::MFCreateMediaSession(const_cast<attributes::wrapped_type*>(conf.get()), &p))
+ throw std::runtime_error("create media session fail");
+ impl_m.reset(p);
+ impl_m->SetTopology(0, topo.get());
+ }
+ session (topology & topo) : base_type(nullptr) {
+ IMFMediaSession * p=nullptr;
+ if (::MFCreateMediaSession(nullptr, &p))
+ throw std::runtime_error("create media session fail");
+ impl_m.reset(p);
+ impl_m->SetTopology(0, topo.get());
+ }
+
+ // starts the media session
+ HRESULT start (GUID const * timefmt, prop_variant const & var) {
+ return impl_m->Start(timefmt, &var.var_m);
+ }
+ HRESULT start (prop_variant const & var) {
+ return start(nullptr, var);
+ }
+ void stop () { impl_m->Stop(); }
+ void pause () { impl_m->Pause(); }
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ms697318%28v=vs.85%29.aspx
+ // Call this method when you are done using the Media Session, before the final call to IUnknown::Release.
+ // Otherwise, your application will leak memory.
+ // ~session () { impl_m->Shutdown(); }
+};
+
+class video_disp_ctrl {
+public:
+ IMFVideoDisplayControl * ctrl_m;
+// video_disp_ctrl(HWND hwnd)
+};
+
+} // namespace media
+
+} // namespace win32
+} // namespace jefuty
+
+#endif /* JEFUTY_MEDIAFOUNDATION_INCLUDED */
View
6 jefuty/jefuty.vcxproj
@@ -86,17 +86,21 @@
<ClCompile Include="..\src\network\network.cpp" />
<ClCompile Include="..\src\win32.cpp" />
<ClCompile Include="..\src\win32\detail\if.cpp" />
+ <ClCompile Include="..\src\win32\media_foundation.cpp" />
<ClCompile Include="..\src\win32\string.cpp" />
<ClCompile Include="..\src\win32\window_handle_t.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\jefuty\array.hpp" />
<ClInclude Include="..\include\jefuty\jefuty.hpp" />
- <ClInclude Include="..\include\jefuty\network\detail\if.hpp" />
<ClInclude Include="..\include\jefuty\network\detail\mac_addr.hpp" />
<ClInclude Include="..\include\jefuty\network\network.hpp" />
<ClInclude Include="..\include\jefuty\polygon.hpp" />
+ <ClInclude Include="..\include\jefuty\type_traits.hpp" />
<ClInclude Include="..\include\jefuty\win32.hpp" />
+ <ClInclude Include="..\include\jefuty\win32\detail\if.hpp" />
+ <ClInclude Include="..\include\jefuty\win32\media\stream_identifier.hpp" />
+ <ClInclude Include="..\include\jefuty\win32\media_foundation.hpp" />
<ClInclude Include="..\include\jefuty\win32\string.hpp" />
<ClInclude Include="..\include\jefuty\win32\window_handle_t.hpp" />
</ItemGroup>
View
27 jefuty/jefuty.vcxproj.filters
@@ -37,6 +37,9 @@
<Filter Include="ソース ファイル\network\detail">
<UniqueIdentifier>{6e98ede7-0c61-47ee-af7a-237c52eefe94}</UniqueIdentifier>
</Filter>
+ <Filter Include="ヘッダー ファイル\win32\media">
+ <UniqueIdentifier>{6da5bfa3-91af-4e4f-97ab-2807493a39d0}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\win32.cpp">
@@ -48,15 +51,18 @@
<ClCompile Include="..\src\win32\window_handle_t.cpp">
<Filter>ソース ファイル\win32</Filter>
</ClCompile>
- <ClCompile Include="..\src\win32\detail\if.cpp">
- <Filter>ソース ファイル\win32\detail</Filter>
- </ClCompile>
<ClCompile Include="..\src\network\network.cpp">
<Filter>ソース ファイル\network</Filter>
</ClCompile>
<ClCompile Include="..\src\network\detail\mac_addr.cpp">
<Filter>ソース ファイル\network\detail</Filter>
</ClCompile>
+ <ClCompile Include="..\src\win32\media_foundation.cpp">
+ <Filter>ソース ファイル\win32</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\win32\detail\if.cpp">
+ <Filter>ソース ファイル\win32\detail</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\jefuty\win32.hpp">
@@ -74,9 +80,6 @@
<ClInclude Include="..\include\jefuty\polygon.hpp">
<Filter>ヘッダー ファイル</Filter>
</ClInclude>
- <ClInclude Include="..\include\jefuty\network\detail\if.hpp">
- <Filter>ヘッダー ファイル\win32\detail</Filter>
- </ClInclude>
<ClInclude Include="..\include\jefuty\network\detail\mac_addr.hpp">
<Filter>ヘッダー ファイル\network\detail</Filter>
</ClInclude>
@@ -86,6 +89,18 @@
<ClInclude Include="..\include\jefuty\network\network.hpp">
<Filter>ヘッダー ファイル\network</Filter>
</ClInclude>
+ <ClInclude Include="..\include\jefuty\win32\media_foundation.hpp">
+ <Filter>ヘッダー ファイル\win32</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\jefuty\win32\detail\if.hpp">
+ <Filter>ヘッダー ファイル\win32\detail</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\jefuty\win32\media\stream_identifier.hpp">
+ <Filter>ヘッダー ファイル\win32\media</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\jefuty\type_traits.hpp">
+ <Filter>ヘッダー ファイル</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="wscript">
View
3  src/win32/media_foundation.cpp
@@ -0,0 +1,3 @@
+
+#include <jefuty/win32/media_foundation.hpp>
+
View
45 test/test.cpp
@@ -1,6 +1,45 @@
#include <iostream>
#include <vector>
+#include <type_traits>
+
#include <jefuty/network/network.hpp>
+#include <jefuty/type_traits.hpp>
+
+namespace test {
+
+template<typename C, typename V = void>
+struct enable_if : std::enable_if<C::value, V>
+{ };
+
+template<typename C, typename V = void>
+struct disable_if : std::enable_if<!C::value, V>
+{ };
+
+};
+
+struct W {
+ void width () { }
+};
+struct H {
+ void height () { }
+};
+
+template<typename T>
+void getw (T const & t, typename test::enable_if< jefuty::type_traits::has_width<T> >::type* =0) {
+ std::cout << "has width()\n";
+}
+template<typename T>
+void getw (T const & t, typename test::disable_if< jefuty::type_traits::has_width<T> >::type* =0) {
+ std::cout << "has no width()\n";
+}
+template<typename T>
+void geth (T const & t, typename test::enable_if< jefuty::type_traits::has_height<T> >::type* =0) {
+ std::cout << "has height()\n";
+}
+template<typename T>
+void geth (T const & t, typename test::disable_if< jefuty::type_traits::has_height<T> >::type* =0) {
+ std::cout << "has no height()\n";
+}
int main () {
using std::cout;
@@ -9,4 +48,10 @@ int main () {
for (std::vector<net::mac_address>::const_iterator it=xs.begin(); it!=xs.end(); ++it)
cout << *it << "\n";
+ getw(W());
+ geth(W());
+ getw(H());
+ geth(H());
}
+
+

No commit comments for this range

Something went wrong with that request. Please try again.