Merge lp:~phablet-team/media-hub/video-support into lp:media-hub

Proposed by Jim Hodapp
Status: Superseded
Proposed branch: lp:~phablet-team/media-hub/video-support
Merge into: lp:media-hub
Diff against target: 1379 lines (+622/-50)
19 files modified
CMakeLists.txt (+1/-0)
include/core/media/player.h (+13/-3)
src/core/media/CMakeLists.txt (+6/-2)
src/core/media/engine.h (+7/-0)
src/core/media/gstreamer/engine.cpp (+69/-9)
src/core/media/gstreamer/engine.h (+7/-0)
src/core/media/gstreamer/playbin.h (+165/-18)
src/core/media/mpris/player.h (+4/-0)
src/core/media/player_implementation.cpp (+53/-7)
src/core/media/player_implementation.h (+3/-0)
src/core/media/player_skeleton.cpp (+94/-5)
src/core/media/player_skeleton.h (+8/-0)
src/core/media/player_stub.cpp (+143/-2)
src/core/media/player_stub.h (+7/-0)
src/core/media/server/server.cpp (+11/-0)
src/core/media/track_list_implementation.cpp (+13/-0)
src/core/media/track_list_implementation.h (+1/-0)
src/core/media/track_list_skeleton.cpp (+15/-3)
src/core/media/track_list_skeleton.h (+2/-1)
To merge this branch: bzr merge lp:~phablet-team/media-hub/video-support
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team code Pending
Review via email: mp+212903@code.launchpad.net

This proposal has been superseded by a proposal from 2014-03-26.

Commit message

* Merged with EOS branch from tvoss
* Added on_frame_available listener and callback
* Create a decoding session and pass it to the hybris layer
* Allow playback to work again after a client quits or dies
* Added two new properties to see if the opened media is video or audio
* Background playlist support

Description of the change

* Merged with EOS branch from tvoss
* Added on_frame_available listener and callback
* Create a decoding session and pass it to the hybris layer
* Allow playback to work again after a client quits or dies
* Added two new properties to see if the opened media is video or audio
* Background playlist support

To post a comment you must log in.
37. By Jim Hodapp

Merged with Sergio's packaging changes. Added a copyright header to server.cpp. Removed any includes for decoding_service.h since it's not being used right now.

38. By Jim Hodapp

Didn't mean to #include <visibility.h> in previous commit, undo that.

39. By Jim Hodapp

Enable libhyris-dev as a build-dep

40. By Jim Hodapp

Get rid of the visibility attribute.

41. By Jim Hodapp

Add libproperties-cpp-dev as a Depends: for libmedia-hub-dev

42. By Jim Hodapp

Merged with upstream changes to disable all unit-tests

43. By Jim Hodapp

Made ricmm's change recommendations and enabled the tests that still work properly.

44. By Jim Hodapp

Snap to the preceeding key unit after doing a seek.

45. By Jim Hodapp

Mock decoding_service_set_client_death_cb so that the unittests don't crash when running on a non-target device.

46. By Jim Hodapp

Enable the seeked_to signal

47. By Jim Hodapp

Merged with ricmm's EOS fix branch

48. By Jim Hodapp

Initial version of apparmor security context arbitration for open_uri. This does not yet check the trust store

49. By Jim Hodapp

Refine the apparmor arbitration a bit. Whitelist music-app explicitly until the trust store lands.

50. By Jim Hodapp

Only start when dbus is started instead of preventing media-hub from being able to be stopped

51. By Jim Hodapp

Enable streaming sources to work with media-hub

52. By Jim Hodapp

Allow apps to access their own media files in /opt

53. By Jim Hodapp

Merged with jdstrand's changes to confine media-hub with apparmor

54. By Jim Hodapp

Slightly improve the get_position_duration_works unit test

55. By Jim Hodapp

