[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