Code Bye

将pcm数据通输出成aac提示Input buffer must be in an uncompre

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);
        }

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明将pcm数据通输出成aac提示Input buffer must be in an uncompre