Merge lp:~thomas-voss/media-hub/introduce-video-sink-interface into lp:media-hub

Proposed by Thomas Voß
Status: Merged
Approved by: Ricardo Mendoza
Approved revision: 109
Merged at revision: 114
Proposed branch: lp:~thomas-voss/media-hub/introduce-video-sink-interface
Merge into: lp:media-hub
Diff against target: 970 lines (+480/-142)
19 files modified
CMakeLists.txt (+3/-1)
debian/changelog (+6/-0)
debian/control (+4/-4)
debian/libmedia-hub-common3.symbols (+1/-1)
include/core/media/player.h (+12/-10)
include/core/media/video/sink.h (+76/-0)
src/core/media/CMakeLists.txt (+10/-1)
src/core/media/engine.h (+3/-1)
src/core/media/mpris/player.h (+11/-0)
src/core/media/player.cpp (+5/-0)
src/core/media/player_implementation.cpp (+6/-23)
src/core/media/player_implementation.h (+2/-4)
src/core/media/player_skeleton.cpp (+23/-3)
src/core/media/player_stub.cpp (+16/-89)
src/core/media/player_stub.h (+2/-5)
src/core/media/video/hybris_gl_sink.cpp (+116/-0)
src/core/media/video/hybris_gl_sink.h (+72/-0)
src/core/media/video/platform_default_sink.cpp (+68/-0)
src/core/media/video/platform_default_sink.h (+44/-0)
To merge this branch: bzr merge lp:~thomas-voss/media-hub/introduce-video-sink-interface
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Jim Hodapp (community) code Approve
Review via email: mp+242872@code.launchpad.net

Commit message

Refactor client-facing interfaces to pull out explicit dependency on hybris-based media layer.
Introduce interface media::video::Sink, and expose it in interfaces
Adjust implementation to account for interface changes.
Introduce an implementation of media::video::Sink relying on Hybris.

Description of the change

Refactor client-facing interfaces to pull out explicit dependency on hybris-based media layer.
Introduce interface media::video::Sink, and expose it in interfaces
Adjust implementation to account for interface changes.
Introduce an implementation of media::video::Sink relying on Hybris.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
100. By Thomas Voß

