从 将pcm数据通过AVAssetWriter输出成aac

_lee_chong 2015-07-22 11:29:10
1,创建的音频AVAssetWriterInput outputSettings 设置为aac
2,pcm 数据通过AudioConverter 软编码成 aac 数据
3,aac 2进制数据创建为CMSampleBufferRef
但是在 AVAssetWriterInput appendSampleBuffer 的时候竟然提示说:
[AVAssetWriterInput appendSampleBuffer:] Input buffer must be in an uncompressed format when outputSettings is not nil


// 创建声音AVAssetWriterInput 的代码
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[ NSNumber numberWithInt: kAudioFormatMPEG4AAC], AVFormatIDKey,
[ NSNumber numberWithInt: _src_channel_count_pcm], AVNumberOfChannelsKey,
[ NSNumber numberWithFloat: _src_sample_rate_pcm], AVSampleRateKey,
[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
//[ NSNumber numberWithInt: 128000 ], AVEncoderBitRateKey,
nil];
assetWriterInput_audio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:outputSettings];
// 初始化pcm -> aac 处代码
memset(&_srcPcmFormat, 0, sizeof(_srcPcmFormat));
_srcPcmFormat.mFormatID = kAudioFormatLinearPCM;
_srcPcmFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
_srcPcmFormat.mBitsPerChannel = _per_sample_bytes_pcm<<3;
_srcPcmFormat.mFramesPerPacket = 1;
_srcPcmFormat.mChannelsPerFrame = _src_channel_count_pcm;
_srcPcmFormat.mSampleRate = _src_sample_rate_pcm;
_srcPcmFormat.mBytesPerPacket
= _srcPcmFormat.mBytesPerFrame = (_srcPcmFormat.mBitsPerChannel >> 3) * _srcPcmFormat.mChannelsPerFrame;
memset(&_dstAACFormat, 0, sizeof(_dstAACFormat));
_dstAACFormat.mFormatID = kAudioFormatMPEG4AAC;
_dstAACFormat.mSampleRate = _srcPcmFormat.mSampleRate;
_dstAACFormat.mChannelsPerFrame = _srcPcmFormat.mChannelsPerFrame;
_dstAACFormat.mFormatFlags = kMPEG4Object_AAC_SSR;
_dstAACFormat.mFramesPerPacket = 1024;
_writerAACFormat = _dstAACFormat;

OSStatus status;
UInt32 size = sizeof(_dstAACFormat);
status = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &_dstAACFormat);
if (status != noErr) {
NSLog(@"initConverterPCMToAAC AudoFormatGetProperty kAudioFormatProperty_FormatInfo error:%d", status);
return false;
}

AudioClassDescription *description =getAudioClassDescriptionWithType(_dstAACFormat.mFormatID,kAppleSoftwareAudioCodecManufacturer);
if(!description){
description =getAudioClassDescriptionWithType(_dstAACFormat.mFormatID,kAppleSoftwareAudioCodecManufacturer);
}
if (!description) {
NSLog(@"initConverterPCMToAAC get audio class Descriptin error.");
return false;
}

status = AudioConverterReset(_audioConverterPCMToAAC);
status = AudioConverterNewSpecific(&_srcPcmFormat, &_dstAACFormat, 1, description, &_audioConverterPCMToAAC);
if (status != noErr) {
NSLog(@"initConverterPCMToAAC create audo converter error:%d", status);
return false;
}

_dstAACBufferSize = _per_frame_bytes_pcm;
_dstAACBuffer = malloc(_dstAACBufferSize);

// 转化pcm -> aac代码
if (!_audioConverterPCMToAAC) return nil;
OSStatus status = noErr;

FillComplexInputParam userParam;
userParam.source = srcPCMBuffer;
userParam.sourceSize = srcBufferSize;
userParam.channelCount = _srcPcmFormat.mChannelsPerFrame;
userParam.packetDescriptions = NULL;

memset(_dstAACBuffer, 0, _dstAACBufferSize);
AudioBufferList outAudioBufferList = {0};
outAudioBufferList.mNumberBuffers = 1;
outAudioBufferList.mBuffers[0].mNumberChannels = _dstAACFormat.mChannelsPerFrame;
outAudioBufferList.mBuffers[0].mDataByteSize = _dstAACBufferSize;
outAudioBufferList.mBuffers[0].mData = _dstAACBuffer;
UInt32 ioOutputDataPacketSize = 1;
AudioStreamPacketDescription *outPacketDescription = NULL;
outPacketDescription = (AudioStreamPacketDescription*)malloc(sizeof(AudioStreamPacketDescription) * ioOutputDataPacketSize);

