summaryrefslogtreecommitdiffstats
path: root/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libavextensions/mediaplayerservice/AVNuUtils.cpp')
-rw-r--r--media/libavextensions/mediaplayerservice/AVNuUtils.cpp257
1 files changed, 235 insertions, 22 deletions
diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
index a8defee..8a78767 100644
--- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
+++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
@@ -30,10 +30,18 @@
#define LOG_TAG "AVNuUtils"
#include <utils/Log.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/OMXCodec.h>
+#include <cutils/properties.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/MediaProfiles.h>
+#include <media/stagefright/Utils.h>
+
+#include <audio_utils/format.h>
#include <nuplayer/NuPlayer.h>
#include <nuplayer/NuPlayerDecoderBase.h>
@@ -46,12 +54,116 @@
namespace android {
+static bool is24bitPCMOffloadEnabled() {
+ char propPCMOfload[PROPERTY_VALUE_MAX] = {0};
+ property_get("audio.offload.pcm.24bit.enable", propPCMOfload, "0");
+ if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload))
+ return true;
+ else
+ return false;
+}
+
+static bool is16bitPCMOffloadEnabled() {
+ char propPCMOfload[PROPERTY_VALUE_MAX] = {0};
+ property_get("audio.offload.pcm.16bit.enable", propPCMOfload, "0");
+ if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload))
+ return true;
+ else
+ return false;
+}
+
sp<MetaData> AVNuUtils::createPCMMetaFromSource(const sp<MetaData> &sMeta) {
- return sMeta;
+ sp<MetaData> tPCMMeta = new MetaData;
+ //hard code as RAW
+ tPCMMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+
+ int32_t bits = 16;
+ sMeta->findInt32(kKeyBitsPerSample, &bits);
+ tPCMMeta->setInt32(kKeyBitsPerSample, bits > 24 ? 24 : bits);
+
+ if (sMeta == NULL) {
+ ALOGW("no meta returning dummy meta");
+ return tPCMMeta;
+ }
+
+ int32_t srate = -1;
+ if (!sMeta->findInt32(kKeySampleRate, &srate)) {
+ ALOGV("No sample rate");
+ }
+ tPCMMeta->setInt32(kKeySampleRate, srate);
+
+ int32_t cmask = 0;
+ if (!sMeta->findInt32(kKeyChannelMask, &cmask) || (cmask == 0)) {
+ ALOGI("No channel mask, try channel count");
+ }
+ int32_t channelCount = 0;
+ if (!sMeta->findInt32(kKeyChannelCount, &channelCount)) {
+ ALOGI("No channel count either");
+ } else {
+ //if channel mask is not set till now, use channel count
+ //to retrieve channel count
+ if (!cmask) {
+ cmask = audio_channel_out_mask_from_count(channelCount);
+ }
+ }
+ tPCMMeta->setInt32(kKeyChannelCount, channelCount);
+ tPCMMeta->setInt32(kKeyChannelMask, cmask);
+
+ int64_t duration = INT_MAX;
+ if (!sMeta->findInt64(kKeyDuration, &duration)) {
+ ALOGW("No duration in meta setting max duration");
+ }
+ tPCMMeta->setInt64(kKeyDuration, duration);
+
+ int32_t bitRate = -1;
+ if (!sMeta->findInt32(kKeyBitRate, &bitRate)) {
+ ALOGW("No bitrate info");
+ } else {
+ tPCMMeta->setInt32(kKeyBitRate, bitRate);
+ }
+
+ return tPCMMeta;
}
-bool AVNuUtils::pcmOffloadException(const sp<MetaData> &) {
- return true;
+bool AVNuUtils::pcmOffloadException(const sp<MetaData> &meta) {
+ bool decision = false;
+ const char *mime = {0};
+
+ if (meta == NULL) {
+ return true;
+ }
+ meta->findCString(kKeyMIMEType, &mime);
+
+ if (!mime) {
+ ALOGV("%s: no audio mime present, ignoring pcm offload", __func__);
+ return true;
+ }
+//#if defined (PCM_OFFLOAD_ENABLED) || defined (PCM_OFFLOAD_ENABLED_24)
+ const char * const ExceptionTable[] = {
+ MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_QCELP,
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ MEDIA_MIMETYPE_AUDIO_EVRC
+ };
+ int countException = (sizeof(ExceptionTable) / sizeof(ExceptionTable[0]));
+
+ for(int i = 0; i < countException; i++) {
+ if (!strcasecmp(mime, ExceptionTable[i])) {
+ decision = true;
+ break;
+ }
+ }
+ ALOGI("decision %d mime %s", decision, mime);
+ return decision;
+#if 0
+ //if PCM offload flag is disabled, do not offload any sessions
+ //using pcm offload
+ decision = true;
+ ALOGI("decision %d mime %s", decision, mime);
+ return decision;
+#endif
}
bool AVNuUtils::isRAWFormat(const sp<MetaData> &meta) {
@@ -83,44 +195,145 @@ bool AVNuUtils::isVorbisFormat(const sp<MetaData> &) {
return false;
}
-int AVNuUtils::updateAudioBitWidth(audio_format_t /*audioFormat*/,
- const sp<AMessage> &){
- return 16;
+int AVNuUtils::updateAudioBitWidth(audio_format_t audioFormat,
+ const sp<AMessage> &format){
+ int bits = 16;
+ if (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat)) {
+ bits = audio_bytes_per_sample(audioFormat) * 8;
+ format->setInt32("bits-per-sample", bits);
+ }
+ return bits;
}
audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &meta) {
- int32_t pcmFormat = 0;
- if (meta->findInt32('pfmt', &pcmFormat))
- return (audio_format_t)pcmFormat;
-
- return AUDIO_FORMAT_PCM_16_BIT;
+ audio_format_t pcmFormat = AUDIO_FORMAT_INVALID;
+ meta->findInt32('pfmt', (int32_t *)&pcmFormat);
+ return pcmFormat;
}
void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &meta, audio_format_t audioFormat) {
- if (audio_is_linear_pcm(audioFormat))
+ if (meta != NULL && audio_is_linear_pcm(audioFormat))
meta->setInt32('pfmt', audioFormat);
}
-audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &/*format*/) {
- return AUDIO_FORMAT_PCM_16_BIT;
+audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &format) {
+ audio_format_t pcmFormat = AUDIO_FORMAT_INVALID;
+ format->findInt32("pcm-format", (int32_t *)&pcmFormat);
+ return pcmFormat;
}
void AVNuUtils::setPCMFormat(const sp<AMessage> &format, audio_format_t audioFormat) {
- if (audio_is_linear_pcm(audioFormat))
+ if (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat))
format->setInt32("pcm-format", audioFormat);
}
-void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &) {
-
+void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &audioMeta) {
+ audio_format_t pcmFormat = getKeyPCMFormat(audioMeta);
+ ALOGI("setSourcePCMFormat fmt=%x", pcmFormat);
+ audioMeta->dumpToLog();
+ if (pcmFormat == AUDIO_FORMAT_INVALID) {
+ int32_t bits = 16;
+ if (audioMeta->findInt32(kKeyBitsPerSample, &bits)) {
+ if (bits == 8)
+ pcmFormat = AUDIO_FORMAT_PCM_8_BIT;
+ if (bits == 24)
+ pcmFormat = AUDIO_FORMAT_PCM_32_BIT;
+ if (bits == 32)
+ pcmFormat = AUDIO_FORMAT_PCM_FLOAT;
+ setKeyPCMFormat(audioMeta, pcmFormat);
+ }
+ }
}
void AVNuUtils::setDecodedPCMFormat(const sp<AMessage> &) {
}
-status_t AVNuUtils::convertToSinkFormatIfNeeded(const sp<ABuffer> &, sp<ABuffer> &,
- audio_format_t /*sinkFormat*/, bool /*isOffload*/) {
- return INVALID_OPERATION;
+status_t AVNuUtils::convertToSinkFormatIfNeeded(
+ const sp<ABuffer> &buffer, sp<ABuffer> &newBuffer,
+ audio_format_t sinkFormat, bool isOffload) {
+
+ audio_format_t srcFormat = AUDIO_FORMAT_INVALID;
+ if (!buffer->meta()->findInt32("pcm-format", (int32_t *)&srcFormat)) {
+ newBuffer = buffer;
+ return OK;
+ }
+
+ size_t bps = audio_bytes_per_sample(srcFormat);
+
+ if (bps <= 0) {
+ ALOGE("Invalid pcmformat %x given for conversion", srcFormat);
+ return INVALID_OPERATION;
+ }
+
+ size_t frames = buffer->size() / bps;
+
+ if (frames == 0) {
+ ALOGE("zero sized buffer, nothing to convert");
+ return BAD_VALUE;
+ }
+
+ ALOGV("convert %zu bytes (frames %d) of format %x",
+ buffer->size(), frames, srcFormat);
+
+ audio_format_t dstFormat;
+ if (isOffload) {
+ switch (sinkFormat) {
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
+ dstFormat = AUDIO_FORMAT_PCM_16_BIT;
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
+ if (srcFormat != AUDIO_FORMAT_PCM_24_BIT_PACKED &&
+ srcFormat != AUDIO_FORMAT_PCM_8_24_BIT) {
+ ALOGE("Invalid src format for 24 bit conversion");
+ return INVALID_OPERATION;
+ }
+ dstFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD;
+ break;
+ case AUDIO_FORMAT_DEFAULT:
+ ALOGI("OffloadInfo not yet initialized, retry");
+ return NO_INIT;
+ default:
+ ALOGE("Invalid offload format %x given for conversion",
+ sinkFormat);
+ return INVALID_OPERATION;
+ }
+ } else {
+ if (sinkFormat == AUDIO_FORMAT_INVALID) {
+ ALOGD("PCM Info not yet initialized, drop buffer");
+ return INVALID_OPERATION;
+ }
+
+ dstFormat = sinkFormat;
+ }
+ if (srcFormat == dstFormat) {
+ ALOGV("same format");
+ newBuffer = buffer;
+ return OK;
+ }
+
+ size_t dstFrameSize = audio_bytes_per_sample(dstFormat);
+ size_t dstBytes = frames * dstFrameSize;
+
+ newBuffer = new ABuffer(dstBytes);
+
+ memcpy_by_audio_format(newBuffer->data(), dstFormat,
+ buffer->data(), srcFormat, frames);
+
+ ALOGV("convert to format %x newBuffer->size() %zu",
+ dstFormat, newBuffer->size());
+
+ // copy over some meta info
+ int64_t timeUs = 0;
+ buffer->meta()->findInt64("timeUs", &timeUs);
+ newBuffer->meta()->setInt64("timeUs", timeUs);
+
+ int32_t eos = false;
+ buffer->meta()->findInt32("eos", &eos);
+ newBuffer->meta()->setInt32("eos", eos);
+
+ newBuffer->meta()->setInt32("pcm-format", (int32_t)dstFormat);
+ return OK;
}
void AVNuUtils::printFileName(int) {}