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

Proposed by Jim Hodapp
Status: Merged
Merged at revision: 28
Proposed branch: lp:~phablet-team/media-hub/video-support
Merge into: lp:media-hub
Prerequisite: lp:~sergiusens/media-hub/packaging
Diff against target: 2005 lines (+1032/-65)
30 files modified
CMakeLists.txt (+2/-0)
debian/control (+3/-0)
debian/media-hub.conf (+1/-1)
debian/media-hub.install (+1/-0)
debian/rules (+4/-0)
debian/usr.bin.media-hub-server (+98/-0)
include/core/media/player.h (+15/-3)
src/core/media/CMakeLists.txt (+6/-2)
src/core/media/apparmor.h (+51/-0)
src/core/media/engine.h (+8/-0)
src/core/media/gstreamer/engine.cpp (+86/-8)
src/core/media/gstreamer/engine.h (+8/-0)
src/core/media/gstreamer/playbin.h (+181/-20)
src/core/media/mpris/player.h (+4/-0)
src/core/media/player_implementation.cpp (+64/-7)
src/core/media/player_implementation.h (+4/-0)
src/core/media/player_skeleton.cpp (+192/-6)
src/core/media/player_skeleton.h (+10/-0)
src/core/media/player_stub.cpp (+167/-3)
src/core/media/player_stub.h (+9/-0)
src/core/media/server/server.cpp (+28/-0)
src/core/media/service.cpp (+1/-1)
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)
tests/acceptance-tests/service.cpp (+1/-1)
tests/unit-tests/CMakeLists.txt (+15/-1)
tests/unit-tests/libmedia-mock.cpp (+26/-0)
tests/unit-tests/test-gstreamer-engine.cpp (+16/-8)
To merge this branch: bzr merge lp:~phablet-team/media-hub/video-support
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ricardo Mendoza (community) Needs Fixing
Jamie Strandboge Pending
Ubuntu Phablet Team code Pending
Review via email: mp+212905@code.launchpad.net

This proposal supersedes 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.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:36
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~jhodapp/media-hub/video-support/+merge/212905/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/media-hub-ci/30/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-trusty-amd64-ci/31/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-trusty-armhf-ci/30/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/media-hub-trusty-i386-ci/30/console

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/media-hub-ci/30/rebuild

review: Needs Fixing (continuous-integration)
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.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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

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

Get rid of the visibility attribute.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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

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

91 +include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS} /usr/include/hybris)
99 + -lmedia

libmedia-dev ships a pkg config file for this

495 + std::cout << "IGBPWrapperHybris: " << igbp << std::endl;
496 + SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp);
497 + std::cout << "SurfaceTextureClientHybris: " << stc << std::endl;

Those couts are probably not needed anymore, even if we are keeping a good chunk of debug info

863 + seeked_to.connect([this](std::uint64_t value)
864 + {
865 + std::cout << "value: " << value << std::endl;
866 + //dbus.seeked_to->emit(value);
867 + });

Lets try and get rid of those ^

1166 + throw std::runtime_error("Problem switching to next track on remote object");

Odd error message from context

review: Needs Fixing
43. By Jim Hodapp

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

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

Snap to the preceeding key unit after doing a seek.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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.

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

Enable the seeked_to signal

47. By Jim Hodapp

Merged with ricmm's EOS fix branch

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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.

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

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

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

Enable streaming sources to work with media-hub

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

Allow apps to access their own media files in /opt

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

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

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

