Код AudioQueue из SpeakHere не работает на iPad
Я использую аудио классы SpeakHere в создаваемом приложении, которое должно одновременно воспроизводить и записывать.
Я использую новейший SDK с целевым устройством 3.2 в универсальной сборке приложений (для iPad и iPhone).
Приложение воспроизводит потоковые фильмы с использованием MPMoviePlayerController и одновременно записывает аудио.
Это прекрасно работает на iPhone.
Тем не менее, это не удается 100% на моих клиентов iPad. Журналы показывают ошибки! Act, которые AudioSession просто отказывается активировать! И каждый файл журнала, который я получил от него, содержит многочисленные прерывания и изменения маршрута (а именно Категория), которые возвращаются в функции обратного вызова. ** На iPhone я не вижу ничего подобного. Журналы показывают только то, что запись была создана и записана в указанный файл. Без перерывов, без изменений маршрута, без глупостей.
Вот соответствующие журналы:
Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <0x1207000>] AudioSessionSetClientPlayState: Error adding running client - session not active
Sat Jul 10 07:15:21 iPad mediaserverd[15502] <Error>: [07:15:21.464 <AudioQueueServer>] AudioQueue: Error '!act' from AudioSessionSetClientPlayState(15642)
Я заглушил обе функции обратного вызова, чтобы просто регистрировать случаи прерываний и изменения маршрута (с указанием причин). Поэтому я не буду публиковать код, поскольку он буквально ничего не делает. Я вижу эти журналы много раз за одну попытку начать запись на iPad.
Я прочитал практически все посты, которые я могу найти на форуме Apple Dev и в Stackru, но не могу найти кого-то с той же проблемой или каких-либо соответствующих заметок в Apple Docs, которые объясняют разницу в поведении iPad. - Примечание: iPad действительно отображал некоторые другие дефектные поведения, которые были исправлены, такие как несовпадающие вызовы Begin Interrupt, которые никогда не заканчивались (поэтому я никогда не деактивирую сеанс).
Я никогда не получаю никаких журналов, указывающих какие-либо неудачные вызовы инициализации или активации из кода AudioQueue или AudioSession. Это просто терпит неудачу, когда я пытаюсь начать запись. - Я даже пытался форсировать AudioSessionSetActive(true); звонки до каждой попытки использования звуковой системы, и я все еще получаю эти ошибки.
Вот соответствующий код для вызовов инициализации:
//Initialize the Sound System
OSStatus error = AudioSessionInitialize(NULL, NULL, interruptionListener, self);
if (error){ printf("ERROR INITIALIZING AUDIO SESSION! %d\n", (int)error); }
else {
//must set the session active first according to devs talking about some defect....
error = AudioSessionSetActive(true);
if (error) NSLog(@"AudioSessionSetActive (true) failed");
UInt32 category = kAudioSessionCategory_PlayAndRecord;
error = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(category), &category);
if (error) printf("couldn't set audio category!\n");
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self);
if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);
//Force mixing!
UInt32 allowMixing = true;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof (allowMixing), &allowMixing );
if (error) printf("ERROR ENABLING MIXING PROPS! %d\n", (int)error);
UInt32 inputAvailable = 0;
UInt32 size = sizeof(inputAvailable);
// we do not want to allow recording if input is not available
error = AudioSessionGetProperty(kAudioSessionProperty_AudioInputAvailable, &size, &inputAvailable);
if (error) printf("ERROR GETTING INPUT AVAILABILITY! %d\n", (int)error);
isInputAvailable = (inputAvailable) ? YES : NO;
//iPad doesn't require the routing changes, branched to help isolate iPad behavioral issues
if(! [Utils GetMainVC].usingiPad){
//redirect to speaker? //this only resets on a category change!
UInt32 doChangeDefaultRoute = 1;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryDefaultToSpeaker, sizeof (doChangeDefaultRoute), &doChangeDefaultRoute);
if (error) printf("ERROR CHANGING DEFAULT ROUTE PROPS! %d\n", (int)error);
//this resets with interruption and/or route changes
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
error = AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride);
if (error) printf("ERROR SPEAKER ROUTE PROPS! %d\n", (int)error);
}
// we also need to listen to see if input availability changes
error = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioInputAvailable, propListener, self);
if (error) printf("ERROR ADDING AUDIO SESSION PROP LISTENER! %d\n", (int)error);
error = AudioSessionSetActive(true);
if (error) NSLog(@"AudioSessionSetActive (true) failed");
}
// Allocate our singleton instance for the recorder & player object
myRecorder = new AQRecorder();
myPlayer = new AQPlayer();
Позже в обратном вызове loadstate для видео я просто пытаюсь начать запись в заранее определенный путь к файлу:
myRecorder->StartRecord((CFStringRef)myPathStr);
И аудиозапись полностью проваливается.
Спасибо за ваше время и помощь в этом.
1 ответ
Оказывается, это странная проблема.
1) Используйте только звукозапись и воспроизводите, и код отлично работает на iPad.
2) Добавьте воспроизведение фильма и НЕ вызывайте никаких изменений в маршрутизации, и на iPad все работает нормально.
Каким-то образом наличия воспроизведения проигрывателя Movie Player достаточно, чтобы изменить AudioSession таким образом, что принудительное изменение маршрута (например, использование динамика устройства вместо наушников) приводит к тому, что AudioSession становится неактивным.