From 4ed260feda32f6c51dd018e1c012e39aa63e61d4 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 2 Mar 2012 14:54:07 -0800 Subject: [PATCH] Add channel mask in AudioSink Add support for specifying a channel mask when opening an AudioSink. This parameter does not replace the channel count parameter in order to not have to duplicate the logic to derive a mask from the channel count everywhere an AudioSink is used without a known mask. A mask of 0 (CHANNEL_MASK_USE_CHANNEL_ORDER) means a mask will be automatically derived from the number of channels. Update existing AudioSink implementations to use the channel mask, and users of AudioSink to specify the mask if available, and CHANNEL_MASK_USE_CHANNEL_ORDER otherwise. Change-Id: Ifa9bd259874816dbc25ead2b03ea52e873cff474 --- include/media/MediaPlayerInterface.h | 4 +++- include/media/stagefright/MetaData.h | 1 + .../MediaPlayerService.cpp | 23 ++++++++++++++----- .../MediaPlayerService.h | 6 ++--- media/libmediaplayerservice/MidiFile.cpp | 3 ++- .../nuplayer/NuPlayer.cpp | 1 + media/libstagefright/AudioPlayer.cpp | 21 ++++++++++++----- 7 files changed, 42 insertions(+), 17 deletions(-) diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index f7491d82a98b1..8168dff803da8 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -60,6 +60,8 @@ enum player_type { #define DEFAULT_AUDIOSINK_BUFFERSIZE 1200 #define DEFAULT_AUDIOSINK_SAMPLERATE 44100 +// when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open() +#define CHANNEL_MASK_USE_CHANNEL_ORDER 0 // callback mechanism for passing messages to MediaPlayer object typedef void (*notify_callback_f)(void* cookie, @@ -91,7 +93,7 @@ public: // If no callback is specified, use the "write" API below to submit // audio data. virtual status_t open( - uint32_t sampleRate, int channelCount, + uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, audio_format_t format=AUDIO_FORMAT_PCM_16_BIT, int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT, AudioCallback cb = NULL, diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 4cdee1702fe08..8b4b8edd64bc8 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -43,6 +43,7 @@ enum { kKeyStride = 'strd', // int32_t kKeySliceHeight = 'slht', // int32_t kKeyChannelCount = '#chn', // int32_t + kKeyChannelMask = 'chnm', // int32_t kKeySampleRate = 'srte', // int32_t (audio sampling rate Hz) kKeyFrameRate = 'frmR', // int32_t (video frame rate fps) kKeyBitRate = 'brte', // int32_t (bps) diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 1e2abf026126f..bd3e07a001dcd 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -1458,7 +1458,8 @@ status_t MediaPlayerService::AudioOutput::getPosition(uint32_t *position) } status_t MediaPlayerService::AudioOutput::open( - uint32_t sampleRate, int channelCount, audio_format_t format, int bufferCount, + uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, + audio_format_t format, int bufferCount, AudioCallback cb, void *cookie) { mCallback = cb; @@ -1470,7 +1471,8 @@ status_t MediaPlayerService::AudioOutput::open( bufferCount = mMinBufferCount; } - ALOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId); + ALOGV("open(%u, %d, 0x%x, %d, %d, %d)", sampleRate, channelCount, channelMask, + format, bufferCount, mSessionId); if (mTrack) close(); int afSampleRate; int afFrameCount; @@ -1485,13 +1487,21 @@ status_t MediaPlayerService::AudioOutput::open( frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate; + if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) { + channelMask = audio_channel_mask_from_count(channelCount); + if (0 == channelMask) { + ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount); + return NO_INIT; + } + } + AudioTrack *t; if (mCallback != NULL) { t = new AudioTrack( mStreamType, sampleRate, format, - (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO, + channelMask, frameCount, 0 /* flags */, CallbackWrapper, @@ -1503,7 +1513,7 @@ status_t MediaPlayerService::AudioOutput::open( mStreamType, sampleRate, format, - (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO, + channelMask, frameCount, 0, NULL, @@ -1751,10 +1761,11 @@ bool CallbackThread::threadLoop() { //////////////////////////////////////////////////////////////////////////////// status_t MediaPlayerService::AudioCache::open( - uint32_t sampleRate, int channelCount, audio_format_t format, int bufferCount, + uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, + audio_format_t format, int bufferCount, AudioCallback cb, void *cookie) { - ALOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount); + ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount); if (mHeap->getHeapID() < 0) { return NO_INIT; } diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 53847eda2a080..681ecab49ef92 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -85,7 +85,7 @@ class MediaPlayerService : public BnMediaPlayerService virtual int getSessionId(); virtual status_t open( - uint32_t sampleRate, int channelCount, + uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, audio_format_t format, int bufferCount, AudioCallback cb, void *cookie); @@ -145,8 +145,8 @@ class MediaPlayerService : public BnMediaPlayerService virtual int getSessionId(); virtual status_t open( - uint32_t sampleRate, int channelCount, audio_format_t format, - int bufferCount = 1, + uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask, + audio_format_t format, int bufferCount = 1, AudioCallback cb = NULL, void *cookie = NULL); virtual void start(); diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index 7cb8c29150dff..8db5b9b8eb777 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -421,7 +421,8 @@ status_t MidiFile::setLooping(int loop) } status_t MidiFile::createOutputTrack() { - if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) { + if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, + CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) { ALOGE("mAudioSink open failed"); return ERROR_OPEN_FAILED; } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index e618f6700195e..526120ab94796 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -336,6 +336,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { CHECK_EQ(mAudioSink->open( sampleRate, numChannels, + CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 8 /* bufferCount */), (status_t)OK); diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index df275664533ba..9427ef7d6ebae 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -110,13 +110,18 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { success = format->findInt32(kKeySampleRate, &mSampleRate); CHECK(success); - int32_t numChannels; + int32_t numChannels, channelMask; success = format->findInt32(kKeyChannelCount, &numChannels); CHECK(success); + if(!format->findInt32(kKeyChannelMask, &channelMask)) { + ALOGW("source format didn't specify channel mask, using channel order"); + channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; + } + if (mAudioSink.get() != NULL) { status_t err = mAudioSink->open( - mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT, + mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT, &AudioPlayer::AudioSinkCallback, this); if (err != OK) { @@ -137,11 +142,15 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { mAudioSink->start(); } else { + // playing to an AudioTrack, set up mask if necessary + audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ? + audio_channel_mask_from_count(numChannels) : channelMask; + if (0 == audioMask) { + return BAD_VALUE; + } + mAudioTrack = new AudioTrack( - AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, - (numChannels == 2) - ? AUDIO_CHANNEL_OUT_STEREO - : AUDIO_CHANNEL_OUT_MONO, + AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask, 0, 0, &AudioCallback, this, 0); if ((err = mAudioTrack->initCheck()) != OK) {