Commit 39fbd063 authored by Thilo Borgmann's avatar Thilo Borgmann

lavd/avfoundation: Add basic transport control observation for capable devices.

parent e38b8b0d
...@@ -88,7 +88,6 @@ typedef struct ...@@ -88,7 +88,6 @@ typedef struct
int64_t first_pts; int64_t first_pts;
int64_t first_audio_pts; int64_t first_audio_pts;
pthread_mutex_t frame_lock; pthread_mutex_t frame_lock;
pthread_cond_t frame_wait_cond;
id avf_delegate; id avf_delegate;
id avf_audio_delegate; id avf_audio_delegate;
...@@ -130,6 +129,10 @@ typedef struct ...@@ -130,6 +129,10 @@ typedef struct
AVCaptureAudioDataOutput *audio_output; AVCaptureAudioDataOutput *audio_output;
CMSampleBufferRef current_frame; CMSampleBufferRef current_frame;
CMSampleBufferRef current_audio_frame; CMSampleBufferRef current_audio_frame;
AVCaptureDevice *observed_device;
AVCaptureDeviceTransportControlsPlaybackMode observed_mode;
int observed_quit;
} AVFContext; } AVFContext;
static void lock_frames(AVFContext* ctx) static void lock_frames(AVFContext* ctx)
...@@ -163,10 +166,50 @@ static void unlock_frames(AVFContext* ctx) ...@@ -163,10 +166,50 @@ static void unlock_frames(AVFContext* ctx)
{ {
if (self = [super init]) { if (self = [super init]) {
_context = context; _context = context;
// start observing if a device is set for it
if (_context->observed_device) {
NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew;
[_context->observed_device addObserver: self
forKeyPath: keyPath
options: options
context: _context];
}
} }
return self; return self;
} }
- (void)dealloc {
// stop observing if a device is set for it
NSString *keyPath = NSStringFromSelector(@selector(transportControlsPlaybackMode));
[_context->observed_device removeObserver: self forKeyPath: keyPath];
[super dealloc];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == _context) {
AVCaptureDeviceTransportControlsPlaybackMode mode =
[change[NSKeyValueChangeNewKey] integerValue];
if (mode != _context->observed_mode) {
if (mode == AVCaptureDeviceTransportControlsNotPlayingMode) {
_context->observed_quit = 1;
}
_context->observed_mode = mode;
}
} else {
[super observeValueForKeyPath: keyPath
ofObject: object
change: change
context: context];
}
}
- (void) captureOutput:(AVCaptureOutput *)captureOutput - (void) captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)videoFrame didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
fromConnection:(AVCaptureConnection *)connection fromConnection:(AVCaptureConnection *)connection
...@@ -179,8 +222,6 @@ static void unlock_frames(AVFContext* ctx) ...@@ -179,8 +222,6 @@ static void unlock_frames(AVFContext* ctx)
_context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame); _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame);
pthread_cond_signal(&_context->frame_wait_cond);
unlock_frames(_context); unlock_frames(_context);
++_context->frames_captured; ++_context->frames_captured;
...@@ -225,8 +266,6 @@ static void unlock_frames(AVFContext* ctx) ...@@ -225,8 +266,6 @@ static void unlock_frames(AVFContext* ctx)
_context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame); _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
pthread_cond_signal(&_context->frame_wait_cond);
unlock_frames(_context); unlock_frames(_context);
++_context->audio_frames_captured; ++_context->audio_frames_captured;
...@@ -253,7 +292,6 @@ static void destroy_context(AVFContext* ctx) ...@@ -253,7 +292,6 @@ static void destroy_context(AVFContext* ctx)
av_freep(&ctx->audio_buffer); av_freep(&ctx->audio_buffer);
pthread_mutex_destroy(&ctx->frame_lock); pthread_mutex_destroy(&ctx->frame_lock);
pthread_cond_destroy(&ctx->frame_wait_cond);
if (ctx->current_frame) { if (ctx->current_frame) {
CFRelease(ctx->current_frame); CFRelease(ctx->current_frame);
...@@ -499,6 +537,15 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device) ...@@ -499,6 +537,15 @@ static int add_video_device(AVFormatContext *s, AVCaptureDevice *video_device)
} }
[ctx->video_output setAlwaysDiscardsLateVideoFrames:ctx->drop_late_frames]; [ctx->video_output setAlwaysDiscardsLateVideoFrames:ctx->drop_late_frames];
// check for transport control support and set observer device if supported
int trans_ctrl = [video_device transportControlsSupported];
AVCaptureDeviceTransportControlsPlaybackMode trans_mode = [video_device transportControlsPlaybackMode];
if (trans_ctrl) {
ctx->observed_mode = trans_mode;
ctx->observed_device = video_device;
}
ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx]; ctx->avf_delegate = [[AVFFrameReceiver alloc] initWithContext:ctx];
queue = dispatch_queue_create("avf_queue", NULL); queue = dispatch_queue_create("avf_queue", NULL);
...@@ -709,7 +756,6 @@ static int avf_read_header(AVFormatContext *s) ...@@ -709,7 +756,6 @@ static int avf_read_header(AVFormatContext *s)
ctx->first_audio_pts = av_gettime(); ctx->first_audio_pts = av_gettime();
pthread_mutex_init(&ctx->frame_lock, NULL); pthread_mutex_init(&ctx->frame_lock, NULL);
pthread_cond_init(&ctx->frame_wait_cond, NULL);
#if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
CGGetActiveDisplayList(0, NULL, &num_screens); CGGetActiveDisplayList(0, NULL, &num_screens);
...@@ -1110,7 +1156,12 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -1110,7 +1156,12 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt)
ctx->current_audio_frame = nil; ctx->current_audio_frame = nil;
} else { } else {
pkt->data = NULL; pkt->data = NULL;
pthread_cond_wait(&ctx->frame_wait_cond, &ctx->frame_lock); unlock_frames(ctx);
if (ctx->observed_quit) {
return AVERROR_EOF;
} else {
return AVERROR(EAGAIN);
}
} }
unlock_frames(ctx); unlock_frames(ctx);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment