首先我使用AVCaptureSession捕获来自camero和micophone的视频和音频。 然后委托下面的方法代码:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{
// if is Vedio data ,append to vedioInputWriter
if (mediaType == kCMMediaType_Vedio){
// ...
// ...
// ...
// write the video data
if (_assetWriterVideoInput.readyForMoreMediaData){
[_assetWriterInputPixelBufferAdaptor appendPixelBuffer:renderedOutputPixelBuffer withPresentationTime:timestamp];
}
return;
}
size_t bufferListSizeNeededOut;
CMBlockBufferRef blockBufferOut = nil;
// get AudioBufferList
err = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(sampleBuffer,
&bufferListSizeNeededOut,
currentInputAudioBufferList,
CAAudioBufferList::CalculateByteSize(currentInputASBD.mChannelsPerFrame),
kCFAllocatorSystemDefault,
kCFAllocatorSystemDefault,
kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
&blockBufferOut);
// mix recorded audio with background music
[self mixAudioBufferListwithBackgroundMusic:currentInputAudioBufferList];
if (!self.audioInputAssetWriter.readyForMoreMediaData) {
if (self.assetWriter.status == AVAssetWriterStatusFailed) {
NSLog(@"assetWrite error=%@",self.viewController.assetWriter.error);
}
return;
}
// tranfer `AudioBufferList` to `CMSampleBuffer`
CMSampleBuffer newSampleBuffer = [self processAudioData:outputBufferList->ABL() framesNumber:numberOfFrames format:&mClientFormat];
// append samplebuffer to assetInputWriter
if ([self.audioInputAssetWriter appendSampleBuffer:newSampleBuffer]) {
NSLog(@" append sample buffer success");
}else{
NSLog(@"append sample buffer failed");
}
}
下面的代码AudioBufferList
到CMSampleBuffer
代码:
- (CMSampleBufferRef)processAudioData:(AudioBufferList *)audioData framesNumber:(UInt32 )num format:(AudioStreamBasicDescription *)asbd
{
CMSampleBufferRef sbuf;
OSStatus status;
// 1.audio foramt description
CMAudioFormatDescriptionRef format;
status = CMAudioFormatDescriptionCreate(kCFAllocatorDefault,&(bufferToSampleFormat), 0, NULL, 0, NULL, NULL, &format);
// 2.sample timing info
CMSampleTimingInfo timing;
timing.duration = CMTimeMake(1,44100);
timing.presentationTimeStamp = kCMTimeZero;
timing.decodeTimeStamp = kCMTimeInvalid;
size_t sampleSizeArray[1] = {4};
// 3.create sample buffer
status = CMSampleBufferCreate(kCFAllocatorDefault,NULL,false, NULL,NULL,format,(CMItemCount)num,1,&timing,0,NULL, &sbuf);
// 4.sample buffer set data buffer from audio buffer list
status = CMSampleBufferSetDataBufferFromAudioBufferList(sbuf, kCFAllocatorDefault, kCFAllocatorDefault, 0, audioData);
if (status != noErr) {
NSLog(@"sample buffer set data buffer from audio buffer list failed -- %d",(int)status);
return nil;
}
return sbuf;
}
最后,将视频和音频数据保存为test.mov
文件。问题是使用Quicktime播放文件,但没有声音。用VLC播放文件,有声音。并且可以用ffmpeg剥离aac格式的音频文件。
我猜问题是转发AudioBufferList
到CMSampleBuffer
,遗漏了一些信息导致Quicktime无法正常播放。