From patchwork Thu Mar 5 21:59:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thilo Borgmann X-Patchwork-Id: 18063 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 196D544AE1D for ; Thu, 5 Mar 2020 23:59:25 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EA7E968A62A; Thu, 5 Mar 2020 23:59:24 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from shout02.mail.de (shout02.mail.de [62.201.172.25]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A82636891E5 for ; Thu, 5 Mar 2020 23:59:18 +0200 (EET) Received: from postfix01.mail.de (postfix01.bt.mail.de [10.0.121.125]) by shout02.mail.de (Postfix) with ESMTP id 39133C0EA8 for ; Thu, 5 Mar 2020 22:59:18 +0100 (CET) Received: from smtp02.mail.de (smtp02.bt.mail.de [10.0.121.212]) by postfix01.mail.de (Postfix) with ESMTP id 215548027D for ; Thu, 5 Mar 2020 22:59:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mail.de; s=mailde201610; t=1583445558; bh=eQWixgKPK2wylVqqxTDkBKUPMOSSVWU5J+GDUtJdduc=; h=From:Subject:To:Date:From; b=KMzd7KbBuJDirM6A1oGxY12JYm9pMlYdNQHyGSa8HnVevchstQ9GYNfX55wRxIa+j 9qdSZA04DaGnYkW0anlmgE6w9DZkFYEYSdRGF9ZP9w8l28XzsQNXFEW75TnXTqA9q/ xr/YTIX6bbgt0vA1Cu1P2f2yDOGYnqyOcIolYgS0= Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtp02.mail.de (Postfix) with ESMTPSA id D8198A051B for ; Thu, 5 Mar 2020 22:59:17 +0100 (CET) From: Thilo Borgmann Autocrypt: addr=thilo.borgmann@mail.de; prefer-encrypt=mutual; keydata= xsBNBF1NyqgBCAC/eJ7l/Ic+5bhj3N4eTyLRMCQVyxPF6sIDu0RqZCsLYx6GjH6BBrPcewbG wLfWNqWPWpcHLbOwDE2FWSBgDbc7Zwrmtkxt4+RNj2/JYRyCiV1uIRm1rlcf80pqDEYM+1O8 23b/JrONn7pQpX8alrYfhP3tLR2PKO/wHmG4AlSEG5T8angmGMvfKVSzxq7E07MIdUqiHHj/ t/F+6WFkpaec++CWcU+9s9IWRV+HskgihqZBqvzRYptvFi81con+VqpYjtpqoYAj4XwqM6j4 /8kTobgPo0n/QRCFcpZYRA7SCT4LbwOvy+qZ1e5372rzOcIF6PGdVzH4CCRT1Ypg1D6TABEB AAHNJ1RoaWxvIEJvcmdtYW5uIDx0aGlsby5ib3JnbWFubkBtYWlsLmRlPsLAqwQTAQoAPhYh BM4dt/RNIPw63Z/+WiV8W48dILkvBQJdTcqoAhsDBQkDwmcABQsJCAcDBRUKCQgLBRYCAwEA Ah4BAheAACEJECV8W48dILkvFiEEzh239E0g/Drdn/5aJXxbjx0guS/UtAf+JkEY+fQ29Gcv 509tfZW+uvTEmXzvIWmMP7TGYHGnHc/swhB8IY25J7/Z88qUxD0tTjnTHlNEEk4ZYAwHrgfv G/epK/AccKmPTj/FsmoUp4cRLwq17rQv2nc8L7i/Yg6syYTHaRF0SCQ8TPvcSoC4hP3IBWZj t23R0TyDeSnvK/+IeIsNejgz37Q+bWBtWsvUl6EBB0y51T6dp1RjsBS3Ot4FkFOqzMqCc3y1 808khhLgBnU24LnA62RMcUfvgMIRx0w8ioj1xJyp3U6c/JFhHxlLW5uVnOZ/odhuf+Hnel2u wyRCQxI2dLhBDZ9LVbospxZQok2GgRJIK6cnX23afc7ATQRdTcqoAQgAxQIqcXiQTaIFAWXc 9YEGuhrQF+TmKF7Jt1IGFmvfdmofnoFZ/8teZB03XP1VSVI/IXM7CTsEfQlBMgGcc9Tj3c9Z v+De/FfjBLJYOYKJIleIfhIZBLr6Hxru2qGma+piKXjbJCBJabSIu4YDM6iH3D2GJwanSspc ee3yvTSR7we1hcoavemw3pseurg6Y4dWsKEJLNP2xZ0C7fyidQsIh7RtNuzKsSVqqx1YbBwO 4cek4gQfJ9UC0nvt9X/pX1COhDeNAsTI8h2iC13Gi14a+EWF8ppvK0V3i5VDaxWrreUDY1Nt L6qGiQte/X4tvzRLEIe1gpT5wRK/QVXARlF8lQARAQABwsCTBBgBCgAmFiEEzh239E0g/Drd n/5aJXxbjx0guS8FAl1NyqgCGwwFCQPCZwAAIQkQJXxbjx0guS8WIQTOHbf0TSD8Ot2f/lol fFuPHSC5L+GLCACkU8DKD+HOEPvxTftn3pQ6YE+yfwSeS1uBjH6D2SsXdTrAZEE9KNjqYExr PuMy1GxAH3CeD+Kqc0sra5I9s3AdNAM1YeHQbY4zWaHfcaeU/cF/c2MxyhnRbr/UF382PUY5 yoWAmIBomSZdaifXXuU/CosZkpk01LDfl5fx5SfF13TrZ1FtPbXmP5S0n2HzxLM64hF0RzVz zR8xEofnP7jWJGcO7KcUCqSy64KGgNlYzyCWso+Tf0AJOtWYkfRvI/MyruItQ31jRs7VRh67 /lX38m5iqqjjwQ2GNZq29qGCNmjmsBjgzMmoy+5jUuoy233waGIGRFt1g9pLiMmchdWR To: FFmpeg development discussions and patches Message-ID: <4ddd1ce7-02fe-21fe-3c4e-27ee0eb36321@mail.de> Date: Thu, 5 Mar 2020 22:59:17 +0100 MIME-Version: 1.0 Content-Language: en-US X-purgate: clean X-purgate: This mail is considered clean (visit http://www.eleven.de for further information) X-purgate-type: clean X-purgate-Ad: Categorized by eleven eXpurgate (R) http://www.eleven.de X-purgate: This mail is considered clean (visit http://www.eleven.de for further information) X-purgate: clean X-purgate-size: 8174 X-purgate-ID: 154282::1583445557-0000058E-C1044482/0/0 Subject: [FFmpeg-devel] [PATCH] lavd/avfoundation: Add basic transport control observation, for capable devices. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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(&ctx->audio_buffer); pthread_mutex_destroy(&ctx->frame_lock); - pthread_cond_destroy(&ctx->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(&ctx->frame_lock, NULL); - pthread_cond_init(&ctx->frame_wait_cond, NULL); #if !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 CGGetActiveDisplayList(0, NULL, &num_screens); @@ -1110,7 +1156,12 @@ static int avf_read_packet(AVFormatContext *s, AVPacket *pkt) ctx->current_audio_frame = nil; } else { 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);