Re: [FFmpeg-devel] [PATCH] lavd/avfoundation: Add basic transport control observation, for capable devices.

2020-03-16 Thread Thilo Borgmann
Am 12.03.20 um 11:26 schrieb Thilo Borgmann:
> Hi,
> 
>> fixes infinite loop waiting for input using e.g. tape devices that suport 
>> transport control.
> 
> will apply soon.

Applied.

-Thilo
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] lavd/avfoundation: Add basic transport control observation, for capable devices.

2020-03-12 Thread Thilo Borgmann
Hi,

> fixes infinite loop waiting for input using e.g. tape devices that suport 
> transport control.

will apply soon.

-Thilo
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

[FFmpeg-devel] [PATCH] lavd/avfoundation: Add basic transport control observation, for capable devices.

2020-03-05 Thread Thilo Borgmann
Hi,

fixes infinite loop waiting for input using e.g. tape devices that suport 
transport control.

-Thilo
From 656f1fe2a91bda6099d0ed3848dce9aec55c8932 Mon Sep 17 00:00:00 2001
From: Thilo Borgmann 
Date: Thu, 5 Mar 2020 12:32:49 +0100
Subject: [PATCH] lavd/avfoundation: Add basic transport control observation
 for capable devices.

---
 libavdevice/avfoundation.m | 67 --
 1 file changed, 59 insertions(+), 8 deletions(-)

diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index 0d854a1..43b2edb 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -88,7 +88,6 @@ typedef struct
 int64_t first_pts;
 int64_t first_audio_pts;
 pthread_mutex_t frame_lock;
-pthread_cond_t  frame_wait_cond;
 id  avf_delegate;
 id  avf_audio_delegate;
 
@@ -130,6 +129,10 @@ typedef struct
 AVCaptureAudioDataOutput *audio_output;
 CMSampleBufferRef current_frame;
 CMSampleBufferRef current_audio_frame;
+
+AVCaptureDevice  *observed_device;
+AVCaptureDeviceTransportControlsPlaybackMode observed_mode;
+int  observed_quit;
 } AVFContext;
 
 static void lock_frames(AVFContext* ctx)
@@ -163,10 +166,50 @@ static void unlock_frames(AVFContext* ctx)
 {
 if (self = [super init]) {
 _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;
 }
 
+- (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
   didOutputSampleBuffer:(CMSampleBufferRef)videoFrame
  fromConnection:(AVCaptureConnection *)connection
@@ -179,8 +222,6 @@ static void unlock_frames(AVFContext* ctx)
 
 _context->current_frame = (CMSampleBufferRef)CFRetain(videoFrame);
 
-pthread_cond_signal(&_context->frame_wait_cond);
-
 unlock_frames(_context);
 
 ++_context->frames_captured;
@@ -225,8 +266,6 @@ static void unlock_frames(AVFContext* ctx)
 
 _context->current_audio_frame = (CMSampleBufferRef)CFRetain(audioFrame);
 
-pthread_cond_signal(&_context->frame_wait_cond);
-
 unlock_frames(_context);
 
 ++_context->audio_frames_captured;
@@ -253,7 +292,6 @@ static void destroy_context(AVFContext* ctx)
 av_freep(>audio_buffer);
 
 pthread_mutex_destroy(>frame_lock);
-pthread_cond_destroy(>frame_wait_cond);
 
 if (ctx->current_frame) {
 CFRelease(ctx->current_frame);
@@ -499,6 +537,15 @@ static int add_video_device(AVFormatContext *s, 
AVCaptureDevice *video_device)
 }
 [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];
 
 queue = dispatch_queue_create("avf_queue", NULL);
@@ -709,7 +756,6 @@ static int avf_read_header(AVFormatContext *s)
 ctx->first_audio_pts= av_gettime();
 
 pthread_mutex_init(>frame_lock, NULL);
-pthread_cond_init(>frame_wait_cond, NULL);
 
 #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070