From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 645294031F for ; Wed, 19 Jan 2022 14:42:47 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 06F7A68B0D2; Wed, 19 Jan 2022 16:42:45 +0200 (EET) Received: from mail-qv1-f43.google.com (mail-qv1-f43.google.com [209.85.219.43]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2610068B058 for ; Wed, 19 Jan 2022 16:42:39 +0200 (EET) Received: by mail-qv1-f43.google.com with SMTP id g13so442439qvw.4 for ; Wed, 19 Jan 2022 06:42:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=mIRS1fptF958ztupuJK/8EGkFYQDkdq0cIsOWLee8to=; b=IFCqd8keytkGdcxBodT1VWgU9SkN3z3BIBdkWyEyw0b1/V16se6tmnktrUIw7d5pkP HP5j1ZcN0tjwm4UT372jZnhmJJjQIj3lhNAk2OgtfHPlRLNl+//UygBnbxalnkGIjD+M PjMbpYoO3N/+Bdvv55UcSeEKlITf/iCEGJfqAbopFNZKtlGFHBYrfIq/BcyfLSLvFNQV l3wBIlcR8EzLszZ2PwZs1dFuC/ghekKGllAaaiT3bOLPpeCZM5HizzsAbkYzthOCX+Vx adHcV2OuMCI6O5NwZ5qtW+qE+9vGTtT/XzfArBU1z/7O2eBSlOStNE8FGdDEuxaHvdhs Tr6w== X-Gm-Message-State: AOAM5322tjymGhgeQdV/jpq1VwveaRcHz8gBMVogJMyUXaxf+q1I2cU/ mMUUEDorhqpwoJavuTtl9VDwFmzWyxxKTkU5 X-Google-Smtp-Source: ABdhPJyld8danldVOvC38o+NFjPaeOBrEGxuNKrbDmSwKEVcFoTaT2R4XZQJl77+KQD2fjMAtFkqvA== X-Received: by 2002:ad4:5be6:: with SMTP id k6mr5532213qvc.29.1642603357584; Wed, 19 Jan 2022 06:42:37 -0800 (PST) Received: from smtpclient.apple ([172.58.4.135]) by smtp.gmail.com with ESMTPSA id h6sm3563178qkk.122.2022.01.19.06.42.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 19 Jan 2022 06:42:36 -0800 (PST) From: Romain Beauxis Message-Id: <721A53D6-1103-4A9B-A1CA-FEC80C93483E@rastageeks.org> Content-Type: multipart/mixed; boundary="Apple-Mail=_A13D1362-13B1-4F92-B033-C3D2B3AD99C4" Mime-Version: 1.0 (Mac OS X Mail 15.0 \(3693.40.0.1.81\)) Date: Wed, 19 Jan 2022 08:42:34 -0600 In-Reply-To: To: FFmpeg development discussions and patches References: X-Mailer: Apple Mail (2.3693.40.0.1.81) Subject: [FFmpeg-devel] [PATCH 5/5] Add AudioToolbox audio input device. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Thilo Borgmann , Marvin Scholz Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: --Apple-Mail=_A13D1362-13B1-4F92-B033-C3D2B3AD99C4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii This patch adds support for a new, audio-specific input device using the = documented and battle-tested AUHAL input. This provides a pendant to the = AudioToolbox audio-only output. A couple of advantages for this: * It avoids a lot of the complexity of supporting audio and video in a = single input * The AUHAL API seems tested, documented and robust * This implementation hopefully gives good control over audio latency = and also minimizes data copy --Apple-Mail=_A13D1362-13B1-4F92-B033-C3D2B3AD99C4 Content-Disposition: attachment; filename=0001-Add-AudioToolbox-audio-input-device.eml Content-Type: message/rfc822; x-unix-mode=0644; name="0001-Add-AudioToolbox-audio-input-device.eml" Content-Transfer-Encoding: quoted-printable =46rom=20803e1aa52018bdac0a448be255f645ca447273e9=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Romain=20Beauxis=20=0A= Date:=20Tue,=2018=20Jan=202022=2016:29:59=20-0600=0ASubject:=20[PATCH]=20= Add=20AudioToolbox=20audio=20input=20device.=0AX-Unsent:=201=0ATo:=20= ffmpeg-devel@ffmpeg.org=0A=0ASigned-off-by:=20Romain=20Beauxis=20= =0A---=0A=20configure=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=20=205=20+=0A=20doc/indevs.texi=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=2044=20++++=0A=20= libavdevice/Makefile=20=20=20=20=20=20=20=20=20=20=20|=20=20=201=20+=0A=20= libavdevice/alldevices.c=20=20=20=20=20=20=20|=20=20=201=20+=0A=20= libavdevice/audiotoolbox_dec.m=20|=20466=20= +++++++++++++++++++++++++++++++++=0A=205=20files=20changed,=20517=20= insertions(+)=0A=20create=20mode=20100644=20= libavdevice/audiotoolbox_dec.m=0A=0Adiff=20--git=20a/configure=20= b/configure=0Aindex=201413122d87..80e39aae44=20100755=0A---=20= a/configure=0A+++=20b/configure=0A@@=20-204,6=20+204,7=20@@=20External=20= library=20support:=0A=20=20=20--disable-avfoundation=20=20=20disable=20= Apple=20AVFoundation=20framework=20[autodetect]=0A=20=20=20= --enable-avisynth=20=20=20=20=20=20=20=20enable=20reading=20of=20= AviSynth=20script=20files=20[no]=0A=20=20=20--disable-bzlib=20=20=20=20=20= =20=20=20=20=20disable=20bzlib=20[autodetect]=0A+=20=20= --disable-coremedia=20=20=20=20=20=20disable=20Apple=20CoreMedia=20= framework=20[autodetect]=0A=20=20=20--disable-coreimage=20=20=20=20=20=20= disable=20Apple=20CoreImage=20framework=20[autodetect]=0A=20=20=20= --enable-chromaprint=20=20=20=20=20enable=20audio=20fingerprinting=20= with=20chromaprint=20[no]=0A=20=20=20--enable-frei0r=20=20=20=20=20=20=20= =20=20=20enable=20frei0r=20video=20filtering=20[no]=0A@@=20-1750,6=20= +1751,7=20@@=20EXTERNAL_AUTODETECT_LIBRARY_LIST=3D"=0A=20=20=20=20=20= appkit=0A=20=20=20=20=20avfoundation=0A=20=20=20=20=20bzlib=0A+=20=20=20=20= coremedia=0A=20=20=20=20=20coreimage=0A=20=20=20=20=20iconv=0A=20=20=20=20= =20libxcb=0A@@=20-3493,6=20+3495,8=20@@=20alsa_outdev_deps=3D"alsa"=0A=20= avfoundation_indev_deps=3D"avfoundation=20corevideo=20coremedia=20= pthreads"=0A=20avfoundation_indev_suggest=3D"coregraphics=20= applicationservices"=0A=20avfoundation_indev_extralibs=3D"-framework=20= Foundation"=0A+audiotoolbox_indev_deps=3D"coremedia=20audiotoolbox"=0A= +audiotoolbox_indev_extralibs=3D"-framework=20CoreMedia=20-framework=20= AudioToolbox"=0A=20audiotoolbox_outdev_deps=3D"audiotoolbox=20pthreads"=0A= =20audiotoolbox_outdev_extralibs=3D"-framework=20AudioToolbox=20= -framework=20CoreAudio"=0A=20bktr_indev_deps_any=3D"dev_bktr_ioctl_bt848_h= =20machine_ioctl_bt848_h=20dev_video_bktr_ioctl_bt848_h=20= dev_ic_bt8xx_h"=0A@@=20-6340,6=20+6344,7=20@@=20check_lib=20camera2ndk=20= "stdbool.h=20stdint.h=20camera/NdkCameraManager.h"=20ACameraManag=0A=20= enabled=20appkit=20=20=20=20=20=20=20&&=20check_apple_framework=20AppKit=0A= =20enabled=20audiotoolbox=20&&=20check_apple_framework=20AudioToolbox=0A=20= enabled=20avfoundation=20&&=20check_apple_framework=20AVFoundation=0A= +enabled=20coremedia=20=20=20=20&&=20check_apple_framework=20CoreMedia=0A= =20enabled=20coreimage=20=20=20=20&&=20check_apple_framework=20CoreImage=0A= =20enabled=20metal=20=20=20=20=20=20=20=20&&=20check_apple_framework=20= Metal=0A=20enabled=20videotoolbox=20&&=20check_apple_framework=20= VideoToolbox=0Adiff=20--git=20a/doc/indevs.texi=20b/doc/indevs.texi=0A= index=20858c0fa4e4..30a91d304f=20100644=0A---=20a/doc/indevs.texi=0A+++=20= b/doc/indevs.texi=0A@@=20-103,6=20+103,50=20@@=20Set=20the=20maximum=20= number=20of=20frames=20to=20buffer.=20Default=20is=205.=0A=20=0A=20@end=20= table=0A=20=0A+@section=20AudioToolbox=0A+=0A+AudioToolbox=20input=20= device.=0A+=0A+Allows=20native=20input=20from=20CoreAudio=20devices=20on=20= OSX.=0A+=0A+All=20available=20devices=20can=20be=20enumerated=20by=20= using=20@option{-list_devices=20true},=20listing=0A+all=20device=20= names,=20and=20corresponding=20unique=20ID.=0A+=0A+@subsection=20Options=0A= +=0A+AudioToolbox=20supports=20the=20following=20options:=0A+=0A+@table=20= @option=0A+=0A+@item=20channels=0A+Set=20the=20number=20of=20channels.=20= Default=20is=20device's=20default.=0A+=0A+@item=20frames_queue_length=0A= +Maximum=20of=20buffers=20in=20the=20input=20queue=0A+=0A+@item=20= buffer_frame_size=0A+Buffer=20frame=20size,=20gouverning=20internal=20= latency=0A+=0A+@item=20big_endian=0A+Return=20big=20endian=20samples=0A+=0A= +@item=20sample_format=0A+Sample=20format=0A+=0A+@end=20table=0A+=0A= +@subsection=20Examples=0A+=0A+@itemize=0A+=0A+@item=0A+Print=20the=20= list=20of=20supported=20devices=0A+@example=0A+$=20ffmpeg=20-f=20= audiotoolbox=20-list_devices=20true=20-i=20""=0A+@end=20example=0A+=0A= +@end=20itemize=0A+=0A=20@section=20avfoundation=0A=20=0A=20AVFoundation=20= input=20device.=0Adiff=20--git=20a/libavdevice/Makefile=20= b/libavdevice/Makefile=0Aindex=2053efda0514..0c73255a21=20100644=0A---=20= a/libavdevice/Makefile=0A+++=20b/libavdevice/Makefile=0A@@=20-14,6=20= +14,7=20@@=20OBJS-$(HAVE_LIBC_MSVCRT)=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20+=3D=20file_open.o=0A=20OBJS-$(CONFIG_ALSA_INDEV)=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20+=3D=20alsa_dec.o=20alsa.o=20= timefilter.o=0A=20OBJS-$(CONFIG_ALSA_OUTDEV)=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20+=3D=20alsa_enc.o=20alsa.o=0A=20= OBJS-$(CONFIG_ANDROID_CAMERA_INDEV)=20=20=20=20=20=20+=3D=20= android_camera.o=0A+OBJS-$(CONFIG_AUDIOTOOLBOX_INDEV)=20=20=20=20=20=20=20= =20+=3D=20audiotoolbox_dec.o=0A=20OBJS-$(CONFIG_AUDIOTOOLBOX_OUTDEV)=20=20= =20=20=20=20=20+=3D=20audiotoolbox.o=0A=20= OBJS-$(CONFIG_AVFOUNDATION_INDEV)=20=20=20=20=20=20=20=20+=3D=20= avfoundation.o=0A=20OBJS-$(CONFIG_BKTR_INDEV)=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20+=3D=20bktr.o=0Adiff=20--git=20= a/libavdevice/alldevices.c=20b/libavdevice/alldevices.c=0Aindex=20= 22323a0a44..fbecdbb0b2=20100644=0A---=20a/libavdevice/alldevices.c=0A+++=20= b/libavdevice/alldevices.c=0A@@=20-26,6=20+26,7=20@@=20extern=20const=20= AVInputFormat=20=20ff_alsa_demuxer;=0A=20extern=20const=20AVOutputFormat=20= ff_alsa_muxer;=0A=20extern=20const=20AVInputFormat=20=20= ff_android_camera_demuxer;=0A=20extern=20const=20AVOutputFormat=20= ff_audiotoolbox_muxer;=0A+extern=20const=20AVInputFormat=20=20= ff_audiotoolbox_demuxer;=0A=20extern=20const=20AVInputFormat=20=20= ff_avfoundation_demuxer;=0A=20extern=20const=20AVInputFormat=20=20= ff_bktr_demuxer;=0A=20extern=20const=20AVOutputFormat=20ff_caca_muxer;=0A= diff=20--git=20a/libavdevice/audiotoolbox_dec.m=20= b/libavdevice/audiotoolbox_dec.m=0Anew=20file=20mode=20100644=0Aindex=20= 0000000000..7334ab20e0=0A---=20/dev/null=0A+++=20= b/libavdevice/audiotoolbox_dec.m=0A@@=20-0,0=20+1,466=20@@=0A+/*=0A+=20*=20= AudioToolbox=20input=20device=0A+=20*=20Copyright=20(c)=202022=20Romain=20= Beauxis=20=0A+=20*=0A+=20*=20This=20file=20is=20= part=20of=20FFmpeg.=0A+=20*=0A+=20*=20FFmpeg=20is=20free=20software;=20= you=20can=20redistribute=20it=20and/or=0A+=20*=20modify=20it=20under=20= the=20terms=20of=20the=20GNU=20Lesser=20General=20Public=0A+=20*=20= License=20as=20published=20by=20the=20Free=20Software=20Foundation;=20= either=0A+=20*=20version=202.1=20of=20the=20License,=20or=20(at=20your=20= option)=20any=20later=20version.=0A+=20*=0A+=20*=20FFmpeg=20is=20= distributed=20in=20the=20hope=20that=20it=20will=20be=20useful,=0A+=20*=20= but=20WITHOUT=20ANY=20WARRANTY;=20without=20even=20the=20implied=20= warranty=20of=0A+=20*=20MERCHANTABILITY=20or=20FITNESS=20FOR=20A=20= PARTICULAR=20PURPOSE.=20=20See=20the=20GNU=0A+=20*=20Lesser=20General=20= Public=20License=20for=20more=20details.=0A+=20*=0A+=20*=20You=20should=20= have=20received=20a=20copy=20of=20the=20GNU=20Lesser=20General=20Public=0A= +=20*=20License=20along=20with=20FFmpeg;=20if=20not,=20write=20to=20the=20= Free=20Software=0A+=20*=20Foundation,=20Inc.,=2051=20Franklin=20Street,=20= Fifth=20Floor,=20Boston,=20MA=2002110-1301=20USA=0A+=20*/=0A+=0A+/**=0A+=20= *=20@file=0A+=20*=20AudioToolbox=20input=20device=0A+=20*=20@author=20= Romain=20Beauxis=20=0A+=20*/=0A+=0A+#import=20= =0A+#import=20=0A+=0A= +#include=20"libavutil/channel_layout.h"=0A+#include=20= "libavformat/internal.h"=0A+#include=20"avdevice.h"=0A+=0A+typedef=20= struct=20{=0A+=20=20=20=20void=20*data;=0A+=20=20=20=20int=20=20size;=0A= +}=20buffer_t;=0A+=0A+typedef=20struct=20{=0A+=20=20=20=20AVClass=20=20=20= =20=20=20=20=20=20=20=20=20=20*class;=0A+=20=20=20=20CMSimpleQueueRef=20=20= =20=20frames_queue;=0A+=20=20=20=20AudioUnit=20=20=20=20=20=20=20=20=20=20= =20audio_unit;=0A+=20=20=20=20AudioStreamBasicDescription=20= record_format;=0A+=20=20=20=20uint64_t=20=20=20=20=20=20=20=20=20=20=20=20= position;=0A+=20=20=20=20int=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20frames_queue_length;=0A+=20=20=20=20int=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20buffer_frame_size;=0A+=20=20=20=20int=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20stream_index;=0A+=20=20=20=20int=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20big_endian;=0A+=20=20=20=20= enum=20AVSampleFormat=20sample_format;=0A+=20=20=20=20int=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20channels;=0A+=20=20=20=20int=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20list_devices;=0A+}=20ATContext;=0A= +=0A+static=20int=20check_status(void=20*ctx,=20OSStatus=20status,=20= const=20char=20*msg)=20{=0A+=20=20=20=20if=20(status=20=3D=3D=20noErr)=20= {=0A+=20=20=20=20=20=20=20=20av_log(ctx,=20AV_LOG_DEBUG,=20"OK:=20%s\n",=20= msg);=0A+=20=20=20=20=20=20=20=20return=200;=0A+=20=20=20=20}=0A+=0A+=20=20= =20=20NSAutoreleasePool=20*pool=20=3D=20[[NSAutoreleasePool=20alloc]=20= init];=0A+=20=20=20=20NSError=20*error=20=3D=20[NSError=20= errorWithDomain:NSOSStatusErrorDomain=20code:status=20userInfo:nil];=0A+=20= =20=20=20av_log(ctx,=20AV_LOG_ERROR,=20"Error:=20%s=20(%s)\n",=20msg,=20= [[error=20localizedDescription]=20UTF8String]);=0A+=20=20=20=20[pool=20= release];=0A+=20=20=20=20return=201;=0A+}=0A+=0A+static=20OSStatus=20= input_callback(void=20*priv,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= AudioUnitRenderActionFlags=20*ioActionFlags,=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20const=20= AudioTimeStamp=20*inTimeStamp,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20UInt32=20= inBusNumber,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20UInt32=20inNumberFrames,=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20AudioBufferList=20*ioData)=20{=0A+=20=20=20=20ATContext=20*ctx=20= =3D=20(ATContext=20*)priv;=0A+=20=20=20=20OSStatus=20err;=0A+=0A+=20=20=20= =20AudioBuffer=20audio_buffer;=0A+=20=20=20=20=0A+=20=20=20=20= audio_buffer.mNumberChannels=20=3D=20ctx->channels;=0A+=20=20=20=20= audio_buffer.mDataByteSize=20=3D=20inNumberFrames=20*=20= ctx->record_format.mBytesPerFrame;=0A+=0A+=20=20=20=20audio_buffer.mData=20= =3D=20av_malloc(audio_buffer.mDataByteSize);=0A+=20=20=20=20= memset(audio_buffer.mData,=200,=20audio_buffer.mDataByteSize);=0A+=0A+=20= =20=20=20AudioBufferList=20bufferList;=0A+=20=20=20=20= bufferList.mNumberBuffers=20=3D=201;=0A+=20=20=20=20= bufferList.mBuffers[0]=20=3D=20audio_buffer;=0A+=0A+=20=20=20=20err=20=3D=20= AudioUnitRender(ctx->audio_unit,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20ioActionFlags,=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20inTimeStamp,=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20inBusNumber,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20inNumberFrames,=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20&bufferList);=0A+=20=20= =20=20if=20(check_status(ctx,=20err,=20"AudioUnitRender"))=20{=0A+=20=20=20= =20=20=20=20=20av_freep(&audio_buffer.mData);=0A+=20=20=20=20=20=20=20=20= return=20err;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20buffer_t=20*buffer=20=3D= =20av_malloc(sizeof(buffer_t));=0A+=20=20=20=20buffer->data=20=3D=20= audio_buffer.mData;=0A+=20=20=20=20buffer->size=20=3D=20= audio_buffer.mDataByteSize;=0A+=20=20=20=20err=20=3D=20= CMSimpleQueueEnqueue(ctx->frames_queue,=20buffer);=0A+=0A+=20=20=20=20if=20= (err=20!=3D=20noErr)=20{=0A+=20=20=20=20=20=20=20=20av_log(ctx,=20= AV_LOG_DEBUG,=20"Could=20not=20enqueue=20audio=20frame!\n");=0A+=20=20=20= =20=20=20=20=20return=20err;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20return=20= noErr;=0A+}=0A+=0A+static=20av_cold=20int=20= audiotoolbox_read_header(AVFormatContext=20*avctx)=20{=0A+=20=20=20=20= ATContext=20*ctx=20=3D=20(ATContext*)avctx->priv_data;=0A+=20=20=20=20= OSStatus=20err=20=3D=20noErr;=0A+=20=20=20=20CFStringRef=20device_UID=20= =3D=20NULL;=0A+=20=20=20=20CFStringRef=20device_name=20=3D=20NULL;=0A+=20= =20=20=20AudioDeviceID=20*devices=20=3D=20NULL;=0A+=20=20=20=20= AudioChannelLayout=20*channel_layout=20=3D=20NULL;=0A+=20=20=20=20= AudioDeviceID=20device=20=3D=200;=0A+=20=20=20=20CFStringRef=20= selected_device_UID=20=3D=20NULL;=0A+=20=20=20=20int=20num_devices;=0A+=20= =20=20=20UInt32=20i;=0A+=0A+=20=20=20=20enum=20AVCodecID=20codec_id=20=3D=20= av_get_pcm_codec(ctx->sample_format,=20ctx->big_endian);=0A+=0A+=20=20=20= =20if=20(codec_id=20=3D=3D=20AV_CODEC_ID_NONE)=20{=0A+=20=20=20=20=20=20=20= av_log(ctx,=20AV_LOG_ERROR,=20"Error:=20invalid=20sample=20format!\n");=0A= +=20=20=20=20=20=20=20return=20AVERROR(EINVAL);=0A+=20=20=20=20}=0A+=0A+=20= =20=20=20//=20get=20devices=0A+=20=20=20=20UInt32=20data_size=20=3D=200;=0A= +=20=20=20=20AudioObjectPropertyAddress=20prop;=0A+=20=20=20=20= prop.mSelector=20=3D=20kAudioHardwarePropertyDevices;=0A+=20=20=20=20= prop.mScope=20=20=20=20=3D=20kAudioObjectPropertyScopeGlobal;=0A+=20=20=20= =20prop.mElement=20=20=3D=200;=0A+=20=20=20=20err=20=3D=20= AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,=20&prop,=200,=20= NULL,=20&data_size);=0A+=20=20=20=20if=20(check_status(avctx,=20err,=20= "AudioObjectGetPropertyDataSize=20devices"))=0A+=20=20=20=20=20=20=20=20= return=20AVERROR(EINVAL);=0A+=0A+=20=20=20=20num_devices=20=3D=20= data_size=20/=20sizeof(AudioDeviceID);=0A+=20=20=20=20devices=20=3D=20= av_malloc(data_size);=0A+=0A+=20=20=20=20err=20=3D=20= AudioObjectGetPropertyData(kAudioObjectSystemObject,=20&prop,=200,=20= NULL,=20&data_size,=20devices);=0A+=20=20=20=20if=20(check_status(avctx,=20= err,=20"AudioObjectGetPropertyData=20devices"))=0A+=20=20=20=20=20=20=20=20= goto=20fail;=0A+=0A+=20=20=20=20if=20(ctx->list_devices)=0A+=20=20=20=20=20= =20=20=20av_log(ctx,=20AV_LOG_INFO,=20"CoreAudio=20input=20devices:\n");=0A= +=0A+=20=20=20=20for(i=20=3D=200;=20i=20<=20num_devices;=20++i)=20{=0A+=20= =20=20=20=20=20=20=20prop.mSelector=20=20=3D=20= kAudioDevicePropertyStreams;=0A+=20=20=20=20=20=20=20=20prop.mScope=20=20= =20=20=20=3D=20kAudioDevicePropertyScopeInput;=0A+=20=20=20=20=20=20=20=20= data_size=20=20=20=20=20=20=20=3D=200;=0A+=0A+=20=20=20=20=20=20=20=20= err=20=3D=20AudioObjectGetPropertyDataSize(devices[i],=20&prop,=200,=20= NULL,=20&data_size);=0A+=20=20=20=20=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioObjectGetPropertyData=20Streams"))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20continue;=0A+=0A+=20=20=20=20=20=20=20= =20UInt32=20streamCount=20=3D=20data_size=20/=20sizeof(AudioStreamID);=0A= +=0A+=20=20=20=20=20=20=20=20if=20(streamCount=20<=3D=200)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20continue;=0A+=0A+=20=20=20=20=20=20=20=20//=20= UID=0A+=20=20=20=20=20=20=20=20data_size=20=3D=20sizeof(device_UID);=0A+=20= =20=20=20=20=20=20=20prop.mSelector=20=3D=20= kAudioDevicePropertyDeviceUID;=0A+=20=20=20=20=20=20=20=20err=20=3D=20= AudioObjectGetPropertyData(devices[i],=20&prop,=200,=20NULL,=20= &data_size,=20&device_UID);=0A+=20=20=20=20=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioObjectGetPropertyData=20UID"))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20continue;=0A+=0A+=20=20=20=20=20=20=20=20= if=20(!strcmp(avctx->url,=20CFStringGetCStringPtr(device_UID,=20= kCFStringEncodingUTF8)))=20{=0A+=20=20=20=20=20=20=20=20=20=20=20=20= selected_device_UID=20=3D=20device_UID;=0A+=20=20=20=20=20=20=20=20=20=20= =20=20device=20=3D=20devices[i];=0A+=20=20=20=20=20=20=20=20}=0A+=0A+=20=20= =20=20=20=20=20=20//=20name=0A+=20=20=20=20=20=20=20=20data_size=20=3D=20= sizeof(device_name);=0A+=20=20=20=20=20=20=20=20prop.mSelector=20=3D=20= kAudioDevicePropertyDeviceNameCFString;=0A+=20=20=20=20=20=20=20=20err=20= =3D=20AudioObjectGetPropertyData(devices[i],=20&prop,=200,=20NULL,=20= &data_size,=20&device_name);=0A+=20=20=20=20=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioObjecTGetPropertyData=20name"))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20continue;=0A+=0A+=20=20=20=20=20=20=20=20= if=20(!strcmp(avctx->url,=20CFStringGetCStringPtr(device_name,=20= kCFStringEncodingUTF8)))=20{=0A+=20=20=20=20=20=20=20=20=20=20=20=20= selected_device_UID=20=3D=20device_name;=0A+=20=20=20=20=20=20=20=20=20=20= =20=20device=20=3D=20devices[i];=0A+=20=20=20=20=20=20=20=20}=0A+=0A+=20=20= =20=20=20=20=20=20if=20(ctx->list_devices)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20av_log(ctx,=20AV_LOG_INFO,=20"ID:=20%s,=20name:=20%s\n",=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= CFStringGetCStringPtr(device_UID,=20kCFStringEncodingUTF8),=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= CFStringGetCStringPtr(device_name,=20kCFStringEncodingUTF8));=0A+=20=20=20= =20}=0A+=0A+=20=20=20=20if=20(!device_UID)=20{=0A+=20=20=20=20=20=20= av_log(ctx,=20AV_LOG_ERROR,=20"No=20device=20found!\n");=0A+=20=20=20=20=20= =20goto=20fail;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20if=20= (ctx->list_devices)=0A+=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20= =20=20Float64=20sample_rate;=0A+=20=20=20=20prop.mSelector=20=3D=20= kAudioDevicePropertyNominalSampleRate;=0A+=20=20=20=20prop.mScope=20=20=20= =20=3D=20kAudioObjectPropertyScopeInput;=0A+=20=20=20=20data_size=20=20=20= =20=20=20=3D=20sizeof(sample_rate);=0A+=20=20=20=20err=20=3D=20= AudioObjectGetPropertyData(device,=20&prop,=200,=20NULL,=20&data_size,=20= &sample_rate);=0A+=20=20=20=20if=20(check_status(avctx,=20err,=20= "AudioObjecTGetPropertyData=20SampleRate"))=0A+=20=20=20=20=20=20=20=20= goto=20fail;=0A+=0A+=20=20=20=20if=20(!ctx->channels)=20{=0A+=20=20=20=20= =20=20=20=20prop.mSelector=20=3D=20= kAudioDevicePropertyPreferredChannelLayout;=0A+=20=20=20=20=20=20=20=20= prop.mScope=20=20=20=20=3D=20kAudioObjectPropertyScopeInput;=0A+=20=20=20= =20=20=20=20=20UInt32=20channel_layout_size;=0A+=0A+=20=20=20=20=20=20=20= =20err=20=3D=20AudioObjectGetPropertyDataSize(device,=20&prop,=200,=20= NULL,=20&channel_layout_size);=0A+=20=20=20=20=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioObjectGetPropertyDataSize=20= PreferredChannelLayout"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20goto=20= fail;=0A+=0A+=20=20=20=20=20=20=20=20channel_layout=20=3D=20= av_malloc(channel_layout_size);=0A+=20=20=20=20=20=20=20=20err=20=3D=20= AudioObjectGetPropertyData(device,=20&prop,=200,=20NULL,=20= &channel_layout_size,=20channel_layout);=0A+=20=20=20=20=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioObjecTGetPropertyData=20= PreferredChannelLayout"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20goto=20= fail;=0A+=0A+=20=20=20=20=20=20=20=20data_size=20=3D=20= sizeof(ctx->channels);=0A+=20=20=20=20=20=20=20=20err=20=3D=20= AudioFormatGetProperty(kAudioFormatProperty_NumberOfChannelsForLayout,=20= channel_layout_size,=20channel_layout,=20&data_size,=20&ctx->channels);=0A= +=20=20=20=20=20=20=20=20if=20(check_status(avctx,=20err,=20= "AudioFormatGetProperty=20NumberOfChannelsForLayout"))=0A+=20=20=20=20=20= =20=20=20=20=20=20goto=20fail;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20= ctx->record_format.mFormatID=20=20=20=20=20=20=20=20=20=3D=20= kAudioFormatLinearPCM;=0A+=20=20=20=20= ctx->record_format.mChannelsPerFrame=20=3D=20ctx->channels;=0A+=20=20=20=20= ctx->record_format.mFormatFlags=20=20=20=20=20=20=3D=20= kAudioFormatFlagIsPacked;=0A+=20=20=20=20= ctx->record_format.mBitsPerChannel=20=20=20=3D=20= av_get_bytes_per_sample(ctx->sample_format)=20<<=203;=0A+=0A+=20=20=20=20= if=20(ctx->big_endian)=0A+=20=20=20=20=20=20=20=20= ctx->record_format.mFormatFlags=20|=3D=20kAudioFormatFlagIsBigEndian;=0A= +=0A+=20=20=20=20switch=20(ctx->sample_format)=20{=0A+=20=20=20=20=20=20=20= =20case=20AV_SAMPLE_FMT_S16:=0A+=20=20=20=20=20=20=20=20case=20= AV_SAMPLE_FMT_S32:=0A+=20=20=20=20=20=20=20=20=20=20=20=20= ctx->record_format.mFormatFlags=20|=3D=20= kAudioFormatFlagIsSignedInteger;=0A+=20=20=20=20=20=20=20=20=20=20=20=20= break;=0A+=20=20=20=20=20=20=20=20case=20AV_SAMPLE_FMT_FLT:=0A+=20=20=20=20= =20=20=20=20=20=20=20=20ctx->record_format.mFormatFlags=20|=3D=20= kAudioFormatFlagIsFloat;=0A+=20=20=20=20=20=20=20=20=20=20=20=20break;=0A= +=20=20=20=20=20=20=20=20default:=0A+=20=20=20=20=20=20=20=20=20=20=20=20= av_log(ctx,=20AV_LOG_ERROR,=20"Error:=20invalid=20sample=20format!\n");=0A= +=20=20=20=20=20=20=20=20=20=20=20=20goto=20fail;=0A+=20=20=20=20}=0A+=0A= +=20=20=20=20av_log(ctx,=20AV_LOG_DEBUG,=20"Audio=20Input:=20%s\n",=20= CFStringGetCStringPtr(selected_device_UID,=20kCFStringEncodingUTF8));=0A= +=20=20=20=20av_log(ctx,=20AV_LOG_DEBUG,=20"samplerate:=20%d\n",=20= (int)sample_rate);=0A+=20=20=20=20av_log(ctx,=20AV_LOG_DEBUG,=20= "channels:=20%d\n",=20ctx->channels);=0A+=20=20=20=20av_log(ctx,=20= AV_LOG_DEBUG,=20"Input=20format:=20%s\n",=20avcodec_get_name(codec_id));=0A= +=0A+=20=20=20=20data_size=20=3D=20sizeof(ctx->record_format);=0A+=20=20=20= =20err=20=3D=20AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,=20= 0,=20NULL,=20&data_size,=20&ctx->record_format);=20=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioFormatGetProperty=20FormatInfo"))=0A= +=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20= AudioComponentDescription=20desc;=0A+=20=20=20=20AudioComponent=20comp;=0A= +=0A+=20=20=20=20desc.componentType=20=3D=20kAudioUnitType_Output;=0A+=20= =20=20=20desc.componentSubType=20=3D=20kAudioUnitSubType_HALOutput;=0A+=20= =20=20=20desc.componentManufacturer=20=3D=20= kAudioUnitManufacturer_Apple;=0A+=20=20=20=20desc.componentFlags=20=3D=20= 0;=0A+=20=20=20=20desc.componentFlagsMask=20=3D=200;=0A+=0A+=20=20=20=20= comp=20=3D=20AudioComponentFindNext(NULL,=20&desc);=0A+=20=20=20=20if=20= (comp=20=3D=3D=20NULL)=20{=0A+=20=20=20=20=20=20=20=20av_log(ctx,=20= AV_LOG_ERROR,=20"Error:=20AudioComponentFindNext\n");=0A+=20=20=20=20=20=20= =20=20goto=20fail;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20err=20=3D=20= AudioComponentInstanceNew(comp,=20&ctx->audio_unit);=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioComponentInstanceNew"))=0A+=20=20=20=20= =20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20UInt32=20enableIO=20=3D=201;=0A= +=20=20=20=20err=20=3D=20AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20kAudioOutputUnitProperty_EnableIO,=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Input,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=201,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &enableIO,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20sizeof(enableIO));=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitSetProperty=20EnableIO"))=0A+=20=20= =20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20enableIO=20=3D=200;=0A= +=20=20=20=20err=20=3D=20AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioOutputUnitProperty_EnableIO,=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20kAudioUnitScope_Output,=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=200,=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &enableIO,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20sizeof(enableIO));=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitSetProperty=20EnableIO"))=0A+=20=20= =20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20err=20=3D=20= AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioOutputUnitProperty_CurrentDevice,=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Global,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=200,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &device,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20sizeof(device));=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitSetProperty=20CurrentDevice"))=0A= +=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20err=20=3D=20= AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitProperty_StreamFormat,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Input,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=200,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &ctx->record_format,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20sizeof(ctx->record_format));=0A= +=20=20=20=20if=20(check_status(avctx,=20err,=20"AudioUnitSetProperty=20= StreamFormat"))=0A+=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20= err=20=3D=20AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitProperty_StreamFormat,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Output,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=201,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &ctx->record_format,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20sizeof(ctx->record_format));=0A= +=20=20=20=20if=20(check_status(avctx,=20err,=20"AudioUnitSetProperty=20= StreamFormat"))=0A+=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20= err=20=3D=20AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioDevicePropertyBufferFrameSize,=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Global,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=200,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &ctx->buffer_frame_size,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= sizeof(ctx->buffer_frame_size));=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitSetProperty=20BufferFrameSize"))=0A= +=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20= AURenderCallbackStruct=20callback=20=3D=20{0};=0A+=20=20=20=20= callback.inputProc=20=3D=20input_callback;=0A+=20=20=20=20= callback.inputProcRefCon=20=3D=20ctx;=0A+=20=20=20=20err=20=3D=20= AudioUnitSetProperty(ctx->audio_unit,=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioOutputUnitProperty_SetInputCallback,=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= kAudioUnitScope_Global,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=200,=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= &callback,=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20sizeof(callback));=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitSetProperty=20= SetInputCallback"))=0A+=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20=20= =20=20err=20=3D=20AudioUnitInitialize(ctx->audio_unit);=0A+=20=20=20=20= if=20(check_status(avctx,=20err,=20"AudioUnitInitialize"))=0A+=20=20=20=20= =20=20=20=20goto=20fail;=0A+=0A+=20=20=20=20err=20=3D=20= CMSimpleQueueCreate(kCFAllocatorDefault,=20ctx->frames_queue_length,=20= &ctx->frames_queue);=0A+=20=20=20=20if=20(check_status(avctx,=20err,=20= "CMSimpleQueueCreate"))=0A+=20=20=20=20=20=20=20=20goto=20fail;=0A+=0A+=20= =20=20=20CFRetain(ctx->frames_queue);=0A+=0A+=20=20=20=20err=20=3D=20= AudioUnitInitialize(ctx->audio_unit);=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioUnitInitialize"))=0A+=20=20=20=20=20=20= =20=20goto=20fail;=0A+=0A+=20=20=20=20err=20=3D=20= AudioOutputUnitStart(ctx->audio_unit);=0A+=20=20=20=20if=20= (check_status(avctx,=20err,=20"AudioOutputUnitStart"))=0A+=20=20=20=20=20= =20=20=20goto=20fail;=0A+=0A+=20=20=20=20AVStream*=20stream=20=3D=20= avformat_new_stream(avctx,=20NULL);=0A+=20=20=20=20= stream->codecpar->codec_type=20=20=20=20=20=3D=20AVMEDIA_TYPE_AUDIO;=0A+=20= =20=20=20stream->codecpar->sample_rate=20=20=20=20=3D=20sample_rate;=0A+=20= =20=20=20stream->codecpar->channels=20=20=20=20=20=20=20=3D=20= ctx->channels;=0A+=20=20=20=20stream->codecpar->channel_layout=20=3D=20= av_get_default_channel_layout(stream->codecpar->channels);=0A+=20=20=20=20= stream->codecpar->codec_id=20=20=20=20=20=20=20=3D=20codec_id;=0A+=0A+=20= =20=20=20avpriv_set_pts_info(stream,=2064,=201,=20sample_rate);=0A+=0A+=20= =20=20=20ctx->stream_index=20=3D=20stream->index;=0A+=20=20=20=20= ctx->position=20=20=20=20=20=3D=200;=0A+=0A+=20=20=20=20= av_freep(&devices);=0A+=20=20=20=20av_freep(&channel_layout);=0A+=20=20=20= =20return=200;=0A+=0A+fail:=0A+=20=20=20=20av_freep(&channel_layout);=0A= +=20=20=20=20return=20AVERROR(EINVAL);=0A+}=0A+=0A+static=20int=20= audiotoolbox_read_packet(AVFormatContext=20*avctx,=20AVPacket=20*pkt)=20= {=0A+=20=20=20=20ATContext=20*ctx=20=3D=20(ATContext*)avctx->priv_data;=0A= +=0A+=20=20=20=20if=20(CMSimpleQueueGetCount(ctx->frames_queue)=20<=201)=0A= +=20=20=20=20=20=20=20=20return=20AVERROR(EAGAIN);=0A+=0A+=20=20=20=20= buffer_t=20*buffer=20=3D=20(buffer_t=20= *)CMSimpleQueueDequeue(ctx->frames_queue);=0A+=0A+=20=20=20=20int=20= status=20=3D=20av_packet_from_data(pkt,=20buffer->data,=20buffer->size);=0A= +=20=20=20=20if=20(status=20<=200)=20{=0A+=20=20=20=20=20=20=20=20= av_freep(&buffer->data);=0A+=20=20=20=20=20=20=20=20av_freep(&buffer);=0A= +=20=20=20=20=20=20=20=20return=20status;=0A+=20=20=20=20}=0A+=0A+=20=20=20= =20pkt->stream_index=20=3D=20ctx->stream_index;=0A+=20=20=20=20= pkt->flags=20=20=20=20=20=20=20|=3D=20AV_PKT_FLAG_KEY;=0A+=20=20=20=20= pkt->pts=20=3D=20pkt->dts=20=3D=20ctx->position;=0A+=0A+=20=20=20=20= ctx->position=20+=3D=20pkt->size=20/=20(ctx->channels=20*=20= av_get_bytes_per_sample(ctx->sample_format));=0A+=0A+=20=20=20=20= av_freep(&buffer);=0A+=20=20=20=20return=200;=0A+}=0A+=0A+static=20= av_cold=20int=20audiotoolbox_close(AVFormatContext=20*avctx)=20{=0A+=20=20= =20=20ATContext=20*ctx=20=3D=20(ATContext*)avctx->priv_data;=0A+=0A+=20=20= =20=20if=20(ctx->audio_unit)=20{=0A+=20=20=20=20=20=20=20=20= AudioOutputUnitStop(ctx->audio_unit);=0A+=20=20=20=20=20=20=20=20= AudioComponentInstanceDispose(ctx->audio_unit);=0A+=20=20=20=20=20=20=20=20= ctx->audio_unit=20=3D=20NULL;=0A+=20=20=20=20}=0A+=0A+=20=20=20=20if=20= (ctx->frames_queue)=20{=0A+=20=20=20=20=20=20=20=20buffer_t=20*buffer=20= =3D=20(buffer_t=20*)CMSimpleQueueDequeue(ctx->frames_queue);=0A+=0A+=20=20= =20=20=20=20=20=20while=20(buffer)=20{=0A+=20=20=20=20=20=20=20=20=20=20= av_freep(&buffer->data);=0A+=20=20=20=20=20=20=20=20=20=20= av_freep(&buffer);=0A+=20=20=20=20=20=20=20=20=20=20buffer=20=3D=20= (buffer_t=20*)CMSimpleQueueDequeue(ctx->frames_queue);=0A+=20=20=20=20=20= =20=20=20}=0A+=0A+=20=20=20=20=20=20=20=20CFRelease(ctx->frames_queue);=0A= +=20=20=20=20=20=20=20=20ctx->frames_queue=20=3D=20NULL;=0A+=20=20=20=20= }=0A+=0A+=20=20=20=20return=200;=0A+}=0A+=0A+static=20const=20AVOption=20= options[]=20=3D=20{=0A+=20=20=20=20{=20"channels",=20"number=20of=20= audio=20channels",=20offsetof(ATContext,=20channels),=20AV_OPT_TYPE_INT,=20= {.i64=3D0},=200,=20INT_MAX,=20AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20=20= =20{=20"frames_queue_length",=20"maximum=20of=20buffers=20in=20the=20= input=20queue",=20offsetof(ATContext,=20frames_queue_length),=20= AV_OPT_TYPE_INT,=20{.i64=3D10},=200,=20INT_MAX,=20= AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20=20=20{=20"buffer_frame_size",=20= "buffer=20frame=20size,=20gouverning=20internal=20latency",=20= offsetof(ATContext,=20buffer_frame_size),=20AV_OPT_TYPE_INT,=20= {.i64=3D1024},=200,=20INT_MAX,=20AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20= =20=20{=20"big_endian",=20"return=20big=20endian=20samples",=20= offsetof(ATContext,=20big_endian),=20AV_OPT_TYPE_BOOL,=20{.i64=3D0},=20= 0,=201,=20AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20=20=20{=20= "sample_format",=20"sample=20format",=20offsetof(ATContext,=20= sample_format),=20AV_OPT_TYPE_INT,=20{.i64=3DAV_SAMPLE_FMT_S16},=200,=20= INT_MAX,=20AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20=20=20{=20= "list_devices",=20"list=20available=20audio=20devices",=20= offsetof(ATContext,=20list_devices),=20AV_OPT_TYPE_BOOL,=20{.i64=3D0},=20= 0,=201,=20AV_OPT_FLAG_ENCODING_PARAM=20},=0A+=20=20=20=20{=20NULL=20},=0A= +};=0A+=0A+static=20const=20AVClass=20audiotoolbox_class=20=3D=20{=0A+=20= =20=20=20.class_name=20=3D=20"AudioToolbox",=0A+=20=20=20=20.item_name=20= =20=3D=20av_default_item_name,=0A+=20=20=20=20.option=20=20=20=20=20=3D=20= options,=0A+=20=20=20=20.version=20=20=20=20=3D=20LIBAVUTIL_VERSION_INT,=0A= +=20=20=20=20.category=20=20=20=3D=20= AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,=0A+};=0A+=0A+const=20= AVInputFormat=20ff_audiotoolbox_demuxer=20=3D=20{=0A+=20=20=20=20.name=20= =20=20=20=20=20=20=20=20=20=20=3D=20"audiotoolbox",=0A+=20=20=20=20= .long_name=20=20=20=20=20=20=3D=20NULL_IF_CONFIG_SMALL("AudioToolbox=20= input=20device"),=0A+=20=20=20=20.priv_data_size=20=3D=20= sizeof(ATContext),=0A+=20=20=20=20.read_header=20=20=20=20=3D=20= audiotoolbox_read_header,=0A+=20=20=20=20.read_packet=20=20=20=20=3D=20= audiotoolbox_read_packet,=0A+=20=20=20=20.read_close=20=20=20=20=20=3D=20= audiotoolbox_close,=0A+=20=20=20=20.flags=20=20=20=20=20=20=20=20=20=20=3D= =20AVFMT_NOFILE,=0A+=20=20=20=20.priv_class=20=20=20=20=20=3D=20= &audiotoolbox_class,=0A+};=0A--=20=0A2.32.0=20(Apple=20Git-132)=0A=0A= --Apple-Mail=_A13D1362-13B1-4F92-B033-C3D2B3AD99C4 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". --Apple-Mail=_A13D1362-13B1-4F92-B033-C3D2B3AD99C4--