Slightly improve the get_position_duration_works unit test

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

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

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
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-02-14 07:19:31 +0000
+++ CMakeLists.txt 2014-04-17 21:13:23 +0000
@@ -25,6 +25,8 @@
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)
29pkg_check_modules(HYBRIS_MEDIA libmedia REQUIRED)
2830
29#####################################################################31#####################################################################
30# Enable code coverage calculation with gcov/gcovr/lcov32# Enable code coverage calculation with gcov/gcovr/lcov
3133
=== modified file 'debian/control'
--- debian/control 2014-03-26 20:18:20 +0000
+++ debian/control 2014-04-17 21:13:23 +0000
@@ -5,6 +5,7 @@
5Build-Depends: cmake,5Build-Depends: cmake,
6 dbus-test-runner,6 dbus-test-runner,
7 debhelper (>= 9),7 debhelper (>= 9),
8 dh-apparmor,
8 doxygen,9 doxygen,
9 gcc-4.7,10 gcc-4.7,
10 g++-4.7,11 g++-4.7,
@@ -39,6 +40,7 @@
39Depends: libmedia-hub-common0 (= ${binary:Version}),40Depends: libmedia-hub-common0 (= ${binary:Version}),
40 libmedia-hub-client0 (= ${binary:Version}),41 libmedia-hub-client0 (= ${binary:Version}),
41 ${misc:Depends},42 ${misc:Depends},
43 libproperties-cpp-dev,
42Suggests: libmedia-hub-doc44Suggests: libmedia-hub-doc
43Description: Simple and lightweight media playback service - development files45Description: Simple and lightweight media playback service - development files
44 Media Hub is a simple and lightweight service for media playback using46 Media Hub is a simple and lightweight service for media playback using
@@ -51,6 +53,7 @@
51Pre-Depends: dpkg (>= 1.15.6~)53Pre-Depends: dpkg (>= 1.15.6~)
52Depends: ${misc:Depends},54Depends: ${misc:Depends},
53 ${shlibs:Depends},55 ${shlibs:Depends},
56Suggests: apparmor (>= 2.8.95~2430-0ubuntu4~)
54Description: Simple and lightweight media playback service57Description: Simple and lightweight media playback service
55 Media Hub is a simple and lightweight service for media playback using58 Media Hub is a simple and lightweight service for media playback using
56 DBus.59 DBus.
5760
=== modified file 'debian/media-hub.conf'
--- debian/media-hub.conf 2014-03-07 14:38:28 +0000
+++ debian/media-hub.conf 2014-04-17 21:13:23 +0000
@@ -1,6 +1,6 @@
1description "Starts the media-hub service"1description "Starts the media-hub service"
22
3start on dbus3start on started dbus
4stop on runlevel [06]4stop on runlevel [06]
55
6exec media-hub-server6exec media-hub-server
77
=== modified file 'debian/media-hub.install'
--- debian/media-hub.install 2014-03-06 22:51:51 +0000
+++ debian/media-hub.install 2014-04-17 21:13:23 +0000
@@ -1,2 +1,3 @@
1debian/media-hub.conf /usr/share/upstart/sessions/1debian/media-hub.conf /usr/share/upstart/sessions/
2debian/usr.bin.media-hub-server etc/apparmor.d
2usr/bin3usr/bin
34
=== modified file 'debian/rules'
--- debian/rules 2014-03-07 22:49:23 +0000
+++ debian/rules 2014-04-17 21:13:23 +0000
@@ -14,3 +14,7 @@
1414
15override_dh_auto_test:15override_dh_auto_test:
16 env -u LD_PRELOAD dh_auto_test16 env -u LD_PRELOAD dh_auto_test
17
18override_dh_installdeb:
19 dh_apparmor --profile-name=usr.bin.media-hub-server -pmedia-hub
20 dh_installdeb
1721
=== added file 'debian/usr.bin.media-hub-server'
--- debian/usr.bin.media-hub-server 1970-01-01 00:00:00 +0000
+++ debian/usr.bin.media-hub-server 2014-04-17 21:13:23 +0000
@@ -0,0 +1,98 @@
1#include <tunables/global>
2
3/usr/bin/media-hub-server (attach_disconnected) {
4 #include <abstractions/base>
5 #include <abstractions/audio>
6 #include <abstractions/nameservice>
7 #include <abstractions/dbus-session>
8 #include <abstractions/dbus-strict>
9 #include <abstractions/user-tmp>
10 #include "/usr/share/apparmor/hardware/audio.d"
11 #include "/usr/share/apparmor/hardware/graphics.d"
12 #include "/usr/share/apparmor/hardware/video.d"
13
14 deny /dev/cpuctl/apps/tasks w,
15 deny /dev/cpuctl/apps/bg_non_interactive/tasks w,
16
17 @{PROC}/interrupts r,
18 owner @{PROC}/cmdline r,
19 owner @{PROC}/[0-9]*/auxv r,
20 owner @{PROC}/[0-9]*/fd/ r,
21 owner @{PROC}/[0-9]*/status r,
22 owner @{PROC}/[0-9]*/task/ r,
23 owner @{PROC}/[0-9]*/task/[0-9]*/ r,
24 owner @{PROC}/[0-9]*/cmdline r,
25
26 /sys/kernel/debug/tracing/trace_marker w,
27 /dev/ashmem rw,
28
29 # Explicitly deny this-- it is not needed
30 /dev/fb0 rw,
31
32 # libhybris
33 /{,var/}run/shm/hybris_shm_data rw,
34 /usr/lib/@{multiarch}/libhybris/*.so mr,
35 /{,android/}system/build.prop r,
36 # These libraries can be in any of:
37 # /vendor/lib
38 # /system/lib
39 # /system/vendor/lib
40 # /android/vendor/lib
41 # /android/system/lib
42 # /android/system/vendor/lib
43 /{,android/}vendor/lib/** r,
44 /{,android/}vendor/lib/**.so m,
45 /{,android/}system/lib/** r,
46 /{,android/}system/lib/**.so m,
47 /{,android/}system/vendor/lib/** r,
48 /{,android/}system/vendor/lib/**.so m,
49
50 # attach_disconnected path
51 /dev/socket/property_service rw,
52
53 # Android logging triggered by platform. Can safely deny
54 deny /dev/log_main w,
55 deny /dev/log_radio w,
56 deny /dev/log_events w,
57 deny /dev/log_system w,
58
59 # Allow all access to powerd for now, but we can fine-tune this if needed
60 dbus (receive, send)
61 bus=system
62 path=/com/canonical/powerd
63 interface=com.canonical.powerd,
64
65 # GStreamer binary registry - hybris pulls this in for everything now, not
66 # just audio
67 owner @{HOME}/.gstreamer*/registry.*.bin* rw,
68 owner @{HOME}/.gstreamer*/ rw,
69 owner @{HOME}/.cache/gstreamer*/registry.*.bin* rw,
70
71 /{,android/}system/etc/media_codecs.xml r,
72 /etc/wildmidi/wildmidi.cfg r,
73
74 audit deny owner /** m,
75
76 # Allow read on all directories
77 /**/ r,
78
79 # Allow read on click install directories, removable media and files in
80 # /usr/local/share.
81 /usr/share/** r,
82 /usr/local/share/** r,
83 /{media,mnt,opt,srv}/** r,
84
85 # Allow reading any files in non-hidden directories
86 owner @{HOME}/[^.]* rk,
87 owner @{HOME}/[^.]*/ rk,
88 owner @{HOME}/[^.]*/** rk,
89
90 # Allow reading files in XDG directories (ie, where apps are allowed to
91 # write)
92 owner @{HOME}/.cache/** rk,
93 owner @{HOME}/.local/share/** rk,
94 owner /{,var/}run/user/[0-9]*/** rk,
95
96 # Site-specific additions and overrides. See local/README for details.
97 #include <local/usr.bin.media-hub-server>
98}
099
=== 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-04-17 21:13:23 +0000
@@ -39,6 +39,12 @@
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);
47 typedef void (*PlaybackCompleteCb)(void *context);
4248
43 struct Configuration;49 struct Configuration;
4450
@@ -74,6 +80,8 @@
74 virtual std::shared_ptr<TrackList> track_list() = 0;80 virtual std::shared_ptr<TrackList> track_list() = 0;
7581
76 virtual bool open_uri(const Track::UriType& uri) = 0;82 virtual bool open_uri(const Track::UriType& uri) = 0;
83 virtual void create_video_sink(uint32_t texture_id) = 0;
84 virtual GLConsumerWrapperHybris gl_consumer() const = 0;
77 virtual void next() = 0;85 virtual void next() = 0;
78 virtual void previous() = 0;86 virtual void previous() = 0;
79 virtual void play() = 0;87 virtual void play() = 0;
@@ -81,11 +89,17 @@
81 virtual void stop() = 0;89 virtual void stop() = 0;
82 virtual void seek_to(const std::chrono::microseconds& offset) = 0;90 virtual void seek_to(const std::chrono::microseconds& offset) = 0;
8391
92 // TODO: Convert this to be a signal
93 virtual void set_frame_available_callback(FrameAvailableCb cb, void *context) = 0;
94 virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context) = 0;
95
84 virtual const core::Property<bool>& can_play() const = 0;96 virtual const core::Property<bool>& can_play() const = 0;
85 virtual const core::Property<bool>& can_pause() const = 0;97 virtual const core::Property<bool>& can_pause() const = 0;
86 virtual const core::Property<bool>& can_seek() const = 0;98 virtual const core::Property<bool>& can_seek() const = 0;
87 virtual const core::Property<bool>& can_go_previous() const = 0;99 virtual const core::Property<bool>& can_go_previous() const = 0;
88 virtual const core::Property<bool>& can_go_next() const = 0;100 virtual const core::Property<bool>& can_go_next() const = 0;
101 virtual const core::Property<bool>& is_video_source() const = 0;
102 virtual const core::Property<bool>& is_audio_source() const = 0;
89 virtual const core::Property<PlaybackStatus>& playback_status() const = 0;103 virtual const core::Property<PlaybackStatus>& playback_status() const = 0;
90 virtual const core::Property<LoopStatus>& loop_status() const = 0;104 virtual const core::Property<LoopStatus>& loop_status() const = 0;
91 virtual const core::Property<PlaybackRate>& playback_rate() const = 0;105 virtual const core::Property<PlaybackRate>& playback_rate() const = 0;
@@ -97,15 +111,13 @@
97 virtual const core::Property<uint64_t>& position() const = 0;111 virtual const core::Property<uint64_t>& position() const = 0;
98 virtual const core::Property<uint64_t>& duration() const = 0;112 virtual const core::Property<uint64_t>& duration() const = 0;
99113
100
101 virtual core::Property<LoopStatus>& loop_status() = 0;114 virtual core::Property<LoopStatus>& loop_status() = 0;
102 virtual core::Property<PlaybackRate>& playback_rate() = 0;115 virtual core::Property<PlaybackRate>& playback_rate() = 0;
103 virtual core::Property<bool>& is_shuffle() = 0;116 virtual core::Property<bool>& is_shuffle() = 0;
104 virtual core::Property<Volume>& volume() = 0;117 virtual core::Property<Volume>& volume() = 0;
105118
106
107 virtual const core::Signal<uint64_t>& seeked_to() const = 0;119 virtual const core::Signal<uint64_t>& seeked_to() const = 0;
108120 virtual const core::Signal<void>& end_of_stream() const = 0;
109 protected:121 protected:
110 Player();122 Player();
111123
112124
=== 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-04-17 21:13:23 +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} ${HYBRIS_MEDIA_CFLAGS})
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 ${HYBRIS_MEDIA_LIBRARIES}
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 ${HYBRIS_MEDIA_LIBRARIES}
85)88)
8689
87include_directories(${PROJECT_SOURCE_DIR}/src/)90include_directories(${PROJECT_SOURCE_DIR}/src/ ${HYBRIS_MEDIA_CFLAGS})
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 ${HYBRIS_MEDIA_LIBRARIES}
105)109)
106110
107install(111install(
108112
=== added file 'src/core/media/apparmor.h'
--- src/core/media/apparmor.h 1970-01-01 00:00:00 +0000
+++ src/core/media/apparmor.h 2014-04-17 21:13:23 +0000
@@ -0,0 +1,51 @@
1/*
2 * Copyright (C) 2013-2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Author: Ricardo Mendoza <ricardo.mendoza@canonical.com>
17 */
18
19#ifndef APPARMOR_H_DBUS_
20#define APPARMOR_H_DBUS_
21
22#include <string>
23#include <chrono>
24
25namespace core
26{
27
28struct Apparmor
29{
30 static std::string& name()
31 {
32 static std::string s = "org.freedesktop.DBus";
33 return s;
34 }
35
36 struct getConnectionAppArmorSecurityContext
37 {
38 static std::string name()
39 {
40 static std::string s = "GetConnectionAppArmorSecurityContext";
41 return s;
42 }
43
44 static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; }
45
46 typedef Apparmor Interface;
47 };
48};
49}
50
51#endif
052
=== 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-04-17 21:13:23 +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,10 @@
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<uint64_t>& seeked_to_signal() const = 0;
120 virtual const core::Signal<void>& end_of_stream_signal() const = 0;
113};121};
114}122}
115}123}
116124
=== 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-04-17 21:13:23 +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,31 @@
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_seeked_to(uint64_t value)
172 {
173 seeked_to(value);
174 }
175
176 void on_end_of_stream()
177 {
178 end_of_stream();
179 }
180
166 Private()181 Private()
167 : meta_data_extractor(new gstreamer::MetaDataExtractor()),182 : meta_data_extractor(new gstreamer::MetaDataExtractor()),
168 volume(media::Engine::Volume(1.)),183 volume(media::Engine::Volume(1.)),
184 is_video_source(false),
185 is_audio_source(false),
169 about_to_finish_connection(186 about_to_finish_connection(
170 playbin.signals.about_to_finish.connect(187 playbin.signals.about_to_finish.connect(
171 std::bind(188 std::bind(
172 &Private::about_to_finish,189 &Private::on_about_to_finish,
173 this))),190 this))),
174 on_state_changed_connection(191 on_state_changed_connection(
175 playbin.signals.on_state_changed.connect(192 playbin.signals.on_state_changed.connect(
@@ -188,7 +205,18 @@
188 std::bind(205 std::bind(
189 &Private::on_volume_changed,206 &Private::on_volume_changed,
190 this,207 this,
191 std::placeholders::_1)))208 std::placeholders::_1))),
209 on_seeked_to_connection(
210 playbin.signals.on_seeked_to.connect(
211 std::bind(
212 &Private::on_seeked_to,
213 this,
214 std::placeholders::_1))),
215 on_end_of_stream_connection(
216 playbin.signals.on_end_of_stream.connect(
217 std::bind(
218 &Private::on_end_of_stream,
219 this)))
192 {220 {
193 }221 }
194222
@@ -198,11 +226,19 @@
198 core::Property<uint64_t> position;226 core::Property<uint64_t> position;
199 core::Property<uint64_t> duration;227 core::Property<uint64_t> duration;
200 core::Property<media::Engine::Volume> volume;228 core::Property<media::Engine::Volume> volume;
229 core::Property<bool> is_video_source;
230 core::Property<bool> is_audio_source;
201 gstreamer::Playbin playbin;231 gstreamer::Playbin playbin;
202 core::ScopedConnection about_to_finish_connection;232 core::ScopedConnection about_to_finish_connection;
203 core::ScopedConnection on_state_changed_connection;233 core::ScopedConnection on_state_changed_connection;
204 core::ScopedConnection on_tag_available_connection;234 core::ScopedConnection on_tag_available_connection;
205 core::ScopedConnection on_volume_changed_connection;235 core::ScopedConnection on_volume_changed_connection;
236 core::ScopedConnection on_seeked_to_connection;
237 core::ScopedConnection on_end_of_stream_connection;
238
239 core::Signal<void> about_to_finish;
240 core::Signal<uint64_t> seeked_to;
241 core::Signal<void> end_of_stream;
206};242};
207243
208gstreamer::Engine::Engine() : d(new Private{})244gstreamer::Engine::Engine() : d(new Private{})
@@ -231,6 +267,11 @@
231 return true;267 return true;
232}268}
233269
270void gstreamer::Engine::create_video_sink(uint32_t texture_id)
271{
272 d->playbin.create_video_sink(texture_id);
273}
274
234bool gstreamer::Engine::play()275bool gstreamer::Engine::play()
235{276{
236 auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);277 auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING);
@@ -268,6 +309,28 @@
268 return d->playbin.seek(ts);309 return d->playbin.seek(ts);
269}310}
270311
312const core::Property<bool>& gstreamer::Engine::is_video_source() const
313{
314 gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
315 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO)
316 d->is_video_source.set(true);
317 else
318 d->is_video_source.set(false);
319
320 return d->is_video_source;
321}
322
323const core::Property<bool>& gstreamer::Engine::is_audio_source() const
324{
325 gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type();
326 if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO)
327 d->is_audio_source.set(true);
328 else
329 d->is_audio_source.set(false);
330
331 return d->is_audio_source;
332}
333
271const core::Property<uint64_t>& gstreamer::Engine::position() const334const core::Property<uint64_t>& gstreamer::Engine::position() const
272{335{
273 d->position.set(d->playbin.position());336 d->position.set(d->playbin.position());
@@ -295,3 +358,18 @@
295{358{
296 return d->track_meta_data;359 return d->track_meta_data;
297}360}
361
362const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const
363{
364 return d->about_to_finish;
365}
366
367const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const
368{
369 return d->seeked_to;
370}
371
372const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const
373{
374 return d->end_of_stream;
375}
298376
=== 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-04-17 21:13:23 +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,10 @@
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<uint64_t>& seeked_to_signal() const;
56 const core::Signal<void>& end_of_stream_signal() const;
57
50private:58private:
51 struct Private;59 struct Private;
52 std::unique_ptr<Private> d;60 std::unique_ptr<Private> d;
5361
=== 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-04-17 21:13:23 +0000
@@ -21,6 +21,10 @@
2121
22#include "bus.h"22#include "bus.h"
2323
24#include <hybris/media/media_codec_layer.h>
25#include <hybris/media/surface_texture_client_hybris.h>
26
27#include <gio/gio.h>
24#include <gst/gst.h>28#include <gst/gst.h>
2529
26#include <chrono>30#include <chrono>
@@ -37,6 +41,13 @@
37 GST_PLAY_FLAG_TEXT = (1 << 2)41 GST_PLAY_FLAG_TEXT = (1 << 2)
38 };42 };
3943
44 enum MediaFileType
45 {
46 MEDIA_FILE_TYPE_NONE,
47 MEDIA_FILE_TYPE_AUDIO,
48 MEDIA_FILE_TYPE_VIDEO
49 };
50
40 static const std::string& pipeline_name()51 static const std::string& pipeline_name()
41 {52 {
42 static const std::string s{"playbin"};53 static const std::string s{"playbin"};
@@ -45,20 +56,22 @@
4556
46 static void about_to_finish(GstElement*,57 static void about_to_finish(GstElement*,
47 gpointer user_data)58 gpointer user_data)
48 { auto thiz = static_cast<Playbin*>(user_data);59 {
4960 auto thiz = static_cast<Playbin*>(user_data);
50 thiz->signals.about_to_finish();61 thiz->signals.about_to_finish();
51 }62 }
5263
53 Playbin()64 Playbin()
54 : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())),65 : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())),
55 bus{gst_element_get_bus(pipeline)},66 bus{gst_element_get_bus(pipeline)},
67 file_type(MEDIA_FILE_TYPE_NONE),
56 on_new_message_connection(68 on_new_message_connection(
57 bus.on_new_message.connect(69 bus.on_new_message.connect(
58 std::bind(70 std::bind(
59 &Playbin::on_new_message,71 &Playbin::on_new_message,
60 this,72 this,
61 std::placeholders::_1)))73 std::placeholders::_1))),
74 is_seeking(false)
62 {75 {
63 if (!pipeline)76 if (!pipeline)
64 throw std::runtime_error("Could not create pipeline for playbin.");77 throw std::runtime_error("Could not create pipeline for playbin.");
@@ -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,16 @@
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_ASYNC_DONE:
157 if (is_seeking)
158 {
159 // FIXME: Pass the actual playback time position to the signal call
160 signals.on_seeked_to(0);
161 is_seeking = false;
162 }
163 break;
164 case GST_MESSAGE_EOS:
165 signals.on_end_of_stream();
104 default:166 default:
105 break;167 break;
106 }168 }
@@ -126,6 +188,8 @@
126 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),188 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"),
127 "audio-sink");189 "audio-sink");
128190
191 std::cout << "audio_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") << std::endl;
192
129 g_object_set (193 g_object_set (
130 pipeline,194 pipeline,
131 "audio-sink",195 "audio-sink",
@@ -136,26 +200,41 @@
136 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)200 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)
137 {201 {
138 auto video_sink = gst_element_factory_make (202 auto video_sink = gst_element_factory_make (
139 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),203 ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"),
140 "video-sink");204 "video-sink");
141205
142 std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;206 std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl;
143207
144 g_object_set (208 g_object_set (
145 pipeline,209 pipeline,
146 "video-sink",210 "video-sink",
147 video_sink,211 video_sink,
148 NULL);212 NULL);
213 }
214 }
215
216 void create_video_sink(uint32_t texture_id)
217 {
218 std::cout << "Creating video sink for texture_id: " << texture_id << std::endl;
219
220 if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr)
221 {
222 GstElement *video_sink = NULL;
223 g_object_get (pipeline, "video_sink", &video_sink, NULL);
224
225 // Get the service-side BufferQueue (IGraphicBufferProducer) and associate it with
226 // the SurfaceTextureClientHybris instance
227 IGBPWrapperHybris igbp = decoding_service_get_igraphicbufferproducer();
228 SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp);
229 // Because mirsink is being loaded, we are definitely doing * hardware rendering.
230 surface_texture_client_set_hardware_rendering (stc, TRUE);
231 g_object_set (G_OBJECT (video_sink), "surface", static_cast<gpointer>(stc), static_cast<char*>(NULL));
149 }232 }
150 }233 }
151234
152 void set_volume(double new_volume)235 void set_volume(double new_volume)
153 {236 {
154 g_object_set(237 g_object_set(pipeline, "volume", new_volume, NULL);
155 pipeline,
156 "volume",
157 new_volume,
158 NULL);
159 }238 }
160239
161 uint64_t position() const240 uint64_t position() const
@@ -178,11 +257,11 @@
178257
179 void set_uri(const std::string& uri)258 void set_uri(const std::string& uri)
180 {259 {
181 g_object_set(260 g_object_set(pipeline, "uri", uri.c_str(), NULL);
182 pipeline,261 if (is_video_file(uri))
183 "uri",262 file_type = MEDIA_FILE_TYPE_VIDEO;
184 uri.c_str(),263 else if (is_audio_file(uri))
185 NULL);264 file_type = MEDIA_FILE_TYPE_AUDIO;
186 }265 }
187266
188 std::string uri() const267 std::string uri() const
@@ -229,16 +308,96 @@
229308
230 bool seek(const std::chrono::microseconds& ms)309 bool seek(const std::chrono::microseconds& ms)
231 {310 {
311 is_seeking = true;
232 return gst_element_seek_simple(312 return gst_element_seek_simple(
233 pipeline,313 pipeline,
234 GST_FORMAT_TIME,314 GST_FORMAT_TIME,
235 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),315 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT |
316 GST_SEEK_FLAG_SNAP_BEFORE),
236 ms.count() * 1000);317 ms.count() * 1000);
237 }318 }
238319
320 std::string get_file_content_type(const std::string& uri) const
321 {
322 if (uri.empty())
323 return std::string();
324
325 std::string filename(uri);
326 std::cout << "filename: " << filename << std::endl;
327 size_t pos = uri.find("file://");
328 if (pos != std::string::npos)
329 filename = uri.substr(pos + 7, std::string::npos);
330 else
331 // Anything other than a file, for now claim that the type
332 // is both audio and video.
333 // FIXME: implement true net stream sampling and get the type from GstCaps
334 return std::string("audio/video/");
335
336
337 GError *error = nullptr;
338 std::unique_ptr<GFile, void(*)(void *)> file(
339 g_file_new_for_path(filename.c_str()), g_object_unref);
340 std::unique_ptr<GFileInfo, void(*)(void *)> info(
341 g_file_query_info(
342 file.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE ","
343 G_FILE_ATTRIBUTE_ETAG_VALUE, G_FILE_QUERY_INFO_NONE,
344 /* cancellable */ NULL, &error),
345 g_object_unref);
346 if (!info)
347 {
348 std::string error_str(error->message);
349 g_error_free(error);
350
351 std::cout << "Failed to query the URI for the presence of video content: "
352 << error_str << std::endl;
353 return std::string();
354 }
355
356 std::string content_type(g_file_info_get_attribute_string(
357 info.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE));
358
359 return content_type;
360 }
361
362 bool is_audio_file(const std::string& uri) const
363 {
364 if (uri.empty())
365 return false;
366
367 if (get_file_content_type(uri).find("audio/") == 0)
368 {
369 std::cout << "Found audio content" << std::endl;
370 return true;
371 }
372
373 return false;
374 }
375
376 bool is_video_file(const std::string& uri) const
377 {
378 if (uri.empty())
379 return false;
380
381 if (get_file_content_type(uri).find("video/") == 0)
382 {
383 std::cout << "Found video content" << std::endl;
384 return true;
385 }
386
387 return false;
388 }
389
390 MediaFileType media_file_type() const
391 {
392 return file_type;
393 }
394
239 GstElement* pipeline;395 GstElement* pipeline;
240 gstreamer::Bus bus;396 gstreamer::Bus bus;
397 MediaFileType file_type;
398 SurfaceTextureClientHybris stc_hybris;
241 core::Connection on_new_message_connection;399 core::Connection on_new_message_connection;
400 bool is_seeking;
242 struct401 struct
243 {402 {
244 core::Signal<void> about_to_finish;403 core::Signal<void> about_to_finish;
@@ -247,6 +406,8 @@
247 core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info;406 core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info;
248 core::Signal<Bus::Message::Detail::Tag> on_tag_available;407 core::Signal<Bus::Message::Detail::Tag> on_tag_available;
249 core::Signal<Bus::Message::Detail::StateChanged> on_state_changed;408 core::Signal<Bus::Message::Detail::StateChanged> on_state_changed;
409 core::Signal<uint64_t> on_seeked_to;
410 core::Signal<void> on_end_of_stream;
250 } signals;411 } signals;
251};412};
252}413}
253414
=== 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-04-17 21:13:23 +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-04-17 21:13:23 +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,38 @@
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->seeked_to_signal().connect([this](uint64_t value)
132 {
133 seeked_to()(value);
134 });
135
136 engine->end_of_stream_signal().connect([this]()
137 {
138 end_of_stream()();
139 });
101}140}
102141
103media::PlayerImplementation::~PlayerImplementation()142media::PlayerImplementation::~PlayerImplementation()
@@ -114,6 +153,17 @@
114 return d->engine->open_resource_for_uri(uri);153 return d->engine->open_resource_for_uri(uri);
115}154}
116155
156void media::PlayerImplementation::create_video_sink(uint32_t texture_id)
157{
158 d->engine->create_video_sink(texture_id);
159}
160
161media::Player::GLConsumerWrapperHybris media::PlayerImplementation::gl_consumer() const
162{
163 // This method is client-side only and is simply a no-op for the service side
164 return NULL;
165}
166
117void media::PlayerImplementation::next()167void media::PlayerImplementation::next()
118{168{
119}169}
@@ -124,11 +174,6 @@
124174
125void media::PlayerImplementation::play()175void media::PlayerImplementation::play()
126{176{
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();177 d->engine->play();
133}178}
134179
@@ -142,6 +187,18 @@
142 d->engine->stop();187 d->engine->stop();
143}188}
144189
190void media::PlayerImplementation::set_frame_available_callback(
191 UNUSED FrameAvailableCb cb, UNUSED void *context)
192{
193 // This method is client-side only and is simply a no-op for the service side
194}
195
196void media::PlayerImplementation::set_playback_complete_callback(
197 UNUSED PlaybackCompleteCb cb, UNUSED void *context)
198{
199 // This method is client-side only and is simply a no-op for the service side
200}
201
145void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)202void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms)
146{203{
147 d->engine->seek_to(ms);204 d->engine->seek_to(ms);
148205
=== 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-04-17 21:13:23 +0000
@@ -43,11 +43,15 @@
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);
54 virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
51 virtual void seek_to(const std::chrono::microseconds& offset);55 virtual void seek_to(const std::chrono::microseconds& offset);
5256
53private:57private:
5458
=== 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-04-17 21:13:23 +0000
@@ -16,6 +16,7 @@
16 * Authored by: Thomas Voß <thomas.voss@canonical.com>16 * Authored by: Thomas Voß <thomas.voss@canonical.com>
17 */17 */
1818
19#include "apparmor.h"
19#include "codec.h"20#include "codec.h"
20#include "player_skeleton.h"21#include "player_skeleton.h"
21#include "player_traits.h"22#include "player_traits.h"
@@ -27,6 +28,7 @@
27#include <core/dbus/object.h>28#include <core/dbus/object.h>
28#include <core/dbus/property.h>29#include <core/dbus/property.h>
29#include <core/dbus/stub.h>30#include <core/dbus/stub.h>
31#include <core/dbus/asio/executor.h>
3032
31namespace dbus = core::dbus;33namespace dbus = core::dbus;
32namespace media = core::ubuntu::media;34namespace media = core::ubuntu::media;
@@ -36,6 +38,7 @@
36 Private(media::PlayerSkeleton* player, const dbus::types::ObjectPath& session)38 Private(media::PlayerSkeleton* player, const dbus::types::ObjectPath& session)
37 : impl(player),39 : impl(player),
38 object(impl->access_service()->add_object_for_path(session)),40 object(impl->access_service()->add_object_for_path(session)),
41 apparmor_session(nullptr),
39 properties42 properties
40 {43 {
41 object->get_property<mpris::Player::Properties::CanPlay>(),44 object->get_property<mpris::Player::Properties::CanPlay>(),
@@ -44,6 +47,8 @@
44 object->get_property<mpris::Player::Properties::CanControl>(),47 object->get_property<mpris::Player::Properties::CanControl>(),
45 object->get_property<mpris::Player::Properties::CanGoNext>(),48 object->get_property<mpris::Player::Properties::CanGoNext>(),
46 object->get_property<mpris::Player::Properties::CanGoPrevious>(),49 object->get_property<mpris::Player::Properties::CanGoPrevious>(),
50 object->get_property<mpris::Player::Properties::IsVideoSource>(),
51 object->get_property<mpris::Player::Properties::IsAudioSource>(),
47 object->get_property<mpris::Player::Properties::PlaybackStatus>(),52 object->get_property<mpris::Player::Properties::PlaybackStatus>(),
48 object->get_property<mpris::Player::Properties::LoopStatus>(),53 object->get_property<mpris::Player::Properties::LoopStatus>(),
49 object->get_property<mpris::Player::Properties::PlaybackRate>(),54 object->get_property<mpris::Player::Properties::PlaybackRate>(),
@@ -54,6 +59,11 @@
54 object->get_property<mpris::Player::Properties::Duration>(),59 object->get_property<mpris::Player::Properties::Duration>(),
55 object->get_property<mpris::Player::Properties::MinimumRate>(),60 object->get_property<mpris::Player::Properties::MinimumRate>(),
56 object->get_property<mpris::Player::Properties::MaximumRate>()61 object->get_property<mpris::Player::Properties::MaximumRate>()
62 },
63 signals
64 {
65 object->get_signal<mpris::Player::Signals::Seeked>(),
66 object->get_signal<mpris::Player::Signals::EndOfStream>()
57 }67 }
58 {68 {
59 }69 }
@@ -111,18 +121,123 @@
111 {121 {
112 }122 }
113123
124 void handle_create_video_sink(const core::dbus::Message::Ptr& in)
125 {
126 uint32_t texture_id;
127 in->reader() >> texture_id;
128 impl->create_video_sink(texture_id);
129
130 auto reply = dbus::Message::make_method_return(in);
131 impl->access_bus()->send(reply);
132 }
133
134 std::string get_client_apparmor_context(const core::dbus::Message::Ptr& msg)
135 {
136 auto bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::session));
137 bus->install_executor(dbus::asio::make_executor(bus));
138
139 auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::Apparmor>::interface_name());
140 apparmor_session = stub_service->object_for_path(dbus::types::ObjectPath("/org/freedesktop/DBus"));
141 // Get the AppArmor security context for the client
142 auto result = apparmor_session->invoke_method_synchronously<core::Apparmor::getConnectionAppArmorSecurityContext, std::string>(msg->sender());
143 if (result.is_error())
144 {
145 std::cout << "Error getting apparmor profile: " << result.error().print() << std::endl;
146 return std::string();
147 }
148
149 return result.value();
150 }
151
152 bool does_client_have_access(const std::string& context, const std::string& uri)
153 {
154 if (context.empty() || uri.empty())
155 {
156 std::cout << "Client denied access since context or uri are empty" << std::endl;
157 return false;
158 }
159
160 if (context == "unconfined")
161 {
162 std::cout << "Client allowed access since it's unconfined" << std::endl;
163 return true;
164 }
165
166 size_t pos = context.find_first_of('_');
167 if (pos == std::string::npos)
168 {
169 std::cout << "Client denied access since it's an invalid apparmor security context" << std::endl;
170 return false;
171 }
172
173 const std::string pkgname = context.substr(0, pos);
174 std::cout << "client pkgname: " << pkgname << std::endl;
175 std::cout << "uri: " << uri << std::endl;
176
177 // All confined apps can access their own files
178 if (uri.find(std::string(".local/share/" + pkgname + "/")) != std::string::npos
179 || uri.find(std::string(".cache/" + pkgname + "/")) != std::string::npos)
180 {
181 std::cout << "Client can access content in ~/.local/share/" << pkgname << " or ~/.cache/" << pkgname << std::endl;
182 return true;
183 }
184 else if (uri.find(std::string("opt/click.ubuntu.com/")) != std::string::npos
185 && uri.find(pkgname) != std::string::npos)
186 {
187 std::cout << "Client can access content in own opt directory" << std::endl;
188 return true;
189 }
190 else if ((uri.find(std::string("/system/media/audio/ui/")) != std::string::npos
191 || uri.find(std::string("/android/system/media/audio/ui/")) != std::string::npos)
192 && pkgname == "com.ubuntu.camera")
193 {
194 std::cout << "Camera app can access ui sounds" << std::endl;
195 return true;
196 }
197 // TODO: Check if the trust store previously allowed direct access to uri
198
199 // Check in ~/Music and ~/Videos
200 // TODO: when the trust store lands, check it to see if this app can access the dirs and
201 // then remove the explicit whitelist of the music-app
202 else if (pkgname == "com.ubuntu.music" &&
203 (uri.find(std::string("Music/")) != std::string::npos
204 || uri.find(std::string("Videos/")) != std::string::npos))
205 {
206 std::cout << "Client can access content in ~/Music or ~/Videos" << std::endl;
207 return true;
208 }
209 else if (uri.find(std::string("http://")) != std::string::npos
210 || uri.find(std::string("rtsp://")) != std::string::npos)
211 {
212 std::cout << "Client can access streaming content" << std::endl;
213 return true;
214 }
215 else
216 {
217 std::cout << "Client denied access to open_uri()" << std::endl;
218 return false;
219 }
220 }
221
114 void handle_open_uri(const core::dbus::Message::Ptr& in)222 void handle_open_uri(const core::dbus::Message::Ptr& in)
115 {223 {
116 Track::UriType uri;224 Track::UriType uri;
117 in->reader() >> uri;225 in->reader() >> uri;
118226
227 std::string context = get_client_apparmor_context(in);
228 bool have_access = does_client_have_access(context, uri);
229
119 auto reply = dbus::Message::make_method_return(in);230 auto reply = dbus::Message::make_method_return(in);
120 reply->writer() << impl->open_uri(uri);231 if (have_access)
232 reply->writer() << impl->open_uri(uri);
233 else
234 reply->writer() << false;
121 impl->access_bus()->send(reply);235 impl->access_bus()->send(reply);
122 }236 }
123237
124 media::PlayerSkeleton* impl;238 media::PlayerSkeleton* impl;
125 dbus::Object::Ptr object;239 dbus::Object::Ptr object;
240 dbus::Object::Ptr apparmor_session;
126 struct241 struct
127 {242 {
128 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;243 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play;
@@ -131,6 +246,8 @@
131 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;246 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;247 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;248 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
249 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
250 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
134251
135 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;252 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;253 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;
@@ -144,10 +261,40 @@
144 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;261 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
145 } properties;262 } properties;
146263
147 /*struct264 struct Signals
148 {265 {
149 std::shared_ptr<dbus::Signal<mpris::Player::Signals::Seeked, uint64_t>> seeked;266 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
150 } signals;*/267 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
268
269 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
270 const std::shared_ptr<DBusEndOfStreamSignal>& eos)
271 : dbus
272 {
273 seeked,
274 eos
275 },
276 seeked_to(),
277 end_of_stream()
278 {
279 seeked_to.connect([this](std::uint64_t value)
280 {
281 dbus.seeked_to->emit(value);
282 });
283
284 end_of_stream.connect([this]()
285 {
286 dbus.end_of_stream->emit();
287 });
288 }
289
290 struct DBus
291 {
292 std::shared_ptr<DBusSeekedToSignal> seeked_to;
293 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
294 } dbus;
295 core::Signal<uint64_t> seeked_to;
296 core::Signal<void> end_of_stream;
297 } signals;
151298
152};299};
153300
@@ -184,6 +331,10 @@
184 std::bind(&Private::handle_set_position,331 std::bind(&Private::handle_set_position,
185 std::ref(d),332 std::ref(d),
186 std::placeholders::_1));333 std::placeholders::_1));
334 d->object->install_method_handler<mpris::Player::CreateVideoSink>(
335 std::bind(&Private::handle_create_video_sink,
336 std::ref(d),
337 std::placeholders::_1));
187 d->object->install_method_handler<mpris::Player::OpenUri>(338 d->object->install_method_handler<mpris::Player::OpenUri>(
188 std::bind(&Private::handle_open_uri,339 std::bind(&Private::handle_open_uri,
189 std::ref(d),340 std::ref(d),
@@ -219,6 +370,16 @@
219 return *d->properties.can_go_next;370 return *d->properties.can_go_next;
220}371}
221372
373const core::Property<bool>& media::PlayerSkeleton::is_video_source() const
374{
375 return *d->properties.is_video_source;
376}
377
378const core::Property<bool>& media::PlayerSkeleton::is_audio_source() const
379{
380 return *d->properties.is_audio_source;
381}
382
222const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const383const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const
223{384{
224 return *d->properties.playback_status;385 return *d->properties.playback_status;
@@ -329,6 +490,17 @@
329 return *d->properties.can_go_next;490 return *d->properties.can_go_next;
330}491}
331492
493core::Property<bool>& media::PlayerSkeleton::is_video_source()
494{
495 return *d->properties.is_video_source;
496}
497
498core::Property<bool>& media::PlayerSkeleton::is_audio_source()
499{
500 return *d->properties.is_audio_source;
501}
502
503
332core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()504core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track()
333{505{
334 return *d->properties.meta_data_for_current_track;506 return *d->properties.meta_data_for_current_track;
@@ -346,6 +518,20 @@
346518
347const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const519const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const
348{520{
349 static const core::Signal<uint64_t> signal;521 return d->signals.seeked_to;
350 return signal;522}
523
524core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to()
525{
526 return d->signals.seeked_to;
527}
528
529const core::Signal<void>& media::PlayerSkeleton::end_of_stream() const
530{
531 return d->signals.end_of_stream;
532}
533
534core::Signal<void>& media::PlayerSkeleton::end_of_stream()
535{
536 return d->signals.end_of_stream;
351}537}
352538
=== 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-04-17 21:13:23 +0000
@@ -1,4 +1,6 @@
1/**1/**
2 * Copyright (C) 2013-2014 Canonical Ltd
3 *
2 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License version 3,5 * under the terms of the GNU Lesser General Public License version 3,
4 * as published by the Free Software Foundation.6 * as published by the Free Software Foundation.
@@ -46,6 +48,8 @@
46 virtual const core::Property<bool>& can_seek() const;48 virtual const core::Property<bool>& can_seek() const;
47 virtual const core::Property<bool>& can_go_previous() const;49 virtual const core::Property<bool>& can_go_previous() const;
48 virtual const core::Property<bool>& can_go_next() const;50 virtual const core::Property<bool>& can_go_next() const;
51 virtual const core::Property<bool>& is_video_source() const;
52 virtual const core::Property<bool>& is_audio_source() const;
49 virtual const core::Property<PlaybackStatus>& playback_status() const;53 virtual const core::Property<PlaybackStatus>& playback_status() const;
50 virtual const core::Property<LoopStatus>& loop_status() const;54 virtual const core::Property<LoopStatus>& loop_status() const;
51 virtual const core::Property<PlaybackRate>& playback_rate() const;55 virtual const core::Property<PlaybackRate>& playback_rate() const;
@@ -63,6 +67,7 @@
63 virtual core::Property<Volume>& volume();67 virtual core::Property<Volume>& volume();
6468
65 virtual const core::Signal<uint64_t>& seeked_to() const;69 virtual const core::Signal<uint64_t>& seeked_to() const;
70 virtual const core::Signal<void>& end_of_stream() const;
6671
67 protected:72 protected:
68 PlayerSkeleton(const core::dbus::types::ObjectPath& session_path);73 PlayerSkeleton(const core::dbus::types::ObjectPath& session_path);
@@ -73,12 +78,17 @@
73 virtual core::Property<bool>& can_seek();78 virtual core::Property<bool>& can_seek();
74 virtual core::Property<bool>& can_go_previous();79 virtual core::Property<bool>& can_go_previous();
75 virtual core::Property<bool>& can_go_next();80 virtual core::Property<bool>& can_go_next();
81 virtual core::Property<bool>& is_video_source();
82 virtual core::Property<bool>& is_audio_source();
76 virtual core::Property<Track::MetaData>& meta_data_for_current_track();83 virtual core::Property<Track::MetaData>& meta_data_for_current_track();
77 virtual core::Property<PlaybackRate>& minimum_playback_rate();84 virtual core::Property<PlaybackRate>& minimum_playback_rate();
78 virtual core::Property<PlaybackRate>& maximum_playback_rate();85 virtual core::Property<PlaybackRate>& maximum_playback_rate();
79 virtual core::Property<uint64_t>& position();86 virtual core::Property<uint64_t>& position();
80 virtual core::Property<uint64_t>& duration();87 virtual core::Property<uint64_t>& duration();
8188
89 virtual core::Signal<uint64_t>& seeked_to();
90 virtual core::Signal<void>& end_of_stream();
91
82 private:92 private:
83 struct Private;93 struct Private;
84 std::unique_ptr<Private> d;94 std::unique_ptr<Private> d;
8595
=== 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-04-17 21:13:23 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,5 * under the terms of the GNU Lesser General Public License version 3,
@@ -31,8 +31,14 @@
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 <hybris/media/media_codec_layer.h>
36#include <hybris/media/surface_texture_client_hybris.h>
37
34#include <limits>38#include <limits>
3539
40#define UNUSED __attribute__((unused))
41
36namespace dbus = core::dbus;42namespace dbus = core::dbus;
37namespace media = core::ubuntu::media;43namespace media = core::ubuntu::media;
3844
@@ -42,6 +48,12 @@
42 const std::shared_ptr<dbus::Service>& remote,48 const std::shared_ptr<dbus::Service>& remote,
43 const dbus::types::ObjectPath& path49 const dbus::types::ObjectPath& path
44 ) : parent(parent),50 ) : parent(parent),
51 texture_id(0),
52 igbc_wrapper(nullptr),
53 glc_wrapper(nullptr),
54 decoding_session(decoding_service_create_session()),
55 frame_available_cb(nullptr),
56 frame_available_context(nullptr),
45 path(path),57 path(path),
46 object(remote->object_for_path(path)),58 object(remote->object_for_path(path)),
47 properties59 properties
@@ -52,6 +64,8 @@
52 object->get_property<mpris::Player::Properties::CanControl>(),64 object->get_property<mpris::Player::Properties::CanControl>(),
53 object->get_property<mpris::Player::Properties::CanGoNext>(),65 object->get_property<mpris::Player::Properties::CanGoNext>(),
54 object->get_property<mpris::Player::Properties::CanGoPrevious>(),66 object->get_property<mpris::Player::Properties::CanGoPrevious>(),
67 object->get_property<mpris::Player::Properties::IsVideoSource>(),
68 object->get_property<mpris::Player::Properties::IsAudioSource>(),
55 object->get_property<mpris::Player::Properties::PlaybackStatus>(),69 object->get_property<mpris::Player::Properties::PlaybackStatus>(),
56 object->get_property<mpris::Player::Properties::LoopStatus>(),70 object->get_property<mpris::Player::Properties::LoopStatus>(),
57 object->get_property<mpris::Player::Properties::PlaybackRate>(),71 object->get_property<mpris::Player::Properties::PlaybackRate>(),
@@ -62,13 +76,67 @@
62 object->get_property<mpris::Player::Properties::Duration>(),76 object->get_property<mpris::Player::Properties::Duration>(),
63 object->get_property<mpris::Player::Properties::MinimumRate>(),77 object->get_property<mpris::Player::Properties::MinimumRate>(),
64 object->get_property<mpris::Player::Properties::MaximumRate>()78 object->get_property<mpris::Player::Properties::MaximumRate>()
79 },
80 signals
81 {
82 object->get_signal<mpris::Player::Signals::Seeked>(),
83 object->get_signal<mpris::Player::Signals::EndOfStream>()
65 }84 }
66 {85 {
67 }86 }
6887
88 ~Private()
89 {
90 }
91
92 static void on_frame_available_cb(UNUSED GLConsumerWrapperHybris wrapper, void *context)
93 {
94 if (context != nullptr) {
95 Private *p = static_cast<Private*>(context);
96 p->on_frame_available();
97 }
98 else
99 std::cout << "context is nullptr, can't call on_frame_available()" << std::endl;
100 }
101
102 void on_frame_available()
103 {
104 if (frame_available_cb != nullptr) {
105 frame_available_cb(frame_available_context);
106 }
107 else
108 std::cout << "frame_available_cb is nullptr, can't call frame_available_cb()" << std::endl;
109 }
110
111 void set_frame_available_cb(FrameAvailableCb cb, void *context)
112 {
113 frame_available_cb = cb;
114 frame_available_context = context;
115
116 gl_consumer_set_frame_available_cb(glc_wrapper, &Private::on_frame_available_cb, static_cast<void*>(this));
117 }
118
119 /** We need a GLConsumerHybris instance for doing texture streaming over the
120 * process boundary **/
121 void get_gl_consumer()
122 {
123 igbc_wrapper = decoding_service_get_igraphicbufferconsumer();
124 glc_wrapper = gl_consumer_create_by_id_with_igbc(texture_id, igbc_wrapper);
125
126 }
127
69 std::shared_ptr<Service> parent;128 std::shared_ptr<Service> parent;
70 std::shared_ptr<TrackList> track_list;129 std::shared_ptr<TrackList> track_list;
71130
131 uint32_t texture_id;
132 IGBCWrapperHybris igbc_wrapper;
133 GLConsumerWrapperHybris glc_wrapper;
134
135 DSSessionWrapperHybris decoding_session;
136
137 FrameAvailableCb frame_available_cb;
138 void *frame_available_context;
139
72 dbus::Bus::Ptr bus;140 dbus::Bus::Ptr bus;
73 dbus::types::ObjectPath path;141 dbus::types::ObjectPath path;
74 dbus::Object::Ptr object;142 dbus::Object::Ptr object;
@@ -81,6 +149,8 @@
81 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control;149 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;150 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;151 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous;
152 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source;
153 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source;
84154
85 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status;155 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;156 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status;
@@ -93,6 +163,56 @@
93 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate;163 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;164 std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate;
95 } properties;165 } properties;
166
167 struct Signals
168 {
169 typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal;
170 typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal;
171
172 Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked,
173 const std::shared_ptr<DBusEndOfStreamSignal>& eos)
174 : dbus
175 {
176 seeked,
177 eos
178 },
179 playback_complete_cb(nullptr),
180 playback_complete_context(nullptr),
181 seeked_to(),
182 end_of_stream()
183 {
184 dbus.seeked_to->connect([this](std::uint64_t value)
185 {
186 std::cout << "seeked_to signal arrived via the bus." << std::endl;
187 seeked_to(value);
188 });
189
190 dbus.end_of_stream->connect([this]()
191 {
192 std::cout << "EndOfStream signal arrived via the bus." << std::endl;
193 if (playback_complete_cb)
194 playback_complete_cb(playback_complete_context);
195 end_of_stream();
196 });
197 }
198
199 struct DBus
200 {
201 std::shared_ptr<DBusSeekedToSignal> seeked_to;
202 std::shared_ptr<DBusEndOfStreamSignal> end_of_stream;
203 } dbus;
204
205 void set_playback_complete_cb(PlaybackCompleteCb cb, void *context)
206 {
207 playback_complete_cb = cb;
208 playback_complete_context = context;
209 }
210
211 PlaybackCompleteCb playback_complete_cb;
212 void *playback_complete_context;
213 core::Signal<uint64_t> seeked_to;
214 core::Signal<void> end_of_stream;
215 } signals;
96};216};
97217
98media::PlayerStub::PlayerStub(218media::PlayerStub::PlayerStub(
@@ -101,6 +221,11 @@
101 : dbus::Stub<Player>(the_session_bus()),221 : dbus::Stub<Player>(the_session_bus()),
102 d(new Private{parent, access_service(), object_path})222 d(new Private{parent, access_service(), object_path})
103{223{
224 auto bus = the_session_bus();
225 worker = std::move(std::thread([bus]()
226 {
227 bus->run();
228 }));
104}229}
105230
106media::PlayerStub::~PlayerStub()231media::PlayerStub::~PlayerStub()
@@ -125,6 +250,21 @@
125 return op.value();250 return op.value();
126}251}
127252
253void media::PlayerStub::create_video_sink(uint32_t texture_id)
254{
255 auto op = d->object->invoke_method_synchronously<mpris::Player::CreateVideoSink, void>(texture_id);
256 d->texture_id = texture_id;
257 d->get_gl_consumer();
258
259 if (op.is_error())
260 throw std::runtime_error("Problem creating new video sink instance on remote object");
261}
262
263GLConsumerWrapperHybris media::PlayerStub::gl_consumer() const
264{
265 return d->glc_wrapper;
266}
267
128void media::PlayerStub::next()268void media::PlayerStub::next()
129{269{
130 auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>();270 auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>();
@@ -173,6 +313,16 @@
173 throw std::runtime_error("Problem stopping playback on remote object");313 throw std::runtime_error("Problem stopping playback on remote object");
174}314}
175315
316void media::PlayerStub::set_frame_available_callback(FrameAvailableCb cb, void *context)
317{
318 d->set_frame_available_cb(cb, context);
319}
320
321void media::PlayerStub::set_playback_complete_callback(PlaybackCompleteCb cb, void *context)
322{
323 d->signals.set_playback_complete_cb(cb, context);
324}
325
176const core::Property<bool>& media::PlayerStub::can_play() const326const core::Property<bool>& media::PlayerStub::can_play() const
177{327{
178 return *d->properties.can_play;328 return *d->properties.can_play;
@@ -198,6 +348,16 @@
198 return *d->properties.can_go_next;348 return *d->properties.can_go_next;
199}349}
200350
351const core::Property<bool>& media::PlayerStub::is_video_source() const
352{
353 return *d->properties.is_video_source;
354}
355
356const core::Property<bool>& media::PlayerStub::is_audio_source() const
357{
358 return *d->properties.is_audio_source;
359}
360
201const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const361const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const
202{362{
203 return *d->properties.playback_status;363 return *d->properties.playback_status;
@@ -270,6 +430,10 @@
270430
271const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const431const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const
272{432{
273 static core::Signal<uint64_t> signal;433 return d->signals.seeked_to;
274 return signal;434}
435
436const core::Signal<void>& media::PlayerStub::end_of_stream() const
437{
438 return d->signals.end_of_stream;
275}439}
276440
=== 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-04-17 21:13:23 +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,16 @@
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 virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context);
59
55 virtual const core::Property<bool>& can_play() const;60 virtual const core::Property<bool>& can_play() const;
56 virtual const core::Property<bool>& can_pause() const;61 virtual const core::Property<bool>& can_pause() const;
57 virtual const core::Property<bool>& can_seek() const;62 virtual const core::Property<bool>& can_seek() const;
58 virtual const core::Property<bool>& can_go_previous() const;63 virtual const core::Property<bool>& can_go_previous() const;
59 virtual const core::Property<bool>& can_go_next() const;64 virtual const core::Property<bool>& can_go_next() const;
65 virtual const core::Property<bool>& is_video_source() const;
66 virtual const core::Property<bool>& is_audio_source() const;
60 virtual const core::Property<PlaybackStatus>& playback_status() const;67 virtual const core::Property<PlaybackStatus>& playback_status() const;
61 virtual const core::Property<LoopStatus>& loop_status() const;68 virtual const core::Property<LoopStatus>& loop_status() const;
62 virtual const core::Property<PlaybackRate>& playback_rate() const;69 virtual const core::Property<PlaybackRate>& playback_rate() const;
@@ -74,10 +81,12 @@
74 virtual core::Property<Volume>& volume();81 virtual core::Property<Volume>& volume();
7582
76 virtual const core::Signal<uint64_t>& seeked_to() const;83 virtual const core::Signal<uint64_t>& seeked_to() const;
84 virtual const core::Signal<void>& end_of_stream() const;
7785
78 private:86 private:
79 struct Private;87 struct Private;
80 std::unique_ptr<Private> d;88 std::unique_ptr<Private> d;
89 std::thread worker;
81};90};
82}91}
83}92}
8493
=== 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-04-17 21:13:23 +0000
@@ -1,13 +1,41 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
17 */
18
1#include <core/media/service.h>19#include <core/media/service.h>
2#include <core/media/player.h>20#include <core/media/player.h>
3#include <core/media/track_list.h>21#include <core/media/track_list.h>
422
23#include <hybris/media/media_codec_layer.h>
24
5#include "core/media/service_implementation.h"25#include "core/media/service_implementation.h"
626
27#include <iostream>
28
7namespace media = core::ubuntu::media;29namespace media = core::ubuntu::media;
830
31using namespace std;
32
9int main()33int main()
10{34{
35 // Init hybris-level DecodingService
36 decoding_service_init();
37 cout << "Starting DecodingService..." << endl;
38
11 auto service = std::make_shared<media::ServiceImplementation>();39 auto service = std::make_shared<media::ServiceImplementation>();
12 service->run();40 service->run();
1341
1442
=== modified file 'src/core/media/service.cpp'
--- src/core/media/service.cpp 2014-01-17 20:58:31 +0000
+++ src/core/media/service.cpp 2014-04-17 21:13:23 +0000
@@ -24,7 +24,7 @@
2424
25const std::shared_ptr<media::Service> media::Service::Client::instance()25const std::shared_ptr<media::Service> media::Service::Client::instance()
26{26{
27 std::cout << "Creating a new Service instance" << std::endl;27 std::cout << "Creating a new static Service instance" << std::endl;
28 static std::shared_ptr<media::Service> instance{new media::ServiceStub()};28 static std::shared_ptr<media::Service> instance{new media::ServiceStub()};
29 return instance;29 return instance;
30}30}
3131
=== 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-04-17 21:13:23 +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-04-17 21:13:23 +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-04-17 21:13:23 +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-04-17 21:13:23 +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();
5758
=== modified file 'tests/acceptance-tests/service.cpp'
--- tests/acceptance-tests/service.cpp 2014-03-06 19:23:19 +0000
+++ tests/acceptance-tests/service.cpp 2014-04-17 21:13:23 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,5 * under the terms of the GNU Lesser General Public License version 3,
66
=== modified file 'tests/unit-tests/CMakeLists.txt'
--- tests/unit-tests/CMakeLists.txt 2014-01-17 20:58:31 +0000
+++ tests/unit-tests/CMakeLists.txt 2014-04-17 21:13:23 +0000
@@ -1,10 +1,21 @@
1include_directories(1include_directories(
2 .2 .
3 ${CMAKE_SOURCE_DIR}/src3 ${CMAKE_SOURCE_DIR}/src
4 ${PC_GSTREAMER_1_0_INCLUDE_DIRS}
4)5)
56
6add_executable(7add_executable(
7 test-gstreamer-engine8 test-gstreamer-engine
9
10 libmedia-mock.cpp
11 ${CMAKE_SOURCE_DIR}/src/core/media/engine.cpp
12 ${CMAKE_SOURCE_DIR}/src/core/media/gstreamer/engine.cpp
13 ${CMAKE_SOURCE_DIR}/src/core/media/player_skeleton.cpp
14 ${CMAKE_SOURCE_DIR}/src/core/media/player_implementation.cpp
15 ${CMAKE_SOURCE_DIR}/src/core/media/service_skeleton.cpp
16 ${CMAKE_SOURCE_DIR}/src/core/media/service_implementation.cpp
17 ${CMAKE_SOURCE_DIR}/src/core/media/track_list_skeleton.cpp
18 ${CMAKE_SOURCE_DIR}/src/core/media/track_list_implementation.cpp
8 test-gstreamer-engine.cpp19 test-gstreamer-engine.cpp
9)20)
1021
@@ -13,12 +24,15 @@
1324
14 media-hub-common25 media-hub-common
15 media-hub-client26 media-hub-client
16 media-hub-service
17 media-hub-test-framework27 media-hub-test-framework
1828
19 ${CMAKE_THREAD_LIBS_INIT}29 ${CMAKE_THREAD_LIBS_INIT}
20 ${Boost_LIBRARIES}30 ${Boost_LIBRARIES}
21 ${DBUS_LIBRARIES}31 ${DBUS_LIBRARIES}
32 ${DBUS_CPP_LDFLAGS}
33 ${GLog_LIBRARY}
34 ${PC_GSTREAMER_1_0_LIBRARIES}
35 ${GIO_LIBRARIES}
2236
23 gmock37 gmock
24 gmock_main38 gmock_main
2539
=== added file 'tests/unit-tests/libmedia-mock.cpp'
--- tests/unit-tests/libmedia-mock.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit-tests/libmedia-mock.cpp 2014-04-17 21:13:23 +0000
@@ -0,0 +1,26 @@
1/*
2 * Copyright © 2013-2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Jim Hodapp <jim.hodapp@canonical.com>
17 */
18
19#include <hybris/media/media_codec_layer.h>
20#include <hybris/media/surface_texture_client_hybris.h>
21
22#define UNUSED __attribute__((unused))
23
24void decoding_service_set_client_death_cb(UNUSED DecodingClientDeathCbHybris callback, UNUSED void *context)
25{
26}
027
=== modified file 'tests/unit-tests/test-gstreamer-engine.cpp'
--- tests/unit-tests/test-gstreamer-engine.cpp 2014-02-26 14:58:36 +0000
+++ tests/unit-tests/test-gstreamer-engine.cpp 2014-04-17 21:13:23 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright © 2013 Canonical Ltd.2 * Copyright © 2013-2014 Canonical Ltd.
3 *3 *
4 * This program is free software: you can redistribute it and/or modify it4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 3,5 * under the terms of the GNU Lesser General Public License version 3,
@@ -198,7 +198,7 @@
198 std::chrono::seconds{40}));198 std::chrono::seconds{40}));
199}199}
200200
201TEST(GStreamerEngine, DISABLED_stop_pause_play_seek_video_works)201TEST(GStreamerEngine, stop_pause_play_seek_video_works)
202{202{
203 const std::string test_file{"/tmp/h264.avi"};203 const std::string test_file{"/tmp/h264.avi"};
204 const std::string test_file_uri{"file:///tmp/h264.avi"};204 const std::string test_file_uri{"file:///tmp/h264.avi"};
@@ -248,8 +248,8 @@
248248
249TEST(GStreamerEngine, get_position_duration_work)249TEST(GStreamerEngine, get_position_duration_work)
250{250{
251 const std::string test_file{"/tmp/test.ogg"};251 const std::string test_file{"/tmp/h264.avi"};
252 const std::string test_file_uri{"file:///tmp/test.ogg"};252 const std::string test_file_uri{"file:///tmp/h264.avi"};
253 std::remove(test_file.c_str());253 std::remove(test_file.c_str());
254 ASSERT_TRUE(test::copy_test_ogg_file_to(test_file));254 ASSERT_TRUE(test::copy_test_ogg_file_to(test_file));
255255
@@ -269,10 +269,18 @@
269 EXPECT_TRUE(wst.wait_for_state_for(269 EXPECT_TRUE(wst.wait_for_state_for(
270 core::ubuntu::media::Engine::State::playing,270 core::ubuntu::media::Engine::State::playing,
271 std::chrono::milliseconds{4000}));271 std::chrono::milliseconds{4000}));
272 sleep(1);272
273273 EXPECT_TRUE(engine.seek_to(std::chrono::seconds{10}));
274 // FIXME: Ideally we want to seek_to and measure the position there, but seek_to seems274 EXPECT_TRUE(engine.play());
275 // broken from within this unit test275 EXPECT_TRUE(wst.wait_for_state_for(
276 core::ubuntu::media::Engine::State::playing,
277 std::chrono::milliseconds{4000}));
278
279 std::cout << "position: " << engine.position() << std::endl;
280 std::cout << "duration: " << engine.duration() << std::endl;
281
282 // FIXME: This should be 10e9, but seek_to seems to be broken from within this unit test
283 // and I haven't been able to figure out why
276 EXPECT_TRUE(engine.position() > 1e9);284 EXPECT_TRUE(engine.position() > 1e9);
277285
278 EXPECT_TRUE(engine.duration() > 1e9);286 EXPECT_TRUE(engine.duration() > 1e9);

Subscribers

People subscribed via source and target branches