Make sure the camer-app can play the click sound when a user captures a picture

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-02-14 07:19:31 +0000
+++ CMakeLists.txt 2014-03-26 17:18:55 +0000
@@ -25,6 +25,7 @@
25pkg_check_modules(DBUS dbus-1 REQUIRED)25pkg_check_modules(DBUS dbus-1 REQUIRED)
26pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED)26pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED)
27pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)27pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED)
28pkg_check_modules(GIO gio-2.0 REQUIRED)
2829
29#####################################################################30#####################################################################
30# Enable code coverage calculation with gcov/gcovr/lcov31# Enable code coverage calculation with gcov/gcovr/lcov
3132
=== modified file 'include/core/media/player.h'
--- include/core/media/player.h 2014-02-18 19:27:01 +0000
+++ include/core/media/player.h 2014-03-26 17:18:55 +0000
@@ -39,6 +39,11 @@
39 public:39 public:
40 typedef double PlaybackRate;40 typedef double PlaybackRate;
41 typedef double Volume;41 typedef double Volume;
42 typedef void* GLConsumerWrapperHybris;
43
44 /** Used to set a callback function to be called when a frame is ready to be rendered **/
45 typedef void (*FrameAvailableCbHybris)(GLConsumerWrapperHybris wrapper, void *context);
46 typedef void (*FrameAvailableCb)(void *context);
4247
43 struct Configuration;48 struct Configuration;
4449
@@ -74,6 +79,8 @@
74 virtual std::shared_ptr<TrackList> track_list() = 0;79 virtual std::shared_ptr<TrackList> track_list() = 0;
7580
76 virtual bool open_uri(const Track::UriType& uri) = 0;81 virtual bool open_uri(const Track::UriType& uri) = 0;
82 virtual void create_video_sink(uint32_t texture_id) = 0;
83 virtual GLConsumerWrapperHybris gl_consumer() const = 0;
77 virtual void next() = 0;84 virtual void next() = 0;
78 virtual void previous() = 0;85 virtual void previous() = 0;
79 virtual void play() = 0;86 virtual void play() = 0;
@@ -81,11 +88,16 @@
81 virtual void stop() = 0;88 virtual void stop() = 0;
82 virtual void seek_to(const std::chrono::microseconds& offset) = 0;89 virtual void seek_to(const std::chrono::microseconds& offset) = 0;
8390
91 // TODO: Convert this to be a signal
92 virtual void set_frame_available_callback(FrameAvailableCb cb, void *context) = 0;
93
84 virtual const core::Property<bool>& can_play() const = 0;94 virtual const core::Property<bool>& can_play() const = 0;
85 virtual const core::Property<bool>& can_pause() const = 0;95 virtual const core::Property<bool>& can_pause() const = 0;
86 virtual const core::Property<bool>& can_seek() const = 0;96 virtual const core::Property<bool>& can_seek() const = 0;
87 virtual const core::Property<bool>& can_go_previous() const = 0;97 virtual const core::Property<bool>& can_go_previous() const = 0;
88 virtual const core::Property<bool>& can_go_next() const = 0;98 virtual const core::Property<bool>& can_go_next() const = 0;
99 virtual const core::Property<bool>& is_video_source() const = 0;
100 virtual const core::Property<bool>& is_audio_source() const = 0;
89 virtual const core::Property<PlaybackStatus>& playback_status() const = 0;101 virtual const core::Property<PlaybackStatus>& playback_status() const = 0;
90 virtual const core::Property<LoopStatus>& loop_status() const = 0;102 virtual const core::Property<LoopStatus>& loop_status() const = 0;
91 virtual const core::Property<PlaybackRate>& playback_rate() const = 0;103 virtual const core::Property<PlaybackRate>& playback_rate() const = 0;
@@ -97,15 +109,13 @@
97 virtual const core::Property<uint64_t>& position() const = 0;109 virtual const core::Property<uint64_t>& position() const = 0;
98 virtual const core::Property<uint64_t>& duration() const = 0;110 virtual const core::Property<uint64_t>& duration() const = 0;
99111
100
101 virtual core::Property<LoopStatus>& loop_status() = 0;112 virtual core::Property<LoopStatus>& loop_status() = 0;
102 virtual core::Property<PlaybackRate>& playback_rate() = 0;113 virtual core::Property<PlaybackRate>& playback_rate() = 0;
103 virtual core::Property<bool>& is_shuffle() = 0;114 virtual core::Property<bool>& is_shuffle() = 0;
104 virtual core::Property<Volume>& volume() = 0;115 virtual core::Property<Volume>& volume() = 0;
105116
106
107 virtual const core::Signal<uint64_t>& seeked_to() const = 0;117 virtual const core::Signal<uint64_t>& seeked_to() const = 0;
108118 virtual const core::Signal<void>& end_of_stream() const = 0;
109 protected:119 protected:
110 Player();120 Player();
111121
112122
=== modified file 'src/core/media/CMakeLists.txt'
--- src/core/media/CMakeLists.txt 2014-02-26 14:58:36 +0000
+++ src/core/media/CMakeLists.txt 2014-03-26 17:18:55 +0000
@@ -1,6 +1,6 @@
1pkg_check_modules(PC_GSTREAMER_1_0 REQUIRED gstreamer-1.0)1pkg_check_modules(PC_GSTREAMER_1_0 REQUIRED gstreamer-1.0)
22
3include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS})3include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS} /usr/include/hybris)
44
5add_library(5add_library(
6 media-hub-common SHARED6 media-hub-common SHARED
@@ -52,6 +52,7 @@
52 ${DBUS_LIBRARIES}52 ${DBUS_LIBRARIES}
53 ${DBUS_CPP_LDFLAGS}53 ${DBUS_CPP_LDFLAGS}
54 ${GLog_LIBRARY}54 ${GLog_LIBRARY}
55 -lmedia
55)56)
5657
57install(58install(
@@ -82,9 +83,11 @@
82 ${DBUS_CPP_LDFLAGS}83 ${DBUS_CPP_LDFLAGS}
83 ${GLog_LIBRARY}84 ${GLog_LIBRARY}
84 ${PC_GSTREAMER_1_0_LIBRARIES}85 ${PC_GSTREAMER_1_0_LIBRARIES}
86 ${GIO_LIBRARIES}
87 -lmedia
85)88)
8689
87include_directories(${PROJECT_SOURCE_DIR}/src/)90include_directories(${PROJECT_SOURCE_DIR}/src/ /usr/include/hybris)
8891
89add_executable(92add_executable(
90 media-hub-server93 media-hub-server
@@ -102,6 +105,7 @@
102 ${DBUS_CPP_LDFLAGS}105 ${DBUS_CPP_LDFLAGS}
103 ${GLog_LIBRARY}106 ${GLog_LIBRARY}
104 ${PC_GSTREAMER_1_0_LIBRARIES}107 ${PC_GSTREAMER_1_0_LIBRARIES}
108 -lmedia
105)109)
106110
107install(111install(
108112
=== modified file 'src/core/media/engine.h'
--- src/core/media/engine.h 2014-02-18 19:27:01 +0000
+++ src/core/media/engine.h 2014-03-26 17:18:55 +0000
@@ -97,12 +97,16 @@
97 virtual const core::Property<State>& state() const = 0;97 virtual const core::Property<State>& state() const = 0;
9898
99 virtual bool open_resource_for_uri(const Track::UriType& uri) = 0;99 virtual bool open_resource_for_uri(const Track::UriType& uri) = 0;
100 virtual void create_video_sink(uint32_t texture_id) = 0;
100101
101 virtual bool play() = 0;102 virtual bool play() = 0;
102 virtual bool stop() = 0;103 virtual bool stop() = 0;
103 virtual bool pause() = 0;104 virtual bool pause() = 0;
104 virtual bool seek_to(const std::chrono::microseconds& ts) = 0;105 virtual bool seek_to(const std::chrono::microseconds& ts) = 0;
105106
107 virtual const core::Property<bool>& is_video_source() const = 0;
108 virtual const core::Property<bool>& is_audio_source() const = 0;
109
106 virtual const core::Property<uint64_t>& position() const = 0;110 virtual const core::Property<uint64_t>& position() const = 0;
107 virtual const core::Property<uint64_t>& duration() const = 0;111 virtual const core::Property<uint64_t>& duration() const = 0;
108112
@@ -110,6 +114,9 @@
110 virtual core::Property<Volume>& volume() = 0;114 virtual core::Property<Volume>& volume() = 0;
111115
112 virtual const core::Property<std::tuple<Track::UriType, Track::MetaData>>& track_meta_data() const = 0;116 virtual const core::Property<std::tuple<Track::UriType, Track::MetaData>>& track_meta_data() const = 0;
117
118 virtual const core::Signal<void>& about_to_finish_signal() const = 0;
119 virtual const core::Signal<void>& end_of_stream_signal() const = 0;
113};120};
114}121}
115}122}
116123
=== modified file 'src/core/media/gstreamer/engine.cpp'
--- src/core/media/gstreamer/engine.cpp 2014-02-20 19:05:17 +0000
+++ src/core/media/gstreamer/engine.cpp 2014-03-26 17:18:55 +0000
@@ -16,6 +16,9 @@
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */17 */
1818
19#include <stdio.h>
20#include <stdlib.h>
21
19#include "bus.h"22#include "bus.h"
20#include "engine.h"23#include "engine.h"
21#include "meta_data_extractor.h"24#include "meta_data_extractor.h"
@@ -43,14 +46,10 @@
4346
44struct gstreamer::Engine::Private47struct gstreamer::Engine::Private
45{48{
46 void about_to_finish()
47 {
48 state = Engine::State::ready;
49 }
50
51 void on_playbin_state_changed(49 void on_playbin_state_changed(
52 const gstreamer::Bus::Message::Detail::StateChanged&)50 const gstreamer::Bus::Message::Detail::StateChanged& state_change)
53 {51 {
52 (void) state_change;
54 }53 }
5554
56 void on_tag_available(const gstreamer::Bus::Message::Detail::Tag& tag)55 void on_tag_available(const gstreamer::Bus::Message::Detail::Tag& tag)
@@ -163,13 +162,26 @@
163 playbin.set_volume(new_volume.value);162 playbin.set_volume(new_volume.value);
164 }163 }
165164
165 void on_about_to_finish()
166 {
167 state = Engine::State::ready;
168 about_to_finish();
169 }
170
171 void on_end_of_stream()
172 {
173 end_of_stream();
174 }
175
166 Private()176 Private()
167 : meta_data_extractor(new gstreamer::MetaDataExtractor()),177 : meta_data_extractor(new gstreamer::MetaDataExtractor()),
168 volume(media::Engine::Volume(1.)),178 volume(media::Engine::Volume(1.)),
179 is_video_source(false),
180 is_audio_source(false),
169 about_to_finish_connection(181 about_to_finish_connection(
170 playbin.signals.about_to_finish.connect(182 playbin.signals.about_to_finish.connect(
171 std::bind(183 std::bind(
172 &Private::about_to_finish,184 &Private::on_about_to_finish,
173 this))),185 this))),
174 on_state_changed_connection(186 on_state_changed_connection(
175 playbin.signals.on_state_changed.connect(187 playbin.signals.on_state_changed.connect(
@@ -188,7 +200,12 @@
188 std::bind(200 std::bind(
189 &Private::on_volume_changed,201 &Private::on_volume_changed,
190 this,202 this,
191 std::placeholders::_1)))203 std::placeholders::_1))),
204 on_end_of_stream_connection(
205 playbin.signals.on_end_of_stream.connect(
206 std::bind(
207 &Private::on_end_of_stream,
208 this)))
192 {209 {
193 }210 }
194211
@@ -198,11 +215,17 @@
198 core::Property<uint64_t> position;215 core::Property<uint64_t> position;
199 core::Property<uint64_t> duration;216 core::Property<uint64_t> duration;
200 core::Property<media::Engine::Volume> volume;217 core::Property<media::Engine::Volume> volume;
218 core::Property<bool> is_video_source;
219 core::Property<bool> is_audio_source;
201 gstreamer::Playbin playbin;220 gstreamer::Playbin playbin;
202 core::ScopedConnection about_to_finish_connection;221 core::ScopedConnection about_to_finish_connection;
203 core::ScopedConnection on_state_changed_connection;222 core::ScopedConnection on_state_changed_connection;
204 core::ScopedConnection on_tag_available_connection;223 core::ScopedConnection on_tag_available_connection;
205 core::ScopedConnection on_volume_changed_connection;224 core::ScopedConnection on_volume_changed_connection;
225 core::ScopedConnection on_end_of_stream_connection;
226
227 core::Signal<void> about_to_finish;
228 core::Signal<void> end_of_stream;
206};229};
207230
208gstreamer::Engine::Engine() : d(new Private{})231gstreamer::Engine::Engine() : d(new Private{})
@@ -231,6 +254,11 @@
231 return true;254 return true;
232}255}
233256
257void gstreamer::Engine::create_video_sink(uint32_t texture_id)
258{
259 d->playbin.create_video_sink(texture_id);
260}
261
234bool gstreamer::Engine::play()262bool gstreamer::Engine::play()
235{263{
236 auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);264 auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
@@ -256,7 +284,7 @@
256bool gstreamer::Engine::pause()284bool gstreamer::Engine::pause()
257{285{
258 auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);286 auto result = d->playbin.set_state_and_wait(GST_STATE_PAUSED);
259287
260 if (result)288 if (result)
261 d->state = media::Engine::State::paused;289 d->state = media::Engine::State::paused;
262290
@@ -268,6 +296,28 @@
268 return d->playbin.seek(ts);296 return d->playbin.seek(ts);
269}297}
270298
299const core::Property<bool>& gstreamer::Engine::is_video_source() const
300{
301 gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
302 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
303 d->is_video_source.set(true);
304 else
305 d->is_video_source.set(false);
306
307 return d->is_video_source;
308}
309
310const core::Property<bool>& gstreamer::Engine::is_audio_source() const
311{
312 gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
313 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
314 d->is_audio_source.set(true);
315 else
316 d->is_audio_source.set(false);
317
318 return d->is_audio_source;
319}
320
271const core::Property<uint64_t>& gstreamer::Engine::position() const321const core::Property<uint64_t>& gstreamer::Engine::position() const
272{322{
273 d->position.set(d->playbin.position());323 d->position.set(d->playbin.position());
@@ -295,3 +345,13 @@
295{345{
296 return d->track_meta_data;346 return d->track_meta_data;
297}347}
348
349const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
350{
351 return d->about_to_finish;
352}
353
354const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
355{
356 return d->end_of_stream;
357}
298358
=== modified file 'src/core/media/gstreamer/engine.h'
--- src/core/media/gstreamer/engine.h 2014-02-18 19:27:01 +0000
+++ src/core/media/gstreamer/engine.h 2014-03-26 17:18:55 +0000
@@ -33,12 +33,16 @@
33 const core::Property<State>& state() const;33 const core::Property<State>& state() const;
3434
35 bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri);35 bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri);
36 void create_video_sink(uint32_t texture_id);
3637
37 bool play();38 bool play();
38 bool stop();39 bool stop();
39 bool pause();40 bool pause();
40 bool seek_to(const std::chrono::microseconds& ts);41 bool seek_to(const std::chrono::microseconds& ts);
4142
43 const core::Property<bool>& is_video_source() const;
44 const core::Property<bool>& is_audio_source() const;
45
42 const core::Property<uint64_t>& position() const;46 const core::Property<uint64_t>& position() const;
43 const core::Property<uint64_t>& duration() const;47 const core::Property<uint64_t>& duration() const;
4448
@@ -47,6 +51,9 @@
4751
48 const core::Property<std::tuple<core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData>>& track_meta_data() const;52 const core::Property<std::tuple<core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData>>& track_meta_data() const;
4953
54 const core::Signal<void>& about_to_finish_signal() const;
55 const core::Signal<void>& end_of_stream_signal() const;
56
50private:57private:
51 struct Private;58 struct Private;
52 std::unique_ptr<Private> d;59 std::unique_ptr<Private> d;
5360
=== modified file 'src/core/media/gstreamer/playbin.h'
--- src/core/media/gstreamer/playbin.h 2014-02-20 19:05:17 +0000
+++ src/core/media/gstreamer/playbin.h 2014-03-26 17:18:55 +0000
@@ -21,6 +21,11 @@
2121
22#include "bus.h"22#include "bus.h"
2323
24#include <media/decoding_service.h>
25#include <media/media_codec_layer.h>
26#include <media/surface_texture_client_hybris.h>
27
28#include <gio/gio.h>
24#include <gst/gst.h>29#include <gst/gst.h>
2530
26#include <chrono>31#include <chrono>
@@ -37,6 +42,13 @@
37 GST_PLAY_FLAG_TEXT = (1 << 2)42 GST_PLAY_FLAG_TEXT = (1 << 2)
38 };43 };
3944
45 enum MediaFileType
46 {
47 MEDIA_FILE_TYPE_NONE,
48 MEDIA_FILE_TYPE_AUDIO,
49 MEDIA_FILE_TYPE_VIDEO
50 };
51
40 static const std::string& pipeline_name()52 static const std::string& pipeline_name()
41 {53 {
42 static const std::string s{"playbin"};54 static const std::string s{"playbin"};
@@ -45,14 +57,15 @@
4557
46 static void about_to_finish(GstElement*,58 static void about_to_finish(GstElement*,
47 gpointer user_data)59 gpointer user_data)
48 { auto thiz = static_cast<Playbin*>(user_data);60 {
4961 auto thiz = static_cast<Playbin*>(user_data);
50 thiz->signals.about_to_finish();62 thiz->signals.about_to_finish();
51 }63 }
5264
53 Playbin()65 Playbin()
54 : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())),66 : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())),
55 bus{gst_element_get_bus(pipeline)},67 bus{gst_element_get_bus(pipeline)},
68 file_type(MEDIA_FILE_TYPE_NONE),
56 on_new_message_connection(69 on_new_message_connection(
57 bus.on_new_message.connect(70 bus.on_new_message.connect(
58 std::bind(71 std::bind(
@@ -74,6 +87,8 @@
74 this87 this
75 );88 );
7689
90 // When a client of media-hub dies, call on_client_died
91 decoding_service_set_client_death_cb(&Playbin::on_client_died_cb, static_cast<void*>(this));
77 }92 }
7893
79 ~Playbin()94 ~Playbin()
@@ -82,6 +97,43 @@
82 gst_object_unref(pipeline);97 gst_object_unref(pipeline);
83 }98 }
8499
100 static void on_client_died_cb(void *context)
101 {
102 if (context)
103 {
104 Playbin *pb = static_cast<Playbin*>(context);
105 pb->on_client_died();
106 }
107 }
108
109 void on_client_died()
110 {
111 std::cout << "Client died, resetting pipeline" << std::endl;
112 // When the client dies, tear down the current pipeline and get it
113 // in a state that is ready for the next client that connects to the
114 // service
115 reset_pipeline();
116 }
117
118 void reset_pipeline()
119 {
120 std::cout << __PRETTY_FUNCTION__ << std::endl;
121 auto ret = gst_element_set_state(pipeline, GST_STATE_NULL);
122 switch(ret)
123 {
124 case GST_STATE_CHANGE_FAILURE:
125 std::cout << "Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
126 break;
127 case GST_STATE_CHANGE_NO_PREROLL:
128 case GST_STATE_CHANGE_SUCCESS:
129 case GST_STATE_CHANGE_ASYNC:
130 break;
131 default:
132 std::cout << "Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl;
133 }
134 file_type = MEDIA_FILE_TYPE_NONE;
135 }
136
85 void on_new_message(const Bus::Message& message)137 void on_new_message(const Bus::Message& message)
86 {138 {
87 switch(message.type)139 switch(message.type)
@@ -101,6 +153,9 @@
101 case GST_MESSAGE_STATE_CHANGED:153 case GST_MESSAGE_STATE_CHANGED:
102 signals.on_state_changed(message.detail.state_changed);154 signals.on_state_changed(message.detail.state_changed);
103 break;155 break;
156 case GST_MESSAGE_EOS:
157 std::cout << "EOS detected" << std::endl;
158 signals.on_end_of_stream();
104 default:159 default:
105 break;160 break;
106 }161 }
@@ -126,6 +181,8 @@
126 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),181 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),
127 "audio-sink");182 "audio-sink");
128183
184 std::cout << "audio_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") << std::endl;
185
129 g_object_set (186 g_object_set (
130 pipeline,187 pipeline,
131 "audio-sink",188 "audio-sink",
@@ -136,26 +193,43 @@
136 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)193 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)
137 {194 {
138 auto video_sink = gst_element_factory_make (195 auto video_sink = gst_element_factory_make (
139 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),196 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),
140 "video-sink");197 "video-sink");
141198
142 std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;199 std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;
143200
144 g_object_set (201 g_object_set (
145 pipeline,202 pipeline,
146 "video-sink",203 "video-sink",
147 video_sink,204 video_sink,
148 NULL);205 NULL);
206 }
207 }
208
209 void create_video_sink(uint32_t texture_id)
210 {
211 std::cout << "Creating video sink for texture_id: " << texture_id << std::endl;
212
213 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)
214 {
215 GstElement *video_sink = NULL;
216 g_object_get (pipeline, "video_sink", &video_sink, NULL);
217
218 // Get the service-side BufferQueue (IGraphicBufferProducer) and associate it with
219 // the SurfaceTextureClientHybris instance
220 IGBPWrapperHybris igbp = decoding_service_get_igraphicbufferproducer();
221 std::cout << "IGBPWrapperHybris: " << igbp << std::endl;
222 SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp);
223 std::cout << "SurfaceTextureClientHybris: " << stc << std::endl;
224 // Because mirsink is being loaded, we are definitely doing * hardware rendering.
225 surface_texture_client_set_hardware_rendering (stc, TRUE);
226 g_object_set (G_OBJECT (video_sink), "surface", static_cast<gpointer>(stc), static_cast<char*>(NULL));
149 }227 }
150 }228 }
151229
152 void set_volume(double new_volume)230 void set_volume(double new_volume)
153 {231 {
154 g_object_set(232 g_object_set(pipeline, "volume", new_volume, NULL);
155 pipeline,
156 "volume",
157 new_volume,
158 NULL);
159 }233 }
160234
161 uint64_t position() const235 uint64_t position() const
@@ -178,11 +252,11 @@
178252
179 void set_uri(const std::string& uri)253 void set_uri(const std::string& uri)
180 {254 {
181 g_object_set(255 g_object_set(pipeline, "uri", uri.c_str(), NULL);
182 pipeline,256 if (is_video_file(uri))
183 "uri",257 file_type = MEDIA_FILE_TYPE_VIDEO;
184 uri.c_str(),258 else if (is_audio_file(uri))
185 NULL);259 file_type = MEDIA_FILE_TYPE_AUDIO;
186 }260 }
187261
188 std::string uri() const262 std::string uri() const
@@ -236,8 +310,80 @@
236 ms.count() * 1000);310 ms.count() * 1000);
237 }311 }
238312
313 std::string get_file_content_type(const std::string& uri) const
314 {
315 if (uri.empty())
316 return std::string();
317
318 std::string filename(uri);
319 size_t pos = uri.find("file://") + 7;
320 if (pos)
321 filename = uri.substr(pos, std::string::npos);
322
323 std::cout << "filename: " << filename << std::endl;
324
325 GError *error = nullptr;
326 std::unique_ptr<GFile, void(*)(void *)> file(
327 g_file_new_for_path(filename.c_str()), g_object_unref);
328 std::unique_ptr<GFileInfo, void(*)(void *)> info(
329 g_file_query_info(
330 file.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE ","
331 G_FILE_ATTRIBUTE_ETAG_VALUE, G_FILE_QUERY_INFO_NONE,
332 /* cancellable */ NULL, &error),
333 g_object_unref);
334 if (!info)
335 {
336 std::string error_str(error->message);
337 g_error_free(error);
338
339 std::cout << "Failed to query the URI for the presence of video content: "
340 << error_str << std::endl;
341 return std::string();
342 }
343
344 std::string content_type(g_file_info_get_attribute_string(
345 info.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
346
347 return content_type;
348 }
349
350 bool is_audio_file(const std::string& uri) const
351 {
352 if (uri.empty())
353 return false;
354
355 if (get_file_content_type(uri).find("audio/") == 0)
356 {
357 std::cout << "Found audio content" << std::endl;
358 return true;
359 }
360
361 return false;
362 }
363
364 bool is_video_file(const std::string& uri) const
365 {
366 if (uri.empty())
367 return false;
368
369 if (get_file_content_type(uri).find("video/") == 0)
370 {
371 std::cout << "Found video content" << std::endl;
372 return true;
373 }
374
375 return false;
376 }
377
378 MediaFileType media_file_type() const
379 {
380 return file_type;
381 }
382
239 GstElement* pipeline;383 GstElement* pipeline;
240 gstreamer::Bus bus;384 gstreamer::Bus bus;
385 MediaFileType file_type;
386 SurfaceTextureClientHybris stc_hybris;
241 core::Connection on_new_message_connection;387 core::Connection on_new_message_connection;
242 struct388 struct
243 {389 {
@@ -247,6 +393,7 @@
247 core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info;393 core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info;
248 core::Signal<Bus::Message::Detail::Tag> on_tag_available;394 core::Signal<Bus::Message::Detail::Tag> on_tag_available;
249 core::Signal<Bus::Message::Detail::StateChanged> on_state_changed;395 core::Signal<Bus::Message::Detail::StateChanged> on_state_changed;
396 core::Signal<void> on_end_of_stream;
250 } signals;397 } signals;
251};398};
252}399}
253400
=== modified file 'src/core/media/mpris/player.h'
--- src/core/media/mpris/player.h 2014-02-18 19:27:01 +0000
+++ src/core/media/mpris/player.h 2014-03-26 17:18:55 +0000
@@ -54,11 +54,13 @@
54 METHOD(Play, Player, std::chrono::seconds(1))54 METHOD(Play, Player, std::chrono::seconds(1))
55 METHOD(Seek, Player, std::chrono::seconds(1))55 METHOD(Seek, Player, std::chrono::seconds(1))
56 METHOD(SetPosition, Player, std::chrono::seconds(1))56 METHOD(SetPosition, Player, std::chrono::seconds(1))
57 METHOD(CreateVideoSink, Player, std::chrono::seconds(1))
57 METHOD(OpenUri, Player, std::chrono::seconds(1))58 METHOD(OpenUri, Player, std::chrono::seconds(1))
5859
59 struct Signals60 struct Signals
60 {61 {
61 SIGNAL(Seeked, Player, uint64_t)62 SIGNAL(Seeked, Player, uint64_t)
63 SIGNAL(EndOfStream, Player, void)
62 };64 };
6365
64 struct Properties66 struct Properties
@@ -74,6 +76,8 @@
74 READABLE_PROPERTY(Duration, Player, uint64_t)76 READABLE_PROPERTY(Duration, Player, uint64_t)
75 READABLE_PROPERTY(MinimumRate, Player, double)77 READABLE_PROPERTY(MinimumRate, Player, double)
76 READABLE_PROPERTY(MaximumRate, Player, double)78 READABLE_PROPERTY(MaximumRate, Player, double)
79 READABLE_PROPERTY(IsVideoSource, Player, bool)
80 READABLE_PROPERTY(IsAudioSource, Player, bool)
77 READABLE_PROPERTY(CanGoNext, Player, bool)81 READABLE_PROPERTY(CanGoNext, Player, bool)
78 READABLE_PROPERTY(CanGoPrevious, Player, bool)82 READABLE_PROPERTY(CanGoPrevious, Player, bool)
79 READABLE_PROPERTY(CanPlay, Player, bool)83 READABLE_PROPERTY(CanPlay, Player, bool)
8084
=== modified file 'src/core/media/player_implementation.cpp'
--- src/core/media/player_implementation.cpp 2014-02-18 20:25:21 +0000
+++ src/core/media/player_implementation.cpp 2014-03-26 17:18:55 +0000
@@ -17,9 +17,13 @@
1717
18#include "player_implementation.h"18#include "player_implementation.h"
1919
20#include <unistd.h>
21
20#include "engine.h"22#include "engine.h"
21#include "track_list_implementation.h"23#include "track_list_implementation.h"
2224
25#define UNUSED __attribute__((unused))
26
23namespace media = core::ubuntu::media;27namespace media = core::ubuntu::media;
2428
25struct media::PlayerImplementation::Private29struct media::PlayerImplementation::Private
@@ -39,7 +43,7 @@
39 {43 {
40 engine->state().changed().connect(44 engine->state().changed().connect(
41 [parent](const Engine::State& state)45 [parent](const Engine::State& state)
42 {46 {
43 switch(state)47 switch(state)
44 {48 {
45 case Engine::State::ready: parent->playback_status().set(media::Player::ready); break;49 case Engine::State::ready: parent->playback_status().set(media::Player::ready); break;
@@ -49,7 +53,8 @@
49 default:53 default:
50 break;54 break;
51 };55 };
52 });56 });
57
53 }58 }
5459
55 PlayerImplementation* parent;60 PlayerImplementation* parent;
@@ -76,6 +81,8 @@
76 can_seek().set(true);81 can_seek().set(true);
77 can_go_previous().set(true);82 can_go_previous().set(true);
78 can_go_next().set(true);83 can_go_next().set(true);
84 is_video_source().set(false);
85 is_audio_source().set(false);
79 is_shuffle().set(true);86 is_shuffle().set(true);
80 playback_rate().set(1.f);87 playback_rate().set(1.f);
81 playback_status().set(Player::PlaybackStatus::null);88 playback_status().set(Player::PlaybackStatus::null);
@@ -98,6 +105,33 @@
98 return d->engine->duration().get();105 return d->engine->duration().get();
99 };106 };
100 duration().install(duration_getter);107 duration().install(duration_getter);
108
109 std::function<bool()> video_type_getter = [this]()
110 {
111 return d->engine->is_video_source().get();
112 };
113 is_video_source().install(video_type_getter);
114
115 std::function<bool()> audio_type_getter = [this]()
116 {
117 return d->engine->is_audio_source().get();
118 };
119 is_audio_source().install(audio_type_getter);
120
121 engine->about_to_finish_signal().connect([this]()
122 {
123 if (d->track_list->has_next())
124 {
125 Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next());
126 if (!uri.empty())
127 d->parent->open_uri(uri);
128 }
129 });
130
131 engine->end_of_stream_signal().connect([this]()
132 {
133 end_of_stream()();
134 });
101}135}
102136
103media::PlayerImplementation::~PlayerImplementation()137media::PlayerImplementation::~PlayerImplementation()
@@ -114,6 +148,17 @@
114 return d->engine->open_resource_for_uri(uri);148 return d->engine->open_resource_for_uri(uri);
115}149}
116150
151void media::PlayerImplementation::create_video_sink(uint32_t texture_id)
152{
153 d->engine->create_video_sink(texture_id);
154}
155
156media::Player::GLConsumerWrapperHybris media::PlayerImplementation::gl_consumer() const
157{
158 // This method is client-side only and is simply a no-op for the service side
159 return NULL;
160}
161
117void media::PlayerImplementation::next()162void media::PlayerImplementation::next()
118{163{
119}164}
@@ -124,11 +169,6 @@
124169
125void media::PlayerImplementation::play()170void media::PlayerImplementation::play()
126{171{
127 /*if (playback_status() == media::Player::null)
128 {
129 if (d->track_list->has_next())
130 if (open_uri(d->track_list->next()->))
131 }*/
132 d->engine->play();172 d->engine->play();
133}173}
134174
@@ -142,6 +182,12 @@
142 d->engine->stop();182 d->engine->stop();
143}183}
144184
185void media::PlayerImplementation::set_frame_available_callback(
186 UNUSED FrameAvailableCb cb, UNUSED void *context)
187{
188 // This method is client-side only and is simply a no-op for the service side
189}
190
145void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)191void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)
146{192{
147 d->engine->seek_to(ms);193 d->engine->seek_to(ms);
148194
=== modified file 'src/core/media/player_implementation.h'
--- src/core/media/player_implementation.h 2014-02-18 20:25:21 +0000
+++ src/core/media/player_implementation.h 2014-03-26 17:18:55 +0000
@@ -43,11 +43,14 @@
43 virtual std::shared_ptr<TrackList> track_list();43 virtual std::shared_ptr<TrackList> track_list();
4444
45 virtual bool open_uri(const Track::UriType& uri);45 virtual bool open_uri(const Track::UriType& uri);
46 virtual void create_video_sink(uint32_t texture_id);
47 virtual GLConsumerWrapperHybris gl_consumer() const;
46 virtual void next();48 virtual void next();
47 virtual void previous();49 virtual void previous();
48 virtual void play();50 virtual void play();
49 virtual void pause();51 virtual void pause();
50 virtual void stop();52 virtual void stop();
53 virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
51 virtual void seek_to(const std::chrono::microseconds& offset);54 virtual void seek_to(const std::chrono::microseconds& offset);
5255
53private:56private:
5457
=== modified file 'src/core/media/player_skeleton.cpp'
--- src/core/media/player_skeleton.cpp 2014-02-20 19:05:17 +0000
+++ src/core/media/player_skeleton.cpp 2014-03-26 17:18:55 +0000
@@ -44,6 +44,8 @@
44 object->get_property<mpris::Player::Properties::CanControl>(),44 object->get_property<mpris::Player::Properties::CanControl>(),
45 object->get_property<mpris::Player::Properties::CanGoNext>(),45 object->get_property<mpris::Player::Properties::CanGoNext>(),
46 object->get_property<mpris::Player::Properties::CanGoPrevious>(),46 object->get_property<mpris::Player::Properties::CanGoPrevious>(),
47 object->get_property<mpris::Player::Properties::IsVideoSource>(),
48 object->get_property<mpris::Player::Properties::IsAudioSource>(),
47 object->get_property<mpris::Player::Properties::PlaybackStatus>(),49 object->get_property<mpris::Player::Properties::PlaybackStatus>(),
48 object->get_property<mpris::Player::Properties::LoopStatus>(),50 object->get_property<mpris::Player::Properties::LoopStatus>(),
49 object->get_property<mpris::Player::Properties::PlaybackRate>(),51 object->get_property<mpris::Player::Properties::PlaybackRate>(),
@@ -54,6 +56,11 @@
54 object->get_property<mpris::Player::Properties::Duration>(),56 object->get_property<mpris::Player::Properties::Duration>(),
55 object->get_property<mpris::Player::Properties::MinimumRate>(),57 object->get_property<mpris::Player::Properties::MinimumRate>(),
56 object->get_property<mpris::Player::Properties::MaximumRate>()58 object->get_property<mpris::Player::Properties::MaximumRate>()
59 },
60 signals
61 {
62 object->get_signal<mpris::Player::Signals::Seeked>(),
63 object->get_signal<mpris::Player::Signals::EndOfStream>()
57 }64 }
58 {65 {
59 }66 }
@@ -111,6 +118,16 @@
111 {118 {
112 }119 }
113120
121 void handle_create_video_sink(const core::dbus::Message::Ptr& in)
122 {
123 uint32_t texture_id;
124 in->reader() >> texture_id;
125 impl->create_video_sink(texture_id);
126
127 auto reply = dbus::Message::make_method_return(in);
128 impl->access_bus()->send(reply);
129 }
130
114 void handle_open_uri(const core::dbus::Message::Ptr& in)131 void handle_open_uri(const core::dbus::Message::Ptr& in)
115 {132 {
116 Track::UriType uri;133 Track::UriType uri;
@@ -131,6 +148,8 @@
131 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;148 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;
132 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;149 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;
133 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;150 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
151 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
152 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
134153
135 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;154 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;
136 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;155 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;
@@ -144,10 +163,41 @@
144 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;163 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
145 } properties;164 } properties;
146165
147 /*struct166 struct Signals
148 {167 {
149 std::shared_ptr<dbus::Signal<mpris::Player::Signals::Seeked, uint64_t>> seeked;168 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
150 } signals;*/169 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
170
171 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
172 const std::shared_ptr<DBusEndOfStreamSignal>& eos)
173 : dbus
174 {
175 seeked,
176 eos
177 },
178 seeked_to(),
179 end_of_stream()
180 {
181 seeked_to.connect([this](std::uint64_t value)
182 {
183 std::cout << "value: " << value << std::endl;
184 //dbus.seeked_to->emit(value);
185 });
186
187 end_of_stream.connect([this]()
188 {
189 dbus.end_of_stream->emit();
190 });
191 }
192
193 struct DBus
194 {
195 std::shared_ptr<DBusSeekedToSignal> seeked_to;
196 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
197 } dbus;
198 core::Signal<uint64_t> seeked_to;
199 core::Signal<void> end_of_stream;
200 } signals;
151201
152};202};
153203
@@ -184,6 +234,10 @@
184 std::bind(&Private::handle_set_position,234 std::bind(&Private::handle_set_position,
185 std::ref(d),235 std::ref(d),
186 std::placeholders::_1));236 std::placeholders::_1));
237 d->object->install_method_handler<mpris::Player::CreateVideoSink>(
238 std::bind(&Private::handle_create_video_sink,
239 std::ref(d),
240 std::placeholders::_1));
187 d->object->install_method_handler<mpris::Player::OpenUri>(241 d->object->install_method_handler<mpris::Player::OpenUri>(
188 std::bind(&Private::handle_open_uri,242 std::bind(&Private::handle_open_uri,
189 std::ref(d),243 std::ref(d),
@@ -219,6 +273,16 @@
219 return *d->properties.can_go_next;273 return *d->properties.can_go_next;
220}274}
221275
276const core::Property<bool>& media::PlayerSkeleton::is_video_source() const
277{
278 return *d->properties.is_video_source;
279}
280
281const core::Property<bool>& media::PlayerSkeleton::is_audio_source() const
282{
283 return *d->properties.is_audio_source;
284}
285
222const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const286const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const
223{287{
224 return *d->properties.playback_status;288 return *d->properties.playback_status;
@@ -329,6 +393,17 @@
329 return *d->properties.can_go_next;393 return *d->properties.can_go_next;
330}394}
331395
396core::Property<bool>& media::PlayerSkeleton::is_video_source()
397{
398 return *d->properties.is_video_source;
399}
400
401core::Property<bool>& media::PlayerSkeleton::is_audio_source()
402{
403 return *d->properties.is_audio_source;
404}
405
406
332core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()407core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()
333{408{
334 return *d->properties.meta_data_for_current_track;409 return *d->properties.meta_data_for_current_track;
@@ -346,6 +421,20 @@
346421
347const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const422const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const
348{423{
349 static const core::Signal<uint64_t> signal;424 return d->signals.seeked_to;
350 return signal;425}
426
427core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to()
428{
429 return d->signals.seeked_to;
430}
431
432const core::Signal<void>& media::PlayerSkeleton::end_of_stream() const
433{
434 return d->signals.end_of_stream;
435}
436
437core::Signal<void>& media::PlayerSkeleton::end_of_stream()
438{
439 return d->signals.end_of_stream;
351}440}
352441
=== modified file 'src/core/media/player_skeleton.h'
--- src/core/media/player_skeleton.h 2014-02-18 19:27:01 +0000
+++ src/core/media/player_skeleton.h 2014-03-26 17:18:55 +0000
@@ -46,6 +46,8 @@
46 virtual const core::Property<bool>& can_seek() const;46 virtual const core::Property<bool>& can_seek() const;
47 virtual const core::Property<bool>& can_go_previous() const;47 virtual const core::Property<bool>& can_go_previous() const;
48 virtual const core::Property<bool>& can_go_next() const;48 virtual const core::Property<bool>& can_go_next() const;
49 virtual const core::Property<bool>& is_video_source() const;
50 virtual const core::Property<bool>& is_audio_source() const;
49 virtual const core::Property<PlaybackStatus>& playback_status() const;51 virtual const core::Property<PlaybackStatus>& playback_status() const;
50 virtual const core::Property<LoopStatus>& loop_status() const;52 virtual const core::Property<LoopStatus>& loop_status() const;
51 virtual const core::Property<PlaybackRate>& playback_rate() const;53 virtual const core::Property<PlaybackRate>& playback_rate() const;
@@ -63,6 +65,7 @@
63 virtual core::Property<Volume>& volume();65 virtual core::Property<Volume>& volume();
6466
65 virtual const core::Signal<uint64_t>& seeked_to() const;67 virtual const core::Signal<uint64_t>& seeked_to() const;
68 virtual const core::Signal<void>& end_of_stream() const;
6669
67 protected:70 protected:
68 PlayerSkeleton(const core::dbus::types::ObjectPath& session_path);71 PlayerSkeleton(const core::dbus::types::ObjectPath& session_path);
@@ -73,12 +76,17 @@
73 virtual core::Property<bool>& can_seek();76 virtual core::Property<bool>& can_seek();
74 virtual core::Property<bool>& can_go_previous();77 virtual core::Property<bool>& can_go_previous();
75 virtual core::Property<bool>& can_go_next();78 virtual core::Property<bool>& can_go_next();
79 virtual core::Property<bool>& is_video_source();
80 virtual core::Property<bool>& is_audio_source();
76 virtual core::Property<Track::MetaData>& meta_data_for_current_track();81 virtual core::Property<Track::MetaData>& meta_data_for_current_track();
77 virtual core::Property<PlaybackRate>& minimum_playback_rate();82 virtual core::Property<PlaybackRate>& minimum_playback_rate();
78 virtual core::Property<PlaybackRate>& maximum_playback_rate();83 virtual core::Property<PlaybackRate>& maximum_playback_rate();
79 virtual core::Property<uint64_t>& position();84 virtual core::Property<uint64_t>& position();
80 virtual core::Property<uint64_t>& duration();85 virtual core::Property<uint64_t>& duration();
8186
87 virtual core::Signal<uint64_t>& seeked_to();
88 virtual core::Signal<void>& end_of_stream();
89
82 private:90 private:
83 struct Private;91 struct Private;
84 std::unique_ptr<Private> d;92 std::unique_ptr<Private> d;
8593
=== modified file 'src/core/media/player_stub.cpp'
--- src/core/media/player_stub.cpp 2014-02-20 19:05:17 +0000
+++ src/core/media/player_stub.cpp 2014-03-26 17:18:55 +0000
@@ -31,8 +31,15 @@
31#include <core/dbus/property.h>31#include <core/dbus/property.h>
32#include <core/dbus/types/object_path.h>32#include <core/dbus/types/object_path.h>
3333
34// Hybris
35#include <media/decoding_service.h>
36#include <media/media_codec_layer.h>
37#include <media/surface_texture_client_hybris.h>
38
34#include <limits>39#include <limits>
3540
41#define UNUSED __attribute__((unused))
42
36namespace dbus = core::dbus;43namespace dbus = core::dbus;
37namespace media = core::ubuntu::media;44namespace media = core::ubuntu::media;
3845
@@ -42,6 +49,12 @@
42 const std::shared_ptr<dbus::Service>& remote,49 const std::shared_ptr<dbus::Service>& remote,
43 const dbus::types::ObjectPath& path50 const dbus::types::ObjectPath& path
44 ) : parent(parent),51 ) : parent(parent),
52 texture_id(0),
53 igbc_wrapper(nullptr),
54 glc_wrapper(nullptr),
55 decoding_session(decoding_service_create_session()),
56 frame_available_cb(nullptr),
57 frame_available_context(nullptr),
45 path(path),58 path(path),
46 object(remote->object_for_path(path)),59 object(remote->object_for_path(path)),
47 properties60 properties
@@ -52,6 +65,8 @@
52 object->get_property<mpris::Player::Properties::CanControl>(),65 object->get_property<mpris::Player::Properties::CanControl>(),
53 object->get_property<mpris::Player::Properties::CanGoNext>(),66 object->get_property<mpris::Player::Properties::CanGoNext>(),
54 object->get_property<mpris::Player::Properties::CanGoPrevious>(),67 object->get_property<mpris::Player::Properties::CanGoPrevious>(),
68 object->get_property<mpris::Player::Properties::IsVideoSource>(),
69 object->get_property<mpris::Player::Properties::IsAudioSource>(),
55 object->get_property<mpris::Player::Properties::PlaybackStatus>(),70 object->get_property<mpris::Player::Properties::PlaybackStatus>(),
56 object->get_property<mpris::Player::Properties::LoopStatus>(),71 object->get_property<mpris::Player::Properties::LoopStatus>(),
57 object->get_property<mpris::Player::Properties::PlaybackRate>(),72 object->get_property<mpris::Player::Properties::PlaybackRate>(),
@@ -62,13 +77,67 @@
62 object->get_property<mpris::Player::Properties::Duration>(),77 object->get_property<mpris::Player::Properties::Duration>(),
63 object->get_property<mpris::Player::Properties::MinimumRate>(),78 object->get_property<mpris::Player::Properties::MinimumRate>(),
64 object->get_property<mpris::Player::Properties::MaximumRate>()79 object->get_property<mpris::Player::Properties::MaximumRate>()
80 },
81 signals
82 {
83 object->get_signal<mpris::Player::Signals::Seeked>(),
84 object->get_signal<mpris::Player::Signals::EndOfStream>()
65 }85 }
66 {86 {
67 }87 }
6888
89 ~Private()
90 {
91 }
92
93 static void on_frame_available_cb(UNUSED GLConsumerWrapperHybris wrapper, void *context)
94 {
95 if (context != nullptr) {
96 Private *p = static_cast<Private*>(context);
97 p->on_frame_available();
98 }
99 else
100 std::cout << "context is nullptr, can't call on_frame_available()" << std::endl;
101 }
102
103 void on_frame_available()
104 {
105 if (frame_available_cb != nullptr) {
106 frame_available_cb(frame_available_context);
107 }
108 else
109 std::cout << "frame_available_cb is nullptr, can't call frame_available_cb()" << std::endl;
110 }
111
112 void set_frame_available_cb(FrameAvailableCb cb, void *context)
113 {
114 frame_available_cb = cb;
115 frame_available_context = context;
116
117 gl_consumer_set_frame_available_cb(glc_wrapper, &Private::on_frame_available_cb, static_cast<void*>(this));
118 }
119
120 /** We need a GLConsumerHybris instance for doing texture streaming over the
121 * process boundary **/
122 void get_gl_consumer()
123 {
124 igbc_wrapper = decoding_service_get_igraphicbufferconsumer();
125 glc_wrapper = gl_consumer_create_by_id_with_igbc(texture_id, igbc_wrapper);
126
127 }
128
69 std::shared_ptr<Service> parent;129 std::shared_ptr<Service> parent;
70 std::shared_ptr<TrackList> track_list;130 std::shared_ptr<TrackList> track_list;
71131
132 uint32_t texture_id;
133 IGBCWrapperHybris igbc_wrapper;
134 GLConsumerWrapperHybris glc_wrapper;
135
136 DSSessionWrapperHybris decoding_session;
137
138 FrameAvailableCb frame_available_cb;
139 void *frame_available_context;
140
72 dbus::Bus::Ptr bus;141 dbus::Bus::Ptr bus;
73 dbus::types::ObjectPath path;142 dbus::types::ObjectPath path;
74 dbus::Object::Ptr object;143 dbus::Object::Ptr object;
@@ -81,6 +150,8 @@
81 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;150 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;
82 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;151 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next;
83 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;152 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
153 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
154 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
84155
85 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;156 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;
86 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;157 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;
@@ -93,6 +164,42 @@
93 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate;164 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate;
94 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;165 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
95 } properties;166 } properties;
167
168 struct Signals
169 {
170 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
171 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
172
173 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
174 const std::shared_ptr<DBusEndOfStreamSignal>& eos)
175 : dbus
176 {
177 seeked,
178 eos
179 },
180 seeked_to(),
181 end_of_stream()
182 {
183 dbus.seeked_to->connect([this](std::uint64_t value)
184 {
185 seeked_to(value);
186 });
187
188 dbus.end_of_stream->connect([this]()
189 {
190 std::cout << "EndOfStream signal arrived via the bus." << std::endl;
191 end_of_stream();
192 });
193 }
194
195 struct DBus
196 {
197 std::shared_ptr<DBusSeekedToSignal> seeked_to;
198 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
199 } dbus;
200 core::Signal<uint64_t> seeked_to;
201 core::Signal<void> end_of_stream;
202 } signals;
96};203};
97204
98media::PlayerStub::PlayerStub(205media::PlayerStub::PlayerStub(
@@ -125,6 +232,21 @@
125 return op.value();232 return op.value();
126}233}
127234
235void media::PlayerStub::create_video_sink(uint32_t texture_id)
236{
237 auto op = d->object->invoke_method_synchronously<mpris::Player::CreateVideoSink, void>(texture_id);
238 d->texture_id = texture_id;
239 d->get_gl_consumer();
240
241 if (op.is_error())
242 throw std::runtime_error("Problem switching to next track on remote object");
243}
244
245GLConsumerWrapperHybris media::PlayerStub::gl_consumer() const
246{
247 return d->glc_wrapper;
248}
249
128void media::PlayerStub::next()250void media::PlayerStub::next()
129{251{
130 auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>();252 auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>();
@@ -173,6 +295,11 @@
173 throw std::runtime_error("Problem stopping playback on remote object");295 throw std::runtime_error("Problem stopping playback on remote object");
174}296}
175297
298void media::PlayerStub::set_frame_available_callback(FrameAvailableCb cb, void *context)
299{
300 d->set_frame_available_cb(cb, context);
301}
302
176const core::Property<bool>& media::PlayerStub::can_play() const303const core::Property<bool>& media::PlayerStub::can_play() const
177{304{
178 return *d->properties.can_play;305 return *d->properties.can_play;
@@ -198,6 +325,16 @@
198 return *d->properties.can_go_next;325 return *d->properties.can_go_next;
199}326}
200327
328const core::Property<bool>& media::PlayerStub::is_video_source() const
329{
330 return *d->properties.is_video_source;
331}
332
333const core::Property<bool>& media::PlayerStub::is_audio_source() const
334{
335 return *d->properties.is_audio_source;
336}
337
201const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const338const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const
202{339{
203 return *d->properties.playback_status;340 return *d->properties.playback_status;
@@ -270,6 +407,10 @@
270407
271const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const408const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const
272{409{
273 static core::Signal<uint64_t> signal;410 return d->signals.seeked_to;
274 return signal;411}
412
413const core::Signal<void>& media::PlayerStub::end_of_stream() const
414{
415 return d->signals.end_of_stream;
275}416}
276417
=== modified file 'src/core/media/player_stub.h'
--- src/core/media/player_stub.h 2014-02-18 19:27:01 +0000
+++ src/core/media/player_stub.h 2014-03-26 17:18:55 +0000
@@ -45,6 +45,8 @@
45 virtual std::shared_ptr<TrackList> track_list();45 virtual std::shared_ptr<TrackList> track_list();
4646
47 virtual bool open_uri(const Track::UriType& uri);47 virtual bool open_uri(const Track::UriType& uri);
48 virtual void create_video_sink(uint32_t texture_id);
49 virtual GLConsumerWrapperHybris gl_consumer() const;
48 virtual void next();50 virtual void next();
49 virtual void previous();51 virtual void previous();
50 virtual void play();52 virtual void play();
@@ -52,11 +54,15 @@
52 virtual void seek_to(const std::chrono::microseconds& offset);54 virtual void seek_to(const std::chrono::microseconds& offset);
53 virtual void stop();55 virtual void stop();
5456
57 virtual void set_frame_available_callback(FrameAvailableCb cb, void *context);
58
55 virtual const core::Property<bool>& can_play() const;59 virtual const core::Property<bool>& can_play() const;
56 virtual const core::Property<bool>& can_pause() const;60 virtual const core::Property<bool>& can_pause() const;
57 virtual const core::Property<bool>& can_seek() const;61 virtual const core::Property<bool>& can_seek() const;
58 virtual const core::Property<bool>& can_go_previous() const;62 virtual const core::Property<bool>& can_go_previous() const;
59 virtual const core::Property<bool>& can_go_next() const;63 virtual const core::Property<bool>& can_go_next() const;
64 virtual const core::Property<bool>& is_video_source() const;
65 virtual const core::Property<bool>& is_audio_source() const;
60 virtual const core::Property<PlaybackStatus>& playback_status() const;66 virtual const core::Property<PlaybackStatus>& playback_status() const;
61 virtual const core::Property<LoopStatus>& loop_status() const;67 virtual const core::Property<LoopStatus>& loop_status() const;
62 virtual const core::Property<PlaybackRate>& playback_rate() const;68 virtual const core::Property<PlaybackRate>& playback_rate() const;
@@ -74,6 +80,7 @@
74 virtual core::Property<Volume>& volume();80 virtual core::Property<Volume>& volume();
7581
76 virtual const core::Signal<uint64_t>& seeked_to() const;82 virtual const core::Signal<uint64_t>& seeked_to() const;
83 virtual const core::Signal<void>& end_of_stream() const;
7784
78 private:85 private:
79 struct Private;86 struct Private;
8087
=== modified file 'src/core/media/server/server.cpp'
--- src/core/media/server/server.cpp 2014-02-12 15:53:57 +0000
+++ src/core/media/server/server.cpp 2014-03-26 17:18:55 +0000
@@ -2,12 +2,23 @@
2#include <core/media/player.h>2#include <core/media/player.h>
3#include <core/media/track_list.h>3#include <core/media/track_list.h>
44
5#include <media/decoding_service.h>
6#include <media/media_codec_layer.h>
7
5#include "core/media/service_implementation.h"8#include "core/media/service_implementation.h"
69
10#include <iostream>
11
7namespace media = core::ubuntu::media;12namespace media = core::ubuntu::media;
813
14using namespace std;
15
9int main()16int main()
10{17{
18 // Init hybris-level DecodingService
19 decoding_service_init();
20 cout << "Starting DecodingService..." << endl;
21
11 auto service = std::make_shared<media::ServiceImplementation>();22 auto service = std::make_shared<media::ServiceImplementation>();
12 service->run();23 service->run();
1324
1425
=== modified file 'src/core/media/track_list_implementation.cpp'
--- src/core/media/track_list_implementation.cpp 2014-02-12 15:53:57 +0000
+++ src/core/media/track_list_implementation.cpp 2014-03-26 17:18:55 +0000
@@ -16,6 +16,9 @@
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */17 */
1818
19#include <stdio.h>
20#include <stdlib.h>
21
19#include "track_list_implementation.h"22#include "track_list_implementation.h"
2023
21#include "engine.h"24#include "engine.h"
@@ -45,6 +48,16 @@
45{48{
46}49}
4750
51media::Track::UriType media::TrackListImplementation::query_uri_for_track(const media::Track::Id& id)
52{
53 auto it = d->meta_data_cache.find(id);
54
55 if (it == d->meta_data_cache.end())
56 return Track::UriType{};
57
58 return std::get<0>(it->second);
59}
60
48media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id)61media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id)
49{62{
50 auto it = d->meta_data_cache.find(id);63 auto it = d->meta_data_cache.find(id);
5164
=== modified file 'src/core/media/track_list_implementation.h'
--- src/core/media/track_list_implementation.h 2014-02-12 15:53:57 +0000
+++ src/core/media/track_list_implementation.h 2014-03-26 17:18:55 +0000
@@ -36,6 +36,7 @@
36 const std::shared_ptr<Engine::MetaDataExtractor>& extractor);36 const std::shared_ptr<Engine::MetaDataExtractor>& extractor);
37 ~TrackListImplementation();37 ~TrackListImplementation();
3838
39 Track::UriType query_uri_for_track(const Track::Id& id);
39 Track::MetaData query_meta_data_for_track(const Track::Id& id);40 Track::MetaData query_meta_data_for_track(const Track::Id& id);
4041
41 void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current);42 void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current);
4243
=== modified file 'src/core/media/track_list_skeleton.cpp'
--- src/core/media/track_list_skeleton.cpp 2014-02-12 15:53:57 +0000
+++ src/core/media/track_list_skeleton.cpp 2014-03-26 17:18:55 +0000
@@ -48,7 +48,8 @@
48 object(object),48 object(object),
49 can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()),49 can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()),
50 tracks(object->get_property<mpris::TrackList::Properties::Tracks>()),50 tracks(object->get_property<mpris::TrackList::Properties::Tracks>()),
51 current_track(tracks->get().begin())51 current_track(tracks->get().begin()),
52 empty_iterator(tracks->get().begin())
52 {53 {
53 }54 }
5455
@@ -103,6 +104,7 @@
103 std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks;104 std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks;
104 std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks;105 std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks;
105 TrackList::ConstIterator current_track;106 TrackList::ConstIterator current_track;
107 TrackList::ConstIterator empty_iterator;
106108
107 core::Signal<void> on_track_list_replaced;109 core::Signal<void> on_track_list_replaced;
108 core::Signal<Track::Id> on_track_added;110 core::Signal<Track::Id> on_track_added;
@@ -142,12 +144,22 @@
142144
143bool media::TrackListSkeleton::has_next() const145bool media::TrackListSkeleton::has_next() const
144{146{
145 return std::next(d->current_track) != d->tracks->get().end();147 return d->current_track != d->tracks->get().end();
146}148}
147149
148const media::Track::Id& media::TrackListSkeleton::next()150const media::Track::Id& media::TrackListSkeleton::next()
149{151{
150 return *(d->current_track = std::next(d->current_track));152 if (d->tracks->get().empty())
153 return *(d->current_track);
154
155 if (d->tracks->get().size() && (d->current_track == d->empty_iterator))
156 {
157 d->current_track = d->tracks->get().begin();
158 return *(d->current_track = std::next(d->current_track));
159 }
160
161 d->current_track = std::next(d->current_track);
162 return *(d->current_track);
151}163}
152164
153const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const165const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const
154166
=== modified file 'src/core/media/track_list_skeleton.h'
--- src/core/media/track_list_skeleton.h 2014-02-12 15:53:57 +0000
+++ src/core/media/track_list_skeleton.h 2014-03-26 17:18:55 +0000
@@ -48,9 +48,10 @@
48 const core::Signal<Track::Id>& on_track_removed() const;48 const core::Signal<Track::Id>& on_track_removed() const;
49 const core::Signal<Track::Id>& on_track_changed() const;49 const core::Signal<Track::Id>& on_track_changed() const;
5050
51 core::Property<Container>& tracks();
52
51protected:53protected:
52 core::Property<bool>& can_edit_tracks();54 core::Property<bool>& can_edit_tracks();
53 core::Property<Container>& tracks();
5455
55 core::Signal<void>& on_track_list_replaced();56 core::Signal<void>& on_track_list_replaced();
56 core::Signal<Track::Id>& on_track_added();57 core::Signal<Track::Id>& on_track_added();

Subscribers

People subscribed via source and target branches