В iOS 18 использование AudioUnit для записи аудио и конвертации PCM формата в AAC приводит к сбою приложения.

Вопрос или проблема

 AudioBufferList* convertPCMToAAC (XDXRecorder *recoder) {
UInt32   maxPacketSize    = 0;
UInt32   size             = sizeof(maxPacketSize);
OSStatus status;

status = AudioConverterGetProperty(_encodeConvertRef,
                                   kAudioConverterPropertyMaximumOutputPacketSize,
                                   &size,
                                   &maxPacketSize);
//    log4cplus_info("AudioConverter","kAudioConverterPropertyMaximumOutputPacketSize status:%d \n",(int)status);

AudioBufferList *bufferList             = (AudioBufferList *)malloc(sizeof(AudioBufferList));
bufferList->mNumberBuffers              = 1;
bufferList->mBuffers[0].mNumberChannels = _targetDes.mChannelsPerFrame;
bufferList->mBuffers[0].mData           = malloc(maxPacketSize);
bufferList->mBuffers[0].mDataByteSize   = kTVURecoderPCMMaxBuffSize;

AudioStreamPacketDescription outputPacketDescriptions;

UInt32 inNumPackets = 1;

pthread_mutex_lock(&pcmBufferMutex);

status = AudioConverterFillComplexBuffer(_encodeConvertRef,
                                         encodeConverterComplexInputDataProc,
                                         pcm_buffer,
                                         &inNumPackets,
                                         bufferList,
                                         &outputPacketDescriptions);
pthread_mutex_unlock(&pcmBufferMutex);
if(status != noErr){
    //        log4cplus_debug("Audio Recoder","set AudioConverterFillComplexBuffer status:%d inNumPackets:%d \n",(int)status, inNumPackets);
    free(bufferList->mBuffers[0].mData);
    free(bufferList);
    return NULL;
}

if (recoder.needsVoiceDemo) {
    OSStatus status = AudioFileWritePackets(recoder.mRecordFile,
                                            FALSE,
                                            bufferList->mBuffers[0].mDataByteSize,
                                            &outputPacketDescriptions,
                                            recoder.mRecordPacket,
                                            &inNumPackets,
                                            bufferList->mBuffers[0].mData);
    //        log4cplus_info("write file","write file status = %d",(int)status);
    if (status == noErr) {
        recoder.mRecordPacket += inNumPackets; 
    }
}

return bufferList;
}

Вышеуказанный код для преобразования PCM в AAC работает нормально в версиях iOS ниже 18, но в iOS 18 происходят сбои во время процесса преобразования. Консоль не предоставляет много полезной информации, и приложение выдает сбой на malloc(maxPacketSize) или AudioConverterFillComplexBuffer(), отображая сообщение AURemoteIO::IOThread (14): EXC_BAD_ACCESS (code=1, address=0x0). Пожалуйста, помогите установить причину сбоя.

Я надеюсь полностью решить эту проблему с сбоем.

Ответ или решение

Причины сбоя при конвертации PCM в AAC в iOS 18

При разработке приложений на iOS, особенно когда речь идет о работе с аудиоданными, могут возникать различные проблемы из-за изменений в системных библиотеках или изменениях в самой платформе. Описанный вами код, работавший должным образом в предыдущих версиях iOS, вызывает сбой при конвертации PCM в AAC в iOS 18. Давайте рассмотрим возможные причины этого сбоя и шаги по его исправлению.

1. Проблема с выделением памяти

Согласно предоставленному коду, проблема может возникать на этапе выполнения функции malloc(maxPacketSize). Система возвращает ошибку EXC_BAD_ACCESS, что указывает на проблему с доступом к памяти. Это может происходить по нескольким причинам:

  • Некорректное значение maxPacketSize: Проверьте, корректно ли вы получаете значение maxPacketSize через AudioConverterGetProperty. Если это значение равно нулю или больше, чем размер доступной памяти, это приведет к сбою.
  • Проблемы с инициализацией AudioConverter: Убедитесь, что _encodeConvertRef инициализирован правильно до вызова AudioConverterFillComplexBuffer(). Неправильная или незавершенная инициализация может вызывать сбой.

2. Безопасность потоков

Вы используете pthread_mutex_lock() и pthread_mutex_unlock(), чтобы защитить доступ к pcm_buffer. Убедитесь, что данные в pcm_buffer корректны и доступны в момент вызова. Также проверьте, что поток, удерживающий мьютекс, не вызывает никаких блокировок или зависаний.

3. Параметры AudioBufferList

Ваша структура AudioBufferList должна корректно соотноситься с ожидаемыми значениями в конфигурации кодировщика AAC. Проверьте, что mNumberChannels и другие поля правильно установлены:

bufferList->mBuffers[0].mNumberChannels = _targetDes.mChannelsPerFrame;
// Убедитесь, что это значение соответствует вашим данным PCM

4. Ошибки в обработчике encodeConverterComplexInputDataProc

Убедитесь, что пользовательская функция обратного вызова encodeConverterComplexInputDataProc возвращает корректные результаты. Неверная реализация этой функции может привести к неправильной интерпретации данных во время конвертации.

5. Проверка адресации памяти и границ массива

Использование bufferList требует надлежащего обращения с памятью, чтобы избежать утечек или переполнения буфера. Убедитесь, что все выделенные массивы имеют правильные размеры и что вы не обращаетесь к области памяти за пределами выделенной.

Рекомендации по исправлению

  1. Проверьте значения переменных: Включите тщательную отладку, чтобы убедиться, что maxPacketSize действительно имеет ожидаемое значение. Если оно равно нулю или низкому значению, исправьте это.

  2. Инициализация AudioConverter: Убедитесь, что _encodeConvertRef корректно инициализирован перед его использованием.

  3. Обработка ошибок: Улучшите обработку ошибок, выводите более подробные сообщения, что позволит легче выявлять источники ошибок.

  4. Тестирование: Запустите ваш код в среде тестирования с различными конфигурациями аудио и наблюдайте за поведением на разных устройствах с iOS 18.

  5. Обновления и исправления: Следите за обновлениями SDK и сравните их с предыдущими версиями, так как изменения могут затрагивать аудио API.

Заключение

Работа с аудио в iOS может быть сложной, и изменения в новых версиях системы иногда требуют гибкости в коде. Обратите внимание на указанные выше аспекты при поиске решения проблемы. Всесторонний подход к отладке и тестированию поможет в выявлении и устранении причин сбоя.

Оцените материал
Добавить комментарий

Капча загружается...