Add support of audio offloading for NuPlayer.
Change-Id: Ic83973339fb46a83b48382e6097925f45d200867
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index b333043..88c59bf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -22,6 +22,7 @@
#include "HTTPLiveSource.h"
#include "NuPlayerDecoder.h"
+#include "NuPlayerDecoderPassThrough.h"
#include "NuPlayerDriver.h"
#include "NuPlayerRenderer.h"
#include "NuPlayerSource.h"
@@ -143,6 +144,7 @@
: mUIDValid(false),
mSourceFlags(0),
mVideoIsAVC(false),
+ mOffloadAudio(false),
mAudioEOS(false),
mVideoEOS(false),
mScanSourcesPending(false),
@@ -500,6 +502,7 @@
ALOGV("kWhatStart");
mVideoIsAVC = false;
+ mOffloadAudio = false;
mAudioEOS = false;
mVideoEOS = false;
mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -517,6 +520,21 @@
flags |= Renderer::FLAG_REAL_TIME;
}
+ sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+ audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
+ if (mAudioSink != NULL) {
+ streamType = mAudioSink->getAudioStreamType();
+ }
+
+ sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
+
+ mOffloadAudio =
+ canOffloadStream(audioMeta, (videoFormat != NULL),
+ true /* is_streaming */, streamType);
+ if (mOffloadAudio) {
+ flags |= Renderer::FLAG_OFFLOAD_AUDIO;
+ }
+
mRenderer = new Renderer(
mAudioSink,
new AMessage(kWhatRendererNotify, id()),
@@ -661,7 +679,7 @@
mAudioSink->close();
- audio_output_flags_t flags;
+ uint32_t flags;
int64_t durationUs;
// FIXME: we should handle the case where the video decoder
// is created after we receive the format change indication.
@@ -682,17 +700,92 @@
channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
}
- CHECK_EQ(mAudioSink->open(
- sampleRate,
- numChannels,
- (audio_channel_mask_t)channelMask,
- AUDIO_FORMAT_PCM_16_BIT,
- 8 /* bufferCount */,
- NULL,
- NULL,
- flags),
- (status_t)OK);
- mAudioSink->start();
+ if (mOffloadAudio) {
+ audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT;
+ audio_offload_info_t offloadInfo =
+ AUDIO_INFO_INITIALIZER;
+
+ AString mime;
+ CHECK(format->findString("mime", &mime));
+
+ status_t err =
+ mapMimeToAudioFormat(audioFormat, mime.c_str());
+ if (err != OK) {
+ ALOGE("Couldn't map mime \"%s\" to a valid "
+ "audio_format", mime.c_str());
+ mOffloadAudio = false;
+ } else {
+ ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
+ mime.c_str(), audioFormat);
+
+ flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+
+ offloadInfo.duration_us = -1;
+ format->findInt64(
+ "durationUs", &offloadInfo.duration_us);
+
+ int avgBitRate = -1;
+ format->findInt32("bit-rate", &avgBitRate);
+
+ offloadInfo.sample_rate = sampleRate;
+ offloadInfo.channel_mask = channelMask;
+ offloadInfo.format = audioFormat;
+ offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
+ offloadInfo.bit_rate = avgBitRate;
+ offloadInfo.has_video = (mVideoDecoder != NULL);
+ offloadInfo.is_streaming = true;
+
+ err = mAudioSink->open(
+ sampleRate,
+ numChannels,
+ (audio_channel_mask_t)channelMask,
+ audioFormat,
+ 8 /* bufferCount */,
+ &NuPlayer::Renderer::AudioSinkCallback,
+ mRenderer.get(),
+ (audio_output_flags_t)flags,
+ &offloadInfo);
+
+ if (err == OK) {
+ // If the playback is offloaded to h/w, we pass
+ // the HAL some metadata information.
+ // We don't want to do this for PCM because it
+ // will be going through the AudioFlinger mixer
+ // before reaching the hardware.
+ sp<MetaData> audioMeta =
+ mSource->getFormatMeta(true /* audio */);
+ sendMetaDataToHal(mAudioSink, audioMeta);
+
+ err = mAudioSink->start();
+ }
+ }
+
+ if (err != OK) {
+ // Clean up, fall back to non offload mode.
+ mAudioSink->close();
+ mAudioDecoder.clear();
+ mRenderer->signalDisableOffloadAudio();
+ mOffloadAudio = false;
+
+ instantiateDecoder(
+ true /* audio */, &mAudioDecoder);
+ }
+ }
+
+ if (!mOffloadAudio) {
+ flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+ CHECK_EQ(mAudioSink->open(
+ sampleRate,
+ numChannels,
+ (audio_channel_mask_t)channelMask,
+ AUDIO_FORMAT_PCM_16_BIT,
+ 8 /* bufferCount */,
+ NULL,
+ NULL,
+ (audio_output_flags_t)flags),
+ (status_t)OK);
+ mAudioSink->start();
+ }
mRenderer->signalAudioSinkChanged();
} else {
@@ -968,8 +1061,15 @@
new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
id());
- *decoder = audio ? new Decoder(notify) :
- new Decoder(notify, mNativeWindow);
+ if (audio) {
+ if (mOffloadAudio) {
+ *decoder = new DecoderPassThrough(notify);
+ } else {
+ *decoder = new Decoder(notify);
+ }
+ } else {
+ *decoder = new Decoder(notify, mNativeWindow);
+ }
(*decoder)->init();
(*decoder)->configure(format);