Skip to content

Instantly share code, notes, and snippets.

@2bbb
Last active May 6, 2020 07:14
Show Gist options
  • Save 2bbb/60fd91de551fcd2c795129b5947e2c51 to your computer and use it in GitHub Desktop.
Save 2bbb/60fd91de551fcd2c795129b5947e2c51 to your computer and use it in GitHub Desktop.
ofxAVFoundationVideoPlayerUtils
//
// ofxAVFoundationVideoPlayerUtils.hpp
//
// Created by 2bit on 2020/05/03.
//
#ifndef ofxAVFoundationVideoPlayerUtils_hpp
#define ofxAVFoundationVideoPlayerUtils_hpp
#include "ofVideoPlayer.h"
namespace ofxAVFoundationVideoPlayerUtils {
void waitReady(ofVideoPlayer &player, std::function<void(ofVideoPlayer &)> cb);
void waitReady(ofVideoPlayer &player);
}
#endif /* ofxAVFoundationVideoPlayerUtils_hpp */
//
// AVFoundationVideoPlayerUtils.mm
//
// Created by 2bit on 2020/05/03.
//
#include "ofxAVFoundationVideoPlayerUtils.h"
#include "ofAVFoundationPlayer.h"
#import "ofAVFoundationVideoPlayer.h"
@interface WaitingReady : NSObject {
dispatch_semaphore_t semaphore;
}
@end
@implementation WaitingReady
- (instancetype)init {
[super init];
semaphore = dispatch_semaphore_create(0);
return self;
}
- (dispatch_semaphore_t)semaphore {
return semaphore;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if([object isKindOfClass:AVPlayerItem.class]) {
AVPlayerItem *item = object;
if(item.status == AVPlayerItemStatusReadyToPlay) {
dispatch_semaphore_signal(semaphore);
[item removeObserver:self
forKeyPath:@"status"];
}
return;
}
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
- (void)dealloc {
dispatch_release(semaphore);
[super dealloc];
}
@end
namespace ofxAVFoundationVideoPlayerUtils {
void waitReady(ofVideoPlayer &player, std::function<void(ofVideoPlayer &player)> cb) {
std::thread([&player, cb] {
waitReady(player);
dispatch_async(dispatch_get_main_queue(), ^ {
cb(player);
});
}).detach();
}
void waitReady(ofVideoPlayer &player) {
auto p = std::dynamic_pointer_cast<ofAVFoundationPlayer>(player.getPlayer());
if(!p) {
ofLogNotice(__func__) << "not avfoundation player";
return false;
}
ofAVFoundationVideoPlayer *avfp = p->getAVFoundationVideoPlayer();
if(avfp.isReady) return true;
WaitingReady *ready = WaitingReady.alloc.init;
[avfp.playerItem addObserver:ready
forKeyPath:@"status"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:nil];
while(dispatch_semaphore_wait(ready.semaphore, DISPATCH_TIME_NOW)) {
[NSRunLoop.currentRunLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1f]];
}
ready = nil;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment