iOS音摄像播放(奥迪(Audi)o Unit播放音频+OpenGL ES绘制录像)

前言

相关小说:
使用VideoToolbox硬编码H.264
使用VideoToolbox硬解码H.264
使用AudioToolbox编码AAC
使用AudioToolbox播放AAC
HLS点播完成(H.264和AAC码流)
HLS推流的达成(iOS和OS
X系统)

iOS在线音频流播放
Audio Unit播放PCM文件
奥迪o
Unit录音(播放伴奏+耳返)

Audio
Unit播放aac/m4a/mp3等文件

奥迪o
Unit和Extended奥迪oFile播放音频

AUGraph结合RemoteI/O Unit与Mixer
Unit

地方的篇章介绍了音摄像音信的加载和分析,在其它的《OpenGLES文集》也详细介绍了OpenGL如何绘制图像。
这一次结合奥迪o Unit和OpenGL
ES,分别加载多媒体文件的节奏和录像消息并播放。

上边是做出来未来的效劳图:

Audio Unit & OpenGL ES.gif

前言

连带作品:
使用VideoToolbox硬编码H.264
使用VideoToolbox硬解码H.264
使用AudioToolbox编码AAC
使用AudioToolbox播放AAC
HLS点播完毕(H.264和AAC码流)
HLS推流的贯彻(iOS和OS
X系统)

iOS在线音频流播放
Audio Unit播放PCM文件
奥迪o
Unit录音(播放伴奏+耳返)

面前两篇介绍了奥迪o
Unit播放PCM文件边录边播,这一次引入AudioConvert兑现aac/m4a/mp5格式的播音。

正文

正文

总体思路

demo包含三大学一年级部分,分别是能源加载旋律播放录像播放

  • 能源加载:是用AVURLAsset加载资源文件,再成立财富读取器AVAssetReader,然后附加音频读取接口mReaderAudioTrackOutput和录制读取接口mReaderVideoTrackOutput到能源读取器。
  • 音频播放
    :从音频读取接口mReaderAudioTrackOutput加载音频音信得到CMSampleBuffer,用方法CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer把拍子数据转成AudioBufferList格式,再采用AudioUnit播放;
  • 摄像播放:从录制读取接口mReaderVideoTrackOutput加载录像信息获得CMSampleBuffer,用方法CMSampleBufferGetImageBuffer把摄像数据转成CVPixelBufferRef格式,再用OpenGL
    ES绘制图像;

    一体化流程图

① 、格式转换

旋律数据的格式转换包蕴采集样品率改变,单声道到多声道的变通、音调的上涨下落等,audio
unit有1个特地格式转换unit(kAudioUnitType_FormatConverter,type of 'aufc')。
AudioUnit不支持vbr的数据,也不支持从一个有损压缩格式转换为pcm或然pcm转换为有损格式,对于有损格式的旋律数据转换,要求用Core奥迪o的奥迪(Audi)o
Converter API。

实际分析

2、AudioFile API 和 Converter

奥迪oFile API提供了API对音频文件的创始、打开、修改和保存;
奥迪(Audi)o Converters 用于音频文件的编解码,还是能用来sample
rate的变更、int到float的转移,最普遍是将音频文件转成pcm播放;
上面Converter的五个格式:

Source Format
Sample Rate:              44100
Format ID:                 .mp3
Format Flags:                 0
Bytes per Packet:             0
Frames per Packet:         1152
Bytes per Frame:              0
Channels per Frame:           2
Bits per Channel:             0

Target Format
Sample Rate:              44100
Format ID:                 lpcm
Format Flags:                 4
Bytes per Packet:             2
Frames per Packet:            1
Bytes per Frame:              2
Channels per Frame:           1
Bits per Channel:            16
① 、资源加载

能源加载用的是AVFoundation提供的法子,先加载音录制的准则音讯。
接下来发轫化好音录制的格式音讯outputSettingsoutputSettingsAVAssetReaderTrackOutput初始化的须求条件之一。

在意音轨和声道的界别,比如说在ktv唱歌的时候,平常伴奏是八个音轨,录到的人声是二个音轨,最终播放的时候举行混合。而声道大家常用声道数的定义,指的是声音播放时的组合音响数量。
音轨=AudioTrack
声道=AudioChannel

三 、具体细节

1、初始化AudioFile,通过AudioFileOpenURL开拓音频文件,并读取对应的音频格式(AudioStreamBasicDescription);这里和Audio
Unit播放PCM文件
差异的是,还索要读取kAudioFilePropertyMaximumPacketSizekAudioFilePropertyAudioDataPacketCount两个属性,分别是单个package的最大size和packet的数目,并因此缓存的轻重和package的size创制AudioStreamPacketDescription的数组;
2、初始化AudioUnit,设置AVAudioSession的Category为AVAudioSessionCategoryPlayback;初始化AudioBufferList,设置AudioUnit的playback回调;
3、在AudioUnit的playback回调中,调用AudioConvert的AudioConverterFillComplexBuffer函数并安装好回调方法lyInInputDataProc;在回调的lyInInputDataProc中,通过AudioFileReadPacketData读取音频数据并把读取的奥迪(Audi)oStreamPacketDescription回传;
④ 、奥迪(Audi)oConvert转换后的旋律数据会填入参数buffList,将相应的多寡复制给奥迪(Audi)oUnit的playback参数;

