Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/cinder/app/cocoa/PlatformCocoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
typedef uint32_t CGDisplayChangeSummaryFlags;
typedef uint32_t CGDirectDisplayID;

struct GLFWmonitor;

namespace cinder {
#if defined( CINDER_MAC )
class DisplayMac;
Expand Down Expand Up @@ -151,6 +153,8 @@ class DisplayMac : public Display {
public:
NSScreen* getNsScreen() const;
CGDirectDisplayID getCgDirectDisplayId() const { return mDirectDisplayId; }
//! Returns the GLFW monitor handle matching this display, or nullptr if none matches. Only meaningful when Cinder is built with the GLFW backend.
GLFWmonitor* getGlfwMonitor() const;

std::string getName() const override;

Expand Down
5 changes: 5 additions & 0 deletions include/cinder/qtime/QuickTimeImplAvf.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "cinder/Thread.h"
#include "cinder/Url.h"

#include <dispatch/dispatch.h>
#include <string>

typedef struct __CVBuffer *CVBufferRef;
Expand Down Expand Up @@ -136,6 +137,8 @@ class MovieBase {
* Returns a boolean value indicating whether the rate value can be played (some media types cannot be played backwards)
*/
bool setRate( float rate );
//! Gets the playback rate. It might be different from the one that was set because setRate failed or palindrome loop kicked off.
float getRate() const;

//! Sets the audio playback volume ranging from [0 - 1.0]
void setVolume( float volume );
Expand Down Expand Up @@ -189,6 +192,7 @@ class MovieBase {
int32_t mFrameCount;
float mFrameRate;
float mDuration;
float mPlayRate;
std::atomic<bool> mAssetLoaded;
bool mLoaded, mPlayThroughOk, mPlayable, mProtected;
bool mPlayingForward, mLoop, mPalindrome;
Expand All @@ -199,6 +203,7 @@ class MovieBase {
AVPlayerItem* mPlayerItem;
AVURLAsset* mAsset;
AVPlayerItemVideoOutput* mPlayerVideoOutput;
dispatch_queue_t mOutputQueue;

std::mutex mMutex;

Expand Down
19 changes: 19 additions & 0 deletions src/cinder/app/cocoa/PlatformCocoa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@
#include <execinfo.h>
#include <pthread.h>

#if defined( CINDER_GLFW )
#define GLFW_EXPOSE_NATIVE_COCOA
#include "glfw/glfw3.h"
#include "glfw/glfw3native.h"
#endif

using namespace std;

namespace cinder { namespace app {
Expand Down Expand Up @@ -439,6 +445,19 @@ NSScreen* DisplayMac::getNsScreen() const
return findNsScreenForCgDirectDisplayId( mDirectDisplayId );
}

GLFWmonitor* DisplayMac::getGlfwMonitor() const
{
#if defined( CINDER_GLFW )
int count = 0;
GLFWmonitor** monitors = ::glfwGetMonitors( &count );
for( int i = 0; i < count; ++i ) {
if( ::glfwGetCocoaMonitor( monitors[i] ) == mDirectDisplayId )
return monitors[i];
}
#endif
return nullptr;
}

DisplayRef app::PlatformCocoa::findFromCgDirectDisplayId( CGDirectDisplayID displayId )
{
for( auto &display : getDisplays() ) {
Expand Down
16 changes: 11 additions & 5 deletions src/cinder/app/glfw/WindowImplGlfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

#if defined( CINDER_MAC )
#include "cinder/app/glfw/AppImplGlfwMac.h"
#include "cinder/app/cocoa/PlatformCocoa.h"
#endif

namespace cinder { namespace app {
Expand Down Expand Up @@ -75,10 +76,12 @@ WindowImplGlfw::WindowImplGlfw( const Window::Format &format, WindowImplGlfw *sh
auto windowSize = displayLinux->getSize();
mGlfwWindow = ::glfwCreateWindow( windowSize.x, windowSize.y, format.getTitle().c_str(), displayLinux->getGlfwMonitor(), sharedGlfwWindow );
#elif defined( CINDER_MAC )
// On macOS, get the primary monitor for fullscreen
GLFWmonitor* primaryMonitor = ::glfwGetPrimaryMonitor();
auto* displayMac = dynamic_cast<cinder::DisplayMac*>( mDisplay.get() );
GLFWmonitor* monitor = displayMac ? displayMac->getGlfwMonitor() : nullptr;
if( ! monitor )
monitor = ::glfwGetPrimaryMonitor();
auto windowSize = mDisplay->getSize();
mGlfwWindow = ::glfwCreateWindow( windowSize.x, windowSize.y, format.getTitle().c_str(), primaryMonitor, sharedGlfwWindow );
mGlfwWindow = ::glfwCreateWindow( windowSize.x, windowSize.y, format.getTitle().c_str(), monitor, sharedGlfwWindow );
#endif
mWindowedSize = format.getSize();
mWindowedPos = format.getPos();
Expand Down Expand Up @@ -140,8 +143,11 @@ void WindowImplGlfw::setFullScreen( bool fullScreen, const app::FullScreenOption
cinder::app::DisplayLinux* displayLinux = dynamic_cast<cinder::app::DisplayLinux*>( mDisplay.get() );
::glfwSetWindowMonitor( mGlfwWindow, displayLinux->getGlfwMonitor(), 0, 0, mDisplay->getWidth(), mDisplay->getHeight(), GLFW_DONT_CARE );
#elif defined( CINDER_MAC )
GLFWmonitor* primaryMonitor = ::glfwGetPrimaryMonitor();
::glfwSetWindowMonitor( mGlfwWindow, primaryMonitor, 0, 0, mDisplay->getWidth(), mDisplay->getHeight(), GLFW_DONT_CARE );
auto* displayMac = dynamic_cast<cinder::DisplayMac*>( mDisplay.get() );
GLFWmonitor* monitor = displayMac ? displayMac->getGlfwMonitor() : nullptr;
if( ! monitor )
monitor = ::glfwGetPrimaryMonitor();
::glfwSetWindowMonitor( mGlfwWindow, monitor, 0, 0, mDisplay->getWidth(), mDisplay->getHeight(), GLFW_DONT_CARE );
#endif
}
else {
Expand Down
46 changes: 39 additions & 7 deletions src/cinder/qtime/QuickTimeImplAvf.mm
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
mPlayerItem( nil ),
mAsset( nil ),
mPlayerVideoOutput( nil ),
mOutputQueue( nil ),
mPlayerDelegate( nil ),
mResponder( nullptr ),
mAssetLoaded( false )
Expand All @@ -192,12 +193,28 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output

MovieBase::~MovieBase()
{
// Stop the output delegate first and drain any in-flight background callback,
// e.g. outputSequenceWasFlushed.
if( mPlayerVideoOutput ) {
[mPlayerVideoOutput setDelegate:nil queue:nil];
if( mOutputQueue ) {
dispatch_sync( mOutputQueue, ^{} );
}
[mPlayerVideoOutput release];
mPlayerVideoOutput = nil;
}
if( mOutputQueue ) {
dispatch_release( mOutputQueue );
mOutputQueue = nil;
}

// remove all observers
removeObservers();

// release resources for AVF objects.
if( mPlayer ) {
[mPlayer cancelPendingPrerolls];
[mPlayer replaceCurrentItemWithPlayerItem:nil];
[mPlayer release];
}

Expand All @@ -206,9 +223,13 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
[mAsset release];
}

if( mPlayerVideoOutput ) {
[mPlayerVideoOutput release];
if( mPlayerDelegate ) {
[mPlayerDelegate release];
mPlayerDelegate = nil;
}

delete mResponder;
mResponder = nullptr;
}

float MovieBase::getPixelAspectRatio() const
Expand Down Expand Up @@ -410,11 +431,20 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
else
success = [mPlayerItem canPlaySlowForward];

mPlayRate = rate;
[mPlayer setRate:rate];

return success;
}

float MovieBase::getRate() const
{
if( ! mPlayer || ! mPlayerItem )
return 0.f;

return mPlayer.rate;
}

void MovieBase::setVolume( float volume )
{
if( ! mPlayer )
Expand Down Expand Up @@ -516,6 +546,7 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
mHeight = -1;
mDuration = -1;
mFrameCount = -1;
mPlayRate = 1;
}

void MovieBase::initFromUrl( const Url& url )
Expand Down Expand Up @@ -700,8 +731,8 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
void MovieBase::createPlayerItemOutput( const AVPlayerItem* playerItem )
{
mPlayerVideoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:avPlayerItemOutputDictionary()];
dispatch_queue_t outputQueue = dispatch_queue_create("movieVideoOutputQueue", DISPATCH_QUEUE_SERIAL);
[mPlayerVideoOutput setDelegate:mPlayerDelegate queue:outputQueue];
mOutputQueue = dispatch_queue_create("movieVideoOutputQueue", DISPATCH_QUEUE_SERIAL);
[mPlayerVideoOutput setDelegate:mPlayerDelegate queue:mOutputQueue];
mPlayerVideoOutput.suppressesPlayerRendering = YES;
[playerItem addOutput:mPlayerVideoOutput];
}
Expand Down Expand Up @@ -758,16 +789,17 @@ - (void)outputSequenceWasFlushed:(AVPlayerItemOutput *)output
{
mSignalReady.emit();

setRate(mPlayRate); // previous setRate calls fail while the player is not ready
if( mPlaying )
play();
}

void MovieBase::playerItemEnded()
{
if( mPalindrome ) {
float rate = -[mPlayer rate];
mPlayingForward = (rate >= 0);
this->setRate( rate );
mPlayRate = -mPlayRate;
mPlayingForward = (mPlayRate >= 0);
this->setRate( mPlayRate );
}
else if( mLoop ) {
this->seekToStart();
Expand Down