From 136ddcec26226a50baa53362daba82fcac7f0cbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Thu, 28 Dec 2017 13:51:04 +0100 Subject: [PATCH] Introduce create_media_source_player --- gecko-media/gecko/glue/Player.cpp | 41 ++++++++++++- .../glue/include/GeckoMediaDecoderOwner.h | 2 +- gecko-media/gecko/glue/include/Player.h | 6 ++ gecko-media/src/player.rs | 58 +++++++++++++------ gecko-media/src/top.rs | 7 +++ 5 files changed, 94 insertions(+), 20 deletions(-) diff --git a/gecko-media/gecko/glue/Player.cpp b/gecko-media/gecko/glue/Player.cpp index 75c3411..1d3fa1a 100644 --- a/gecko-media/gecko/glue/Player.cpp +++ b/gecko-media/gecko/glue/Player.cpp @@ -10,6 +10,9 @@ #include "GeckoMediaDecoder.h" #include "GeckoMediaDecoderOwner.h" #include "GeckoMediaMacros.h" +#include "GeckoMediaSource.h" +#include "MediaSource.h" +#include "MediaSourceDecoder.h" #include "RustMediaResource.h" #include "UniquePtr.h" #include "mozilla/RefPtr.h" @@ -111,6 +114,42 @@ GeckoMedia_Player_CreateNetworkPlayer(size_t aId, resource->SetDecoder(reflector->mDecoder); } +bool +GeckoMedia_Player_CreateMediaSourcePlayer(size_t aId, + size_t aMediaSourceId, + PlayerCallbackObject aCallback, + FrameAllocatorObject aAllocator) +{ + Player* reflector = + sReflectors.AppendElement(Player(aId, aCallback, aAllocator)); + MOZ_ASSERT(GetReflector(aId) == reflector); + + MediaDecoderInit decoderInit( + reflector->mDecoderOwner.get(), + 1.0, // volume + true, // mPreservesPitch + 1.0, // mPlaybackRate + false, // mMinimizePreroll + false, // mHasSuspendTaint + false, // mLooping + MediaContainerType(MEDIAMIMETYPE("application/x.mediasource"))); + RefPtr decoder = new MediaSourceDecoder(decoderInit); + reflector->mDecoder = static_cast(decoder); + reflector->mDecoderOwner->SetDecoder(reflector->mDecoder); + + RefPtr mediaSource = + GetMediaSource(aMediaSourceId); + if (NS_WARN_IF(!mediaSource || !mediaSource->Attach(decoder))) { + return false; + } + + if (NS_WARN_IF(reflector->mDecoder->Load(nullptr) != NS_OK)) { + return false; + } + + return true; +} + void GeckoMedia_Player_Play(size_t aId) { @@ -144,5 +183,5 @@ void GeckoMedia_Player_SetPlaybackRate(size_t aId, double rate) { IMPL_GECKO_MEDIA_REFLECTOR_GET(Player) - reflector->mDecoder->SetPlaybackRate(rate); + reflector->mDecoder->SetPlaybackRate(rate); } diff --git a/gecko-media/gecko/glue/include/GeckoMediaDecoderOwner.h b/gecko-media/gecko/glue/include/GeckoMediaDecoderOwner.h index ff23872..a43d2bf 100644 --- a/gecko-media/gecko/glue/include/GeckoMediaDecoderOwner.h +++ b/gecko-media/gecko/glue/include/GeckoMediaDecoderOwner.h @@ -165,7 +165,7 @@ class GeckoMediaDecoderOwner : public MediaDecoderOwner void NotifyWaitingForKey() override; /* - * Methods that are used only in Gecko go here. We provide defaul + * Methods that are used only in Gecko go here. We provide default * implementations so they can compile in Servo without modification. */ // Return an abstract thread on which to run main thread runnables. diff --git a/gecko-media/gecko/glue/include/Player.h b/gecko-media/gecko/glue/include/Player.h index cabe1f5..6e529e5 100644 --- a/gecko-media/gecko/glue/include/Player.h +++ b/gecko-media/gecko/glue/include/Player.h @@ -132,6 +132,12 @@ GeckoMedia_Player_CreateNetworkPlayer(size_t aId, PlayerCallbackObject aCallback, FrameAllocatorObject aAllocator); +bool +GeckoMedia_Player_CreateMediaSourcePlayer(size_t aId, + size_t aMediaSourceId, + PlayerCallbackObject aCallback, + FrameAllocatorObject aAllocator); + void GeckoMedia_Player_Play(size_t aId); diff --git a/gecko-media/src/player.rs b/gecko-media/src/player.rs index 99cfb20..bef25a2 100644 --- a/gecko-media/src/player.rs +++ b/gecko-media/src/player.rs @@ -2,6 +2,7 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use bindings::GeckoMedia_Player_CreateMediaSourcePlayer; use bindings::NetworkResourceObject; use bindings::{CachedRangesObserverObject, FrameAllocatorObject, GeckoImagePlane}; use bindings::{GeckoMediaByteRange, GeckoPlanarYCbCrImage, GeckoPlanarYCbCrImageData}; @@ -16,7 +17,7 @@ use std::mem; use std::ops::Range; use std::os::raw::c_char; use std::slice; -use std::sync::{Arc, Mutex}; +use std::sync::{mpsc, Arc, Mutex}; use timestamp::TimeStamp; /// Holds useful metadata extracted from a media resource during loading. @@ -287,10 +288,7 @@ impl Player { _ => return Err(()), }; let ffi_frame_allocator = to_ffi_frame_allocator(video_frame_allocator.clone()); - let player = Player { - gecko_media, - id, - }; + let player = Player { gecko_media, id }; player.gecko_media.queue_task(move || unsafe { GeckoMedia_Player_CreateBlobPlayer( id, @@ -318,10 +316,7 @@ impl Player { let callback = to_ffi_callback(sink, video_frame_allocator.clone()); let ffi_frame_allocator = to_ffi_frame_allocator(video_frame_allocator.clone()); let resource = to_ffi_resource(resource); - let player = Player { - gecko_media, - id, - }; + let player = Player { gecko_media, id }; player.gecko_media.queue_task(move || unsafe { GeckoMedia_Player_CreateNetworkPlayer( id, @@ -334,6 +329,34 @@ impl Player { Ok(player) } + pub fn from_media_source( + gecko_media: GeckoMedia, + id: usize, + media_source_id: usize, + sink: Box, + ) -> Result { + let video_frame_allocator = Arc::new(Mutex::new(VideoFrameAllocator::new())); + let callback = to_ffi_callback(sink, video_frame_allocator.clone()); + let ffi_frame_allocator = to_ffi_frame_allocator(video_frame_allocator.clone()); + let player = Player { gecko_media, id }; + let (sender, receiver) = mpsc::channel(); + player.gecko_media.queue_task(move || unsafe { + sender + .send(GeckoMedia_Player_CreateMediaSourcePlayer( + id, + media_source_id, + callback, + ffi_frame_allocator, + )) + .unwrap(); + }); + if receiver.recv().unwrap() { + Ok(player) + } else { + Err(()) + } + } + /// Starts playback of the media resource. While playing, /// PlayerEventSink::time_update() will be called once per frame, /// or every 40 milliseconds if there is no video. @@ -405,9 +428,10 @@ impl CachedRangesSink { }); } unsafe { - self.observer.mUpdate.as_ref().map(|f| { - f(self.observer.mResourceID, data.as_ptr(), data.len()) - }); + self.observer + .mUpdate + .as_ref() + .map(|f| f(self.observer.mResourceID, data.as_ptr(), data.len())); } } } @@ -546,9 +570,9 @@ fn to_ffi_resource(callbacks: Box) -> NetworkResourceObject { unsafe extern "C" fn set_ranges_observer(ptr: *mut c_void, observer: CachedRangesObserverObject) { let wrapper = &*(ptr as *mut Wrapper); - wrapper.callbacks.set_cached_ranges_sink(CachedRangesSink { - observer, - }) + wrapper + .callbacks + .set_cached_ranges_sink(CachedRangesSink { observer }) } unsafe extern "C" fn read_at( @@ -599,9 +623,7 @@ fn to_ffi_resource(callbacks: Box) -> NetworkResourceObject { mLength: Some(length), mReadFromCache: Some(read_from_cache), mFree: Some(free), - mData: Box::into_raw(Box::new(Wrapper { - callbacks, - })) as *mut c_void, + mData: Box::into_raw(Box::new(Wrapper { callbacks })) as *mut c_void, } } diff --git a/gecko-media/src/top.rs b/gecko-media/src/top.rs index 5cfc7cb..d2c976e 100644 --- a/gecko-media/src/top.rs +++ b/gecko-media/src/top.rs @@ -141,6 +141,13 @@ impl GeckoMedia { Player::from_network_resource(handle, id, resource, mime_type, sink) } + /// Creates a Player to play from a MediaSource. + pub fn create_media_source_player(media_source_id: usize, sink: Box) -> Result { + let handle = GeckoMedia::get()?; + let id = NEXT_PLAYER_ID.fetch_add(1, Ordering::SeqCst); + Player::from_media_source(handle, id, media_source_id, sink) + } + /// Creates a MediaSource instance and its corresponding GeckoMediaSource reflector. impl_gecko_media_struct_constructor!( create_media_source,