[Merge] lp:~thomas-voss/media-hub/introduce-video-sink-interface into lp:media-hub
Jim Hodapp
jim.hodapp at canonical.com
Mon Dec 1 20:53:40 UTC 2014
Review: Needs Fixing code
Looks good, just 1 inline comment below. Also, make sure to rebase with trunk changes. This would be the very first MR I'd like to see get put into a silo so that I can test it well. This is a nice limited-scope MR but still is important. I want to try to avoid having to test all of the MRs combined in one silo, but instead would like to incrementally test one or 2 MRs at a time and land, then test 1 or two more and land, etc.
Diff comments:
> === modified file 'debian/changelog'
> --- debian/changelog 2014-11-20 18:33:08 +0000
> +++ debian/changelog 2014-11-26 12:39:46 +0000
> @@ -1,3 +1,9 @@
> +media-hub (3.0.0) UNRELEASED; urgency=medium
> +
> + * Refactor client-facing interfaces to pull out explicit dependency on hybris-based media layer.
> +
> + -- Thomas Voss <thomas.voss at canonical.com> Tue, 11 Nov 2014 17:15:52 +0100
> +
> media-hub (2.0.0+15.04.20141120.1-0ubuntu1) vivid; urgency=low
>
> [ Jim Hodapp ]
>
> === modified file 'debian/control'
> --- debian/control 2014-11-12 19:10:24 +0000
> +++ debian/control 2014-11-26 12:39:46 +0000
> @@ -42,8 +42,8 @@
> Architecture: any
> Multi-Arch: same
> Pre-Depends: dpkg (>= 1.15.6~)
> -Depends: libmedia-hub-common2 (= ${binary:Version}),
> - libmedia-hub-client2 (= ${binary:Version}),
> +Depends: libmedia-hub-common3 (= ${binary:Version}),
> + libmedia-hub-client3 (= ${binary:Version}),
> ${misc:Depends},
> libproperties-cpp-dev,
> Suggests: libmedia-hub-doc
> @@ -65,7 +65,7 @@
> .
> This package contains the runtime.
>
> -Package: libmedia-hub-common2
> +Package: libmedia-hub-common3
> Architecture: any
> Multi-Arch: same
> Pre-Depends: dpkg (>= 1.15.6~)
> @@ -77,7 +77,7 @@
> .
> This package contains the common libraries.
>
> -Package: libmedia-hub-client2
> +Package: libmedia-hub-client3
> Architecture: any
> Multi-Arch: same
> Pre-Depends: dpkg (>= 1.15.6~)
>
> === renamed file 'debian/libmedia-hub-client2.install' => 'debian/libmedia-hub-client3.install'
> === renamed file 'debian/libmedia-hub-common2.install' => 'debian/libmedia-hub-common3.install'
> === renamed file 'debian/libmedia-hub-common2.symbols' => 'debian/libmedia-hub-common3.symbols'
> --- debian/libmedia-hub-common2.symbols 2014-09-10 21:11:00 +0000
> +++ debian/libmedia-hub-common3.symbols 2014-11-26 12:39:46 +0000
> @@ -1,2 +1,2 @@
> -libmedia-hub-common.so.2 libmedia-hub-common2 #MINVER#
> +libmedia-hub-common.so.3 libmedia-hub-common3 #MINVER#
> (c++)"core::ubuntu::media::the_session_bus()@Base" 2.0.0+14.10.20140910.2
>
> === modified file 'include/core/media/player.h'
> --- include/core/media/player.h 2014-10-14 20:05:20 +0000
> +++ include/core/media/player.h 2014-11-26 12:39:46 +0000
> @@ -20,6 +20,7 @@
> #define CORE_UBUNTU_MEDIA_PLAYER_H_
>
> #include <core/media/track.h>
> +#include <core/media/video/sink.h>
>
> #include <core/property.h>
>
> @@ -43,10 +44,15 @@
> typedef uint32_t PlayerKey;
> typedef void* GLConsumerWrapperHybris;
>
> - /** Used to set a callback function to be called when a frame is ready to be rendered **/
> - typedef void (*FrameAvailableCbHybris)(GLConsumerWrapperHybris wrapper, void *context);
> - typedef void (*FrameAvailableCb)(void *context);
> - typedef void (*PlaybackCompleteCb)(void *context);
> + struct Error
> + {
> + Error() = delete;
> +
> + struct OutOfProcessBufferStreamingNotSupported : public std::runtime_error
> + {
> + OutOfProcessBufferStreamingNotSupported();
> + };
> + };
>
> struct Configuration;
>
> @@ -103,9 +109,9 @@
> virtual std::shared_ptr<TrackList> track_list() = 0;
> virtual PlayerKey key() const = 0;
>
> + virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id) = 0;
> +
> virtual bool open_uri(const Track::UriType& uri) = 0;
> - virtual void create_video_sink(uint32_t texture_id) = 0;
> - virtual GLConsumerWrapperHybris gl_consumer() const = 0;
> virtual void next() = 0;
> virtual void previous() = 0;
> virtual void play() = 0;
> @@ -113,10 +119,6 @@
> virtual void stop() = 0;
> virtual void seek_to(const std::chrono::microseconds& offset) = 0;
>
> - // TODO: Convert this to be a signal
> - virtual void set_frame_available_callback(FrameAvailableCb cb, void *context) = 0;
> - virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context) = 0;
> -
> virtual const core::Property<bool>& can_play() const = 0;
> virtual const core::Property<bool>& can_pause() const = 0;
> virtual const core::Property<bool>& can_seek() const = 0;
>
> === added directory 'include/core/media/video'
> === added file 'include/core/media/video/sink.h'
> --- include/core/media/video/sink.h 1970-01-01 00:00:00 +0000
> +++ include/core/media/video/sink.h 2014-11-26 12:39:46 +0000
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * 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 Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
> +#define CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
> +
> +#include <core/signal.h>
> +
> +#include <memory>
> +
> +namespace core
> +{
> +namespace ubuntu
> +{
> +namespace media
> +{
> +namespace video
> +{
> +/** @brief A video sink abstracts a queue of buffers, that receives
> + * a stream of decoded video buffers from an arbitrary source.
> + */
> +struct Sink
> +{
> + /** @brief To save us some typing. */
> + typedef std::shared_ptr<Sink> Ptr;
> +
> + /** @cond */
> + Sink() = default;
> + Sink(const Sink&) = delete;
> + virtual ~Sink() = default;
> +
> + Sink& operator=(const Sink&) = delete;
> + /** @endcond */
> +
> + /**
> + * @brief The signal is emitted whenever a new frame is available and a subsequent
> + * call to swap_buffers will not block and return true.
> + */
> + virtual const core::Signal<void>& frame_available() const = 0;
> +
> + /**
> + * @brief Queries the 4x4 transformation matrix for the current frame, placing the data into 'matrix'.
> + * @param matrix [out] The destination array representing the matrix, we expect 4*4 float elements in the array.
I would add to this comment that the matrix is expected to be in column-major format.
Also, shouldn't the last part of the comment read like "we expect a 4*4 element array"?
> + * @returns true iff the data has been set. Returns false and leaves 'matrix' unchanged in case of issues.
> + */
> + virtual bool transformation_matrix(float* matrix) const = 0;
> +
> + /**
> + * @brief Releases the current buffer, and consumes the next buffer in the queue,
> + * making it available for consumption by consumers of this API in an
> + * implementation-specific way. Clients will usually rely on a GL texture
> + * to receive the latest buffer.
> + */
> + virtual bool swap_buffers() const = 0;
> +};
> +}
> +}
> +}
> +}
> +
> +#endif // CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
>
> === modified file 'src/core/media/CMakeLists.txt'
> --- src/core/media/CMakeLists.txt 2014-11-12 19:10:24 +0000
> +++ src/core/media/CMakeLists.txt 2014-11-26 12:39:46 +0000
> @@ -6,7 +6,10 @@
> # out all symbols that are not in core::ubuntu::media*
> set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")
>
> -file(GLOB MPRIS_HEADERS mpris/ *.h)
> +file(GLOB_RECURSE MEDIA_HUB_HEADERS ${CMAKE_SOURCE_DIR}/include/*.h)
> +file(GLOB MPRIS_HEADERS mpris/*.h)
> +
> +message(STATUS ${MEDIA_HUB_HEADERS})
>
> add_subdirectory(call-monitor)
>
> @@ -36,6 +39,8 @@
> add_library(
> media-hub-client SHARED
>
> + ${MEDIA_HUB_HEADERS}
> +
> player.cpp
> service.cpp
> track.cpp
> @@ -44,6 +49,9 @@
> player_stub.cpp
> service_stub.cpp
> track_list_stub.cpp
> +
> + video/hybris_gl_sink.cpp
> + video/platform_default_sink.cpp
> )
>
> set_target_properties(
> @@ -75,6 +83,7 @@
> add_library(
> media-hub-service
>
> + ${MEDIA_HUB_HEADERS}
> ${MPRIS_HEADERS}
>
> cover_art_resolver.cpp
>
> === modified file 'src/core/media/engine.h'
> --- src/core/media/engine.h 2014-11-03 18:00:48 +0000
> +++ src/core/media/engine.h 2014-11-26 12:39:46 +0000
> @@ -76,6 +76,8 @@
> virtual const core::Property<State>& state() const = 0;
>
> virtual bool open_resource_for_uri(const Track::UriType& uri) = 0;
> + // Throws core::ubuntu::media::Player::Error::OutOfProcessBufferStreamingNotSupported if the implementation does not
> + // support this feature.
> virtual void create_video_sink(uint32_t texture_id) = 0;
>
> virtual bool play() = 0;
>
> === modified file 'src/core/media/mpris/player.h'
> --- src/core/media/mpris/player.h 2014-10-14 20:05:20 +0000
> +++ src/core/media/mpris/player.h 2014-11-26 12:39:46 +0000
> @@ -103,6 +103,17 @@
> static constexpr const char* stopped{"Stopped"};
> };
>
> + struct Error
> + {
> + struct OutOfProcessBufferStreamingNotSupported
> + {
> + static constexpr const char* name
> + {
> + "mpris.Player.Error.OutOfProcessBufferStreamingNotSupported"
> + };
> + };
> + };
> +
> typedef std::map<std::string, core::dbus::types::Variant> Dictionary;
>
> DBUS_CPP_METHOD_DEF(Next, Player)
>
> === modified file 'src/core/media/player.cpp'
> --- src/core/media/player.cpp 2014-09-09 10:28:32 +0000
> +++ src/core/media/player.cpp 2014-11-26 12:39:46 +0000
> @@ -22,6 +22,11 @@
>
> namespace media = core::ubuntu::media;
>
> +media::Player::Error::OutOfProcessBufferStreamingNotSupported::OutOfProcessBufferStreamingNotSupported()
> + : std::runtime_error{"Implementation does not support out-of-process buffer streaming"}
> +{
> +}
> +
> const media::Player::Configuration& media::Player::Client::default_configuration()
> {
> static const media::Player::Configuration config
>
> === modified file 'src/core/media/player_implementation.cpp'
> --- src/core/media/player_implementation.cpp 2014-11-03 18:00:48 +0000
> +++ src/core/media/player_implementation.cpp 2014-11-26 12:39:46 +0000
> @@ -458,22 +458,17 @@
> return d->key;
> }
>
> +media::video::Sink::Ptr media::PlayerImplementation::create_gl_texture_video_sink(std::uint32_t texture_id)
> +{
> + d->engine->create_video_sink(texture_id);
> + return media::video::Sink::Ptr{};
> +}
> +
> bool media::PlayerImplementation::open_uri(const Track::UriType& uri)
> {
> return d->engine->open_resource_for_uri(uri);
> }
>
> -void media::PlayerImplementation::create_video_sink(uint32_t texture_id)
> -{
> - d->engine->create_video_sink(texture_id);
> -}
> -
> -media::Player::GLConsumerWrapperHybris media::PlayerImplementation::gl_consumer() const
> -{
> - // This method is client-side only and is simply a no-op for the service side
> - return NULL;
> -}
> -
> void media::PlayerImplementation::next()
> {
> }
> @@ -498,18 +493,6 @@
> d->engine->stop();
> }
>
> -void media::PlayerImplementation::set_frame_available_callback(
> - UNUSED FrameAvailableCb cb, UNUSED void *context)
> -{
> - // This method is client-side only and is simply a no-op for the service side
> -}
> -
> -void media::PlayerImplementation::set_playback_complete_callback(
> - UNUSED PlaybackCompleteCb cb, UNUSED void *context)
> -{
> - // This method is client-side only and is simply a no-op for the service side
> -}
> -
> void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)
> {
> d->engine->seek_to(ms);
>
> === modified file 'src/core/media/player_implementation.h'
> --- src/core/media/player_implementation.h 2014-09-25 04:35:46 +0000
> +++ src/core/media/player_implementation.h 2014-11-26 12:39:46 +0000
> @@ -46,16 +46,14 @@
> virtual std::shared_ptr<TrackList> track_list();
> virtual PlayerKey key() const;
>
> + virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id);
> +
> virtual bool open_uri(const Track::UriType& uri);
> - virtual void create_video_sink(uint32_t texture_id);
> - virtual GLConsumerWrapperHybris gl_consumer() const;
> virtual void next();
> virtual void previous();
> virtual void play();
> virtual void pause();
> virtual void stop();
> - virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
> - virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
> virtual void seek_to(const std::chrono::microseconds& offset);
>
> const core::Signal<>& on_client_disconnected() const;
>
> === modified file 'src/core/media/player_skeleton.cpp'
> --- src/core/media/player_skeleton.cpp 2014-10-14 20:15:56 +0000
> +++ src/core/media/player_skeleton.cpp 2014-11-26 12:39:46 +0000
> @@ -135,9 +135,29 @@
> {
> uint32_t texture_id;
> in->reader() >> texture_id;
> - impl->create_video_sink(texture_id);
> -
> - auto reply = dbus::Message::make_method_return(in);
> +
> + core::dbus::Message::Ptr reply;
> +
> + try
> + {
> + impl->create_gl_texture_video_sink(texture_id);
> + reply = dbus::Message::make_method_return(in);
> + }
> + catch (const media::Player::Error::OutOfProcessBufferStreamingNotSupported& e)
> + {
> + reply = dbus::Message::make_error(
> + in,
> + mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name,
> + e.what());
> + }
> + catch (...)
> + {
> + reply = dbus::Message::make_error(
> + in,
> + mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name,
> + std::string{});
> + }
> +
> bus->send(reply);
> }
>
>
> === modified file 'src/core/media/player_stub.cpp'
> --- src/core/media/player_stub.cpp 2014-11-05 20:41:03 +0000
> +++ src/core/media/player_stub.cpp 2014-11-26 12:39:46 +0000
> @@ -19,6 +19,7 @@
>
> #include <core/media/service.h>
> #include <core/media/track_list.h>
> +#include <core/media/video/platform_default_sink.h>
>
> #include "codec.h"
> #include "player_stub.h"
> @@ -48,13 +49,8 @@
> Private(const std::shared_ptr<Service>& parent,
> const std::shared_ptr<core::dbus::Object>& object
> ) : parent(parent),
> - texture_id(0),
> - igbc_wrapper(nullptr),
> - glc_wrapper(nullptr),
> - decoding_session(nullptr),
> - frame_available_cb(nullptr),
> - frame_available_context(nullptr),
> object(object),
> + key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()),
> properties
> {
> // Link the properties from the server side to the client side over the bus
> @@ -87,64 +83,20 @@
> object->get_signal<mpris::Player::Signals::VideoDimensionChanged>()
> }
> {
> - auto op = object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>();
> - decoding_session = decoding_service_create_session(op.value());
> + decoding_session = decoding_service_create_session(key);
> }
>
> ~Private()
> {
> }
>
> - static void on_frame_available_cb(UNUSED GLConsumerWrapperHybris wrapper, void *context)
> - {
> - if (context != nullptr) {
> - Private *p = static_cast<Private*>(context);
> - p->on_frame_available();
> - }
> - else
> - std::cerr << "context is nullptr, can't call on_frame_available()" << std::endl;
> - }
> -
> - void on_frame_available()
> - {
> - if (frame_available_cb != nullptr) {
> - frame_available_cb(frame_available_context);
> - }
> - else
> - std::cerr << "frame_available_cb is nullptr, can't call frame_available_cb()" << std::endl;
> - }
> -
> - void set_frame_available_cb(FrameAvailableCb cb, void *context)
> - {
> - frame_available_cb = cb;
> - frame_available_context = context;
> -
> - gl_consumer_set_frame_available_cb(glc_wrapper, &Private::on_frame_available_cb, static_cast<void*>(this));
> - }
> -
> - /** We need a GLConsumerHybris instance for doing texture streaming over the
> - * process boundary **/
> - void get_gl_consumer()
> - {
> - igbc_wrapper = decoding_service_get_igraphicbufferconsumer();
> - glc_wrapper = gl_consumer_create_by_id_with_igbc(texture_id, igbc_wrapper);
> -
> - }
> -
> std::shared_ptr<Service> parent;
> std::shared_ptr<TrackList> track_list;
>
> - uint32_t texture_id;
> - IGBCWrapperHybris igbc_wrapper;
> - GLConsumerWrapperHybris glc_wrapper;
> -
> DSSessionWrapperHybris decoding_session;
>
> - FrameAvailableCb frame_available_cb;
> - void *frame_available_context;
> -
> dbus::Object::Ptr object;
> -
> + media::Player::PlayerKey key;
> struct
> {
> std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;
> @@ -181,9 +133,7 @@
> const std::shared_ptr<DBusEndOfStreamSignal>& eos,
> const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status,
> const std::shared_ptr<DBusVideoDimensionChangedSignal>& d)
> - : playback_complete_cb(nullptr),
> - playback_complete_context(nullptr),
> - seeked_to(),
> + : seeked_to(),
> end_of_stream(),
> playback_status_changed(),
> video_dimension_changed(),
> @@ -204,8 +154,6 @@
> dbus.end_of_stream->connect([this]()
> {
> std::cout << "EndOfStream signal arrived via the bus." << std::endl;
> - if (playback_complete_cb)
> - playback_complete_cb(playback_complete_context);
> end_of_stream();
> });
>
> @@ -220,16 +168,8 @@
> std::cout << "VideoDimensionChanged signal arrived via the bus." << std::endl;
> video_dimension_changed(mask);
> });
> - }
> -
> - void set_playback_complete_cb(PlaybackCompleteCb cb, void *context)
> - {
> - playback_complete_cb = cb;
> - playback_complete_context = context;
> }
>
> - PlaybackCompleteCb playback_complete_cb;
> - void *playback_complete_context;
> core::Signal<int64_t> seeked_to;
> core::Signal<void> end_of_stream;
> core::Signal<media::Player::PlaybackStatus> playback_status_changed;
> @@ -269,9 +209,7 @@
>
> media::Player::PlayerKey media::PlayerStub::key() const
> {
> - auto op = d->object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>();
> -
> - return op.value();
> + return d->key;
> }
>
> bool media::PlayerStub::open_uri(const media::Track::UriType& uri)
> @@ -281,19 +219,19 @@
> return op.value();
> }
>
> -void media::PlayerStub::create_video_sink(uint32_t texture_id)
> +media::video::Sink::Ptr media::PlayerStub::create_gl_texture_video_sink(std::uint32_t texture_id)
> {
> auto op = d->object->invoke_method_synchronously<mpris::Player::CreateVideoSink, void>(texture_id);
> - d->texture_id = texture_id;
> - d->get_gl_consumer();
>
> if (op.is_error())
> - throw std::runtime_error("Problem creating new video sink instance on remote object");
> -}
> + {
> + if (op.error().name() == mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name)
> + throw media::Player::Error::OutOfProcessBufferStreamingNotSupported{};
> + else
> + throw std::runtime_error{op.error().print()};
> + }
>
> -GLConsumerWrapperHybris media::PlayerStub::gl_consumer() const
> -{
> - return d->glc_wrapper;
> + return media::video::make_platform_default_sink(texture_id, d->key);
> }
>
> void media::PlayerStub::next()
> @@ -344,16 +282,6 @@
> throw std::runtime_error("Problem stopping playback on remote object");
> }
>
> -void media::PlayerStub::set_frame_available_callback(FrameAvailableCb cb, void *context)
> -{
> - d->set_frame_available_cb(cb, context);
> -}
> -
> -void media::PlayerStub::set_playback_complete_callback(PlaybackCompleteCb cb, void *context)
> -{
> - d->signals.set_playback_complete_cb(cb, context);
> -}
> -
> const core::Property<bool>& media::PlayerStub::can_play() const
> {
> return *d->properties.can_play;
>
> === modified file 'src/core/media/player_stub.h'
> --- src/core/media/player_stub.h 2014-10-22 20:08:22 +0000
> +++ src/core/media/player_stub.h 2014-11-26 12:39:46 +0000
> @@ -46,9 +46,9 @@
> virtual std::shared_ptr<TrackList> track_list();
> virtual PlayerKey key() const;
>
> - virtual bool open_uri(const Track::UriType& uri);
> - virtual void create_video_sink(uint32_t texture_id);
> - virtual GLConsumerWrapperHybris gl_consumer() const;
> + virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id);
> +
> + virtual bool open_uri(const Track::UriType& uri);
> virtual void next();
> virtual void previous();
> virtual void play();
> @@ -56,9 +56,6 @@
> virtual void seek_to(const std::chrono::microseconds& offset);
> virtual void stop();
>
> - virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
> - virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
> -
> virtual const core::Property<bool>& can_play() const;
> virtual const core::Property<bool>& can_pause() const;
> virtual const core::Property<bool>& can_seek() const;
>
> === added directory 'src/core/media/video'
> === added file 'src/core/media/video/hybris_gl_sink.cpp'
> --- src/core/media/video/hybris_gl_sink.cpp 1970-01-01 00:00:00 +0000
> +++ src/core/media/video/hybris_gl_sink.cpp 2014-11-26 12:39:46 +0000
> @@ -0,0 +1,105 @@
> +/*
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * 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 Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <core/media/video/hybris_gl_sink.h>
> +
> +#if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
> +// Hybris
> +#include <hybris/media/media_codec_layer.h>
> +#include <hybris/media/surface_texture_client_hybris.h>
> +
> +namespace media = core::ubuntu::media;
> +namespace video = core::ubuntu::media::video;
> +
> +struct video::HybrisGlSink::Private
> +{
> + static void on_frame_available_callback(GLConsumerWrapperHybris, void* context)
> + {
> + if (not context)
> + return;
> +
> + auto thiz = static_cast<Private*>(context);
> +
> + thiz->frame_available();
> + }
> +
> + Private(std::uint32_t gl_texture, const media::Player::PlayerKey& player_key)
> + : gl_texture{gl_texture},
> + player_key{player_key},
> + decoding_service_session{decoding_service_create_session(player_key)},
> + graphics_buffer_consumer{decoding_service_get_igraphicbufferconsumer()},
> + gl_texture_consumer{gl_consumer_create_by_id_with_igbc(gl_texture, graphics_buffer_consumer)}
> + {
> + if (not decoding_service_session) throw std::runtime_error
> + {
> + "video::HybrisGlSink: Could not connect to the remote decoding service and establish a session."
> + };
> +
> + if (not graphics_buffer_consumer) throw std::runtime_error
> + {
> + "video::HybrisGlSink: Could not connect to remote buffer queue."
> + };
> +
> + if (not gl_texture_consumer) throw std::runtime_error
> + {
> + "video::HybrisGlSink: Could not associate local texture id with remote buffer streak."
> + };
> +
> + gl_consumer_set_frame_available_cb(gl_texture_consumer, Private::on_frame_available_callback, this);
> + }
> +
> + ~Private()
> + {
> + gl_consumer_set_frame_available_cb(gl_texture_consumer, Private::on_frame_available_callback, nullptr);
> + }
> +
> + std::uint32_t gl_texture;
> + media::Player::PlayerKey player_key;
> + core::Signal<void> frame_available;
> + DSSessionWrapperHybris decoding_service_session;
> + IGBCWrapperHybris graphics_buffer_consumer;
> + GLConsumerWrapperHybris gl_texture_consumer;
> +};
> +
> +video::HybrisGlSink::HybrisGlSink(std::uint32_t gl_texture, const media::Player::PlayerKey& key) : d{new Private{gl_texture, key}}
> +{
> +}
> +
> +video::HybrisGlSink::~HybrisGlSink()
> +{
> +}
> +
> +const core::Signal<void>& video::HybrisGlSink::frame_available() const
> +{
> + return d->frame_available;
> +}
> +
> +bool video::HybrisGlSink::transformation_matrix(float* matrix) const
> +{
> + // TODO: The underlying API really should tell us if everything is ok.
> + gl_consumer_get_transformation_matrix(d->gl_texture_consumer, matrix.to_float());
> + return true;
> +}
> +
> +bool video::HybrisGlSink::swap_buffers() const
> +{
> + // TODO: The underlying API really should tell us if everything is ok.
> + gl_consumer_update_texture(d->gl_texture_consumer);
> + return true;
> +}
> +#endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
>
> === added file 'src/core/media/video/hybris_gl_sink.h'
> --- src/core/media/video/hybris_gl_sink.h 1970-01-01 00:00:00 +0000
> +++ src/core/media/video/hybris_gl_sink.h 2014-11-26 12:39:46 +0000
> @@ -0,0 +1,67 @@
> +/*
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * 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 Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
> +#define CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
> +
> +#include <core/media/video/sink.h>
> +
> +#include <core/media/player.h>
> +
> +namespace core
> +{
> +namespace ubuntu
> +{
> +namespace media
> +{
> +namespace video
> +{
> +class HybrisGlSink : public video::Sink
> +{
> +public:
> + // Creates a new instance for the given gl texture, connecting to the remote part known
> + // under the given key or throw in case of issues.
> + HybrisGlSink(std::uint32_t gl_texture, const media::Player::PlayerKey& key);
> +
> + // Need this to avoid std::unique_ptr complaining about forward-declared Private.
> + ~HybrisGlSink();
> +
> + // The signal is emitted whenever a new frame is available and a subsequent
> + // call to swap_buffers will not block and return true.
> + const core::Signal<void>& frame_available() const override;
> +
> + // Queries the transformation matrix for the current frame, placing the data into 'matrix'
> + // and returns true or returns false and leaves 'matrix' unchanged in case
> + // of issues.
> + bool transformation_matrix(float* matrix) const override;
> +
> + // Releases the current buffer, and consumes the next buffer in the queue,
> + // making it available for consumption by consumers of this API in an
> + // implementation-specific way. Clients will usually rely on a GL texture
> + // to receive the latest buffer.
> + bool swap_buffers() const override;
> +
> +private:
> + struct Private;
> + std::unique_ptr<Private> d;
> +};
> +}
> +}
> +}
> +}
> +
> +#endif // CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
>
> === added file 'src/core/media/video/platform_default_sink.cpp'
> --- src/core/media/video/platform_default_sink.cpp 1970-01-01 00:00:00 +0000
> +++ src/core/media/video/platform_default_sink.cpp 2014-11-26 12:39:46 +0000
> @@ -0,0 +1,68 @@
> +/*
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * 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 Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +
> +#include <core/media/video/platform_default_sink.h>
> +
> +namespace media = core::ubuntu::media;
> +namespace video = core::ubuntu::media::video;
> +
> +namespace
> +{
> +struct NullSink : public video::Sink
> +{
> + // The signal is emitted whenever a new frame is available and a subsequent
> + // call to swap_buffers will not block and return true.
> + const core::Signal<void>& frame_available() const
> + {
> + return signal_frame_available;
> + }
> +
> + // Queries the transformation matrix for the current frame, placing the data into 'matrix'
> + // and returns true or returns false and leaves 'matrix' unchanged in case
> + // of issues.
> + bool transformation_matrix(float*) const
> + {
> + return true;
> + }
> +
> + // Releases the current buffer, and consumes the next buffer in the queue,
> + // making it available for consumption by consumers of this API in an
> + // implementation-specific way. Clients will usually rely on a GL texture
> + // to receive the latest buffer.
> + bool swap_buffers() const
> + {
> + return true;
> + }
> +
> + core::Signal<void> signal_frame_available;
> +};
> +}
> +
> +#if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
> +#include <core/media/video/hybris_gl_sink.h>
> +
> +video::Sink::Ptr video::make_platform_default_sink(std::uint32_t gl_texture, const media::Player::PlayerKey& key)
> +{
> + return std::make_shared<video::HybrisGlSink>(gl_texture, key);
> +}
> +#else // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
> +video::Sink::Ptr video::make_platform_default_sink(std::uint32_t, const media::Player::PlayerKey&)
> +{
> + return std::make_shared<NullSink>();
> +}
> +#endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
>
> === added file 'src/core/media/video/platform_default_sink.h'
> --- src/core/media/video/platform_default_sink.h 1970-01-01 00:00:00 +0000
> +++ src/core/media/video/platform_default_sink.h 2014-11-26 12:39:46 +0000
> @@ -0,0 +1,41 @@
> +/*
> + * Copyright © 2014 Canonical Ltd.
> + *
> + * This program is free software: you can redistribute it and/or modify it
> + * under the terms of the GNU Lesser General Public License version 3,
> + * as published by the Free Software Foundation.
> + *
> + * 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 Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + *
> + * Authored by: Thomas Voß <thomas.voss at canonical.com>
> + */
> +#ifndef CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_
> +#define CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_
> +
> +#include <core/media/video/sink.h>
> +
> +#include <core/media/player.h>
> +
> +namespace core
> +{
> +namespace ubuntu
> +{
> +namespace media
> +{
> +namespace video
> +{
> +// Returns the platform default video sink for the given parameters. Never returns null, but
> +// throws in case of issues.
> +Sink::Ptr make_platform_default_sink(std::uint32_t gl_texture, const Player::PlayerKey& key);
> +}
> +}
> +}
> +}
> +
> +#endif // CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_
>
--
https://code.launchpad.net/~thomas-voss/media-hub/introduce-video-sink-interface/+merge/242872
Your team Ubuntu Phablet Team is subscribed to branch lp:media-hub.
More information about the Ubuntu-reviews
mailing list