贰 、音频播放

旋律播放效果用的是奥迪o Unit,个中的RemoteIO
Unit只好接受PCM数据,故而供给读取出来的韵律消息务必是PCM格式的,并且安装给奥迪(Audi)o
Unit的格式须求与outputSettings一致。

相遇的题材

三 、录像播放

录像播放其实就是图像消息的绘图,从能源我们得以读取到图像信息,再把图像传给已经封装好的LYOpenGLView类,就能够绘制图像。图像消息占用内部存储器较为鲜明,供给小心内部存款和储蓄器的回收。

1、API替换

一开首用的是AudioFileReadPackets情势读取音频数据,后边在碰到标题后发觉AudioFileReadPackets被替换来AudioFileReadPacketData,参数近似;

遇上的难点

贰 、奥迪oConverter的转移函数的重返值

调用AudioConverterFillComplexBuffer后,在回调方法lyInInputDataProc中,如果设置
*ioNumberDataPackets = 0,并且再次来到 noErr, AudioConverter 会进入
Finished 的状态;

回去非零的值,表示数据未成功,比如在demo中回到了NO_MORE_DATANO_MORE_DATA是自定义的非零重返值;

① 、明确奥迪o Unit音频格式

品尝加载能源文件的音频格式并安装给奥迪o Unit,但因为奥迪o
Unit不能够接受资源文件的格式(大部分文本的音频文件格式为AAC)。
焚薮而田方案是直接设置读取的音频格式音讯为PCM,并且手动初始化ASBD,保障两端的格式一致。
一般来说,是能源文件的韵律读取格式和手动开首化的格式:

    NSMutableDictionary *outputSettings = [NSMutableDictionary dictionary];
    [outputSettings setObject:@(kAudioFormatLinearPCM) forKey:AVFormatIDKey];
    [outputSettings setObject:@(16) forKey:AVLinearPCMBitDepthKey];
    [outputSettings setObject:@(NO) forKey:AVLinearPCMIsBigEndianKey];
    [outputSettings setObject:@(NO) forKey:AVLinearPCMIsFloatKey];
    [outputSettings setObject:@(YES) forKey:AVLinearPCMIsNonInterleaved];
    [outputSettings setObject:@(44100.0) forKey:AVSampleRateKey];
    [outputSettings setObject:@(1) forKey:AVNumberOfChannelsKey];

    AudioStreamBasicDescription inputFormat;
    inputFormat.mSampleRate = 44100;
    inputFormat.mFormatID = kAudioFormatLinearPCM;
    inputFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved;
    inputFormat.mFramesPerPacket = 1;
    inputFormat.mChannelsPerFrame = 1;
    inputFormat.mBytesPerPacket = 2;
    inputFormat.mBytesPerFrame = 2;
    inputFormat.mBitsPerChannel = 16;
    self.fileFormat = inputFormat;

3、AudioConverterNewSpecific返回-50

通过OSStatus,能够见见-50是AV奥迪(Audi)oSessionErrorCodeBadParam
参数不平等;
自作者批评代码,发现是在利用奥迪oConverterNewSpecific()
创设转换器的时候输入流格式与出口流格式的声道数设置不一样;(化解方案正是声道数改成一致)

贰 、音录像同步

demo中留存四个变量self.mAudioTimeStampself.mVideoTimeStamp,分别代表音频播放和摄像播放的时光戳。
其间音频播放进度由奥迪(Audi)o
Unit驱动,录制播放进度由CADisplayLink驱动,为了确认保障录像进程不超过音频进程,添加了if (self.mVideoTimeStamp < self.mAudioTimeStamp)的判断。
但在模拟器运营的时候,录制的辨析比音频解析的快慢小很多,造成相比较强烈的分裂步。
在真机运营的时候,那种场馆有如雷贯耳的校订。
当前还没找到较好的四只方式,如若有精晓请指教。

4、AudioConverterFillComplexBuffer返回561015652

通过OSStatus,查到561015652是kAudioConverterErr_RequiresPacketDescriptionsError = '!pkd',意思是没有回调AudioStreamPacketDescriptions参数;
对此音频格式mBytesPerPacket=0的数据,需要AudioStreamPacketDescriptions参数来帮衬转换音频数据;
赶尽杀绝方案正是新建AudioStreamPacketDescriptions数组,并且在读取后赋值给outDataPacketDescription(见demo);

总结

本文没有扩大更加多的韵律和摄像知识,通过整合四个部分文化,组成大旨的音录制播放流程。
是因为时间原因,所做的技术预备性研商不能好好,代码没有很好的磨擦。
demo更加多是履行有个别想法,要是代码存在难点,恳请提出,辅助你自小编她少踩一些坑。

总结

奥迪(Audi)oUnit和奥迪oConvert的API尽管不难,却是效率强大。
小说中的介绍越多是和谐在念书进程中的一些拿走,对于知识点的牵线很多是不够全面和仔细的,对此提出看看参考目录
Extended Audio File ServicesAudio File Services
Audio Converter Services
的重组,提供统一的接口实行拍卖,下篇或许会是Extended Audio File相关。

参考

Playing a sound file using the Default Output Audio
Unit

Supported Audio File and Data Formats in OS
X

相关文章