nsresult GonkAudioDecoderManager::Output(int64_t aStreamOffset, nsRefPtr<MediaData>& aOutData) { aOutData = nullptr; status_t err; err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US); switch (err) { case OK: { nsRefPtr<AudioData> data; nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data)); if (rv == NS_ERROR_NOT_AVAILABLE) { // Decoder outputs an empty video buffer, try again return NS_ERROR_NOT_AVAILABLE; } else if (rv != NS_OK || data == nullptr) { return NS_ERROR_UNEXPECTED; } aOutData = data; return NS_OK; } case android::INFO_FORMAT_CHANGED: { // If the format changed, update our cached info. GADM_LOG("Decoder format changed"); sp<AMessage> audioCodecFormat; if (mDecoder->getOutputFormat(&audioCodecFormat) != OK || audioCodecFormat == nullptr) { return NS_ERROR_UNEXPECTED; } int32_t codec_channel_count = 0; int32_t codec_sample_rate = 0; if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) || !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) { return NS_ERROR_UNEXPECTED; } // Update AudioInfo mAudioChannels = codec_channel_count; mAudioRate = codec_sample_rate; return Output(aStreamOffset, aOutData); } case android::INFO_OUTPUT_BUFFERS_CHANGED: { GADM_LOG("Info Output Buffers Changed"); if (mDecoder->UpdateOutputBuffers()) { return Output(aStreamOffset, aOutData); } return NS_ERROR_FAILURE; } case -EAGAIN: { return NS_ERROR_NOT_AVAILABLE; } case android::ERROR_END_OF_STREAM: { GADM_LOG("Got EOS frame!"); nsRefPtr<AudioData> data; nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data)); if (rv == NS_ERROR_NOT_AVAILABLE) { // For EOS, no need to do any thing. return NS_ERROR_ABORT; } else if (rv != NS_OK || data == nullptr) { GADM_LOG("Failed to create audio data!"); return NS_ERROR_UNEXPECTED; } aOutData = data; return NS_ERROR_ABORT; } case -ETIMEDOUT: { GADM_LOG("Timeout. can try again next time"); return NS_ERROR_UNEXPECTED; } default: { GADM_LOG("Decoder failed, err=%d", err); return NS_ERROR_UNEXPECTED; } } return NS_OK; }
nsresult GonkAudioDecoderManager::Output(int64_t aStreamOffset, nsAutoPtr<MediaData>& aOutData) { aOutData = nullptr; status_t err; err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US); switch (err) { case OK: { AudioData* data = nullptr; nsresult rv = CreateAudioData(aStreamOffset, &data); if (rv == NS_ERROR_NOT_AVAILABLE) { // Decoder outputs an empty video buffer, try again return NS_ERROR_NOT_AVAILABLE; } else if (rv != NS_OK || data == nullptr) { return NS_ERROR_UNEXPECTED; } aOutData = data; return NS_OK; } case android::INFO_FORMAT_CHANGED: case android::INFO_OUTPUT_BUFFERS_CHANGED: { // If the format changed, update our cached info. ALOG("Decoder format changed"); return Output(aStreamOffset, aOutData); } case -EAGAIN: { return NS_ERROR_NOT_AVAILABLE; } case android::ERROR_END_OF_STREAM: { ALOG("Got EOS frame!"); AudioData* data = nullptr; nsresult rv = CreateAudioData(aStreamOffset, &data); if (rv == NS_ERROR_NOT_AVAILABLE) { // For EOS, no need to do any thing. return NS_ERROR_ABORT; } else if (rv != NS_OK || data == nullptr) { ALOG("Failed to create audio data!"); return NS_ERROR_UNEXPECTED; } aOutData = data; return NS_ERROR_ABORT; } case -ETIMEDOUT: { ALOG("Timeout. can try again next time"); return NS_ERROR_UNEXPECTED; } default: { ALOG("Decoder failed, err=%d", err); return NS_ERROR_UNEXPECTED; } } return NS_OK; }
nsresult GonkAudioDecoderManager::Output(int64_t aStreamOffset, RefPtr<MediaData>& aOutData) { aOutData = nullptr; if (mAudioQueue.GetSize() > 0) { aOutData = mAudioQueue.PopFront(); return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK; } status_t err; MediaBuffer* audioBuffer = nullptr; err = mDecoder->Output(&audioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US); AutoReleaseMediaBuffer a(audioBuffer, mDecoder.get()); switch (err) { case OK: { nsresult rv = CreateAudioData(audioBuffer, aStreamOffset); NS_ENSURE_SUCCESS(rv, rv); break; } case android::INFO_FORMAT_CHANGED: { // If the format changed, update our cached info. GADM_LOG("Decoder format changed"); sp<AMessage> audioCodecFormat; if (mDecoder->getOutputFormat(&audioCodecFormat) != OK || audioCodecFormat == nullptr) { return NS_ERROR_UNEXPECTED; } int32_t codec_channel_count = 0; int32_t codec_sample_rate = 0; if (!audioCodecFormat->findInt32("channel-count", &codec_channel_count) || !audioCodecFormat->findInt32("sample-rate", &codec_sample_rate)) { return NS_ERROR_UNEXPECTED; } // Update AudioInfo mAudioChannels = codec_channel_count; mAudioRate = codec_sample_rate; return Output(aStreamOffset, aOutData); } case android::INFO_OUTPUT_BUFFERS_CHANGED: { GADM_LOG("Info Output Buffers Changed"); if (mDecoder->UpdateOutputBuffers()) { return Output(aStreamOffset, aOutData); } return NS_ERROR_FAILURE; } case -EAGAIN: { return NS_ERROR_NOT_AVAILABLE; } case android::ERROR_END_OF_STREAM: { GADM_LOG("Got EOS frame!"); nsresult rv = CreateAudioData(audioBuffer, aStreamOffset); NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT); MOZ_ASSERT(mAudioQueue.GetSize() > 0); mAudioQueue.Finish(); break; } case -ETIMEDOUT: { GADM_LOG("Timeout. can try again next time"); return NS_ERROR_UNEXPECTED; } default: { GADM_LOG("Decoder failed, err=%d", err); return NS_ERROR_UNEXPECTED; } } if (mAudioQueue.GetSize() > 0) { aOutData = mAudioQueue.PopFront(); // Return NS_ERROR_ABORT at the last sample. return mAudioQueue.AtEndOfStream() ? NS_ERROR_ABORT : NS_OK; } return NS_ERROR_NOT_AVAILABLE; }