Adjust debian/*.install and debian/*.symbols to account for major version bump.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote :

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.

review: Needs Fixing (code)
Revision history for this message
Thomas Voß (thomas-voss) wrote :

> Looks good, just 1 inline comment below. Also, make sure to rebase with trunk
> changes.

They should be up to date, and the train takes care of remerging with trunk.

> 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.

Well, I wonder if we could at least group together the introduce-MRs into one silo and collectively test them to avoid retesting the same thing over and over again.

101. By Thomas Voß

Adjust comment according to review.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
102. By Thomas Voß

[ Jim Hodapp ]
* Resubmitting with prerequisite branch (LP: #1331041)
[ Justin McPherson ]
* Resubmitting with prerequisite branch (LP: #1331041)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
103. By Thomas Voß

Adjust major version in CMake setup.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote :

Looks good

review: Approve (code)
104. By Thomas Voß

Default to Hybris based implemenations.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
105. By Thomas Voß

[ Jim Hodapp ]
* Error reporting all the way up to the app level from the playbin
  pipeline.
[ Ubuntu daily release ]
* New rebuild forced
[ Jim Hodapp ]
* Don't auto-resume playback of videos after a phone call ends. (LP:
  #1411273)
[ Ubuntu daily release ]
* New rebuild forced
[ Ricardo Salveti de Araujo ]
* service_implementation: adding debug for call started/ended signals.
  Make sure account and connection are available when setting up
  account manager (patch from Gustavo Boiko). call_monitor: don't
  check caps when hooking up on/off signals, until bug 1409125 is
  fixed. Enable parallel building . (LP: #1409125)
[ Jim Hodapp ]
* Pause playback when recording begins. (LP: #1398047)
[ Ricardo Salveti de Araujo ]
* call_monitor.cpp: waiting for bridge to be up, and also protecting
  the on_change call (LP: #1408137)

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
106. By Thomas Voß

Fix FTBFS.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
107. By Thomas Voß

Funnel creation of video::Sink instances via a factory to allow for early initialization
tasks that should/have to be carried out as soon as the player's identity on the service
side is established and the respective key is known.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
108. By Thomas Voß

* debian/control:
  - Removing pre-depends that are not required
  - Bumping standards-version to 3.9.6
[ Ricardo Salveti de Araujo ]
* Migrating tests to use ogg instead of mp3/avi removed:
  tests/h264.avi tests/test.mp3 added: tests/test-audio-1.ogg
  tests/test-video.ogg tests/test.mp3 renamed: tests/test.ogg =>
  tests/test-audio.ogg

109. By Thomas Voß

Remove Pre-Depends as trunk suggests.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-11-13 23:50:01 +0000
3+++ CMakeLists.txt 2015-03-12 11:38:55 +0000
4@@ -2,7 +2,7 @@
5
6 project(ubuntu-media-hub)
7
8-set(UBUNTU_MEDIA_HUB_VERSION_MAJOR 2)
9+set(UBUNTU_MEDIA_HUB_VERSION_MAJOR 3)
10 set(UBUNTU_MEDIA_HUB_VERSION_MINOR 0)
11 set(UBUNTU_MEDIA_HUB_VERSION_PATCH 0)
12
13@@ -30,6 +30,8 @@
14 pkg_check_modules(GIO gio-2.0 REQUIRED)
15 pkg_check_modules(HYBRIS_MEDIA libmedia REQUIRED)
16
17+add_definitions(-DMEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
18+
19 #####################################################################
20 # Enable code coverage calculation with gcov/gcovr/lcov
21 # Usage:
22
23=== modified file 'debian/changelog'
24--- debian/changelog 2015-03-12 03:06:40 +0000
25+++ debian/changelog 2015-03-12 11:38:55 +0000
26@@ -1,3 +1,9 @@
27+media-hub (3.0.0) UNRELEASED; urgency=medium
28+
29+ * Refactor client-facing interfaces to pull out explicit dependency on hybris-based media layer.
30+
31+ -- Thomas Voss <thomas.voss@canonical.com> Tue, 11 Nov 2014 17:15:52 +0100
32+
33 media-hub (2.0.0+15.04.20150303-0ubuntu2) vivid; urgency=medium
34
35 * debian/control:
36
37=== modified file 'debian/control'
38--- debian/control 2015-03-12 03:06:29 +0000
39+++ debian/control 2015-03-12 11:38:55 +0000
40@@ -39,8 +39,8 @@
41 Section: libdevel
42 Architecture: any
43 Multi-Arch: same
44-Depends: libmedia-hub-common2 (= ${binary:Version}),
45- libmedia-hub-client2 (= ${binary:Version}),
46+Depends: libmedia-hub-common3 (= ${binary:Version}),
47+ libmedia-hub-client3 (= ${binary:Version}),
48 ${misc:Depends},
49 libproperties-cpp-dev,
50 Suggests: libmedia-hub-doc
51@@ -61,7 +61,7 @@
52 .
53 This package contains the runtime.
54
55-Package: libmedia-hub-common2
56+Package: libmedia-hub-common3
57 Architecture: any
58 Multi-Arch: same
59 Depends: ${misc:Depends},
60@@ -72,7 +72,7 @@
61 .
62 This package contains the common libraries.
63
64-Package: libmedia-hub-client2
65+Package: libmedia-hub-client3
66 Architecture: any
67 Multi-Arch: same
68 Depends: ${misc:Depends},
69
70=== renamed file 'debian/libmedia-hub-client2.install' => 'debian/libmedia-hub-client3.install'
71=== renamed file 'debian/libmedia-hub-common2.install' => 'debian/libmedia-hub-common3.install'
72=== renamed file 'debian/libmedia-hub-common2.symbols' => 'debian/libmedia-hub-common3.symbols'
73--- debian/libmedia-hub-common2.symbols 2014-09-10 21:11:00 +0000
74+++ debian/libmedia-hub-common3.symbols 2015-03-12 11:38:55 +0000
75@@ -1,2 +1,2 @@
76-libmedia-hub-common.so.2 libmedia-hub-common2 #MINVER#
77+libmedia-hub-common.so.3 libmedia-hub-common3 #MINVER#
78 (c++)"core::ubuntu::media::the_session_bus()@Base" 2.0.0+14.10.20140910.2
79
80=== modified file 'include/core/media/player.h'
81--- include/core/media/player.h 2015-01-19 21:48:01 +0000
82+++ include/core/media/player.h 2015-03-12 11:38:55 +0000
83@@ -20,6 +20,7 @@
84 #define CORE_UBUNTU_MEDIA_PLAYER_H_
85
86 #include <core/media/track.h>
87+#include <core/media/video/sink.h>
88
89 #include <core/property.h>
90
91@@ -44,10 +45,15 @@
92 typedef void* GLConsumerWrapperHybris;
93 typedef std::map<std::string, std::string> HeadersType;
94
95- /** Used to set a callback function to be called when a frame is ready to be rendered **/
96- typedef void (*FrameAvailableCbHybris)(GLConsumerWrapperHybris wrapper, void *context);
97- typedef void (*FrameAvailableCb)(void *context);
98- typedef void (*PlaybackCompleteCb)(void *context);
99+ struct Errors
100+ {
101+ Errors() = delete;
102+
103+ struct OutOfProcessBufferStreamingNotSupported : public std::runtime_error
104+ {
105+ OutOfProcessBufferStreamingNotSupported();
106+ };
107+ };
108
109 struct Configuration;
110
111@@ -120,10 +126,10 @@
112 virtual std::shared_ptr<TrackList> track_list() = 0;
113 virtual PlayerKey key() const = 0;
114
115+ virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id) = 0;
116+
117 virtual bool open_uri(const Track::UriType& uri) = 0;
118 virtual bool open_uri(const Track::UriType& uri, const HeadersType&) = 0;
119- virtual void create_video_sink(uint32_t texture_id) = 0;
120- virtual GLConsumerWrapperHybris gl_consumer() const = 0;
121 virtual void next() = 0;
122 virtual void previous() = 0;
123 virtual void play() = 0;
124@@ -131,10 +137,6 @@
125 virtual void stop() = 0;
126 virtual void seek_to(const std::chrono::microseconds& offset) = 0;
127
128- // TODO: Convert this to be a signal
129- virtual void set_frame_available_callback(FrameAvailableCb cb, void *context) = 0;
130- virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context) = 0;
131-
132 virtual const core::Property<bool>& can_play() const = 0;
133 virtual const core::Property<bool>& can_pause() const = 0;
134 virtual const core::Property<bool>& can_seek() const = 0;
135
136=== added directory 'include/core/media/video'
137=== added file 'include/core/media/video/sink.h'
138--- include/core/media/video/sink.h 1970-01-01 00:00:00 +0000
139+++ include/core/media/video/sink.h 2015-03-12 11:38:55 +0000
140@@ -0,0 +1,76 @@
141+/*
142+ * Copyright © 2014 Canonical Ltd.
143+ *
144+ * This program is free software: you can redistribute it and/or modify it
145+ * under the terms of the GNU Lesser General Public License version 3,
146+ * as published by the Free Software Foundation.
147+ *
148+ * This program is distributed in the hope that it will be useful,
149+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
150+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151+ * GNU Lesser General Public License for more details.
152+ *
153+ * You should have received a copy of the GNU Lesser General Public License
154+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
155+ *
156+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
157+ */
158+#ifndef CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
159+#define CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
160+
161+#include <core/signal.h>
162+
163+#include <memory>
164+
165+namespace core
166+{
167+namespace ubuntu
168+{
169+namespace media
170+{
171+namespace video
172+{
173+/** @brief A video sink abstracts a queue of buffers, that receives
174+ * a stream of decoded video buffers from an arbitrary source.
175+ */
176+struct Sink
177+{
178+ /** @brief To save us some typing. */
179+ typedef std::shared_ptr<Sink> Ptr;
180+
181+ /** @cond */
182+ Sink() = default;
183+ Sink(const Sink&) = delete;
184+ virtual ~Sink() = default;
185+
186+ Sink& operator=(const Sink&) = delete;
187+ /** @endcond */
188+
189+ /**
190+ * @brief The signal is emitted whenever a new frame is available and a subsequent
191+ * call to swap_buffers will not block and return true.
192+ */
193+ virtual const core::Signal<void>& frame_available() const = 0;
194+
195+ /**
196+ * @brief Queries the 4x4 transformation matrix for the current frame, placing the data into 'matrix'.
197+ * @param matrix [out] The destination array representing the matrix in column-major format.
198+ * We expect at least 4*4 float elements in the array.
199+ * @returns true iff the data has been set. Returns false and leaves 'matrix' unchanged in case of issues.
200+ */
201+ virtual bool transformation_matrix(float* matrix) const = 0;
202+
203+ /**
204+ * @brief Releases the current buffer, and consumes the next buffer in the queue,
205+ * making it available for consumption by consumers of this API in an
206+ * implementation-specific way. Clients will usually rely on a GL texture
207+ * to receive the latest buffer.
208+ */
209+ virtual bool swap_buffers() const = 0;
210+};
211+}
212+}
213+}
214+}
215+
216+#endif // CORE_UBUNTU_MEDIA_VIDEO_SINK_H_
217
218=== modified file 'src/core/media/CMakeLists.txt'
219--- src/core/media/CMakeLists.txt 2014-11-12 19:10:24 +0000
220+++ src/core/media/CMakeLists.txt 2015-03-12 11:38:55 +0000
221@@ -6,7 +6,10 @@
222 # out all symbols that are not in core::ubuntu::media*
223 set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")
224
225-file(GLOB MPRIS_HEADERS mpris/ *.h)
226+file(GLOB_RECURSE MEDIA_HUB_HEADERS ${CMAKE_SOURCE_DIR}/include/*.h)
227+file(GLOB MPRIS_HEADERS mpris/*.h)
228+
229+message(STATUS ${MEDIA_HUB_HEADERS})
230
231 add_subdirectory(call-monitor)
232
233@@ -36,6 +39,8 @@
234 add_library(
235 media-hub-client SHARED
236
237+ ${MEDIA_HUB_HEADERS}
238+
239 player.cpp
240 service.cpp
241 track.cpp
242@@ -44,6 +49,9 @@
243 player_stub.cpp
244 service_stub.cpp
245 track_list_stub.cpp
246+
247+ video/hybris_gl_sink.cpp
248+ video/platform_default_sink.cpp
249 )
250
251 set_target_properties(
252@@ -75,6 +83,7 @@
253 add_library(
254 media-hub-service
255
256+ ${MEDIA_HUB_HEADERS}
257 ${MPRIS_HEADERS}
258
259 cover_art_resolver.cpp
260
261=== modified file 'src/core/media/engine.h'
262--- src/core/media/engine.h 2015-01-13 14:18:59 +0000
263+++ src/core/media/engine.h 2015-03-12 11:38:55 +0000
264@@ -75,8 +75,10 @@
265
266 virtual const core::Property<State>& state() const = 0;
267
268- virtual bool open_resource_for_uri(const Track::UriType& uri) = 0;
269+ virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri) = 0;
270 virtual bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri, const Player::HeadersType&) = 0;
271+ // Throws core::ubuntu::media::Player::Error::OutOfProcessBufferStreamingNotSupported if the implementation does not
272+ // support this feature.
273 virtual void create_video_sink(uint32_t texture_id) = 0;
274
275 virtual bool play() = 0;
276
277=== modified file 'src/core/media/mpris/player.h'
278--- src/core/media/mpris/player.h 2015-01-13 14:18:59 +0000
279+++ src/core/media/mpris/player.h 2015-03-12 11:38:55 +0000
280@@ -103,6 +103,17 @@
281 static constexpr const char* stopped{"Stopped"};
282 };
283
284+ struct Error
285+ {
286+ struct OutOfProcessBufferStreamingNotSupported
287+ {
288+ static constexpr const char* name
289+ {
290+ "mpris.Player.Error.OutOfProcessBufferStreamingNotSupported"
291+ };
292+ };
293+ };
294+
295 typedef std::map<std::string, core::dbus::types::Variant> Dictionary;
296
297 DBUS_CPP_METHOD_DEF(Next, Player)
298
299=== modified file 'src/core/media/player.cpp'
300--- src/core/media/player.cpp 2014-09-09 10:28:32 +0000
301+++ src/core/media/player.cpp 2015-03-12 11:38:55 +0000
302@@ -22,6 +22,11 @@
303
304 namespace media = core::ubuntu::media;
305
306+media::Player::Errors::OutOfProcessBufferStreamingNotSupported::OutOfProcessBufferStreamingNotSupported()
307+ : std::runtime_error{"Implementation does not support out-of-process buffer streaming"}
308+{
309+}
310+
311 const media::Player::Configuration& media::Player::Client::default_configuration()
312 {
313 static const media::Player::Configuration config
314
315=== modified file 'src/core/media/player_implementation.cpp'
316--- src/core/media/player_implementation.cpp 2015-01-13 14:18:59 +0000
317+++ src/core/media/player_implementation.cpp 2015-03-12 11:38:55 +0000
318@@ -470,6 +470,12 @@
319 return d->key;
320 }
321
322+media::video::Sink::Ptr media::PlayerImplementation::create_gl_texture_video_sink(std::uint32_t texture_id)
323+{
324+ d->engine->create_video_sink(texture_id);
325+ return media::video::Sink::Ptr{};
326+}
327+
328 bool media::PlayerImplementation::open_uri(const Track::UriType& uri)
329 {
330 return d->engine->open_resource_for_uri(uri);
331@@ -480,17 +486,6 @@
332 return d->engine->open_resource_for_uri(uri, headers);
333 }
334
335-void media::PlayerImplementation::create_video_sink(uint32_t texture_id)
336-{
337- d->engine->create_video_sink(texture_id);
338-}
339-
340-media::Player::GLConsumerWrapperHybris media::PlayerImplementation::gl_consumer() const
341-{
342- // This method is client-side only and is simply a no-op for the service side
343- return NULL;
344-}
345-
346 void media::PlayerImplementation::next()
347 {
348 }
349@@ -515,18 +510,6 @@
350 d->engine->stop();
351 }
352
353-void media::PlayerImplementation::set_frame_available_callback(
354- UNUSED FrameAvailableCb cb, UNUSED void *context)
355-{
356- // This method is client-side only and is simply a no-op for the service side
357-}
358-
359-void media::PlayerImplementation::set_playback_complete_callback(
360- UNUSED PlaybackCompleteCb cb, UNUSED void *context)
361-{
362- // This method is client-side only and is simply a no-op for the service side
363-}
364-
365 void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)
366 {
367 d->engine->seek_to(ms);
368
369=== modified file 'src/core/media/player_implementation.h'
370--- src/core/media/player_implementation.h 2015-01-13 14:18:59 +0000
371+++ src/core/media/player_implementation.h 2015-03-12 11:38:55 +0000
372@@ -46,17 +46,15 @@
373 virtual std::shared_ptr<TrackList> track_list();
374 virtual PlayerKey key() const;
375
376+ virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id);
377+
378 virtual bool open_uri(const Track::UriType& uri);
379 virtual bool open_uri(const Track::UriType& uri, const Player::HeadersType& headers);
380- virtual void create_video_sink(uint32_t texture_id);
381- virtual GLConsumerWrapperHybris gl_consumer() const;
382 virtual void next();
383 virtual void previous();
384 virtual void play();
385 virtual void pause();
386 virtual void stop();
387- virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
388- virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
389 virtual void seek_to(const std::chrono::microseconds& offset);
390
391 const core::Signal<>& on_client_disconnected() const;
392
393=== modified file 'src/core/media/player_skeleton.cpp'
394--- src/core/media/player_skeleton.cpp 2015-01-13 14:18:59 +0000
395+++ src/core/media/player_skeleton.cpp 2015-03-12 11:38:55 +0000
396@@ -136,9 +136,29 @@
397 {
398 uint32_t texture_id;
399 in->reader() >> texture_id;
400- impl->create_video_sink(texture_id);
401-
402- auto reply = dbus::Message::make_method_return(in);
403+
404+ core::dbus::Message::Ptr reply;
405+
406+ try
407+ {
408+ impl->create_gl_texture_video_sink(texture_id);
409+ reply = dbus::Message::make_method_return(in);
410+ }
411+ catch (const media::Player::Errors::OutOfProcessBufferStreamingNotSupported& e)
412+ {
413+ reply = dbus::Message::make_error(
414+ in,
415+ mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name,
416+ e.what());
417+ }
418+ catch (...)
419+ {
420+ reply = dbus::Message::make_error(
421+ in,
422+ mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name,
423+ std::string{});
424+ }
425+
426 bus->send(reply);
427 }
428
429
430=== modified file 'src/core/media/player_stub.cpp'
431--- src/core/media/player_stub.cpp 2015-01-19 18:38:29 +0000
432+++ src/core/media/player_stub.cpp 2015-03-12 11:38:55 +0000
433@@ -19,6 +19,7 @@
434
435 #include <core/media/service.h>
436 #include <core/media/track_list.h>
437+#include <core/media/video/platform_default_sink.h>
438
439 #include "codec.h"
440 #include "player_stub.h"
441@@ -48,13 +49,9 @@
442 Private(const std::shared_ptr<Service>& parent,
443 const std::shared_ptr<core::dbus::Object>& object
444 ) : parent(parent),
445- texture_id(0),
446- igbc_wrapper(nullptr),
447- glc_wrapper(nullptr),
448- decoding_session(nullptr),
449- frame_available_cb(nullptr),
450- frame_available_context(nullptr),
451 object(object),
452+ key(object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>().value()),
453+ sink_factory(media::video::make_platform_default_sink_factory(key)),
454 properties
455 {
456 // Link the properties from the server side to the client side over the bus
457@@ -89,64 +86,17 @@
458 object->get_signal<mpris::Player::Signals::Error>()
459 }
460 {
461- auto op = object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>();
462- decoding_session = decoding_service_create_session(op.value());
463 }
464
465 ~Private()
466 {
467 }
468
469- static void on_frame_available_cb(UNUSED GLConsumerWrapperHybris wrapper, void *context)
470- {
471- if (context != nullptr) {
472- Private *p = static_cast<Private*>(context);
473- p->on_frame_available();
474- }
475- else
476- std::cerr << "context is nullptr, can't call on_frame_available()" << std::endl;
477- }
478-
479- void on_frame_available()
480- {
481- if (frame_available_cb != nullptr) {
482- frame_available_cb(frame_available_context);
483- }
484- else
485- std::cerr << "frame_available_cb is nullptr, can't call frame_available_cb()" << std::endl;
486- }
487-
488- void set_frame_available_cb(FrameAvailableCb cb, void *context)
489- {
490- frame_available_cb = cb;
491- frame_available_context = context;
492-
493- gl_consumer_set_frame_available_cb(glc_wrapper, &Private::on_frame_available_cb, static_cast<void*>(this));
494- }
495-
496- /** We need a GLConsumerHybris instance for doing texture streaming over the
497- * process boundary **/
498- void get_gl_consumer()
499- {
500- igbc_wrapper = decoding_service_get_igraphicbufferconsumer();
501- glc_wrapper = gl_consumer_create_by_id_with_igbc(texture_id, igbc_wrapper);
502-
503- }
504-
505 std::shared_ptr<Service> parent;
506 std::shared_ptr<TrackList> track_list;
507-
508- uint32_t texture_id;
509- IGBCWrapperHybris igbc_wrapper;
510- GLConsumerWrapperHybris glc_wrapper;
511-
512- DSSessionWrapperHybris decoding_session;
513-
514- FrameAvailableCb frame_available_cb;
515- void *frame_available_context;
516-
517 dbus::Object::Ptr object;
518-
519+ media::Player::PlayerKey key;
520+ media::video::SinkFactory sink_factory;
521 struct
522 {
523 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;
524@@ -186,9 +136,7 @@
525 const std::shared_ptr<DBusPlaybackStatusChangedSignal>& status,
526 const std::shared_ptr<DBusVideoDimensionChangedSignal>& d,
527 const std::shared_ptr<DBusErrorSignal>& e)
528- : playback_complete_cb(nullptr),
529- playback_complete_context(nullptr),
530- seeked_to(),
531+ : seeked_to(),
532 end_of_stream(),
533 playback_status_changed(),
534 video_dimension_changed(),
535@@ -211,8 +159,6 @@
536 dbus.end_of_stream->connect([this]()
537 {
538 std::cout << "EndOfStream signal arrived via the bus." << std::endl;
539- if (playback_complete_cb)
540- playback_complete_cb(playback_complete_context);
541 end_of_stream();
542 });
543
544@@ -235,14 +181,6 @@
545 });
546 }
547
548- void set_playback_complete_cb(PlaybackCompleteCb cb, void *context)
549- {
550- playback_complete_cb = cb;
551- playback_complete_context = context;
552- }
553-
554- PlaybackCompleteCb playback_complete_cb;
555- void *playback_complete_context;
556 core::Signal<int64_t> seeked_to;
557 core::Signal<void> end_of_stream;
558 core::Signal<media::Player::PlaybackStatus> playback_status_changed;
559@@ -284,9 +222,7 @@
560
561 media::Player::PlayerKey media::PlayerStub::key() const
562 {
563- auto op = d->object->invoke_method_synchronously<mpris::Player::Key, media::Player::PlayerKey>();
564-
565- return op.value();
566+ return d->key;
567 }
568
569 bool media::PlayerStub::open_uri(const media::Track::UriType& uri)
570@@ -296,6 +232,7 @@
571 return op.value();
572 }
573
574+
575 bool media::PlayerStub::open_uri(const Track::UriType& uri, const Player::HeadersType& headers)
576 {
577 auto op = d->object->invoke_method_synchronously<mpris::Player::OpenUriExtended, bool>(uri, headers);
578@@ -303,19 +240,19 @@
579 return op.value();
580 }
581
582-void media::PlayerStub::create_video_sink(uint32_t texture_id)
583+media::video::Sink::Ptr media::PlayerStub::create_gl_texture_video_sink(std::uint32_t texture_id)
584 {
585 auto op = d->object->invoke_method_synchronously<mpris::Player::CreateVideoSink, void>(texture_id);
586- d->texture_id = texture_id;
587- d->get_gl_consumer();
588
589 if (op.is_error())
590- throw std::runtime_error("Problem creating new video sink instance on remote object");
591-}
592+ {
593+ if (op.error().name() == mpris::Player::Error::OutOfProcessBufferStreamingNotSupported::name)
594+ throw media::Player::Errors::OutOfProcessBufferStreamingNotSupported{};
595+ else
596+ throw std::runtime_error{op.error().print()};
597+ }
598
599-GLConsumerWrapperHybris media::PlayerStub::gl_consumer() const
600-{
601- return d->glc_wrapper;
602+ return d->sink_factory(texture_id);
603 }
604
605 void media::PlayerStub::next()
606@@ -366,16 +303,6 @@
607 throw std::runtime_error("Problem stopping playback on remote object");
608 }
609
610-void media::PlayerStub::set_frame_available_callback(FrameAvailableCb cb, void *context)
611-{
612- d->set_frame_available_cb(cb, context);
613-}
614-
615-void media::PlayerStub::set_playback_complete_callback(PlaybackCompleteCb cb, void *context)
616-{
617- d->signals.set_playback_complete_cb(cb, context);
618-}
619-
620 const core::Property<bool>& media::PlayerStub::can_play() const
621 {
622 return *d->properties.can_play;
623
624=== modified file 'src/core/media/player_stub.h'
625--- src/core/media/player_stub.h 2015-01-13 14:18:59 +0000
626+++ src/core/media/player_stub.h 2015-03-12 11:38:55 +0000
627@@ -46,10 +46,10 @@
628 virtual std::shared_ptr<TrackList> track_list();
629 virtual PlayerKey key() const;
630
631+ virtual video::Sink::Ptr create_gl_texture_video_sink(std::uint32_t texture_id);
632+
633 virtual bool open_uri(const Track::UriType& uri);
634 virtual bool open_uri(const Track::UriType& uri, const Player::HeadersType& headers);
635- virtual void create_video_sink(uint32_t texture_id);
636- virtual GLConsumerWrapperHybris gl_consumer() const;
637 virtual void next();
638 virtual void previous();
639 virtual void play();
640@@ -57,9 +57,6 @@
641 virtual void seek_to(const std::chrono::microseconds& offset);
642 virtual void stop();
643
644- virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
645- virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
646-
647 virtual const core::Property<bool>& can_play() const;
648 virtual const core::Property<bool>& can_pause() const;
649 virtual const core::Property<bool>& can_seek() const;
650
651=== added directory 'src/core/media/video'
652=== added file 'src/core/media/video/hybris_gl_sink.cpp'
653--- src/core/media/video/hybris_gl_sink.cpp 1970-01-01 00:00:00 +0000
654+++ src/core/media/video/hybris_gl_sink.cpp 2015-03-12 11:38:55 +0000
655@@ -0,0 +1,116 @@
656+/*
657+ * Copyright © 2014 Canonical Ltd.
658+ *
659+ * This program is free software: you can redistribute it and/or modify it
660+ * under the terms of the GNU Lesser General Public License version 3,
661+ * as published by the Free Software Foundation.
662+ *
663+ * This program is distributed in the hope that it will be useful,
664+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
665+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
666+ * GNU Lesser General Public License for more details.
667+ *
668+ * You should have received a copy of the GNU Lesser General Public License
669+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
670+ *
671+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
672+ */
673+
674+#include <core/media/video/hybris_gl_sink.h>
675+
676+#if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
677+// Hybris
678+#include <hybris/media/media_codec_layer.h>
679+#include <hybris/media/surface_texture_client_hybris.h>
680+
681+namespace media = core::ubuntu::media;
682+namespace video = core::ubuntu::media::video;
683+
684+struct video::HybrisGlSink::Private
685+{
686+ static void on_frame_available_callback(GLConsumerWrapperHybris, void* context)
687+ {
688+ if (not context)
689+ return;
690+
691+ auto thiz = static_cast<Private*>(context);
692+
693+ thiz->frame_available();
694+ }
695+
696+ Private(std::uint32_t gl_texture)
697+ : gl_texture{gl_texture},
698+ graphics_buffer_consumer{decoding_service_get_igraphicbufferconsumer()},
699+ gl_texture_consumer{gl_consumer_create_by_id_with_igbc(gl_texture, graphics_buffer_consumer)}
700+ {
701+ if (not graphics_buffer_consumer) throw std::runtime_error
702+ {
703+ "video::HybrisGlSink: Could not connect to remote buffer queue."
704+ };
705+
706+ if (not gl_texture_consumer) throw std::runtime_error
707+ {
708+ "video::HybrisGlSink: Could not associate local texture id with remote buffer streak."
709+ };
710+
711+ gl_consumer_set_frame_available_cb(gl_texture_consumer, Private::on_frame_available_callback, this);
712+ }
713+
714+ ~Private()
715+ {
716+ gl_consumer_set_frame_available_cb(gl_texture_consumer, Private::on_frame_available_callback, nullptr);
717+ }
718+
719+ std::uint32_t gl_texture;
720+ core::Signal<void> frame_available;
721+ IGBCWrapperHybris graphics_buffer_consumer;
722+ GLConsumerWrapperHybris gl_texture_consumer;
723+};
724+
725+std::function<video::Sink::Ptr(std::uint32_t)> video::HybrisGlSink::factory_for_key(const media::Player::PlayerKey& key)
726+{
727+ // It's okay-ish to use static map here. Point being that we currently have no way
728+ // of terminating the session with the decoding service anyway.
729+ static std::map<media::Player::PlayerKey, DSSessionWrapperHybris> lut;
730+ static std::mutex lut_guard;
731+
732+ // Scoping access to the lut to ensure that the lock is kept for as short as possible.
733+ {
734+ std::lock_guard<std::mutex> lg{lut_guard};
735+ if (lut.count(key) == 0)
736+ lut[key] = decoding_service_create_session(key);
737+ }
738+
739+ return [](std::uint32_t texture)
740+ {
741+ return video::Sink::Ptr{new video::HybrisGlSink{texture}};
742+ };
743+}
744+
745+video::HybrisGlSink::HybrisGlSink(std::uint32_t gl_texture) : d{new Private{gl_texture}}
746+{
747+}
748+
749+video::HybrisGlSink::~HybrisGlSink()
750+{
751+}
752+
753+const core::Signal<void>& video::HybrisGlSink::frame_available() const
754+{
755+ return d->frame_available;
756+}
757+
758+bool video::HybrisGlSink::transformation_matrix(float* matrix) const
759+{
760+ // TODO: The underlying API really should tell us if everything is ok.
761+ gl_consumer_get_transformation_matrix(d->gl_texture_consumer, matrix);
762+ return true;
763+}
764+
765+bool video::HybrisGlSink::swap_buffers() const
766+{
767+ // TODO: The underlying API really should tell us if everything is ok.
768+ gl_consumer_update_texture(d->gl_texture_consumer);
769+ return true;
770+}
771+#endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
772
773=== added file 'src/core/media/video/hybris_gl_sink.h'
774--- src/core/media/video/hybris_gl_sink.h 1970-01-01 00:00:00 +0000
775+++ src/core/media/video/hybris_gl_sink.h 2015-03-12 11:38:55 +0000
776@@ -0,0 +1,72 @@
777+/*
778+ * Copyright © 2014 Canonical Ltd.
779+ *
780+ * This program is free software: you can redistribute it and/or modify it
781+ * under the terms of the GNU Lesser General Public License version 3,
782+ * as published by the Free Software Foundation.
783+ *
784+ * This program is distributed in the hope that it will be useful,
785+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
786+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
787+ * GNU Lesser General Public License for more details.
788+ *
789+ * You should have received a copy of the GNU Lesser General Public License
790+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
791+ *
792+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
793+ */
794+#ifndef CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
795+#define CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
796+
797+#include <core/media/video/sink.h>
798+
799+#include <core/media/player.h>
800+
801+#include <functional>
802+
803+namespace core
804+{
805+namespace ubuntu
806+{
807+namespace media
808+{
809+namespace video
810+{
811+class HybrisGlSink : public video::Sink
812+{
813+public:
814+ // Returns a factory functor that allows for creating actual sink instances.
815+ static std::function<video::Sink::Ptr(std::uint32_t)> factory_for_key(const media::Player::PlayerKey&);
816+
817+ // Need this to avoid std::unique_ptr complaining about forward-declared Private.
818+ ~HybrisGlSink();
819+
820+ // The signal is emitted whenever a new frame is available and a subsequent
821+ // call to swap_buffers will not block and return true.
822+ const core::Signal<void>& frame_available() const override;
823+
824+ // Queries the transformation matrix for the current frame, placing the data into 'matrix'
825+ // and returns true or returns false and leaves 'matrix' unchanged in case
826+ // of issues.
827+ bool transformation_matrix(float* matrix) const override;
828+
829+ // Releases the current buffer, and consumes the next buffer in the queue,
830+ // making it available for consumption by consumers of this API in an
831+ // implementation-specific way. Clients will usually rely on a GL texture
832+ // to receive the latest buffer.
833+ bool swap_buffers() const override;
834+
835+private:
836+ // Creates a new instance for the given gl texture, connecting to the remote part known
837+ // under the given key or throw in case of issues.
838+ HybrisGlSink(std::uint32_t gl_texture);
839+
840+ struct Private;
841+ std::unique_ptr<Private> d;
842+};
843+}
844+}
845+}
846+}
847+
848+#endif // CORE_UBUNTU_MEDIA_VIDEO_HYBRIS_GL_SINK_H_
849
850=== added file 'src/core/media/video/platform_default_sink.cpp'
851--- src/core/media/video/platform_default_sink.cpp 1970-01-01 00:00:00 +0000
852+++ src/core/media/video/platform_default_sink.cpp 2015-03-12 11:38:55 +0000
853@@ -0,0 +1,68 @@
854+/*
855+ * Copyright © 2014 Canonical Ltd.
856+ *
857+ * This program is free software: you can redistribute it and/or modify it
858+ * under the terms of the GNU Lesser General Public License version 3,
859+ * as published by the Free Software Foundation.
860+ *
861+ * This program is distributed in the hope that it will be useful,
862+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
863+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
864+ * GNU Lesser General Public License for more details.
865+ *
866+ * You should have received a copy of the GNU Lesser General Public License
867+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
868+ *
869+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
870+ */
871+
872+#include <core/media/video/platform_default_sink.h>
873+
874+namespace media = core::ubuntu::media;
875+namespace video = core::ubuntu::media::video;
876+
877+namespace
878+{
879+struct NullSink : public video::Sink
880+{
881+ // The signal is emitted whenever a new frame is available and a subsequent
882+ // call to swap_buffers will not block and return true.
883+ const core::Signal<void>& frame_available() const
884+ {
885+ return signal_frame_available;
886+ }
887+
888+ // Queries the transformation matrix for the current frame, placing the data into 'matrix'
889+ // and returns true or returns false and leaves 'matrix' unchanged in case
890+ // of issues.
891+ bool transformation_matrix(float*) const
892+ {
893+ return true;
894+ }
895+
896+ // Releases the current buffer, and consumes the next buffer in the queue,
897+ // making it available for consumption by consumers of this API in an
898+ // implementation-specific way. Clients will usually rely on a GL texture
899+ // to receive the latest buffer.
900+ bool swap_buffers() const
901+ {
902+ return true;
903+ }
904+
905+ core::Signal<void> signal_frame_available;
906+};
907+}
908+
909+#if defined(MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER)
910+#include <core/media/video/hybris_gl_sink.h>
911+
912+video::SinkFactory video::make_platform_default_sink_factory(const media::Player::PlayerKey& key)
913+{
914+ return video::HybrisGlSink::factory_for_key(key);
915+}
916+#else // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
917+video::SinkFactory video::make_platform_default_sink_factory(const media::Player::PlayerKey&)
918+{
919+ return [](std::uint32_t) { return video::Sink::Ptr{}; };
920+}
921+#endif // MEDIA_HUB_HAVE_HYBRIS_MEDIA_COMPAT_LAYER
922
923=== added file 'src/core/media/video/platform_default_sink.h'
924--- src/core/media/video/platform_default_sink.h 1970-01-01 00:00:00 +0000
925+++ src/core/media/video/platform_default_sink.h 2015-03-12 11:38:55 +0000
926@@ -0,0 +1,44 @@
927+/*
928+ * Copyright © 2014 Canonical Ltd.
929+ *
930+ * This program is free software: you can redistribute it and/or modify it
931+ * under the terms of the GNU Lesser General Public License version 3,
932+ * as published by the Free Software Foundation.
933+ *
934+ * This program is distributed in the hope that it will be useful,
935+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
936+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
937+ * GNU Lesser General Public License for more details.
938+ *
939+ * You should have received a copy of the GNU Lesser General Public License
940+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
941+ *
942+ * Authored by: Thomas Voß <thomas.voss@canonical.com>
943+ */
944+#ifndef CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_
945+#define CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_
946+
947+#include <core/media/video/sink.h>
948+
949+#include <core/media/player.h>
950+
951+#include <functional>
952+
953+namespace core
954+{
955+namespace ubuntu
956+{
957+namespace media
958+{
959+namespace video
960+{
961+// A functor that allows for creating actual sinks given a texture id.
962+typedef std::function<Sink::Ptr(std::uint32_t)> SinkFactory;
963+// Returns the platform default sink factory for the player instance identified by the given key.
964+SinkFactory make_platform_default_sink_factory(const Player::PlayerKey& key);
965+}
966+}
967+}
968+}
969+
970+#endif // CORE_UBUNTU_MEDIA_VIDEO_PLATFORM_DEFAULT_SINK_H_

Subscribers

People subscribed via source and target branches