void MyPropertyListenerProc( void * inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 * ioFlags) { // this is called by audio file stream when it finds property values MyData* myData = (MyData*)inClientData; OSStatus err = noErr; printf("found property '%c%c%c%c'\n", (inPropertyID>>24)&255, (inPropertyID>>16)&255, (inPropertyID>>8)&255, inPropertyID&255); switch (inPropertyID) { case kAudioFileStreamProperty_ReadyToProducePackets : { // the file stream parser is now ready to produce audio packets. // get the stream format. AudioStreamBasicDescription asbd; UInt32 asbdSize = sizeof(asbd); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd); if (err) { PRINTERROR("get kAudioFileStreamProperty_DataFormat"); myData->failed = true; break; } // create the audio queue err = AudioQueueNewOutput(&asbd, MyAudioQueueOutputCallback, myData, NULL, NULL, 0, &myData->audioQueue); if (err) { PRINTERROR("AudioQueueNewOutput"); myData->failed = true; break; } // allocate audio queue buffers for (unsigned int i = 0; i < kNumAQBufs; ++i) { err = AudioQueueAllocateBuffer(myData->audioQueue, kAQBufSize, &myData->audioQueueBuffer[i]); if (err) { PRINTERROR("AudioQueueAllocateBuffer"); myData->failed = true; break; } } // get the cookie size UInt32 cookieSize; Boolean writable; err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); if (err) { PRINTERROR("info kAudioFileStreamProperty_MagicCookieData"); break; } printf("cookieSize %d\n", cookieSize); // get the cookie data void* cookieData = calloc(1, cookieSize); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); if (err) { PRINTERROR("get kAudioFileStreamProperty_MagicCookieData"); free(cookieData); break; } // set the cookie on the queue. err = AudioQueueSetProperty(myData->audioQueue, kAudioQueueProperty_MagicCookie, cookieData, cookieSize); free(cookieData); if (err) { PRINTERROR("set kAudioQueueProperty_MagicCookie"); break; } // listen for kAudioQueueProperty_IsRunning err = AudioQueueAddPropertyListener(myData->audioQueue, kAudioQueueProperty_IsRunning, MyAudioQueueIsRunningCallback, myData); if (err) { PRINTERROR("AudioQueueAddPropertyListener"); myData->failed = true; break; } break; } } }
void Audio_Queue::setCookiesForStream(AudioFileStreamID inAudioFileStream) { OSStatus err; // get the cookie size UInt32 cookieSize; Boolean writable; err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); if (err) { AQ_TRACE("error in info kAudioFileStreamProperty_MagicCookieData\n"); return; } AQ_TRACE("cookieSize %lu\n", cookieSize); // get the cookie data void* cookieData = calloc(1, cookieSize); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); if (err) { AQ_TRACE("error in get kAudioFileStreamProperty_MagicCookieData"); free(cookieData); return; } // set the cookie on the queue. err = AudioQueueSetProperty(m_outAQ, kAudioQueueProperty_MagicCookie, cookieData, cookieSize); free(cookieData); if (err) { AQ_TRACE("error in set kAudioQueueProperty_MagicCookie"); } }
void Audio_Stream::setCookiesForStream(AudioFileStreamID inAudioFileStream) { OSStatus err; // get the cookie size UInt32 cookieSize; Boolean writable; err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); if (err) { return; } // get the cookie data void* cookieData = calloc(1, cookieSize); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); if (err) { free(cookieData); return; } // set the cookie on the queue. if (m_audioConverter) { err = AudioConverterSetProperty(m_audioConverter, kAudioConverterDecompressionMagicCookie, cookieSize, cookieData); } free(cookieData); }
static void _MetadataCallback(void* aAppleATDecoder, AudioFileStreamID aStream, AudioFileStreamPropertyID aProperty, UInt32* aFlags) { AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aAppleATDecoder); LOG("MetadataCallback receiving: '%s'", FourCC2Str(aProperty)); if (aProperty == kAudioFileStreamProperty_MagicCookieData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aStream, aProperty, &size, &writeable); if (rv) { LOG("Couldn't get property info for '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } nsAutoArrayPtr<uint8_t> data(new uint8_t[size]); rv = AudioFileStreamGetProperty(aStream, aProperty, &size, data); if (rv) { LOG("Couldn't get property '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } decoder->mMagicCookie.AppendElements(data.get(), size); } }
/* This is called by audio file stream parser when it finds property values */ void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) { AS_TRACE("%s\n", __PRETTY_FUNCTION__); Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData); if (!THIS->m_audioStreamParserRunning) { AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__); return; } switch (inPropertyID) { case kAudioFileStreamProperty_DataOffset: { SInt64 offset; UInt32 offsetSize = sizeof(offset); OSStatus result = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset); if (result == 0) { THIS->m_dataOffset = offset; } else { AS_TRACE("%s: reading kAudioFileStreamProperty_DataOffset property failed\n", __PRETTY_FUNCTION__); } break; } default: { THIS->m_audioQueue->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags); break; } } }
void AudioStreamDecoder::PropertyCallback(AudioFileStreamID stream, AudioFileStreamPropertyID property, UInt32* flags) { if (property != kAudioFileStreamProperty_ReadyToProducePackets) return; long err; void* buffer = NULL; unsigned char writable; AudioStreamBasicDescription desc = {0}; UInt32 size = sizeof(desc); BAIL_IF(!stream || stream != mStream, "Invalid stream %p\n", stream); err = AudioFileStreamGetProperty(mStream, kAudioFileStreamProperty_DataFormat, &size, &desc); BAIL_IF(err, "AudioFileStreamGetProperty returned %ld\n", err); err = AudioQueueNewOutput(&desc, StaticBufferCompleteCallback, this, NULL, NULL, 0, &mQueue); BAIL_IF(err, "AudioQueueNewOutput returned %ld\n", err); err = AudioQueueAddPropertyListener(mQueue, kAudioQueueProperty_IsRunning, StaticQueueRunningCallback, this); BAIL_IF(err, "AudioQueueAddPropertyListener returned %ld\n", err); for (int i = 0; i < kBufferCount; i++) { err = AudioQueueAllocateBufferWithPacketDescriptions(mQueue, kBufferSize, kBufferPacketDescs, mBuffers + i); BAIL_IF(err, "AudioQueueAllocateBuffer returned %ld\n", err); } mCurrentBuffer = mBuffers; (*mCurrentBuffer)->mUserData = this; err = AudioFileStreamGetPropertyInfo(mStream, kAudioFileStreamProperty_MagicCookieData, &size, &writable); BAIL_IF(err, "AudioFileStreamGetPropertyInfo returned %ld\n", err); buffer = malloc(size); BAIL_IF(!buffer, "Failed to allocate %u byte buffer for cookie\n", (unsigned int)size); err = AudioFileStreamGetProperty(mStream, kAudioFileStreamProperty_MagicCookieData, &size, buffer); BAIL_IF(err, "AudioFileStreamGetProperty returned %ld\n", err); err = AudioQueueSetProperty(mQueue, kAudioQueueProperty_MagicCookie, buffer, size); BAIL_IF(err, "AudioQueueSetProperty returned %ld\n", err); bail: free(buffer); }
void DZAudioQueuePlayer::onProperty(AudioFileStreamPropertyID pID) { UInt32 propertySize = 0; switch (pID) { // Create audio queue with given data format. case kAudioFileStreamProperty_DataFormat: propertySize = sizeof(this->_format); if (dzDebugOK(AudioFileStreamGetProperty(this->_parser, pID, &(propertySize), &(this->_format)), "Fail to get audio file stream property: DataFormat.")) { if (this->_queue != NULL) { dzDebug(!noErr, "Audio file stream duplicated data format."); } else { if (dzDebugError(AudioQueueNewOutput(&(this->_format), QueueCallback, this, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &(this->_queue)), "Create new output audio queue failed.")) { this->_queue = NULL; } } } break; // Extract magic cookie data. case kAudioFileStreamProperty_MagicCookieData: if (noErr == AudioFileStreamGetPropertyInfo(this->_parser, pID, &(propertySize), NULL)) { this->_magicCookie = malloc(propertySize); this->_magicCookieSize = propertySize; if (this->_magicCookie != NULL && dzDebugError(AudioFileStreamGetProperty(this->_parser, pID, &(propertySize), this->_magicCookie), "Fail to get audio file stream property: MagicCookieData.")) { free(this->_magicCookie); this->_magicCookie = NULL; this->_magicCookieSize = 0; } } break; // Set magic cookie data if any. (Queue shall be already created.) case kAudioFileStreamProperty_ReadyToProducePackets: if (this->_queue != NULL && this->_magicCookie != NULL) { dzDebug(AudioQueueSetProperty(this->_queue, kAudioQueueProperty_MagicCookie, this->_magicCookie, this->_magicCookieSize), "Fail to set audio queue property: MagicCookie."); } if (this->_queue != NULL && this->_parser != NULL) { this->_status = DZAudioQueuePlayerStatus_ReadyToStart; } break; default: break; } }
void Audio_Queue::handlePropertyChange(AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) { OSStatus err = noErr; AQ_TRACE("found property '%lu%lu%lu%lu'\n", (inPropertyID>>24)&255, (inPropertyID>>16)&255, (inPropertyID>>8)&255, inPropertyID&255); switch (inPropertyID) { case kAudioFileStreamProperty_ReadyToProducePackets: { // the file stream parser is now ready to produce audio packets. // get the stream format. AudioStreamBasicDescription asbd; memset(&asbd, 0, sizeof(asbd)); UInt32 asbdSize = sizeof(asbd); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd); if (err) { AQ_TRACE("get kAudioFileStreamProperty_DataFormat\n"); m_lastError = err; break; } // create the audio queue err = AudioQueueNewOutput(&asbd, audioQueueOutputCallback, this, NULL, NULL, 0, &m_outAQ); if (err) { AQ_TRACE("AudioQueueNewOutput\n"); m_lastError = err; break; } // allocate audio queue buffers for (unsigned int i = 0; i < AQ_BUFFERS; ++i) { err = AudioQueueAllocateBuffer(m_outAQ, AQ_BUFSIZ, &m_audioQueueBuffer[i]); if (err) { AQ_TRACE("AudioQueueAllocateBuffer\n"); m_lastError = err; break; } } setCookiesForStream(inAudioFileStream); // listen for kAudioQueueProperty_IsRunning err = AudioQueueAddPropertyListener(m_outAQ, kAudioQueueProperty_IsRunning, audioQueueIsRunningCallback, this); if (err) { AQ_TRACE("error in AudioQueueAddPropertyListener"); m_lastError = err; break; } break; } } }
SInt64 DZAudioQueuePlayer::seek(float time) { // Cannot seek if parameters not available or parser/queue not ready. if (this->_format.mSampleRate <= 0 || this->_format.mFramesPerPacket <= 0) { return -1; } if (this->_parser == NULL || this->_queue == NULL || this->_status == DZAudioQueuePlayerStatus_NotReady || this->_status == DZAudioQueuePlayerStatus_Error) { return -1; } // Get audio data offset. SInt64 dataOffset = 0; UInt32 propertySize = sizeof(dataOffset); if (dzDebugError(AudioFileStreamGetProperty(this->_parser, kAudioFileStreamProperty_DataOffset, &propertySize, &dataOffset), "Fail to get stream data offset.")) { return -1; } // Reset audio queue to clear the current queue buffer. if (dzDebugError(AudioQueueReset(this->_queue), "Fail to reset audio queue.")) { return -1; } // Get audio queue current time. AudioTimeStamp timeStamp; if (this->_status == DZAudioQueuePlayerStatus_ReadyToStart) { timeStamp.mSampleTime = 0; } else if (dzDebugError(AudioQueueGetCurrentTime(this->_queue, NULL, &(timeStamp), NULL), "Fail to get audio queue current time.")) { return -1; } // Calculate packet offset and so the byte offset. SInt64 packetOffset = round(time * this->_format.mSampleRate / this->_format.mFramesPerPacket); SInt64 byteOffset = 0; UInt32 ioFlag = 0; if (dzDebugError(AudioFileStreamSeek(this->_parser, packetOffset, &byteOffset, &ioFlag), "Fail to seek in audio file stream.")) { return -1; } this->_timeAmendment = time - timeStamp.mSampleTime / this->_format.mSampleRate; return byteOffset + dataOffset; }
/* * Query the MP3 parser for a piece of metadata. */ static nsresult GetProperty(AudioFileStreamID aAudioFileStream, AudioFileStreamPropertyID aPropertyID, void *aData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aAudioFileStream, aPropertyID, &size, &writeable); if (rv) { LOGW("Couldn't get property " PROPERTY_ID_FORMAT "\n", PROPERTY_ID_PRINT(aPropertyID)); return NS_ERROR_FAILURE; } rv = AudioFileStreamGetProperty(aAudioFileStream, aPropertyID, &size, aData); return NS_OK; }
static void _MetadataCallback(void* aAppleATDecoder, AudioFileStreamID aStream, AudioFileStreamPropertyID aProperty, UInt32* aFlags) { AppleATDecoder* decoder = static_cast<AppleATDecoder*>(aAppleATDecoder); MOZ_RELEASE_ASSERT(decoder->mTaskQueue->IsCurrentThreadIn()); LOGEX(decoder, "MetadataCallback receiving: '%s'", FourCC2Str(aProperty)); if (aProperty == kAudioFileStreamProperty_MagicCookieData) { UInt32 size; Boolean writeable; OSStatus rv = AudioFileStreamGetPropertyInfo(aStream, aProperty, &size, &writeable); if (rv) { LOGEX(decoder, "Couldn't get property info for '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } auto data = MakeUnique<uint8_t[]>(size); rv = AudioFileStreamGetProperty(aStream, aProperty, &size, data.get()); if (rv) { LOGEX(decoder, "Couldn't get property '%s' (%s)", FourCC2Str(aProperty), FourCC2Str(rv)); decoder->mFileStreamError = true; return; } decoder->mMagicCookie.AppendElements(data.get(), size); } }
void Audio_Queue::handlePropertyChange(AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) { OSStatus err = noErr; AQ_TRACE("found property '%lu%lu%lu%lu'\n", (inPropertyID>>24)&255, (inPropertyID>>16)&255, (inPropertyID>>8)&255, inPropertyID&255); switch (inPropertyID) { case kAudioFileStreamProperty_ReadyToProducePackets: { cleanup(); // the file stream parser is now ready to produce audio packets. // get the stream format. memset(&m_streamDesc, 0, sizeof(m_streamDesc)); UInt32 asbdSize = sizeof(m_streamDesc); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &m_streamDesc); if (err) { AQ_TRACE("%s: error in kAudioFileStreamProperty_DataFormat\n", __PRETTY_FUNCTION__); m_lastError = err; break; } // create the audio queue err = AudioQueueNewOutput(&m_streamDesc, audioQueueOutputCallback, this, CFRunLoopGetCurrent(), NULL, 0, &m_outAQ); if (err) { AQ_TRACE("%s: error in AudioQueueNewOutput\n", __PRETTY_FUNCTION__); if (m_delegate) { m_delegate->audioQueueInitializationFailed(); } m_lastError = err; break; } // allocate audio queue buffers for (unsigned int i = 0; i < AQ_BUFFERS; ++i) { err = AudioQueueAllocateBuffer(m_outAQ, AQ_BUFSIZ, &m_audioQueueBuffer[i]); if (err) { /* If allocating the buffers failed, everything else will fail, too. * Dispose the queue so that we can later on detect that this * queue in fact has not been initialized. */ AQ_TRACE("%s: error in AudioQueueAllocateBuffer\n", __PRETTY_FUNCTION__); (void)AudioQueueDispose(m_outAQ, true); m_outAQ = 0; if (m_delegate) { m_delegate->audioQueueInitializationFailed(); } m_lastError = err; break; } } setCookiesForStream(inAudioFileStream); // listen for kAudioQueueProperty_IsRunning err = AudioQueueAddPropertyListener(m_outAQ, kAudioQueueProperty_IsRunning, audioQueueIsRunningCallback, this); if (err) { AQ_TRACE("%s: error in AudioQueueAddPropertyListener\n", __PRETTY_FUNCTION__); m_lastError = err; break; } break; } } }
/* This is called by audio file stream parser when it finds property values */ void Audio_Stream::propertyValueCallback(void *inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 *ioFlags) { AS_TRACE("%s\n", __PRETTY_FUNCTION__); Audio_Stream *THIS = static_cast<Audio_Stream*>(inClientData); if (!THIS->m_audioStreamParserRunning) { AS_TRACE("%s: stray callback detected!\n", __PRETTY_FUNCTION__); return; } switch (inPropertyID) { case kAudioFileStreamProperty_DataOffset: { SInt64 offset; UInt32 offsetSize = sizeof(offset); OSStatus result = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataOffset, &offsetSize, &offset); if (result == 0) { THIS->m_dataOffset = offset; } else { AS_TRACE("%s: reading kAudioFileStreamProperty_DataOffset property failed\n", __PRETTY_FUNCTION__); } break; } case kAudioFileStreamProperty_AudioDataByteCount: { UInt32 byteCountSize = sizeof(UInt64); OSStatus err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_AudioDataByteCount, &byteCountSize, &THIS->m_audioDataByteCount); if (err) { THIS->m_audioDataByteCount = 0; } break; } case kAudioFileStreamProperty_ReadyToProducePackets: { memset(&(THIS->m_srcFormat), 0, sizeof m_srcFormat); UInt32 asbdSize = sizeof(m_srcFormat); OSStatus err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &(THIS->m_srcFormat)); if (err) { AS_TRACE("Unable to set the src format\n"); break; } THIS->m_packetDuration = THIS->m_srcFormat.mFramesPerPacket / THIS->m_srcFormat.mSampleRate; AS_TRACE("srcFormat, bytes per packet %i\n", (unsigned int)THIS->m_srcFormat.mBytesPerPacket); if (THIS->m_audioConverter) { AudioConverterDispose(THIS->m_audioConverter); } err = AudioConverterNew(&(THIS->m_srcFormat), &(THIS->m_dstFormat), &(THIS->m_audioConverter)); if (err) { AS_TRACE("Error in creating an audio converter, error %i\n", err); THIS->m_initializationError = err; } THIS->setCookiesForStream(inAudioFileStream); THIS->audioQueue()->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags); break; } default: { THIS->audioQueue()->handlePropertyChange(inAudioFileStream, inPropertyID, ioFlags); break; } } }
void StreamPropertyListenerProc(void * inClientData, AudioFileStreamID inAudioFileStream, AudioFileStreamPropertyID inPropertyID, UInt32 * ioFlags) { // this is called by audio file stream when it finds property values struct audioPlayer* player = (struct audioPlayer*)inClientData; OSStatus err = noErr; // printf("found property '%c%c%c%c'\n", (inPropertyID>>24)&255, (inPropertyID>>16)&255, (inPropertyID>>8)&255, inPropertyID&255); switch (inPropertyID) { case kAudioFileStreamProperty_ReadyToProducePackets : { // the file stream parser is now ready to produce audio packets. // get the stream format. AudioStreamBasicDescription asbd; UInt32 asbdSize = sizeof(asbd); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_DataFormat, &asbdSize, &asbd); if (err) { PRINTERROR("get kAudioFileStreamProperty_DataFormat"); player->failed = true; break; } //TODO: Is this really right!?! player->songDuration = player->waith.contentLength * 2000 / asbd.mSampleRate; player->samplerate = asbd.mSampleRate; player->packetDuration = asbd.mFramesPerPacket / asbd.mSampleRate; // create the audio queue err = AudioQueueNewOutput(&asbd, PianobarAudioQueueOutputCallback, player, NULL, NULL, 0, &player->audioQueue); if (err) { PRINTERROR("AudioQueueNewOutput"); player->failed = true; break; } // allocate audio queue buffers for (unsigned int i = 0; i < kNumAQBufs; ++i) { err = AudioQueueAllocateBuffer(player->audioQueue, kAQBufSize, &player->audioQueueBuffer[i]); if (err) { PRINTERROR("AudioQueueAllocateBuffer"); player->failed = true; break; } } // get the cookie size UInt32 cookieSize; Boolean writable; err = AudioFileStreamGetPropertyInfo(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, &writable); if (err) { PRINTERROR("info kAudioFileStreamProperty_MagicCookieData"); break; } // get the cookie data void* cookieData = calloc(1, cookieSize); err = AudioFileStreamGetProperty(inAudioFileStream, kAudioFileStreamProperty_MagicCookieData, &cookieSize, cookieData); if (err) { PRINTERROR("get kAudioFileStreamProperty_MagicCookieData"); free(cookieData); break; } // set the cookie on the queue. err = AudioQueueSetProperty(player->audioQueue, kAudioQueueProperty_MagicCookie, cookieData, cookieSize); free(cookieData); if (err) { PRINTERROR("set kAudioQueueProperty_MagicCookie"); break; } // listen for kAudioQueueProperty_IsRunning err = AudioQueueAddPropertyListener(player->audioQueue, kAudioQueueProperty_IsRunning, AudioQueueIsRunningCallback, player); if (err) { PRINTERROR("AudioQueueAddPropertyListener"); player->failed = true; break; } break; } } }