2017-03-22 1 views
5

내 응용 프로그램에서 SIP 호출을 구현하고, 해결해야 할 첫 번째 문제는 ADTS 헤더가있는 압축 된 AAC 형식의 오디오를 선형 PCM으로 변환하는 것입니다.AudioConverterFillComplexBuffer를 사용하여 PCM에 AAC 압축 프레임을 디코딩하는 방법 iOS

내 입력 데이터는 프레임 크기가 다른 ADTS 프레임의 NSArray입니다. 각 프레임은 NSMutableData의 형식입니다. 각 프레임의 형식과 샘플 속도는 동일하지만 차이점은 프레임 화입니다.

this issue에 대한 Igor Rotaru가 제안한 샘플 코드를 구현하려고했지만 작동하지 못했습니다.

이제 내 코드는 다음과 같습니다. 그 후

- (void)configureAudioConverter { 
    AudioStreamBasicDescription inFormat; 
    memset(&inFormat, 0, sizeof(inFormat)); 
    inputFormat.mBitsPerChannel = 0; 
    inputFormat.mBytesPerFrame = 0; 
    inputFormat.mBytesPerPacket = 0; 
    inputFormat.mChannelsPerFrame = 1; 
    inputFormat.mFormatFlags = kMPEG4Object_AAC_LC; 
    inputFormat.mFormatID = kAudioFormatMPEG4AAC; 
    inputFormat.mFramesPerPacket = 1024; 
    inputFormat.mReserved = 0; 
    inputFormat.mSampleRate = 22050; 

    AudioStreamBasicDescription outputFormat; 
    memset(&outputFormat, 0, sizeof(outputFormat)); 
    outputFormat.mSampleRate  = inputFormat.mSampleRate; 
    outputFormat.mFormatID   = kAudioFormatLinearPCM; 
    outputFormat.mFormatFlags  = kLinearPCMFormatFlagIsSignedInteger; 
    outputFormat.mBytesPerPacket = 2; 
    outputFormat.mFramesPerPacket = 1; 
    outputFormat.mBytesPerFrame = 2; 
    outputFormat.mChannelsPerFrame = 1; 
    outputFormat.mBitsPerChannel = 16; 
    outputFormat.mReserved   = 0; 

    AudioClassDescription *description = [self 
             getAudioClassDescriptionWithType:kAudioFormatMPEG4AAC 
             fromManufacturer:kAppleSoftwareAudioCodecManufacturer]; 

    OSStatus status = AudioConverterNewSpecific(&inputFormat, &outputFormat, 1, description, &_audioConverter); 

    if (status != 0) { 
     printf("setup converter error, status: %i\n", (int)status); 
    } 
} 

내가 콜백 함수를 썼다 : 우선, 나는 AudioConverter를 구성

struct MyUserData { 
    UInt32 mChannels; 
    UInt32 mDataSize; 
    const void* mData; 
    AudioStreamPacketDescription mPacket; 
}; 

OSStatus inInputDataProc(AudioConverterRef inAudioConverter, 
         UInt32 *ioNumberDataPackets, 
         AudioBufferList *ioData, 
         AudioStreamPacketDescription **outDataPacketDescription, 
         void *inUserData) 
{ 
    struct MyUserData* userData = (struct MyUserData*)(inUserData); 

    if (!userData->mDataSize) { 
     *ioNumberDataPackets = 0; 
     return kNoMoreDataError; 
    } 

    if (outDataPacketDescription) { 
     userData->mPacket.mStartOffset = 0; 
     userData->mPacket.mVariableFramesInPacket = 0; 
     userData->mPacket.mDataByteSize = userData->mDataSize; 
     *outDataPacketDescription = &userData->mPacket; 
    } 

    ioData->mBuffers[0].mNumberChannels = userData->mChannels; 
    ioData->mBuffers[0].mDataByteSize = userData->mDataSize; 
    ioData->mBuffers[0].mData = (void *)userData->mData; 

    // No more data to provide following this run. 
    userData->mDataSize = 0; 

    return noErr; 
} 

및 디코딩 프레임 내 기능은 다음과 같습니다

- (void)startDecodingAudio { 
    if (!_converterConfigured){ 
     return; 
    } 

    while (true){ 
     if ([self hasFramesToDecode]){ 
      struct MyUserData userData = {1, (UInt32)_decoderBuffer[_currPosInDecoderBuf].length, _decoderBuffer[_currPosInDecoderBuf].bytes}; 

      uint8_t *buffer = (uint8_t *)malloc(128 * sizeof(short int)); 
      AudioBufferList decBuffer; 
      decBuffer.mNumberBuffers = 1; 
      decBuffer.mBuffers[0].mNumberChannels = 1; 
      decBuffer.mBuffers[0].mDataByteSize = 128 * sizeof(short int); 
      decBuffer.mBuffers[0].mData = buffer; 

      UInt32 numFrames = 128; 

      AudioStreamPacketDescription outPacketDescription; 
      memset(&outPacketDescription, 0, sizeof(AudioStreamPacketDescription)); 
      outPacketDescription.mDataByteSize = 128; 
      outPacketDescription.mStartOffset = 0; 
      outPacketDescription.mVariableFramesInPacket = 0; 

      OSStatus status = AudioConverterFillComplexBuffer(_audioConverter, 
                   inInputDataProc, 
                   &userData, 
                   &numFrames, 
                   &decBuffer, 
                   &outPacketDescription); 

      NSError *error = nil; 

      if (status == kNoMoreDataError) { 
       NSLog(@"%u bytes decoded", (unsigned int)decBuffer.mBuffers[0].mDataByteSize); 
       [_decodedData appendData:[NSData dataWithBytes:decBuffer.mBuffers[0].mData length:decBuffer.mBuffers[0].mDataByteSize]]; 
       _currPosInDecoderBuf += 1; 
      } else { 
       error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; 
      } 
     } else { 
      break; 
     } 
    } 
} 

때마다 , AudioConverterFillComplexBuffer는 Apple API에 따라 kAudioCodecIllegalOperationError 인 상태 1852797029를 반환합니다. 누군가가 그러한 형식으로 변환에 성공한 경우, 몇 가지 예 또는 조언을 제공해주십시오.

+0

이미 문제를 해결 했습니까? – vladiqtx

+0

@VladislavRudskoy 네, 아래 내 대답을 참조하십시오. –

답변

4

마지막으로, 내 바이트를 StreamingKit 라이브러리 (원래 저장소는 here)로 디코딩했습니다.

관련 문제