status = AudioConverterFillComplexBuffer(_audioConverterPCMToAAC, audioConverterComplexInputDataProc, &userParam, &ioOutputDataPacketSize, &outAudioBufferList, outPacketDescription);

if (status == noErr) {
_writerAACFormat.mBytesPerPacket = outPacketDescription->mDataByteSize;
return [self sampleBufferFromAACData:outAudioBufferList.mBuffers[0].mData srcSize:outAudioBufferList.mBuffers[0].mDataByteSize timestamp:timestamp];
}

// aac代码转化 SampleBuffer代码

CMBlockBufferRef audioBlockBuf=NULL;
CMSampleBufferRef audioSampleBuf=NULL;
OSStatus result;

result=CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, NULL, srcSize, kCFAllocatorDefault, NULL, 0, srcSize, kCMBlockBufferAssureMemoryNowFlag, &audioBlockBuf);

result=CMBlockBufferReplaceDataBytes(src, audioBlockBuf, 0, srcSize);
static CMAudioFormatDescriptionRef audioFormatDes=NULL;
if(audioFormatDes==NULL)
{
result = CMAudioFormatDescriptionCreate(kCFAllocatorDefault,
&_writerAACFormat,
0,
NULL,
0,
NULL,
NULL,
&audioFormatDes
);
}
result = CMAudioSampleBufferCreateWithPacketDescriptions(
kCFAllocatorDefault, audioBlockBuf, TRUE, 0, NULL, audioFormatDes, 1, timestamp, NULL, &audioSampleBuf);
if (result != noErr) {
NSLog(@"sampleBufferFromAACData Failled to create aac samplebuffer.\n");
}
CFRelease(audioBlockBuf);

//添加样本

CMTime time = CMTimeMake (encodeFrames * _video_fps_num, _video_fps_den);

CMSampleBufferRef sampleBufRef = [self convertPCMToAAC:samples srcBufferSize:samplesSize timestamp:time];
if (sampleBufRef) {
BOOL result = [audioInput appendSampleBuffer:sampleBufRef];// 此处报错
if (result == NO) {
NSLog(@"Failed to append sample to audio,%@,%@\n",[assetWriter.error domain],[assetWriter.error localizedDescription]);
break;
}
while ((audioInput.readyForMoreMediaData)==NO )
{
[NSThread sleepForTimeInterval:0.01];
}
CFRelease(sampleBufRef);
}
...全文
1660 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
vmaster 2017-05-31
  • 打赏
  • 举报
回复
楼主,我也遇到相同的问题,但是我现在如果直接appendbuffer的话,录像时间会变得很长并且没有声音,例如:60:33:56(实际只录音了几秒) ,可否发一下您的inputsetting和outputsetting设置给我参考下?谢谢,我的邮箱 7049014@qq.com
lornstary 2016-10-26
  • 打赏
  • 举报
回复
有demo吗。
_lee_chong 2015-08-25
  • 打赏
  • 举报
回复
引用 5 楼 crosskkk 的回复:
请问你怎麽解决的?
不需要用AudioConverter将pcm 转为aac, AVAssetWriter会自动转换只要以下步骤: 1,创建的音频AVAssetWriterInput outputSettings 设置为aac 2, pcm 数据创建为 CMSampleBufferRef 3, AVAssetWriterInput appendSampleBuffer
crosskkk 2015-08-13
  • 打赏
  • 举报
回复
请问你怎麽解决的?
Ctrl_zq 2015-07-28
  • 打赏
  • 举报
回复
没做过这方面的
_lee_chong 2015-07-28
  • 打赏
  • 举报
回复
散分了~~~~~~~~~~~
_lee_chong 2015-07-24
  • 打赏
  • 举报
回复
已解决,来人散分了
_lee_chong 2015-07-23
  • 打赏
  • 举报
回复
怎么没人弄这方面么

29,027

社区成员

发帖
与我相关
我的任务
社区描述
主要讨论与iOS相关的软件和技术
社区管理员
  • iOS
  • 大熊猫侯佩
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