diff options
43 files changed, 1859 insertions, 213 deletions
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 5f9eb01..e17bbbe 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -1,8 +1,8 @@ /* - * Copyright (C) 2007 The Android Open Source Project * Copyright (c) 2013, The Linux Foundation. All rights reserved. - * Not a Contribution, Apache license notifications and license are retained - * for attribution purposes only. + * Not a Contribution. + * + * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index 0df9fd4..9ea3449 100644..100755 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -33,12 +33,11 @@ enum camcorder_quality { CAMCORDER_QUALITY_480P = 4, CAMCORDER_QUALITY_720P = 5, CAMCORDER_QUALITY_1080P = 6, - CAMCORDER_QUALITY_QVGA = 11, - CAMCORDER_QUALITY_FWVGA = 7, - CAMCORDER_QUALITY_WVGA = 8, - CAMCORDER_QUALITY_VGA = 9, - CAMCORDER_QUALITY_WQVGA = 10, - + CAMCORDER_QUALITY_QVGA = 7, + CAMCORDER_QUALITY_FWVGA = 8, + CAMCORDER_QUALITY_WVGA = 9, + CAMCORDER_QUALITY_VGA = 10, + CAMCORDER_QUALITY_WQVGA = 11, CAMCORDER_QUALITY_LIST_END = 11, CAMCORDER_QUALITY_TIME_LAPSE_LIST_START = 1000, @@ -50,7 +49,11 @@ enum camcorder_quality { CAMCORDER_QUALITY_TIME_LAPSE_720P = 1005, CAMCORDER_QUALITY_TIME_LAPSE_1080P = 1006, CAMCORDER_QUALITY_TIME_LAPSE_QVGA = 1007, - CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1007, + CAMCORDER_QUALITY_TIME_LAPSE_FWVGA = 1008, + CAMCORDER_QUALITY_TIME_LAPSE_WVGA = 1009, + CAMCORDER_QUALITY_TIME_LAPSE_VGA = 1010, + CAMCORDER_QUALITY_TIME_LAPSE_WQVGA = 1011, + CAMCORDER_QUALITY_TIME_LAPSE_LIST_END = 1011, }; /** diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index 4489254..33081cc 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -104,6 +105,19 @@ private: AudioSource(const AudioSource &); AudioSource &operator=(const AudioSource &); + +#ifdef QCOM_HARDWARE + //additions for tunnel source +public: + AudioSource( + audio_source_t inputSource, const sp<MetaData>& meta ); + +private: + audio_format_t mFormat; + String8 mMime; + int32_t mMaxBufferSize; + int64_t bufferDurationUs( ssize_t n ); +#endif }; } // namespace android diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h index dfb845b..8f2b624 100644 --- a/include/media/stagefright/MediaCodecList.h +++ b/include/media/stagefright/MediaCodecList.h @@ -99,6 +99,10 @@ private: status_t addTypeFromAttributes(const char **attrs); void addType(const char *name); +#ifdef QCOM_HARDWARE + friend class QCUtilityClass; +#endif + DISALLOW_EVIL_CONSTRUCTORS(MediaCodecList); }; diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h index f63926c..db8d89e 100644 --- a/include/media/stagefright/MediaDefs.h +++ b/include/media/stagefright/MediaDefs.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,7 +32,6 @@ extern const char *MEDIA_MIMETYPE_VIDEO_RAW; extern const char *MEDIA_MIMETYPE_AUDIO_AMR_NB; extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB; -extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS; extern const char *MEDIA_MIMETYPE_AUDIO_MPEG; // layer III extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I; extern const char *MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II; @@ -43,6 +43,7 @@ extern const char *MEDIA_MIMETYPE_AUDIO_G711_MLAW; extern const char *MEDIA_MIMETYPE_AUDIO_RAW; extern const char *MEDIA_MIMETYPE_AUDIO_FLAC; extern const char *MEDIA_MIMETYPE_AUDIO_AAC_ADTS; +extern const char *MEDIA_MIMETYPE_AUDIO_DTS; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; @@ -57,6 +58,27 @@ extern const char *MEDIA_MIMETYPE_CONTAINER_WVM; extern const char *MEDIA_MIMETYPE_TEXT_3GPP; extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP; +#ifdef QCOM_HARDWARE +extern const char *MEDIA_MIMETYPE_AUDIO_AC3; +extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS; +extern const char *MEDIA_MIMETYPE_AUDIO_DTS; +extern const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR; +extern const char *MEDIA_MIMETYPE_AUDIO_EAC3; +extern const char *MEDIA_MIMETYPE_AUDIO_EVRC; +extern const char *MEDIA_MIMETYPE_AUDIO_WMA; + +extern const char *MEDIA_MIMETYPE_CONTAINER_3G2; +extern const char *MEDIA_MIMETYPE_CONTAINER_AAC; +extern const char *MEDIA_MIMETYPE_CONTAINER_ASF; +extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2; +extern const char *MEDIA_MIMETYPE_CONTAINER_QCP; + +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX; +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX311; +extern const char *MEDIA_MIMETYPE_VIDEO_DIVX4; +extern const char *MEDIA_MIMETYPE_VIDEO_WMV; +#endif + } // namespace android #endif // MEDIA_DEFS_H_ diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index bdd35a4..630f5af 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 The Android Open Source Project - * Copyright (c) 2010 - 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2010 - 2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -392,7 +392,9 @@ private: #ifdef QCOM_HARDWARE status_t setWMAFormat(const sp<MetaData> &inputFormat); void setAC3Format(int32_t numChannels, int32_t sampleRate); + bool mNumBFrames; #endif + }; struct CodecCapabilities { diff --git a/include/media/stagefright/QCOMXCodec.h b/include/media/stagefright/QCOMXCodec.h index ee6ea88..333487d 100644 --- a/include/media/stagefright/QCOMXCodec.h +++ b/include/media/stagefright/QCOMXCodec.h @@ -96,6 +96,8 @@ struct QCOMXCodec { static void checkIfInterlaced(const uint8_t *ptr, const sp<MetaData> &meta); + static bool useHWAACDecoder(const char *mime); + }; } diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp index 21d3c30..07e20dc 100755 --- a/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp +++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditorVideoDecoder.cpp @@ -830,8 +830,13 @@ M4OSA_ERR VideoEditorVideoDecoder_configureFromMetadata(M4OSA_Context pContext, pDecShellContext->mCropRect.top = cropTop; pDecShellContext->mCropRect.bottom = cropBottom; +#ifdef QCOM_HARDWARE + width = vWidth; + height = vHeight; +#else width = cropRight - cropLeft + 1; height = cropBottom - cropTop + 1; +#endif ALOGV("VideoDecoder_configureFromMetadata : W=%d H=%d", width, height); VIDEOEDITOR_CHECK((0 != width) && (0 != height), M4ERR_PARAMETER); diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 2725b5b..087a567 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -1,7 +1,7 @@ /* ** ** Copyright 2008, The Android Open Source Project -** Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +** Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -136,6 +136,7 @@ status_t AudioRecord::set( ALOGV("set(): sampleRate %d, channelMask %#x, frameCount %d",sampleRate, channelMask, frameCount); AutoMutex lock(mLock); + status_t status; if (mAudioRecord != 0) { return INVALID_OPERATION; @@ -185,12 +186,61 @@ status_t AudioRecord::set( return BAD_VALUE; } +#ifdef QCOM_HARDWARE + size_t inputBuffSizeInBytes = -1; + if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes) + != NO_ERROR) { + ALOGE("AudioSystem could not query the input buffer size."); + return NO_INIT; + } + ALOGV("AudioRecord::set() inputBuffSizeInBytes = %d", inputBuffSizeInBytes ); + + if (inputBuffSizeInBytes == 0) { + ALOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d", + sampleRate, channelCount, format); + return BAD_VALUE; + } + + // Change for Codec type + int frameSizeInBytes = 0; + if(inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION) { + if (audio_is_linear_pcm(format)) { + frameSizeInBytes = channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? sizeof(int16_t) +: sizeof(int8_t)); + } else { + frameSizeInBytes = channelCount *sizeof(int16_t); + } + } else { + if (format ==AUDIO_FORMAT_AMR_NB) { + frameSizeInBytes = channelCount * 32; // Full rate framesize + } else if (format ==AUDIO_FORMAT_EVRC) { + frameSizeInBytes = channelCount * 23; // Full rate framesize + } else if (format ==AUDIO_FORMAT_QCELP) { + frameSizeInBytes = channelCount * 35; // Full rate framesize + } else if (format ==AUDIO_FORMAT_AAC) { + frameSizeInBytes = 2048; + } else if ((format ==AUDIO_FORMAT_PCM_16_BIT) || (format ==AUDIO_FORMAT_PCM_8_BIT)) { + if (audio_is_linear_pcm(format)) { + frameSizeInBytes = channelCount * (format == AUDIO_FORMAT_PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t)); + } else { + frameSizeInBytes = sizeof(int8_t); + } + } else if(format == AUDIO_FORMAT_AMR_WB) { + frameSizeInBytes = channelCount * 61; + + } + } + // We use 2* size of input buffer for ping pong use of record buffer. + int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes; +#else // validate framecount int minFrameCount = 0; - status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); + status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); if (status != NO_ERROR) { return status; } +#endif + ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); if (frameCount == 0) { @@ -203,6 +253,10 @@ status_t AudioRecord::set( notificationFrames = frameCount/2; } +#ifdef QCOM_HARDWARE + //update mInputSource before openRecord_l + mInputSource = inputSource; +#endif // create the IAudioRecord status = openRecord_l(sampleRate, format, channelMask, frameCount, input); @@ -233,7 +287,9 @@ status_t AudioRecord::set( mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; +#ifndef QCOM_HARDWARE mInputSource = inputSource; +#endif mInput = input; AudioSystem::acquireAudioSessionId(mSessionId); @@ -269,11 +325,36 @@ uint32_t AudioRecord::frameCount() const size_t AudioRecord::frameSize() const { - if (audio_is_linear_pcm(mFormat)) { - return channelCount()*audio_bytes_per_sample(mFormat); +#ifdef QCOM_HARDWARE + if(inputSource() == AUDIO_SOURCE_VOICE_COMMUNICATION) { + if (audio_is_linear_pcm(mFormat)) { + return channelCount()*audio_bytes_per_sample(mFormat); + } else { + return channelCount()*sizeof(int16_t); + } } else { - return sizeof(uint8_t); + if (format() ==AUDIO_FORMAT_AMR_NB) { + return channelCount() * 32; // Full rate framesize + } else if (format() == AUDIO_FORMAT_EVRC) { + return channelCount() * 23; // Full rate framesize + } else if (format() == AUDIO_FORMAT_QCELP) { + return channelCount() * 35; // Full rate framesize + } else if (format() == AUDIO_FORMAT_AAC) { + // Not actual framsize but for variable frame rate AAC encoding, + // buffer size is treated as a frame size + return 2048; + } else if(format() == AUDIO_FORMAT_AMR_WB) { + return channelCount() * 61; + } +#endif + if (audio_is_linear_pcm(mFormat)) { + return channelCount()*audio_bytes_per_sample(mFormat); + } else { + return sizeof(uint8_t); + } +#ifdef QCOM_HARDWARE } +#endif } audio_source_t AudioRecord::inputSource() const @@ -453,7 +534,7 @@ status_t AudioRecord::openRecord_l( sampleRate, format, channelMask, frameCount, - IAudioFlinger::TRACK_DEFAULT, + (int16_t)inputSource(), tid, &mSessionId, &status); diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index a2f4348..1025799 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -69,25 +69,31 @@ status_t AudioTrack::getMinFrameCount( // audio_format_t format // audio_channel_mask_t channelMask // audio_output_flags_t flags - int afSampleRate; + int afSampleRate = 0; if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; } - int afFrameCount; + int afFrameCount = 0; if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) { return NO_INIT; } - uint32_t afLatency; + uint32_t afLatency = 0; if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { return NO_INIT; } + if(!afSampleRate || !afFrameCount) { + ALOGW("samplerate or framecount 0"); + return NO_INIT; + } + // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate); if (minBufCount < 2) minBufCount = 2; *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount : - afFrameCount * minBufCount * sampleRate / afSampleRate; + afFrameCount * minBufCount * sampleRate / afSampleRate; + ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d", *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency); return NO_ERROR; @@ -455,11 +461,23 @@ uint32_t AudioTrack::frameCount() const size_t AudioTrack::frameSize() const { - if (audio_is_linear_pcm(mFormat)) { - return channelCount()*audio_bytes_per_sample(mFormat); +#ifdef QCOM_HARDWARE + if ((audio_stream_type_t)mStreamType == AUDIO_STREAM_VOICE_CALL) { + if (audio_is_linear_pcm(mFormat)) { + return channelCount()*audio_bytes_per_sample(mFormat); + } else { + return channelCount()*sizeof(int16_t); + } } else { - return sizeof(uint8_t); +#endif + if (audio_is_linear_pcm(mFormat)) { + return channelCount()*audio_bytes_per_sample(mFormat); + } else { + return sizeof(uint8_t); + } +#ifdef QCOM_HARDWARE } +#endif } sp<IMemory>& AudioTrack::sharedBuffer() @@ -980,20 +998,26 @@ status_t AudioTrack::createTrack_l( } else if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { // FIXME move these calculations and associated checks to server - int afSampleRate; + int afSampleRate = 0; if (AudioSystem::getSamplingRate(output, streamType, &afSampleRate) != NO_ERROR) { return NO_INIT; } - int afFrameCount; + int afFrameCount = 0; if (AudioSystem::getFrameCount(output, streamType, &afFrameCount) != NO_ERROR) { return NO_INIT; } + if(!afSampleRate && !afFrameCount) { + ALOGW("samplerate or framecount zero"); + return NO_INIT; + } + // Ensure that buffer depth covers at least audio hardware latency uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate); if (minBufCount < 2) minBufCount = 2; - int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + uint32_t minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + ALOGV("minFrameCount: %d, afFrameCount=%d, minBufCount=%d, sampleRate=%d, afSampleRate=%d" ", afLatency=%d", minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency); @@ -1088,7 +1112,10 @@ status_t AudioTrack::createTrack_l( mCblk->waitTimeMs = 0; mRemainingFrames = mNotificationFramesAct; // FIXME don't believe this lie - mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; + if(sampleRate) + mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate; + else + mLatency = afLatency; // If IAudioTrack is re-created, don't let the requested frameCount // decrease. This can confuse clients that cache frameCount(). if (mCblk->frameCount > mFrameCount) { diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index fa536a6..e1299c2 100644..100755 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -87,31 +87,35 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"timelapse720p", CAMCORDER_QUALITY_TIME_LAPSE_720P}, {"timelapse1080p", CAMCORDER_QUALITY_TIME_LAPSE_1080P}, {"timelapseqvga", CAMCORDER_QUALITY_TIME_LAPSE_QVGA}, + {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA}, + {"timelapsewvga", CAMCORDER_QUALITY_TIME_LAPSE_WVGA}, + {"timelapsefwvga", CAMCORDER_QUALITY_TIME_LAPSE_FWVGA}, + {"timelapsewqvga", CAMCORDER_QUALITY_TIME_LAPSE_WQVGA}, }; /*static*/ void MediaProfiles::logVideoCodec(const MediaProfiles::VideoCodec& codec) { - ALOGV("video codec:"); - ALOGV("codec = %d", codec.mCodec); - ALOGV("bit rate: %d", codec.mBitRate); - ALOGV("frame width: %d", codec.mFrameWidth); - ALOGV("frame height: %d", codec.mFrameHeight); - ALOGV("frame rate: %d", codec.mFrameRate); +ALOGV("video codec:"); +ALOGV("codec = %d", codec.mCodec); +ALOGV("bit rate: %d", codec.mBitRate); +ALOGV("frame width: %d", codec.mFrameWidth); +ALOGV("frame height: %d", codec.mFrameHeight); +ALOGV("frame rate: %d", codec.mFrameRate); } /*static*/ void MediaProfiles::logAudioCodec(const MediaProfiles::AudioCodec& codec) { - ALOGV("audio codec:"); - ALOGV("codec = %d", codec.mCodec); - ALOGV("bit rate: %d", codec.mBitRate); - ALOGV("sample rate: %d", codec.mSampleRate); - ALOGV("number of channels: %d", codec.mChannels); +ALOGV("audio codec:"); +ALOGV("codec = %d", codec.mCodec); +ALOGV("bit rate: %d", codec.mBitRate); +ALOGV("sample rate: %d", codec.mSampleRate); +ALOGV("number of channels: %d", codec.mChannels); } /*static*/ void -MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap) + MediaProfiles::logVideoEncoderCap(const MediaProfiles::VideoEncoderCap& cap) { ALOGV("video encoder cap:"); ALOGV("codec = %d", cap.mCodec); diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 1cc21d6..d978e90 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -41,10 +41,12 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_STATIC_LIBRARIES := \ libstagefright_nuplayer \ libstagefright_rtsp \ + libmedia_helper \ LOCAL_C_INCLUDES := \ $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/av/media/libstagefright/include \ + $(TOP)/frameworks/av/include/media \ $(TOP)/frameworks/av/media/libstagefright/rtsp \ $(TOP)/frameworks/av/media/libstagefright/wifi-display \ $(TOP)/frameworks/native/include/media/openmax \ diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 972de37..d41c3b5 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -1,9 +1,9 @@ /* ** -** Copyright 2008, The Android Open Source Project ** Copyright (c) 2013, The Linux Foundation. All rights reserved. -** Not a Contribution, Apache license notifications and license are retained -** for attribution purposes only. +** Not a Contribution. +** +** Copyright (C) 2008 The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 5e8d435..4d25277 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -21,7 +21,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "StagefrightRecorder" #include <utils/Log.h> - +#include <media/AudioParameter.h> #include "StagefrightRecorder.h" #include <binder/IPCThreadState.h> @@ -33,13 +33,6 @@ #include <media/stagefright/AudioSource.h> #include <media/stagefright/AMRWriter.h> #include <media/stagefright/AACWriter.h> -#ifdef QCOM_HARDWARE -#include <media/stagefright/ExtendedWriter.h> -#include <media/stagefright/WAVEWriter.h> -#endif -#ifdef QCOM_FM_ENABLED -#include <media/stagefright/FMA2DPWriter.h> -#endif #include <media/stagefright/CameraSource.h> #include <media/stagefright/CameraSourceTimeLapse.h> #include <media/stagefright/MPEG2TSWriter.h> @@ -53,18 +46,26 @@ #include <camera/ICamera.h> #include <camera/CameraParameters.h> #include <gui/Surface.h> +#include <utils/String8.h> #include <utils/Errors.h> #include <sys/types.h> #include <ctype.h> #include <unistd.h> -#include <system/audio.h> #ifdef QCOM_HARDWARE +#include <media/stagefright/ExtendedWriter.h> +#include <media/stagefright/WAVEWriter.h> #include <QCMediaDefs.h> #include <cutils/properties.h> +#include <QCUtilityClass.h> +#endif +#ifdef QCOM_FM_ENABLED +#include <media/stagefright/FMA2DPWriter.h> #endif +#include <system/audio.h> + #include "ARTPWriter.h" namespace android { @@ -117,6 +118,12 @@ status_t StagefrightRecorder::setAudioSource(audio_source_t as) { return BAD_VALUE; } +#ifdef QCOM_HARDWARE + if(QCUtilityClass::helper_StagefrightRecoder_checkIfAudioDisable()) { + return OK; + } +#endif + if (as == AUDIO_SOURCE_DEFAULT) { mAudioSource = AUDIO_SOURCE_MIC; } else { @@ -168,6 +175,12 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { return BAD_VALUE; } +#ifdef QCOM_HARDWARE + if(QCUtilityClass::helper_StagefrightRecoder_checkIfAudioDisable()) { + return OK; + } +#endif + if (ae == AUDIO_ENCODER_DEFAULT) { mAudioEncoder = AUDIO_ENCODER_AMR_NB; } else { @@ -187,7 +200,7 @@ status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) { } else if(mAudioEncoder == AUDIO_ENCODER_AMR_WB) { mSampleRate = 16000; mAudioChannels = 1; - mAudioBitRate = 23850; + mAudioBitRate = mAudioBitRate ? mAudioBitRate : 23850; } else { mSampleRate = mSampleRate ? mSampleRate : 8000; mAudioChannels = mAudioChannels ? mAudioChannels : 1; @@ -856,6 +869,47 @@ status_t StagefrightRecorder::start() { } sp<MediaSource> StagefrightRecorder::createAudioSource() { +#ifdef QCOM_ENHANCED_AUDIO + bool tunneledSource = false; + const char *tunnelMime; + { + AudioParameter param; + String8 key("tunneled-input-formats"); + param.add( key, String8("get") ); + String8 valueStr = AudioSystem::getParameters( 0, param.toString()); + AudioParameter result(valueStr); + int value; + if ( mAudioEncoder == AUDIO_ENCODER_AMR_NB && + result.getInt(String8("AMR"),value) == NO_ERROR ) { + tunneledSource = true; + tunnelMime = MEDIA_MIMETYPE_AUDIO_AMR_NB; + } + else if ( mAudioEncoder == AUDIO_ENCODER_QCELP && + result.getInt(String8("QCELP"),value) == NO_ERROR ) { + tunneledSource = true; + tunnelMime = MEDIA_MIMETYPE_AUDIO_QCELP; + } + else if ( mAudioEncoder == AUDIO_ENCODER_EVRC && + result.getInt(String8("EVRC"),value) == NO_ERROR ) { + tunneledSource = true; + tunnelMime = MEDIA_MIMETYPE_AUDIO_EVRC; + } + } + + if ( tunneledSource ) { + sp<AudioSource> audioSource = NULL; + sp<MetaData> meta = new MetaData; + meta->setInt32(kKeyChannelCount, mAudioChannels); + meta->setInt32(kKeySampleRate, mSampleRate); + meta->setInt32(kKeyBitRate, mAudioBitRate); + if (mAudioTimeScale > 0) { + meta->setInt32(kKeyTimeScale, mAudioTimeScale); + } + meta->setCString( kKeyMIMEType, tunnelMime ); + audioSource = new AudioSource( mAudioSource, meta); + return audioSource->initCheck( ) == OK ? audioSource : NULL; + } +#endif sp<AudioSource> audioSource = new AudioSource( mAudioSource, @@ -1550,6 +1604,19 @@ status_t StagefrightRecorder::setupVideoEncoder( if (mVideoTimeScale > 0) { enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale); } + +#ifdef QCOM_HARDWARE + status_t retVal = + QCUtilityClass::helper_StageFrightRecoder_hfr(meta,enc_meta, mMaxFileDurationUs, + mFrameRate, mVideoEncoder); + if(retVal != OK) { + return retVal; + } + + QCUtilityClass::helper_StagefrightRecoder_setUserprofile(mVideoEncoder, + mVideoEncoderProfile); +#endif + if (mVideoEncoderProfile != -1) { enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile); } diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index ddf95dc..a9e344d 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -32,6 +32,16 @@ #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> +#include <media/stagefright/MetaData.h> + +#ifdef QCOM_ENHANCED_AUDIO +#include <QCMediaDefs.h> +#include <QCMetaData.h> +#include <QOMX_AudioExtensions.h> +#include <OMX_QCOMExtns.h> +#include "include/QCUtilityClass.h" +#endif + #include <media/hardware/HardwareAPI.h> #include <OMX_Component.h> @@ -925,6 +935,100 @@ status_t ACodec::configureCodec( mIsEncoder = encoder; +#ifdef QCOM_ENHANCED_AUDIO + if (!strcasecmp(mime, "audio/x-ms-wma")) { + if (mIsEncoder) { + ALOGE("WMA encoding not supported"); + return ERROR_UNSUPPORTED; + } else { + int32_t version; + OMX_AUDIO_PARAM_WMATYPE paramWMA; + QOMX_AUDIO_PARAM_WMA10PROTYPE paramWMA10; + CHECK(msg->findInt32("WMA-Version", &version)); + int32_t numChannels; + int32_t bitRate; + int32_t sampleRate; + int32_t encodeOptions; + int32_t blockAlign; + int32_t bitspersample; + int32_t formattag; + int32_t advencopt1; + int32_t advencopt2; + int32_t VirtualPktSize; + if(version==kTypeWMAPro || version==kTypeWMALossLess) { + CHECK(msg->findInt32("bsps", &bitspersample)); + CHECK(msg->findInt32("fmtt", &formattag)); + CHECK(msg->findInt32("ade1",&advencopt1)); + CHECK(msg->findInt32("ade2",&advencopt2)); + CHECK(msg->findInt32("vpks",&VirtualPktSize)); + } + if(version==kTypeWMA) { + InitOMXParams(¶mWMA); + paramWMA.nPortIndex = kPortIndexInput; + } else if(version==kTypeWMAPro || version==kTypeWMALossLess) { + InitOMXParams(¶mWMA10); + paramWMA10.nPortIndex = kPortIndexInput; + } + CHECK(msg->findInt32("channel-count", &numChannels)); + CHECK(msg->findInt32("sample-rate", &sampleRate)); + CHECK(msg->findInt32("brte", &bitRate)); + CHECK(msg->findInt32("eopt", &encodeOptions)); + CHECK(msg->findInt32("blka", &blockAlign)); + ALOGV("Channels: %d, SampleRate: %d, BitRate; %d" + "EncodeOptions: %d, blockAlign: %d", numChannels, + sampleRate, bitRate, encodeOptions, blockAlign); + if(sampleRate>48000 || numChannels>2){ + ALOGE("Unsupported samplerate/channels"); + return ERROR_UNSUPPORTED; + } + if(version==kTypeWMAPro || version==kTypeWMALossLess){ + ALOGV("Bitspersample: %d, wmaformattag: %d," + "advencopt1: %d, advencopt2: %d VirtualPktSize %d", bitspersample, + formattag, advencopt1, advencopt2, VirtualPktSize); + } + status_t err = OK; + OMX_INDEXTYPE index; + if(version==kTypeWMA) { + err = mOMX->getParameter( + mNode,OMX_IndexParamAudioWma, ¶mWMA, sizeof(paramWMA)); + } else if(version==kTypeWMAPro || version==kTypeWMALossLess) { + mOMX->getExtensionIndex(mNode,"OMX.Qualcomm.index.audio.wma10Pro",&index); + err = mOMX->getParameter( + mNode, index, ¶mWMA10, sizeof(paramWMA10)); + } + CHECK_EQ(err, (status_t)OK); + if(version==kTypeWMA) { + paramWMA.nChannels = numChannels; + paramWMA.nSamplingRate = sampleRate; + paramWMA.nEncodeOptions = encodeOptions; + paramWMA.nBitRate = bitRate; + paramWMA.nBlockAlign = blockAlign; + err = mOMX->setParameter( + mNode, OMX_IndexParamAudioWma, ¶mWMA, sizeof(paramWMA)); + } else if(version==kTypeWMAPro || version==kTypeWMALossLess) { + paramWMA10.nChannels = numChannels; + paramWMA10.nSamplingRate = sampleRate; + paramWMA10.nEncodeOptions = encodeOptions; + paramWMA10.nBitRate = bitRate; + paramWMA10.nBlockAlign = blockAlign; + paramWMA10.advancedEncodeOpt = advencopt1; + paramWMA10.advancedEncodeOpt2 = advencopt2; + paramWMA10.formatTag = formattag; + paramWMA10.validBitsPerSample = bitspersample; + paramWMA10.nVirtualPktSize = VirtualPktSize; + err = mOMX->setParameter( + mNode, index, ¶mWMA10, sizeof(paramWMA10)); + } + CHECK_EQ(err, (status_t)OK); + int32_t maxInputSize1; + if (msg->findInt32("max-input-size", &maxInputSize1)) { + setMinBufferSize(kPortIndexInput, (size_t)maxInputSize1); + } + return err; + } + } +#endif + status_t err = setComponentRole(encoder /* isEncoder */, mime); if (err != OK) { @@ -1482,7 +1586,8 @@ status_t ACodec::setSupportedOutputFormat() { || format.eColorFormat == OMX_COLOR_FormatCbYCrY || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar - || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka); + || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka + || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m ); return mOMX->setParameter( mNode, OMX_IndexParamVideoPortFormat, @@ -3146,9 +3251,33 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; AString mime; + uint32_t quirks = 0; +#ifdef QCOM_ENHANCED_AUDIO + msg->findString("mime", &mime); + + if(!(strcmp(mime.c_str(),"audio/x-ms-wma"))){ + mCodec->mQuirks = quirks; + mCodec->mOMX = omx; + + mCodec->mPortEOS[kPortIndexInput] = + mCodec->mPortEOS[kPortIndexOutput] = false; + + mCodec->mInputEOSResult = OK; + + { + sp<AMessage> notify = mCodec->mNotify->dup(); + notify->setInt32("what", ACodec::kWhatComponentAllocated); + notify->setString("componentName", mCodec->mComponentName.c_str()); + notify->post(); + } + + mCodec->changeState(mCodec->mLoadedState); + + return true; + } +#endif AString componentName; - uint32_t quirks = 0; if (msg->findString("componentName", &componentName)) { ssize_t index = matchingCodecs.add(); OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index); @@ -3173,7 +3302,6 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { 0, // flags &matchingCodecs); } - sp<CodecObserver> observer = new CodecObserver; IOMX::node_id node = NULL; @@ -3327,11 +3455,93 @@ bool ACodec::LoadedState::onConfigureComponent( const sp<AMessage> &msg) { ALOGV("onConfigureComponent"); - CHECK(mCodec->mNode != NULL); - AString mime; CHECK(msg->findString("mime", &mime)); +#ifdef QCOM_ENHANCED_AUDIO + if (!strcasecmp(mime.c_str(), "audio/x-ms-wma")){ + OMXClient client; + CHECK_EQ(client.connect(), (status_t)OK); + sp<IOMX> omx = client.interface(); + Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs; + AString componentName; + uint32_t quirks = 0; + int32_t version = -1; + + msg->findInt32("WMA-Version", &version); + if(kTypeWMA == version){ + componentName = "OMX.qcom.audio.decoder.wma"; + } else if(kTypeWMAPro == version){ + componentName = "OMX.qcom.audio.decoder.wma10Pro"; + } else if(kTypeWMALossLess == version){ + componentName = "OMX.qcom.audio.decoder.wmaLossLess"; + } else { + mCodec->signalError(OMX_ErrorComponentNotFound); + return false; + } + + int32_t encoder; + if (!msg->findInt32("encoder", &encoder)) { + encoder = false; + } + + OMXCodec::findMatchingCodecs( + mime.c_str(), + encoder, // createEncoder + componentName.c_str(), // matchComponentName + 0, // flags + &matchingCodecs); + + sp<CodecObserver> observer = new CodecObserver; + IOMX::node_id node = NULL; + + for (size_t matchIndex = 0; matchIndex < matchingCodecs.size(); + ++matchIndex) { + componentName = matchingCodecs.itemAt(matchIndex).mName.string(); + quirks = matchingCodecs.itemAt(matchIndex).mQuirks; + + pid_t tid = androidGetTid(); + int prevPriority = androidGetThreadPriority(tid); + androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND); + status_t err = omx->allocateNode(componentName.c_str(), observer, &node); + androidSetThreadPriority(tid, prevPriority); + + if (err == OK) { + break; + } + node = NULL; + } + if (node == NULL) { + if (!mime.empty()) { + ALOGE("Unable to instantiate a decoder for type '%s'.", + mime.c_str()); + } else { + ALOGE("Unable to instantiate decoder '%s'.", componentName.c_str()); + } + + mCodec->signalError(OMX_ErrorComponentNotFound); + return false; + } + sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id()); + observer->setNotificationMessage(notify); + + mCodec->mComponentName = componentName; + mCodec->mFlags = 0; + + if (componentName.endsWith(".secure")) { + mCodec->mFlags |= kFlagIsSecure; + } + + mCodec->mQuirks = quirks; + mCodec->mOMX = omx; + mCodec->mNode = node; + + mCodec->mPortEOS[kPortIndexInput] = + mCodec->mPortEOS[kPortIndexOutput] = false; + } +#endif + + CHECK(mCodec->mNode != NULL); status_t err = mCodec->configureCodec(mime.c_str(), msg); if (err != OK) { diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 193291e..766cf5e 100755 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -92,7 +92,8 @@ LOCAL_SRC_FILES += \ QCMediaDefs.cpp \ QCOMXCodec.cpp \ WAVEWriter.cpp \ - ExtendedExtractor.cpp + ExtendedExtractor.cpp \ + QCUtilityClass.cpp LOCAL_C_INCLUDES += \ $(TOP)/hardware/qcom/media/mm-core/inc diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index deb6b70..80b64c2 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -500,11 +500,11 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) { { Mutex::Autolock autoLock(mLock); mNumFramesPlayed += size_done / mFrameSize; - mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); if (mReachedEOS) { mPinnedTimeUs = mNumFramesPlayedSysTimeUs; } else { + mNumFramesPlayedSysTimeUs = ALooper::GetNowUs(); mPinnedTimeUs = -1ll; } } @@ -535,14 +535,21 @@ int64_t AudioPlayer::getRealTimeUsLocked() const { // compensate using system time. int64_t diffUs; if (mPinnedTimeUs >= 0ll) { - diffUs = mPinnedTimeUs; + if(mReachedEOS) + diffUs = ALooper::GetNowUs(); + else + diffUs = mPinnedTimeUs; + } else { diffUs = ALooper::GetNowUs(); } diffUs -= mNumFramesPlayedSysTimeUs; - return result + diffUs; + if(result + diffUs <= mPositionTimeRealUs) + return result + diffUs; + else + return mPositionTimeRealUs; } int64_t AudioPlayer::getMediaTimeUs() { diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index bb2d415..2bb721c 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 The Android Open Source Project - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,17 @@ #include <cutils/properties.h> #include <stdlib.h> -namespace android { +#ifdef QCOM_ENHANCED_AUDIO +#define AMR_FRAMESIZE 32 +#define QCELP_FRAMESIZE 35 +#define EVRC_FRAMESIZE 23 +#define AMR_WB_FRAMESIZE 61 +#endif +namespace android { +// Treat time out as an error if we have not received any output +// buffers after 1 seconds +const static int64_t WaitLockEventTimeOutNs = 1000000000LL; static void AudioRecordCallbackFunction(int event, void *user, void *info) { AudioSource *source = (AudioSource *) user; switch (event) { @@ -55,7 +64,13 @@ AudioSource::AudioSource( mSampleRate(sampleRate), mPrevSampleTimeUs(0), mNumFramesReceived(0), - mNumClientOwnedBuffers(0) { + mNumClientOwnedBuffers(0) +#ifdef QCOM_ENHANCED_AUDIO + ,mFormat(AUDIO_FORMAT_PCM_16_BIT), + mMime(MEDIA_MIMETYPE_AUDIO_RAW) +#endif +{ + ALOGV("sampleRate: %d, channelCount: %d", sampleRate, channelCount); CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6); @@ -64,10 +79,23 @@ AudioSource::AudioSource( sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount)); + +#ifdef QCOM_ENHANCED_AUDIO + if ( NO_ERROR != AudioSystem::getInputBufferSize( + sampleRate, mFormat, channelCount, (size_t*)&mMaxBufferSize) ) { + mMaxBufferSize = kMaxBufferSize; + ALOGV("mMaxBufferSize = %d", mMaxBufferSize); + } +#endif + if (status == OK) { // make sure that the AudioRecord callback never returns more than the maximum // buffer size +#ifdef QCOM_ENHANCED_AUDIO + int frameCount = mMaxBufferSize / sizeof(int16_t) / channelCount; +#else int frameCount = kMaxBufferSize / sizeof(int16_t) / channelCount; +#endif // make sure that the AudioRecord total buffer size is large enough int bufCount = 2; @@ -78,7 +106,11 @@ AudioSource::AudioSource( mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), +#ifdef QCOM_ENHANCED_AUDIO + 4 * mMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */ +#else bufCount * frameCount, +#endif AudioRecordCallbackFunction, this, frameCount); @@ -99,6 +131,62 @@ AudioSource::AudioSource( } } +#ifdef QCOM_ENHANCED_AUDIO +AudioSource::AudioSource( audio_source_t inputSource, const sp<MetaData>& meta ) + : mStarted(false), + mPrevSampleTimeUs(0), + mNumFramesReceived(0), + mNumClientOwnedBuffers(0), + mFormat(AUDIO_FORMAT_PCM_16_BIT), + mMime(MEDIA_MIMETYPE_AUDIO_RAW) { + + const char * mime; + ALOGE("SK: in AudioSource : inputSource: %d", inputSource); + CHECK( meta->findCString( kKeyMIMEType, &mime ) ); + mMime = mime; + int32_t sampleRate = 0; //these are the only supported values + int32_t channels = 0; //for the below tunnel formats + CHECK( meta->findInt32( kKeyChannelCount, &channels ) ); + CHECK( meta->findInt32( kKeySampleRate, &sampleRate ) ); + int32_t frameSize = -1; + mSampleRate = sampleRate; + if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_NB ) ) { + mFormat = AUDIO_FORMAT_AMR_NB; + frameSize = AMR_FRAMESIZE; + mMaxBufferSize = AMR_FRAMESIZE*10; + } + else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_QCELP ) ) { + mFormat = AUDIO_FORMAT_QCELP; + frameSize = QCELP_FRAMESIZE; + mMaxBufferSize = QCELP_FRAMESIZE*10; + } + else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_EVRC ) ) { + mFormat = AUDIO_FORMAT_EVRC; + frameSize = EVRC_FRAMESIZE; + mMaxBufferSize = EVRC_FRAMESIZE*10; + } + else if ( !strcasecmp( mime, MEDIA_MIMETYPE_AUDIO_AMR_WB ) ) { + mFormat = AUDIO_FORMAT_AMR_WB; + frameSize = AMR_WB_FRAMESIZE; + mMaxBufferSize = AMR_WB_FRAMESIZE*10; + } + else { + CHECK(0); + } + mAutoRampStartUs = 0; + CHECK(channels == 1 || channels == 2); + + mRecord = new AudioRecord( + inputSource, sampleRate, mFormat, + channels > 1? AUDIO_CHANNEL_IN_STEREO: + AUDIO_CHANNEL_IN_MONO, + 4*mMaxBufferSize/channels/frameSize, + AudioRecordCallbackFunction, + this); + mInitCheck = mRecord->initCheck(); +} +#endif + AudioSource::~AudioSource() { if (mStarted) { reset(); @@ -184,10 +272,17 @@ sp<MetaData> AudioSource::getFormat() { } sp<MetaData> meta = new MetaData; +#ifdef QCOM_ENHANCED_AUDIO + meta->setCString(kKeyMIMEType, mMime); + meta->setInt32(kKeySampleRate, mRecord->getSampleRate()); + meta->setInt32(kKeyChannelCount, mRecord->channelCount()); + meta->setInt32(kKeyMaxInputSize, mMaxBufferSize); +#else meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); meta->setInt32(kKeySampleRate, mSampleRate); meta->setInt32(kKeyChannelCount, mRecord->channelCount()); meta->setInt32(kKeyMaxInputSize, kMaxBufferSize); +#endif return meta; } @@ -234,7 +329,9 @@ status_t AudioSource::read( } while (mStarted && mBuffersReceived.empty()) { - mFrameAvailableCondition.wait(mLock); + status_t err = mFrameAvailableCondition.waitRelative(mLock,WaitLockEventTimeOutNs); + if(err == -ETIMEDOUT) + return (status_t)err; } if (!mStarted) { return OK; @@ -249,24 +346,33 @@ status_t AudioSource::read( int64_t timeUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); int64_t elapsedTimeUs = timeUs - mStartTimeUs; - if (elapsedTimeUs < mAutoRampStartUs) { - memset((uint8_t *) buffer->data(), 0, buffer->range_length()); - } else if (elapsedTimeUs < mAutoRampStartUs + kAutoRampDurationUs) { - int32_t autoRampDurationFrames = - (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; - - int32_t autoRampStartFrames = - (mAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; - - int32_t nFrames = mNumFramesReceived - autoRampStartFrames; - rampVolume(nFrames, autoRampDurationFrames, - (uint8_t *) buffer->data(), buffer->range_length()); +#ifdef QCOM_ENHANCED_AUDIO + if ( mFormat == AUDIO_FORMAT_PCM_16_BIT ) { +#endif + if (elapsedTimeUs < mAutoRampStartUs) { + memset((uint8_t *) buffer->data(), 0, buffer->range_length()); + } else if (elapsedTimeUs < mAutoRampStartUs + kAutoRampDurationUs) { + int32_t autoRampDurationFrames = + (kAutoRampDurationUs * mSampleRate + 500000LL) / 1000000LL; + + int32_t autoRampStartFrames = + (mAutoRampStartUs * mSampleRate + 500000LL) / 1000000LL; + + int32_t nFrames = mNumFramesReceived - autoRampStartFrames; + rampVolume(nFrames, autoRampDurationFrames, + (uint8_t *) buffer->data(), buffer->range_length()); + } +#ifdef QCOM_ENHANCED_AUDIO } +#endif // Track the max recording signal amplitude. if (mTrackMaxAmplitude) { - trackMaxAmplitude( - (int16_t *) buffer->data(), buffer->range_length() >> 1); +#ifdef QCOM_ENHANCED_AUDIO + if (mFormat == AUDIO_FORMAT_PCM_16_BIT) +#endif + trackMaxAmplitude( + (int16_t *) buffer->data(), buffer->range_length() >> 1); } *out = buffer; @@ -321,7 +427,9 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { } CHECK_EQ(numLostBytes & 1, 0u); +#ifndef QCOM_ENHANCED_AUDIO CHECK_EQ(audioBuffer.size & 1, 0u); +#endif if (numLostBytes > 0) { // Loss of audio frames should happen rarely; thus the LOGW should // not cause a logging spam @@ -359,19 +467,45 @@ status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) { void AudioSource::queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs) { const size_t bufferSize = buffer->range_length(); const size_t frameSize = mRecord->frameSize(); +#ifdef QCOM_ENHANCED_AUDIO + int64_t timestampUs = mPrevSampleTimeUs; + int64_t recordDurationUs = 0; + if ( mFormat == AUDIO_FORMAT_PCM_16_BIT ){ + recordDurationUs = ((1000000LL * (bufferSize / (2 * mRecord->channelCount()))) + + (mSampleRate >> 1)) / mSampleRate; + } else { + recordDurationUs = bufferDurationUs(bufferSize); + } + timestampUs += recordDurationUs; +#else const int64_t timestampUs = mPrevSampleTimeUs + ((1000000LL * (bufferSize / frameSize)) + (mSampleRate >> 1)) / mSampleRate; +#endif if (mNumFramesReceived == 0) { buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs); } buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); - buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs); +#ifdef QCOM_ENHANCED_AUDIO + if (mFormat == AUDIO_FORMAT_PCM_16_BIT) { +#endif + buffer->meta_data()->setInt64(kKeyDriftTime, timeUs - mInitialReadTimeUs); +#ifdef QCOM_ENHANCED_AUDIO + } else { + int64_t wallClockTimeUs = timeUs - mInitialReadTimeUs; + int64_t mediaTimeUs = mStartTimeUs + mPrevSampleTimeUs; + buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs); + } +#endif mPrevSampleTimeUs = timestampUs; +#ifdef QCOM_ENHANCED_AUDIO + mNumFramesReceived += buffer->range_length() / sizeof(int16_t); +#else mNumFramesReceived += bufferSize / frameSize; +#endif mBuffersReceived.push_back(buffer); mFrameAvailableCondition.signal(); } @@ -399,4 +533,27 @@ int16_t AudioSource::getMaxAmplitude() { return value; } +#ifdef QCOM_ENHANCED_AUDIO +int64_t AudioSource::bufferDurationUs( ssize_t n ) { + + int64_t dataDurationMs = 0; + if (mFormat == AUDIO_FORMAT_AMR_NB) { + dataDurationMs = (n/AMR_FRAMESIZE) * 20; //ms + } + else if (mFormat == AUDIO_FORMAT_EVRC) { + dataDurationMs = (n/EVRC_FRAMESIZE) * 20; //ms + } + else if (mFormat == AUDIO_FORMAT_QCELP) { + dataDurationMs = (n/QCELP_FRAMESIZE) * 20; //ms + } + else if (mFormat == AUDIO_FORMAT_AMR_WB) { + dataDurationMs = (n/AMR_WB_FRAMESIZE) * 20; //ms + } + + else + CHECK(0); + + return dataDurationMs*1000LL; +} +#endif } // namespace android diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index c68b476..ad221d1 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -57,6 +57,9 @@ #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXCodec.h> +#ifdef QCOM_HARDWARE +#include "include/QCUtilityClass.h" +#endif #include <gui/ISurfaceTexture.h> #include <gui/SurfaceTextureClient.h> @@ -255,6 +258,46 @@ AwesomePlayer::~AwesomePlayer() { mClient.disconnect(); } +void AwesomePlayer::printStats() { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.sf.statistics", value, "0"); + if (atoi(value) && mVideoSource != NULL) { + ALOGE("===========================\n" + " videoDimensions(%d x %d)\n" + " Total Video Frames Decoded(%lld)\n" + " Total Video Frames Rendered(%lld)\n" + " Total Playback Duration(%lld ms)\n" + " numVideoFramesDropped(%lld)\n" + " Average Frames Per Second(%.4f)\n" + " Last Seek To Time(%lld ms)\n" + " Last Paused Time(%lld ms)\n" + " First Frame Latency (%lld ms)\n" + " Number of times AV Sync Lost(%u)\n" + " Max Video Ahead Time Delta(%u)\n" + " Max Video Behind Time Delta(%u)\n" + " Max Time Sync Loss(%u)\n" + " EOS(%d)\n" + " PLAYING(%d)\n" + "===========================\n\n", + mStats.mVideoWidth, + mStats.mVideoHeight, + mStats.mNumVideoFramesDecoded, + mStats.mTotalFrames, + mStats.mTotalTimeUs/1000, + mStats.mNumVideoFramesDropped, + mStats.mTotalTimeUs > 0 ? ((double)(mStats.mTotalFrames)*1E6)/((double)mStats.mTotalTimeUs) : 0, + mStats.mLastSeekToTimeMs, + mStats.mLastPausedTimeMs, + mStats.mFirstFrameLatencyUs/1000, + mStats.mNumTimesSyncLoss, + -mStats.mMaxEarlyDelta/1000, + mStats.mMaxLateDelta/1000, + mStats.mMaxTimeSyncLoss/1000, + (mFlags & VIDEO_AT_EOS) > 0, + (mFlags & PLAYING) > 0); + } +} + void AwesomePlayer::cancelPlayerEvents(bool keepNotifications) { mQueue.cancelEvent(mVideoEvent->eventID()); mVideoEventPending = false; @@ -448,7 +491,11 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) { &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex); stat->mMIME = mime.string(); } - } else if (!haveAudio && !strncasecmp(mime.string(), "audio/", 6)) { + } else if (!haveAudio && +#ifdef QCOM_HARDWARE + !QCUtilityClass::helper_Awesomeplayer_checkIfAudioDisable() && +#endif + !strncasecmp(mime.string(), "audio/", 6)) { setAudioSource(extractor->getTrack(i)); haveAudio = true; mActiveAudioTrackIndex = i; @@ -573,6 +620,8 @@ void AwesomePlayer::reset_l() { mVideoRenderer.clear(); + modifyFlags(PLAYING, CLEAR); + printStats(); if (mVideoSource != NULL) { shutdownVideoDecoder_l(); } @@ -1039,7 +1088,7 @@ status_t AwesomePlayer::play_l() { // We don't want to post an error notification at this point, // the error returned from MediaPlayer::start() will suffice. bool sendErrorNotification = false; -#ifdef IS_TUNNEL_MODE +#ifdef USE_TUNNEL_MODE if(mIsTunnelAudio) { // For tunnel Audio error has to be posted to the client sendErrorNotification = true; @@ -1080,6 +1129,7 @@ status_t AwesomePlayer::play_l() { if (mAudioSource != NULL && mVideoSource != NULL) { postVideoLagEvent_l(); } + printStats(); } if (mFlags & AT_EOS) { @@ -1296,9 +1346,10 @@ status_t AwesomePlayer::pause_l(bool at_eos) { Playback::PAUSE, 0); } - if(!(mFlags & AT_EOS)){ + if(!(mFlags & VIDEO_AT_EOS)){ Mutex::Autolock autoLock(mStatsLock); mStats.mLastPausedTimeMs = mVideoTimeUs/1000; + printStats(); } uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder; @@ -1832,6 +1883,7 @@ void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) { mStats.mLastSeekToTimeMs = mSeekTimeUs/1000; logFirstFrame(); } + printStats(); } void AwesomePlayer::onVideoEvent() { diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp index 9f63ec0..f7d452b 100755 --- a/media/libstagefright/CameraSource.cpp +++ b/media/libstagefright/CameraSource.cpp @@ -30,7 +30,10 @@ #include <gui/Surface.h> #include <utils/String8.h> #include <cutils/properties.h> - +#ifdef QCOM_HARDWARE +#include "include/QCUtilityClass.h" +#include <QCMetaData.h> +#endif #ifdef USE_TI_CUSTOM_DOMX #include <OMX_TI_IVCommon.h> #endif @@ -569,6 +572,11 @@ status_t CameraSource::initWithCameraAccess( mMeta->setInt32(kKeyStride, mVideoSize.width); mMeta->setInt32(kKeySliceHeight, mVideoSize.height); mMeta->setInt32(kKeyFrameRate, mVideoFrameRate); + +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_CameraSource_hfr(params, mMeta); +#endif + return OK; } diff --git a/media/libstagefright/LPAPlayerALSA.cpp b/media/libstagefright/LPAPlayerALSA.cpp index 0aa419c..e2f30ed 100644 --- a/media/libstagefright/LPAPlayerALSA.cpp +++ b/media/libstagefright/LPAPlayerALSA.cpp @@ -51,10 +51,9 @@ static const char mName[] = "LPAPlayer"; -#define MEM_PADDING 64 -#define MEM_BUFFER_SIZE (256*1024) +#define MEM_METADATA_SIZE 64 +#define MEM_BUFFER_SIZE ((256*1024) - MEM_METADATA_SIZE) #define MEM_BUFFER_COUNT 4 - #define PCM_FORMAT 2 #define NUM_FDS 2 #define LPA_BUFFER_TIME 1500000 diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 6d1f8c6..04b508b 100755 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -40,6 +40,10 @@ #include "include/ESDS.h" +#ifdef QCOM_HARDWARE +#include "include/QCUtilityClass.h" +#endif + namespace android { static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024; @@ -2161,6 +2165,12 @@ status_t MPEG4Writer::Track::threadEntry() { meta_data->findInt32(kKeyIsSyncFrame, &isSync); CHECK(meta_data->findInt64(kKeyTime, ×tampUs)); +#ifdef QCOM_HARDWARE + if(!mIsAudio) { + QCUtilityClass::helper_MPEG4Writer_hfr(mMeta, timestampUs); + } +#endif + //////////////////////////////////////////////////////////////////////////////// if (mStszTableEntries->count() == 0) { mFirstSampleTimeRealUs = systemTime() / 1000; @@ -2190,6 +2200,10 @@ status_t MPEG4Writer::Track::threadEntry() { */ int64_t decodingTimeUs; CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs)); +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_MPEG4Writer_hfr(mMeta, decodingTimeUs); +#endif + decodingTimeUs -= previousPausedDurationUs; cttsOffsetTimeUs = timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs; diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp index d24337f..f815ec9 100644 --- a/media/libstagefright/MediaCodecList.cpp +++ b/media/libstagefright/MediaCodecList.cpp @@ -28,6 +28,10 @@ #include <libexpat/expat.h> +#ifdef QCOM_HARDWARE +#include "include/QCUtilityClass.h" +#endif + namespace android { static Mutex sInitMutex; @@ -64,6 +68,14 @@ MediaCodecList::MediaCodecList() addMediaCodec( false /* encoder */, "OMX.google.raw.decoder", "audio/raw"); + +#ifdef QCOM_HARDWARE + Vector<AString> QcomAACQuirks; + QcomAACQuirks.push(AString("requires-allocate-on-input-ports")); + QcomAACQuirks.push(AString("requires-allocate-on-output-ports")); + QCUtilityClass::helper_addMediaCodec(mCodecInfos, mTypes, false, "OMX.qcom.audio.decoder.multiaac", + "audio/mp4a-latm", QCUtilityClass::helper_getCodecSpecificQuirks(mCodecQuirks, QcomAACQuirks)); +#endif } #if 0 diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp index 1eb5c19..33e526a 100644 --- a/media/libstagefright/MediaExtractor.cpp +++ b/media/libstagefright/MediaExtractor.cpp @@ -35,6 +35,7 @@ #include "include/AACExtractor.h" #ifdef QCOM_HARDWARE #include "include/ExtendedExtractor.h" +#include "include/QCUtilityClass.h" #endif #include "matroska/MatroskaExtractor.h" @@ -60,7 +61,6 @@ uint32_t MediaExtractor::flags() const { sp<MediaExtractor> MediaExtractor::Create( const sp<DataSource> &source, const char *mime) { sp<AMessage> meta; - bool bCheckExtendedExtractor = false; String8 tmp; if (mime == NULL) { @@ -107,9 +107,6 @@ sp<MediaExtractor> MediaExtractor::Create( } else { ret = new MPEG4Extractor(source); } -#ifdef QCOM_ENHANCED_AUDIO - bCheckExtendedExtractor = true; -#endif } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { ret = new MP3Extractor(source, meta); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB) @@ -147,49 +144,13 @@ sp<MediaExtractor> MediaExtractor::Create( } #ifdef QCOM_HARDWARE - //If default extractor created and flag is not set to check extended extractor, - // then pass default extractor. - if (ret && (!bCheckExtendedExtractor) ) { - ALOGD("returning default extractor"); - return ret; - } - - //Create Extended Extractor only if default extractor are not selected - ALOGV("Using ExtendedExtractor"); - sp<MediaExtractor> retextParser = ExtendedExtractor::CreateExtractor(source, mime); - //if we came here, it means we do not have to use the default extractor, if created above. - bool bUseDefaultExtractor = false; - - if(bCheckExtendedExtractor) { - ALOGV("bCheckExtendedExtractor is true"); - //bCheckExtendedExtractor is true which means default extractor was found - // but we want to give preference to extended extractor based on certain - // codec type.Set bUseDefaultExtractor to true if extended extractor - //does not return specific codec type that we are looking for. - bUseDefaultExtractor = true; - ALOGV(" bCheckExtendedExtractor is true..checking extended extractor"); - for (size_t i = 0; (retextParser!=NULL) && (i < retextParser->countTracks()); ++i) { - sp<MetaData> meta = retextParser->getTrackMetaData(i); - const char *mime; - bool success = meta->findCString(kKeyMIMEType, &mime); - if( (success == true) && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) { - ALOGV("Discarding default extractor and using the extended one"); - //We found what we were looking for, set bUseDefaultExtractor to false; - bUseDefaultExtractor = false; - if(ret) { - //delete the default extractor as we will be using extended extractor.. - delete ret; - } - break; - } - } - } - if( (retextParser != NULL) && (!bUseDefaultExtractor) ) { - ALOGV("returning retextParser"); - return retextParser; - } -#endif + //ret will get deleted within if replaced + return QCUtilityClass::helper_MediaExtractor_CreateIfNeeded(ret, + source, + mime); +#else return ret; +#endif } } // namespace android diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index b8b3ec4..26cae65 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -52,7 +52,9 @@ #include <QCMetaData.h> #include <QOMX_AudioExtensions.h> #include <OMX_QCOMExtns.h> +#include "include/QCUtilityClass.h" #endif + #include "include/avc_utils.h" #ifdef USE_SAMSUNG_COLORFORMAT @@ -415,7 +417,14 @@ sp<MediaSource> OMXCodec::Create( CHECK(success); Vector<CodecNameAndQuirks> matchingCodecs; - findMatchingCodecs( + +#ifdef QCOM_HARDWARE + if (QCOMXCodec::useHWAACDecoder(mime)) { + findMatchingCodecs(mime, createEncoder, + "OMX.qcom.audio.decoder.multiaac", flags, &matchingCodecs); + } else +#endif + findMatchingCodecs( mime, createEncoder, matchComponentName, flags, &matchingCodecs); if (matchingCodecs.isEmpty()) { @@ -1054,6 +1063,11 @@ void OMXCodec::setVideoInputFormat( CHECK(success); CHECK(stride != 0); +#ifdef QCOM_HARDWARE + int32_t newFrameRate = frameRate; + QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate); +#endif + OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused; if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) { compressionFormat = OMX_VIDEO_CodingAVC; @@ -1288,7 +1302,11 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) { h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; - h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate); + int32_t newFrameRate = frameRate; +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate); +#endif + h263type.nPFrames = setPFramesSpacing(iFramesInterval, newFrameRate); if (h263type.nPFrames == 0) { h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; } @@ -1339,7 +1357,11 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; - mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate); + int32_t newFrameRate = frameRate; +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate); +#endif + mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, newFrameRate); if (mpeg4type.nPFrames == 0) { mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; } @@ -1360,6 +1382,9 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) { mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile); mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel); +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_OMXCodec_setBFrames(mpeg4type, mNumBFrames); +#endif err = mOMX->setParameter( mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type)); CHECK_EQ(err, (status_t)OK); @@ -1397,7 +1422,12 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile); h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel); - // XXX + int32_t newFrameRate = frameRate; +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_OMXCodec_hfr(meta, frameRate, bitRate, newFrameRate); +#endif + +#ifndef QCOM_HARDWARE #ifdef USE_TI_DUCATI_H264_PROFILE if ((strncmp(mComponentName, "OMX.TI.DUCATI1", 14) != 0) && (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline)) { @@ -1405,19 +1435,22 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) { #endif ALOGW("Use baseline profile instead of %d for AVC recording", - h264type.eProfile); + h264type.eProfile); h264type.eProfile = OMX_VIDEO_AVCProfileBaseline; } +#endif if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) { h264type.nSliceHeaderSpacing = 0; h264type.bUseHadamard = OMX_TRUE; h264type.nRefFrames = 1; h264type.nBFrames = 0; +#ifndef QCOM_HARDWARE h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate); if (h264type.nPFrames == 0) { h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; } +#endif h264type.nRefIdx10ActiveMinus1 = 0; h264type.nRefIdx11ActiveMinus1 = 0; h264type.bEntropyCodingCABAC = OMX_FALSE; @@ -1428,6 +1461,12 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) { h264type.nCabacInitIdc = 0; } +#ifdef QCOM_HARDWARE + QCUtilityClass::helper_OMXCodec_setBFrames(h264type, + mNumBFrames, + iFramesInterval, + newFrameRate); +#endif if (h264type.nBFrames != 0) { h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; } @@ -1509,6 +1548,7 @@ status_t OMXCodec::setVideoOutputFormat( || format.eColorFormat == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka + || format.eColorFormat == OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m #ifdef USE_SAMSUNG_COLORFORMAT || format.eColorFormat == OMX_SEC_COLOR_FormatNV12TPhysicalAddress || format.eColorFormat == OMX_SEC_COLOR_FormatNV12Tiled @@ -1653,7 +1693,11 @@ OMXCodec::OMXCodec( mNativeWindow( (!strncmp(componentName, "OMX.google.", 11) || !strcmp(componentName, "OMX.Nvidia.mpeg2v.decode")) - ? NULL : nativeWindow) { + ? NULL : nativeWindow) +#ifdef QCOM_HARDWARE + ,mNumBFrames(0) +#endif +{ mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; @@ -2152,6 +2196,15 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() { return err; } +#ifdef QCOM_BSP + err = mNativeWindow.get()->perform(mNativeWindow.get(), + NATIVE_WINDOW_SET_BUFFERS_SIZE, def.nBufferSize); + if (err != 0) { + ALOGE("native_window_set_buffers_size failed: %s (%d)", strerror(-err), + -err); + return err; + } +#endif CODEC_LOGV("allocating %lu buffers from a native window of size %lu on " "output port", def.nBufferCountActual, def.nBufferSize); @@ -3028,13 +3081,30 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) { mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexOutput] = ENABLED; - if ((mFlags & kEnableGrallocUsageProtected) && - mNativeWindow != NULL) { - // We push enough 1x1 blank buffers to ensure that one of - // them has made it to the display. This allows the OMX - // component teardown to zero out any protected buffers - // without the risk of scanning out one of those buffers. - pushBlankBuffersToNativeWindow(); + if (mNativeWindow != NULL) { +#ifdef QCOM_BSP + /* + * reset buffer size field with SurfaceTexture + * back to 0. This will ensure proper size + * buffers are allocated if the same SurfaceTexture + * is re-used in a different decode session + */ + int err = + mNativeWindow.get()->perform(mNativeWindow.get(), + NATIVE_WINDOW_SET_BUFFERS_SIZE, + 0); + if (err != 0) { + ALOGE("set_buffers_size failed: %s (%d)", strerror(-err), + -err); + } +#endif + if (mFlags & kEnableGrallocUsageProtected) { + // We push enough 1x1 blank buffers to ensure that one of + // them has made it to the display. This allows the OMX + // component teardown to zero out any protected buffers + // without the risk of scanning out one of those buffers. + pushBlankBuffersToNativeWindow(); + } } setState(IDLE_TO_LOADED); @@ -3305,7 +3375,10 @@ void OMXCodec::drainInputBuffers() { } if (mFlags & kOnlySubmitOneInputBufferAtOneTime) { - break; +#ifdef QCOM_HARDWARE + if (i == mNumBFrames) +#endif + break; } } } @@ -3757,6 +3830,9 @@ void OMXCodec::setRawAudioFormat( OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = portIndex; +#ifdef QCOM_ENHANCED_AUDIO + def.format.audio.cMIMEType = NULL; +#endif status_t err = mOMX->getParameter( mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); CHECK_EQ(err, (status_t)OK); @@ -5235,6 +5311,10 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { if (mNativeWindow != NULL) { initNativeWindowCrop(); } +#ifdef QCOM_HARDWARE + } else { + QCUtilityClass::helper_OMXCodec_hfr(inputFormat, mOutputFormat); +#endif } break; } diff --git a/media/libstagefright/QCOMXCodec.cpp b/media/libstagefright/QCOMXCodec.cpp index fcc57f2..a2f3b35 100644 --- a/media/libstagefright/QCOMXCodec.cpp +++ b/media/libstagefright/QCOMXCodec.cpp @@ -30,6 +30,7 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "QCOMXCodec" #include <utils/Log.h> +#include <cutils/properties.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MediaDefs.h> @@ -593,7 +594,7 @@ void QCOMXCodec::setQCSpecificVideoFormat(const sp<MetaData> &meta, sp<IOMX> OMX void QCOMXCodec::checkIfInterlaced(const uint8_t *ptr, const sp<MetaData> &meta) { uint16_t spsSize = (((uint16_t)ptr[6]) << 8) + (uint16_t)(ptr[7]); - int32_t width = 0, height = 0, isInterlaced = 0; + int32_t width = 0, height = 0, isInterlaced = 1; const uint8_t *spsStart = &ptr[8]; sp<ABuffer> seqParamSet = new ABuffer(spsSize); @@ -607,4 +608,14 @@ void QCOMXCodec::checkIfInterlaced(const uint8_t *ptr, const sp<MetaData> &meta) return; } +bool QCOMXCodec::useHWAACDecoder(const char *mime) { + char value[PROPERTY_VALUE_MAX]; + int aaccodectype = property_get("media.aaccodectype", value, NULL); + if (!strcmp("0", value) && aaccodectype && !strcmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { + ALOGI("Using Hardware AAC Decoder"); + return true; + } + return false; +} + } diff --git a/media/libstagefright/QCUtilityClass.cpp b/media/libstagefright/QCUtilityClass.cpp new file mode 100644 index 0000000..1efc040 --- /dev/null +++ b/media/libstagefright/QCUtilityClass.cpp @@ -0,0 +1,356 @@ +/*Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +//#define LOG_NDEBUG 0 +#define LOG_TAG "QCUtilClass" +#include <utils/Log.h> + +#include <include/QCUtilityClass.h> +#include "include/ExtendedExtractor.h" +#include <media/stagefright/MetaData.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/OMXCodec.h> + +namespace android { + +//-- START :: HFR Related Changes ----- + +status_t QCUtilityClass::helper_StageFrightRecoder_hfr(sp<MetaData> &meta, sp<MetaData> &enc_meta, + int64_t &maxFileDurationUs, int32_t frameRate, + video_encoder videoEncoder) { + status_t retVal = OK; + int32_t hfr = 0; + + if (!meta->findInt32(kKeyHFR, &hfr)) { + ALOGW("hfr not found, default to 0"); + } + + if (hfr && frameRate) { + maxFileDurationUs = maxFileDurationUs * (hfr/frameRate); + } + + enc_meta->setInt32(kKeyHFR, hfr); + int32_t width = 0, height = 0; + + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + + char mDeviceName[100]; + property_get("ro.board.platform",mDeviceName,"0"); + if (!strncmp(mDeviceName, "msm7627a", 8)) { + if (hfr && (width * height > 432*240)) { + ALOGE("HFR mode is supported only upto WQVGA resolution"); + return INVALID_OPERATION; + } + } else { + if(hfr && ((videoEncoder != VIDEO_ENCODER_H264) || (width * height > 800*480))) { + ALOGE("HFR mode is supported only upto WVGA and H264 codec."); + return INVALID_OPERATION; + } + } + return retVal; +} + +void QCUtilityClass::helper_CameraSource_hfr(const CameraParameters& params, + sp<MetaData> &meta) { + const char *hfr_str = params.get("video-hfr"); + int32_t hfr = -1; + + if (hfr_str != NULL) { + hfr = atoi(hfr_str); + } + if (hfr < 0) { + ALOGW("Invalid hfr value(%d) set from app. Disabling HFR.", hfr); + hfr = 0; + } + meta->setInt32(kKeyHFR, hfr); +} + +void QCUtilityClass::helper_MPEG4Writer_hfr(sp<MetaData> &meta, + int64_t ×tampUs) { + int32_t frameRate = 0, hfr = 0, multiple = 0; + + if (!(meta->findInt32(kKeyFrameRate, &frameRate))) { + return; + } + + if (!(meta->findInt32(kKeyHFR, &hfr))) { + return; + } + + multiple = hfr ? (hfr/frameRate) : 1; + timestampUs = multiple * timestampUs; +} + +void QCUtilityClass::helper_OMXCodec_hfr(const sp<MetaData> &meta, + int32_t &frameRate, + int32_t &bitRate, + int32_t &newFrameRate) { + int32_t hfr = 0, hfrRatio = 0; + if (!(meta->findInt32(kKeyHFR, &hfr))) { + return; + } + + hfrRatio = hfr ? hfr/frameRate : 1; + frameRate = hfr?hfr:frameRate; + bitRate = hfr ? (hfrRatio*bitRate) : bitRate; + newFrameRate = frameRate / hfrRatio; +} + +void QCUtilityClass::helper_OMXCodec_hfr(const sp<MetaData> &inputFormat, + sp<MetaData> &outputFormat) { + int32_t frameRate = 0, hfr = 0; + inputFormat->findInt32(kKeyHFR, &hfr); + inputFormat->findInt32(kKeyFrameRate, &frameRate); + outputFormat->setInt32(kKeyHFR, hfr); + outputFormat->setInt32(kKeyFrameRate, frameRate); +} + +//-- END :: HFR related changes ----- + + +//-- START :: AUDIO disable and change in profile base on property ----- + +bool QCUtilityClass::helper_Awesomeplayer_checkIfAudioDisable() { + bool retVal = false; + char disableAudio[PROPERTY_VALUE_MAX]; + property_get("persist.debug.sf.noaudio", disableAudio, "0"); + if (atoi(disableAudio) == 1) { + retVal = true; + } + return retVal; +} + +bool QCUtilityClass::helper_StagefrightRecoder_checkIfAudioDisable() { + bool retVal = false; + char disableAudio[PROPERTY_VALUE_MAX]; + property_get("camcorder.debug.disableaudio", disableAudio, "0"); + if (atoi(disableAudio) == 1) { + retVal = true; + } + return retVal; +} + +void QCUtilityClass::helper_StagefrightRecoder_setUserprofile(video_encoder &videoEncoder, + int32_t &videoEncoderProfile) { + char value[PROPERTY_VALUE_MAX]; + bool customProfile = false; + if (!property_get("encoder.video.profile", value, NULL) > 0) { + return; + } + + switch (videoEncoder) { + case VIDEO_ENCODER_H264: + if (strncmp("base", value, 4) == 0) { + videoEncoderProfile = OMX_VIDEO_AVCProfileBaseline; + ALOGI("H264 Baseline Profile"); + } else if (strncmp("main", value, 4) == 0) { + videoEncoderProfile = OMX_VIDEO_AVCProfileMain; + ALOGI("H264 Main Profile"); + } else if (strncmp("high", value, 4) == 0) { + videoEncoderProfile = OMX_VIDEO_AVCProfileHigh; + ALOGI("H264 High Profile"); + } else { + ALOGW("Unsupported H264 Profile"); + } + break; + case VIDEO_ENCODER_MPEG_4_SP: + if (strncmp("simple", value, 5) == 0 ) { + videoEncoderProfile = OMX_VIDEO_MPEG4ProfileSimple; + ALOGI("MPEG4 Simple profile"); + } else if (strncmp("asp", value, 3) == 0 ) { + videoEncoderProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; + ALOGI("MPEG4 Advanced Simple Profile"); + } else { + ALOGW("Unsupported MPEG4 Profile"); + } + break; + default: + ALOGW("No custom profile support for other codecs"); + break; + } +} + +void QCUtilityClass::helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, + bool &numBFrames) { + if (mpeg4type.eProfile > OMX_VIDEO_MPEG4ProfileSimple) { + mpeg4type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; + mpeg4type.nBFrames = 1; + mpeg4type.nPFrames /= (mpeg4type.nBFrames + 1); + numBFrames = mpeg4type.nBFrames; + } + return; +} + +void QCUtilityClass::helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_AVCTYPE &h264type, + bool &numBFrames, + int32_t iFramesInterval, + int32_t frameRate) { + OMX_U32 val = 0; + if (iFramesInterval < 0) { + val = 0xFFFFFFFF; + } else if (iFramesInterval == 0) { + val = 0; + } else { + val = frameRate * iFramesInterval - 1; + CHECK(val > 1); + } + + h264type.nPFrames = val; + + if (h264type.nPFrames == 0) { + h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI; + } + + if (h264type.eProfile > OMX_VIDEO_AVCProfileBaseline) { + h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB; + h264type.nBFrames = 1; + h264type.nPFrames /= (h264type.nBFrames + 1); + numBFrames = h264type.nBFrames; + } + return; +} +//-- END :: AUDIO disable and change in profile base on property ----- +void QCUtilityClass::helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos, + KeyedVector<AString, size_t> &mTypes, + bool encoder, const char *name, + const char *type, uint32_t quirks) { + mCodecInfos.push(); + MediaCodecList::CodecInfo *info = &mCodecInfos.editItemAt(mCodecInfos.size() - 1); + info->mName = name; + info->mIsEncoder = encoder; + ssize_t index = mTypes.indexOfKey(type); + uint32_t bit = mTypes.valueAt(index); + info->mTypes |= 1ul << bit; + info->mQuirks = quirks; +} + +uint32_t QCUtilityClass::helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks, + Vector<AString> quirks) { + size_t i = 0, numQuirks = quirks.size(); + uint32_t bit = 0, value = 0; + for (i = 0; i < numQuirks; i++) + { + ssize_t index = mCodecQuirks.indexOfKey(quirks.itemAt(i)); + bit = mCodecQuirks.valueAt(index); + value |= 1ul << bit; + } + return value; +} + +//- returns NULL if we dont really need a new extractor (or cannot), +// valid extractor is returned otherwise +//- caller needs to check for NULL +// defaultExt - the existing extractor +// source - file source +// mime - container mime +// Note that defaultExt will be deleted in this function if the new parser is taken +sp<MediaExtractor> QCUtilityClass::helper_MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt, + const sp<DataSource> &source, + const char *mime) { + bool bCheckExtendedExtractor = false; + bool videoOnly = true; + bool amrwbAudio = false; + if (defaultExt != NULL) { + for (size_t i = 0; i < defaultExt->countTracks(); ++i) { + sp<MetaData> meta = defaultExt->getTrackMetaData(i); + const char *_mime; + CHECK(meta->findCString(kKeyMIMEType, &_mime)); + + String8 mime = String8(_mime); + + if (!strncasecmp(mime.string(), "audio/", 6)) { + videoOnly = false; + + amrwbAudio = !strncasecmp(mime.string(), + MEDIA_MIMETYPE_AUDIO_AMR_WB, + strlen(MEDIA_MIMETYPE_AUDIO_AMR_WB)); + if (amrwbAudio) break; + } + } + bCheckExtendedExtractor = videoOnly || amrwbAudio; + } else { + bCheckExtendedExtractor = true; + } + + if (!bCheckExtendedExtractor) { + ALOGD("extended extractor not needed, return default"); + return defaultExt; + } + + sp<MediaExtractor> retextParser; + + //Create Extended Extractor only if default extractor are not selected + ALOGD("Try creating ExtendedExtractor"); + retextParser = ExtendedExtractor::CreateExtractor(source, mime); + + if (retextParser == NULL) { + ALOGD("Couldn't create the extended extractor, return default one"); + return defaultExt; + } + + if (defaultExt == NULL) { + ALOGD("default one is NULL, return extended extractor"); + return retextParser; + } + + //bCheckExtendedExtractor is true which means default extractor was found + //but we want to give preference to extended extractor based on certain + //conditions. + + //needed to prevent a leak in case both extractors are valid + //but we still dont want to use the extended one. we need + //to delete the new one + bool bUseDefaultExtractor = true; + + for (size_t i = 0; (i < retextParser->countTracks()); ++i) { + sp<MetaData> meta = retextParser->getTrackMetaData(i); + const char *mime; + bool success = meta->findCString(kKeyMIMEType, &mime); + if ((success == true) && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)) { + ALOGD("Discarding default extractor and using the extended one"); + bUseDefaultExtractor = false; + break; + } + } + + if (bUseDefaultExtractor) { + ALOGD("using default extractor inspite of having a new extractor"); + retextParser.clear(); + return defaultExt; + } else { + defaultExt.clear(); + return retextParser; + } +} + +} diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp index d9858d7..4a42a70 100644 --- a/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/SampleTable.cpp @@ -360,8 +360,9 @@ status_t SampleTable::setCompositionTimeToSampleParams( return ERROR_IO; } - if (U32_AT(header) != 0) { - // Expected version = 0, flags = 0. + if (U32_AT(header) != 0 && + U32_AT(header) != 0x01000000) { + // Expected version = 0/1, flags = 0. return ERROR_MALFORMED; } diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 74e9222..7bd2032 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -28,6 +28,17 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> +#ifdef QCOM_ENHANCED_AUDIO +#include <QCMediaDefs.h> +#include <QCMetaData.h> +#include <QOMX_AudioExtensions.h> +#include <OMX_QCOMExtns.h> +#include "include/avc_utils.h" + +#include "include/QCUtilityClass.h" +#endif + + namespace android { uint16_t U16_AT(const uint8_t *ptr) { @@ -111,6 +122,46 @@ status_t convertMetaDataToMessage( if (meta->findInt32(kKeyIsADTS, &isADTS)) { msg->setInt32("is-adts", true); } +#ifdef QCOM_ENHANCED_AUDIO + int32_t keyWMAVersion; + if (meta->findInt32(kKeyWMAVersion, &keyWMAVersion)) { + msg->setInt32("WMA-Version", keyWMAVersion); + } + int32_t bitRate; + int32_t encodeOptions; + int32_t blockAlign; + int32_t bitspersample; + int32_t formattag; + int32_t advencopt1; + int32_t advencopt2; + int32_t VirtualPktSize; + + if (meta->findInt32(kKeyWMABitspersample, &bitspersample)) { + msg->setInt32("bsps", bitspersample); + } + if (meta->findInt32(kKeyWMAFormatTag, &formattag)) { + msg->setInt32("fmtt", formattag); + } + if (meta->findInt32(kKeyWMAAdvEncOpt1, &advencopt1)) { + msg->setInt32("ade1", advencopt1); + } + + if (meta->findInt32(kKeyWMAAdvEncOpt2, &advencopt2)) { + msg->setInt32("ade2", advencopt2); + } + if (meta->findInt32(kKeyWMAVirPktSize, &VirtualPktSize)) { + msg->setInt32("vpks", VirtualPktSize); + } + if (meta->findInt32(kKeyBitRate, &bitRate)) { + msg->setInt32("brte", bitRate); + } + if (meta->findInt32(kKeyWMAEncodeOpt, &encodeOptions)) { + msg->setInt32("eopt", encodeOptions); + } + if (meta->findInt32(kKeyWMABlockAlign, &blockAlign)) { + msg->setInt32("blka", blockAlign); + } +#endif } int32_t maxInputSize; diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp index a38400b..2640319 100644 --- a/media/libstagefright/WAVExtractor.cpp +++ b/media/libstagefright/WAVExtractor.cpp @@ -192,8 +192,8 @@ status_t WAVExtractor::init() { mNumChannels = U16_LE_AT(&formatSpec[2]); if (mWaveFormat != WAVE_FORMAT_EXTENSIBLE) { - if (mNumChannels != 1 && mNumChannels != 2) { - ALOGW("More than 2 channels (%d) in non-WAVE_EXT, unknown channel mask", + if (mNumChannels != 1 && mNumChannels != 2 && mNumChannels != 4) { + ALOGW("More than 4 channels (%d) in non-WAVE_EXT, unknown channel mask", mNumChannels); } } else { @@ -271,6 +271,10 @@ status_t WAVExtractor::init() { if (mValidFormat) { mDataOffset = offset; mDataSize = chunkSize; + off64_t dataSourceSize = 0; + + if (OK == mDataSource->getSize(&dataSourceSize) && mDataSize > (dataSourceSize - offset)) + mDataSize = dataSourceSize - offset; mTrackMeta = new MetaData; diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp index fbe98f1..7bfa375 100644 --- a/media/libstagefright/avc_utils.cpp +++ b/media/libstagefright/avc_utils.cpp @@ -60,7 +60,11 @@ void FindAVCDimensions( parseUE(&br); // bit_depth_luma_minus8 parseUE(&br); // bit_depth_chroma_minus8 br.skipBits(1); // qpprime_y_zero_transform_bypass_flag - CHECK_EQ(br.getBits(1), 0u); // seq_scaling_matrix_present_flag + bool seq_scaling_matrix_present = (br.getBits(1) != 0u); + if (isInterlaced != NULL && seq_scaling_matrix_present) { + return; + } + CHECK_EQ(seq_scaling_matrix_present, false); // seq_scaling_matrix_present_flag } parseUE(&br); // log2_max_frame_num_minus4 @@ -128,11 +132,11 @@ void FindAVCDimensions( (frame_crop_left_offset + frame_crop_right_offset) * cropUnitX; *height -= (frame_crop_top_offset + frame_crop_bottom_offset) * cropUnitY; - - if (isInterlaced != NULL) { - *isInterlaced = !frame_mbs_only_flag; - } } + if (isInterlaced != NULL) { + *isInterlaced = !frame_mbs_only_flag; + } + } status_t getNextNALUnit( diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index d88813e..606a43d 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -358,9 +358,13 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { inInfo->mOwnedByUs = false; notifyEmptyBufferDone(inHeader); - if (!mIsFirst) { + if (!mIsFirst || mInputBufferCount) { // flush out the decoder's delayed data by calling DecodeFrame // one more time, with the AACDEC_FLUSH flag set + + // for the use case where the first frame in the buffer is EOS, + // decode the header to update the sample rate and channel mode + // and flush out the buffer. INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>( outHeader->pBuffer + outHeader->nOffset); @@ -392,6 +396,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { } outHeader->nFlags = OMX_BUFFERFLAG_EOS; + outHeader->nTimeStamp = + mAnchorTimeUs + + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate; outQueue.erase(outQueue.begin()); outInfo->mOwnedByUs = false; diff --git a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp index 07f8b4f..27dea92 100644 --- a/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp +++ b/media/libstagefright/codecs/amrnb/enc/SoftAMRNBEncoder.cpp @@ -71,7 +71,7 @@ void SoftAMRNBEncoder::initPorts() { def.eDir = OMX_DirInput; def.nBufferCountMin = kNumBuffers; def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t); + def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4; def.bEnabled = OMX_TRUE; def.bPopulated = OMX_FALSE; def.eDomain = OMX_PortDomainAudio; diff --git a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp index 9ccb49c..afd2b32 100644 --- a/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp +++ b/media/libstagefright/codecs/amrwbenc/SoftAMRWBEncoder.cpp @@ -78,7 +78,7 @@ void SoftAMRWBEncoder::initPorts() { def.eDir = OMX_DirInput; def.nBufferCountMin = kNumBuffers; def.nBufferCountActual = def.nBufferCountMin; - def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t); + def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 4; def.bEnabled = OMX_TRUE; def.bPopulated = OMX_FALSE; def.eDomain = OMX_PortDomainAudio; diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp index fb1135c..aade29c 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp @@ -110,7 +110,7 @@ void SoftMP3::initPorts() { void SoftMP3::initDecoder() { mConfig->equalizerType = flat; mConfig->crcEnabled = false; - + mConfig->samplingRate = mSamplingRate; uint32_t memRequirements = pvmp3_decoderMemRequirements(); mDecoderBuf = malloc(memRequirements); @@ -237,10 +237,13 @@ void SoftMP3::onQueueFilled(OMX_U32 portIndex) { if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR && decoderErr != SIDE_INFO_ERROR) { ALOGE("mp3 decoder returned error %d", decoderErr); - - notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); - mSignalledError = true; - return; + if(decoderErr == SYNCH_LOST_ERROR) { + mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); + } else { + notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); + mSignalledError = true; + return; + } } if (mConfig->outputFrameSize == 0) { diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 8bda7f8..b77cc86 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -308,6 +308,7 @@ private: void logCatchUp(int64_t ts, int64_t clock, int64_t delta); void logLate(int64_t ts, int64_t clock, int64_t delta); void logOnTime(int64_t ts, int64_t clock, int64_t delta); + void printStats(); int64_t getTimeOfDayUs(); #ifdef QCOM_HARDWARE void checkTunnelExceptions(); diff --git a/media/libstagefright/include/QCUtilityClass.h b/media/libstagefright/include/QCUtilityClass.h new file mode 100644 index 0000000..91b184f --- /dev/null +++ b/media/libstagefright/include/QCUtilityClass.h @@ -0,0 +1,111 @@ +/*Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef QC_UTIL_CLASS_H_ +#define QC_UTIL_CLASS_H_ + +#include <QCMetaData.h> +#include <cutils/properties.h> +#include <QCMediaDefs.h> + +#include <media/Metadata.h> +#include <media/stagefright/MediaSource.h> +#include <media/stagefright/foundation/AString.h> +#include <media/stagefright/MediaCodecList.h> + +#include <utils/Errors.h> +#include <sys/types.h> +#include <ctype.h> +#include <unistd.h> +#include <utils/StrongPointer.h> + +#include <media/MediaRecorderBase.h> +#include <camera/CameraParameters.h> + +#include <OMX_Video.h> +#include <media/stagefright/MediaExtractor.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/MediaDebug.h> +#include <media/stagefright/MediaDefs.h> + +namespace android { + +struct QCUtilityClass +{ + // helper function to enable Stagefright Recoder to recalculate fileduration + // when hfr property is set + static status_t helper_StageFrightRecoder_hfr(sp<MetaData> &meta, sp<MetaData> &enc_meta, + int64_t &maxFileDurationUs, int32_t frameRate, + video_encoder videoEncoder); + + // helper function to enable camera source to set kKeyHFR when video-hfr is enabled + static void helper_CameraSource_hfr(const CameraParameters& params, sp<MetaData> &meta); + + // helper function to enable MPEG4Writer to compute timestamp when hfr is enable + static void helper_MPEG4Writer_hfr(sp<MetaData> &meta, int64_t ×tampUs); + + // helper function to enable OMXCodec to recalculate frameRate, bitrate when hfr is enable + static void helper_OMXCodec_hfr(const sp<MetaData> &meta, int32_t &frameRate, + int32_t &bitRate, int32_t &newFrameRate); + + // helper function to enable OMXCodec to set HFR and FrameRate on output format when + // present on input format + static void helper_OMXCodec_hfr(const sp<MetaData> &inputFormat, sp<MetaData> &outputFormat); + + // helper function to disable audio when decode audio disable prop is set + static bool helper_Awesomeplayer_checkIfAudioDisable(); + + // helper function to disable audio when encode audio disable prop is set + static bool helper_StagefrightRecoder_checkIfAudioDisable(); + + //helper function to set encoding profiles + static void helper_StagefrightRecoder_setUserprofile(video_encoder &videoEncoder, + int32_t &videoEncoderProfile); + //helper function to setBframe related info for MPEG4type + static void helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE &mpeg4type, bool &numBFrames); + + //helper function to setBframe related info for H264 type + static void helper_OMXCodec_setBFrames(OMX_VIDEO_PARAM_AVCTYPE &h264type, bool &numBFrames, + int32_t iFramesInterval, int32_t frameRate); + + //helper function to add media codecs with specific quirks + static void helper_addMediaCodec(Vector<MediaCodecList::CodecInfo> &mCodecInfos, + KeyedVector<AString, size_t> &mTypes, + bool encoder, const char *name, + const char *type, uint32_t quirks); + + //helper function to calculate the value of quirks from strings + static uint32_t helper_getCodecSpecificQuirks(KeyedVector<AString, size_t> &mCodecQuirks, + Vector<AString> quirks); + static sp<MediaExtractor> helper_MediaExtractor_CreateIfNeeded(sp<MediaExtractor> defaultExt, + const sp<DataSource> &source, + const char *mime); +}; + +} +#endif //QC_UTIL_CLASS diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index bff3def..e41b342 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -599,15 +599,20 @@ status_t OMXNodeInstance::freeBuffer( OMX_U32 portIndex, OMX::buffer_id buffer) { Mutex::Autolock autoLock(mLock); - removeActiveBuffer(portIndex, buffer); - OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)buffer; BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate); OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header); - delete buffer_meta; - buffer_meta = NULL; + if (err != OMX_ErrorNone) { + ALOGW("OMX_FreeBuffer failed w/ err %x, do not remove from active buffer list", err); + } else { + ALOGI("OMX_FreeBuffer for buffer header %p successful", header); + removeActiveBuffer(portIndex, buffer); + + delete buffer_meta; + buffer_meta = NULL; + } return StatusFromOMXError(err); } diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk index 1ff87c8..3dde663 100644 --- a/media/mediaserver/Android.mk +++ b/media/mediaserver/Android.mk @@ -16,6 +16,10 @@ ifeq ($(BOARD_USE_SECTVOUT),true) LOCAL_SHARED_LIBRARIES += libTVOut endif +ifeq ($(TARGET_QCOM_AUDIO_VARIANT),caf) + LOCAL_CFLAGS += -DQCOM_ENHANCED_AUDIO +endif + # FIXME The duplicate audioflinger is temporary LOCAL_C_INCLUDES := \ frameworks/av/media/libmediaplayerservice \ diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index a14c205..771b8c9 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -51,6 +51,14 @@ LOCAL_SHARED_LIBRARIES := \ libdl \ libpowermanager +# SRS Processing +ifeq ($(strip $(BOARD_USES_SRS_TRUEMEDIA)),true) +LOCAL_SHARED_LIBRARIES += libsrsprocessing +LOCAL_CFLAGS += -DSRS_PROCESSING +LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-effects +endif +# SRS Processing + LOCAL_STATIC_LIBRARIES := \ libscheduling_policy \ libcpustats \ diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 3c04c1c..0c3cb14 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -88,6 +88,10 @@ #include <media/nbaio/SourceAudioBufferProvider.h> #include "SchedulingPolicyService.h" +#ifdef SRS_PROCESSING +#include "srs_processing.h" +#include "postpro_patch_ics.h" +#endif // ---------------------------------------------------------------------------- @@ -125,7 +129,7 @@ static const int8_t kMaxTrackStartupRetries = 50; // allow less retry attempts on direct output thread. // direct outputs can be a scarce resource in audio hardware and should // be released as quickly as possible. -static const int8_t kMaxTrackRetriesDirect = 2; +static const int8_t kMaxTrackRetriesDirect = 5; static const int kDumpLockRetries = 50; static const int kDumpLockSleepUs = 20000; @@ -667,11 +671,11 @@ Exit: void AudioFlinger::deleteEffectSession() { - Mutex::Autolock _l(mLock); ALOGV("deleteSession"); // -2 is invalid session ID mLPASessionId = -2; if (mLPAEffectChain != NULL) { + mLPAEffectChain->lock(); mLPAEffectChain->setLPAFlag(false); size_t i, numEffects = mLPAEffectChain->getNumEffects(); for(i = 0; i < numEffects; i++) { @@ -684,6 +688,7 @@ void AudioFlinger::deleteEffectSession() } effect->configure(); } + mLPAEffectChain->unlock(); mLPAEffectChain.clear(); mLPAEffectChain = NULL; } @@ -691,7 +696,8 @@ void AudioFlinger::deleteEffectSession() // ToDo: Should we go ahead with this frameCount? #define DEAFULT_FRAME_COUNT 1200 -void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBuffer, int size) +bool AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, + int16_t *outBuffer, int size, bool force) { ALOGV("applyEffectsOn: inBuf %p outBuf %p size %d token %p", inBuffer, outBuffer, size, token); // This might be the first buffer to apply effects after effect config change @@ -699,6 +705,12 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu mIsEffectConfigChanged = false; volatile size_t numEffects = 0; + +#ifdef SRS_PROCESSING + POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(token, AUDIO_FORMAT_PCM_16_BIT, outBuffer, size, + mLPASampleRate, mLPANumChannels); +#endif + if(mLPAEffectChain != NULL) { numEffects = mLPAEffectChain->getNumEffects(); } @@ -729,16 +741,17 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu bool isEffectEnabled = false; for(i = 0; i < numEffects; i++) { // If effect configuration is changed while applying effects do not process further - if(mIsEffectConfigChanged) { + + if(mIsEffectConfigChanged && !force) { mLPAEffectChain->unlock(); - ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing"); - return; + ALOGV("applyEffectsOn: mIsEffectConfigChanged is set - no further processing %d",frameCount); + return false; } sp<EffectModule> effect = mLPAEffectChain->getEffectFromIndex_l(i); if(effect == NULL) { ALOGE("getEffectFromIndex_l(%d) returned NULL ptr", i); mLPAEffectChain->unlock(); - return; + return false; } if(i == 0) { // For the first set input and output buffers different @@ -773,13 +786,14 @@ void AudioFlinger::applyEffectsOn(void *token, int16_t *inBuffer, int16_t *outBu } } - if (!numEffects) { + if (!numEffects && !force) { ALOGV("applyEffectsOn: There are no effects to be applied"); if(inBuffer != outBuffer) { // No effect applied so just copy input buffer to output buffer memcpy(outBuffer, inBuffer, size); } } + return true; } #endif @@ -1154,6 +1168,11 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& // ioHandle == 0 means the parameters are global to the audio hardware interface if (ioHandle == 0) { Mutex::Autolock _l(mLock); +#ifdef SRS_PROCESSING + POSTPRO_PATCH_ICS_PARAMS_SET(keyValuePairs); + if (!mDirectAudioTracks.isEmpty()) + audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL); +#endif status_t final_result = NO_ERROR; { AutoMutex lock(mHardwareLock); @@ -1232,6 +1251,12 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& String8 key = String8(AudioParameter::keyRouting); int device; if (param.getInt(key, device) == NO_ERROR) { + +#ifdef SRS_PROCESSING + ALOGV("setParameters:: routing change to device %d", device); + desc->device = (audio_devices_t)device; + POSTPRO_PATCH_ICS_OUTPROC_MIX_ROUTE(desc->trackRefPtr, param, device); +#endif if(mLPAEffectChain != NULL){ mLPAEffectChain->setDevice_l(device); audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL); @@ -1281,6 +1306,9 @@ String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& k if (ioHandle == 0) { String8 out_s8; +#ifdef SRS_PROCESSING + POSTPRO_PATCH_ICS_PARAMS_GET(keys, out_s8); +#endif for (size_t i = 0; i < mAudioHwDevs.size(); i++) { char *s; { @@ -1596,10 +1624,8 @@ status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs) #ifdef QCOM_HARDWARE void AudioFlinger::ThreadBase::effectConfigChanged() { - mAudioFlinger->mLock.lock(); ALOGV("New effect is being added to LPA chain, Notifying LPA Direct Track"); mAudioFlinger->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL); - mAudioFlinger->mLock.unlock(); } #endif @@ -2176,7 +2202,9 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac // This is probably too conservative, but legacy application code may depend on it. // If you change this calculation, also review the start threshold which is related. uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream); - uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); + uint32_t minBufCount = 0; + if(mSampleRate) + minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate); if (minBufCount < 2) { minBufCount = 2; } @@ -2188,7 +2216,17 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac } if (mType == DIRECT) { - if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) { +#ifdef QCOM_ENHANCED_AUDIO + if (((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) + ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AMR_NB) + ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AMR_WB) + ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRC) + ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRCB) + ||((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_EVRCWB)) +#else + if ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) +#endif + { if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) { ALOGE("createTrack_l() Bad parameter: sampleRate %d format %d, channelMask 0x%08x \"" "for output %p with format %d", @@ -2274,7 +2312,10 @@ uint32_t AudioFlinger::MixerThread::correctLatency(uint32_t latency) const { if (mFastMixer != NULL) { MonoPipe *pipe = (MonoPipe *)mPipeSink.get(); - latency += (pipe->getAvgFrames() * 1000) / mSampleRate; + if(mSampleRate) + latency += (pipe->getAvgFrames() * 1000) / mSampleRate; + else + ALOGW("SampleRate is 0"); } return latency; } @@ -2950,6 +2991,13 @@ bool AudioFlinger::PlaybackThread::threadLoop() standbyTime = systemTime(); +#ifdef SRS_PROCESSING +if (mType == MIXER) { + POSTPRO_PATCH_ICS_OUTPROC_MIX_INIT(this, gettid()); + } else if (mType == DUPLICATING) { + POSTPRO_PATCH_ICS_OUTPROC_DUPE_INIT(this, gettid()); + } +#endif // MIXER nsecs_t lastWarning = 0; @@ -3064,6 +3112,15 @@ bool AudioFlinger::PlaybackThread::threadLoop() // sleepTime == 0 means we must write to audio hardware if (sleepTime == 0) { +#ifdef SRS_PROCESSING + if (mType == MIXER) { + POSTPRO_PATCH_ICS_OUTPROC_MIX_SAMPLES(this, mFormat, mMixBuffer, + mixBufferSize, mSampleRate, mChannelCount); + } else if (mType == DUPLICATING) { + POSTPRO_PATCH_ICS_OUTPROC_DUPE_SAMPLES(this, mFormat, mMixBuffer, + mixBufferSize, mSampleRate, mChannelCount); + } +#endif threadLoop_write(); if (mType == MIXER) { @@ -3115,6 +3172,13 @@ if (mType == MIXER) { } } +#ifdef SRS_PROCESSING + if (mType == MIXER) { + POSTPRO_PATCH_ICS_OUTPROC_MIX_EXIT(this, gettid()); + } else if (mType == DUPLICATING) { + POSTPRO_PATCH_ICS_OUTPROC_DUPE_EXIT(this, gettid()); + } +#endif releaseWakeLock(); ALOGV("Thread %p type %d exiting", this, mType); @@ -3516,7 +3580,12 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac minFrames = mNormalFrameCount; } else { // +1 for rounding and +1 for additional sample needed for interpolation - minFrames = (mNormalFrameCount * t->sampleRate()) / mSampleRate + 1 + 1; + if(mSampleRate) + minFrames = (mNormalFrameCount * t->sampleRate()) / mSampleRate + 1 + 1; + else { + minFrames = 2; + ALOGW("SampleRate is 0"); + } // add frames already consumed but not yet released by the resampler // because cblk->framesReady() will include these frames minFrames += mAudioMixer->getUnreleasedFrames(track->name()); @@ -3873,6 +3942,9 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() String8 keyValuePair = mNewParameters[0]; AudioParameter param = AudioParameter(keyValuePair); int value; +#ifdef SRS_PROCESSING + POSTPRO_PATCH_ICS_OUTPROC_MIX_ROUTE(this, param, value); +#endif if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) { reconfig = true; @@ -4462,7 +4534,10 @@ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread) { Mutex::Autolock _l(mLock); // FIXME explain this formula - int frameCount = (3 * mNormalFrameCount * mSampleRate) / thread->sampleRate(); + int sampleRate = thread->sampleRate(); + int frameCount = 0; + if (sampleRate) + frameCount = (3 * mNormalFrameCount * mSampleRate) / sampleRate; OutputTrack *outputTrack = new OutputTrack(thread, this, mSampleRate, @@ -4548,6 +4623,9 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( audio_format_t format, audio_channel_mask_t channelMask, int frameCount, +#ifdef QCOM_ENHANCED_AUDIO + uint32_t flags, +#endif const sp<IMemory>& sharedBuffer, int sessionId) : RefBase(), @@ -4561,6 +4639,9 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mSampleRate(sampleRate), mFormat(format), mStepServerFailed(false), +#ifdef QCOM_ENHANCED_AUDIO + mFlags(0), +#endif mSessionId(sessionId) // mChannelCount // mChannelMask @@ -4570,7 +4651,40 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( // ALOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); size_t size = sizeof(audio_track_cblk_t); uint8_t channelCount = popcount(channelMask); +#ifdef QCOM_ENHANCED_AUDIO + size_t bufferSize = 0; + if ((int16_t)flags == 0x1) { + bufferSize = frameCount*channelCount*sizeof(int16_t); + } else { + if ( (format == AUDIO_FORMAT_PCM_16_BIT) || + (format == AUDIO_FORMAT_PCM_8_BIT)) + { + bufferSize = frameCount*channelCount*sizeof(int16_t); + } + else if (format == AUDIO_FORMAT_AMR_NB) + { + bufferSize = frameCount*channelCount*32; // full rate frame size + } + else if (format == AUDIO_FORMAT_EVRC) + { + bufferSize = frameCount*channelCount*23; // full rate frame size + } + else if (format == AUDIO_FORMAT_QCELP) + { + bufferSize = frameCount*channelCount*35; // full rate frame size + } + else if (format == AUDIO_FORMAT_AAC) + { + bufferSize = frameCount*2048; // full rate frame size + } + else if (format == AUDIO_FORMAT_AMR_WB) + { + bufferSize = frameCount*channelCount*61; // full rate frame size + } + } +#else size_t bufferSize = frameCount*channelCount*sizeof(int16_t); +#endif if (sharedBuffer == 0) { size += bufferSize; } @@ -4593,7 +4707,39 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mChannelMask = channelMask; if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); +#ifdef QCOM_ENHANCED_AUDIO + if ((int16_t)flags == 0x1) { + bufferSize = frameCount*channelCount*sizeof(int16_t); + } else { + if ((format == AUDIO_FORMAT_PCM_16_BIT) || + (format == AUDIO_FORMAT_PCM_8_BIT)) + { + memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); + } + else if (format == AUDIO_FORMAT_AMR_NB) + { + memset(mBuffer, 0, frameCount*channelCount*32); // full rate frame size + } + else if (format == AUDIO_FORMAT_EVRC) + { + memset(mBuffer, 0, frameCount*channelCount*23); // full rate frame size + } + else if (format == AUDIO_FORMAT_QCELP) + { + memset(mBuffer, 0, frameCount*channelCount*35); // full rate frame size + } + else if (format == AUDIO_FORMAT_AAC) + { + memset(mBuffer, 0, frameCount*2048); // full rate frame size + } + else if (format == AUDIO_FORMAT_AMR_WB) + { + memset(mBuffer, 0, frameCount*channelCount*61); // full rate frame size + } + } +#else memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); +#endif // Force underrun condition to avoid false underrun callback until first data is // written to buffer (other flags are cleared) mCblk->flags = CBLK_UNDERRUN_ON; @@ -4696,13 +4842,21 @@ void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t f int8_t *bufferEnd = bufferStart + frames * frameSize; // Check validity of returned pointer in case the track control block would have been corrupted. +#ifdef QCOM_ENHANCED_AUDIO + if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd){ + ALOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ + server %u, serverBase %u, user %u, userBase %u", + bufferStart, bufferEnd, mBuffer, mBufferEnd, + cblk->server, cblk->serverBase, cblk->user, cblk->userBase); + return 0; + } +#else ALOG_ASSERT(!(bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd), "TrackBase::getBuffer buffer out of range:\n" " start: %p, end %p , mBuffer %p mBufferEnd %p\n" " server %u, serverBase %u, user %u, userBase %u, frameSize %d", - bufferStart, bufferEnd, mBuffer, mBufferEnd, cblk->server, cblk->serverBase, cblk->user, cblk->userBase, frameSize); - +#endif return bufferStart; } @@ -4726,7 +4880,11 @@ AudioFlinger::PlaybackThread::Track::Track( const sp<IMemory>& sharedBuffer, int sessionId, IAudioFlinger::track_flags_t flags) - : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, sessionId), + : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, +#ifdef QCOM_ENHANCED_AUDIO + ((audio_stream_type_t)streamType == AUDIO_STREAM_VOICE_CALL)?0x1:0x0, +#endif + sharedBuffer, sessionId), mMute(false), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed @@ -4745,7 +4903,12 @@ AudioFlinger::PlaybackThread::Track::Track( if (mCblk != NULL) { // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack - mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t); +#ifdef QCOM_ENHANCED_AUDIO + if ((audio_stream_type_t)streamType == AUDIO_STREAM_VOICE_CALL) + mCblk->frameSize = mChannelCount * sizeof(int16_t); + else +#endif + mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t); // to avoid leaking a track name, do not allocate one unless there is an mCblk mName = thread->getTrackName_l(channelMask, sessionId); mCblk->mName = mName; @@ -5776,12 +5939,44 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( audio_format_t format, audio_channel_mask_t channelMask, int frameCount, +#ifdef QCOM_ENHANCED_AUDIO + uint32_t flags, +#endif int sessionId) - : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, 0 /*sharedBuffer*/, sessionId), + : TrackBase(thread, client, sampleRate, format,channelMask,frameCount, +#ifdef QCOM_ENHANCED_AUDIO + ((audio_source_t)((int16_t)flags) == AUDIO_SOURCE_VOICE_COMMUNICATION) ? + ((flags & 0xffff0000)| 0x1) : ((flags & 0xffff0000)), +#endif + 0 /*sharedBuffer*/, sessionId), mOverflow(false) { + uint8_t channelCount = popcount(channelMask); if (mCblk != NULL) { +#ifdef QCOM_ENHANCED_AUDIO + ALOGV("RecordTrack constructor, size %d flags %d", (int)mBufferEnd - (int)mBuffer,flags); + if ((audio_source_t)((int16_t)flags) == AUDIO_SOURCE_VOICE_COMMUNICATION) { + mCblk->frameSize = mChannelCount * sizeof(int16_t); + } else { + if (format == AUDIO_FORMAT_AMR_NB) { + mCblk->frameSize = channelCount * 32; + } else if (format == AUDIO_FORMAT_EVRC) { + mCblk->frameSize = channelCount * 23; + } else if (format == AUDIO_FORMAT_QCELP) { + mCblk->frameSize = channelCount * 35; + } else if (format == AUDIO_FORMAT_AAC) { + mCblk->frameSize = 2048; + } else if (format == AUDIO_FORMAT_PCM_16_BIT) { + mCblk->frameSize = mChannelCount * sizeof(int16_t); + } else if (format == AUDIO_FORMAT_PCM_8_BIT) { + mCblk->frameSize = mChannelCount * sizeof(int8_t); + } else if (format == AUDIO_FORMAT_AMR_WB) { + mCblk->frameSize = channelCount * 61; + } else { + mCblk->frameSize = sizeof(int8_t); + } + } +#else ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer); if (format == AUDIO_FORMAT_PCM_16_BIT) { mCblk->frameSize = mChannelCount * sizeof(int16_t); @@ -5790,6 +5985,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( } else { mCblk->frameSize = sizeof(int8_t); } +#endif } } @@ -6200,8 +6396,14 @@ AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFl int output, AudioSessionDescriptor *outputDesc, IDirectTrackClient* client, audio_output_flags_t outflag) : BnDirectTrack(), mIsPaused(false), mAudioFlinger(audioFlinger), mOutput(output), mOutputDesc(outputDesc), - mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag) + mClient(client), mEffectConfigChanged(false), mKillEffectsThread(false), mFlag(outflag), + mEffectsThreadScratchBuffer(NULL) { +#ifdef SRS_PROCESSING + ALOGD("SRS_Processing - DirectAudioTrack - OutNotify_Init: %p TID %d\n", this, gettid()); + POSTPRO_PATCH_ICS_OUTPROC_DIRECT_INIT(this, gettid()); + SRS_Processing::ProcessOutRoute(SRS_Processing::AUTO, this, outputDesc->device); +#endif if (mFlag & AUDIO_OUTPUT_FLAG_LPA) { createEffectThread(); @@ -6209,6 +6411,13 @@ AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFl mAudioFlinger->registerClient(mAudioFlingerClient); allocateBufPool(); +#ifdef SRS_PROCESSING + } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) { + ALOGV("create effects thread for TUNNEL"); + createEffectThread(); + mAudioFlingerClient = new AudioFlingerDirectTrackClient(this); + mAudioFlinger->registerClient(mAudioFlingerClient); +#endif } outputDesc->mVolumeScale = 1.0; mDeathRecipient = new PMDeathRecipient(this); @@ -6216,11 +6425,21 @@ AudioFlinger::DirectAudioTrack::DirectAudioTrack(const sp<AudioFlinger>& audioFl } AudioFlinger::DirectAudioTrack::~DirectAudioTrack() { +#ifdef SRS_PROCESSING + ALOGD("SRS_Processing - DirectAudioTrack - OutNotify_Init: %p TID %d\n", this, gettid()); + POSTPRO_PATCH_ICS_OUTPROC_DIRECT_EXIT(this, gettid()); +#endif if (mFlag & AUDIO_OUTPUT_FLAG_LPA) { requestAndWaitForEffectsThreadExit(); mAudioFlinger->deregisterClient(mAudioFlingerClient); mAudioFlinger->deleteEffectSession(); deallocateBufPool(); +#ifdef SRS_PROCESSING + } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) { + requestAndWaitForEffectsThreadExit(); + mAudioFlinger->deregisterClient(mAudioFlingerClient); + mAudioFlinger->deleteEffectSession(); +#endif } AudioSystem::releaseOutput(mOutput); releaseWakeLock(); @@ -6276,9 +6495,11 @@ ssize_t AudioFlinger::DirectAudioTrack::write(const void *buffer, size_t size) { memcpy((char *) buf.localBuf, (char *)buffer, size); buf.bytesToWrite = size; mEffectsPool.push_back(buf); - mAudioFlinger->applyEffectsOn(static_cast<void *>(this), (int16_t*)buf.localBuf,(int16_t*)buffer,(int)size); + mAudioFlinger->applyEffectsOn(static_cast<void *>(this), + (int16_t*)buf.localBuf, (int16_t*)buffer, (int)size, true); mEffectLock.unlock(); } + ALOGV("out of Writing to AudioSessionOut"); return mOutputDesc->stream->write(mOutputDesc->stream, buffer, size); } @@ -6352,6 +6573,10 @@ void AudioFlinger::DirectAudioTrack::allocateBufPool() { ALOGV("The MEM that is allocated buffer is %x, size %d",(unsigned int)dsp_buf,nSize); } + + mEffectsThreadScratchBuffer = malloc(nSize); + ALOGV("effectsThreadScratchBuffer = %x",mEffectsThreadScratchBuffer); + free(buf); } @@ -6370,6 +6595,9 @@ void AudioFlinger::DirectAudioTrack::deallocateBufPool() { ALOGV("Removing from bufpool"); mBufPool.erase(it); } + + free(mEffectsThreadScratchBuffer); + mEffectsThreadScratchBuffer = NULL; } status_t AudioFlinger::DirectAudioTrack::onTransact( @@ -6397,18 +6625,40 @@ void AudioFlinger::DirectAudioTrack::EffectsThreadEntry() { if (mEffectConfigChanged) { mEffectConfigChanged = false; - for ( List<BufferInfo>::iterator it = mEffectsPool.begin(); - it != mEffectsPool.end(); it++) { - ALOGV("Apply effects on the buffer dspbuf %p, mEffectsPool.size() %d",it->dspBuf,mEffectsPool.size()); - mAudioFlinger->applyEffectsOn(static_cast<void *>(this), - (int16_t *)it->localBuf, - (int16_t *)it->dspBuf, - it->bytesToWrite); - if (mEffectConfigChanged) { - break; - } - } + if (mFlag & AUDIO_OUTPUT_FLAG_LPA) { + for ( List<BufferInfo>::iterator it = mEffectsPool.begin(); + it != mEffectsPool.end(); it++) { + ALOGV("ete: calling applyEffectsOn buff %x",it->localBuf); + bool isEffectsApplied = mAudioFlinger->applyEffectsOn( + static_cast<void *>(this), + (int16_t *)it->localBuf, + (int16_t *)mEffectsThreadScratchBuffer, + it->bytesToWrite, + false); + if (isEffectsApplied == true){ + ALOGV("ete:dsp updated for local buf %x",it->localBuf); + memcpy(it->dspBuf, mEffectsThreadScratchBuffer, it->bytesToWrite); + } + else + ALOGV("ete:dsp updated for local buf %x SKIPPED",it->localBuf); + if (mEffectConfigChanged) { + ALOGE("ete:effects changed, abort effects application"); + break; + } + } +#ifdef SRS_PROCESSING + } else if (mFlag & AUDIO_OUTPUT_FLAG_TUNNEL) { + ALOGV("applying effects for TUNNEL"); + char buffer[2]; + //dummy buffer to ensure the SRS processing takes place + // The API mandates Sample rate and channel mode. Hence + // defaulted the sample rate channel mode to 48000 and 2 respectively + POSTPRO_PATCH_ICS_OUTPROC_DIRECT_SAMPLES(static_cast<void *>(this), + AUDIO_FORMAT_PCM_16_BIT, + (int16_t*)buffer, 2, 48000, 2); +#endif + } } mEffectLock.unlock(); } @@ -6614,6 +6864,10 @@ sp<IAudioRecord> AudioFlinger::openRecord( sp<RecordThread::RecordTrack> recordTrack; sp<RecordHandle> recordHandle; sp<Client> client; +#ifdef QCOM_ENHANCED_AUDIO + size_t inputBufferSize = 0; + uint32_t channelCount = popcount(channelMask); +#endif status_t lStatus; RecordThread *thread; size_t inFrameCount; @@ -6625,6 +6879,15 @@ sp<IAudioRecord> AudioFlinger::openRecord( goto Exit; } +#ifdef QCOM_ENHANCED_AUDIO + // Check that audio input stream accepts requested audio parameters + inputBufferSize = getInputBufferSize(sampleRate, format, channelCount); + if (inputBufferSize == 0) { + lStatus = BAD_VALUE; + ALOGE("Bad audio input parameters: sampling rate %u, format %d, channels %d", sampleRate, format, channelCount); + goto Exit; + } +#endif // add client to list { // scope for mLock Mutex::Autolock _l(mLock); @@ -6645,6 +6908,41 @@ sp<IAudioRecord> AudioFlinger::openRecord( *sessionId = lSessionId; } } +#ifdef QCOM_ENHANCED_AUDIO + // frameCount must be a multiple of input buffer size + // Change for Codec type + uint8_t channelCount = popcount(channelMask); + if ((audio_source_t)((int16_t)flags) == AUDIO_SOURCE_VOICE_COMMUNICATION) { + inFrameCount = inputBufferSize/channelCount/sizeof(short); + } else { + if ((format == AUDIO_FORMAT_PCM_16_BIT) || + (format == AUDIO_FORMAT_PCM_8_BIT)) + { + inFrameCount = inputBufferSize/channelCount/sizeof(short); + } + else if (format == AUDIO_FORMAT_AMR_NB) + { + inFrameCount = inputBufferSize/channelCount/32; + } + else if (format == AUDIO_FORMAT_EVRC) + { + inFrameCount = inputBufferSize/channelCount/23; + } + else if (format == AUDIO_FORMAT_QCELP) + { + inFrameCount = inputBufferSize/channelCount/35; + } + else if (format == AUDIO_FORMAT_AAC) + { + inFrameCount = inputBufferSize/2048; + } + else if (format == AUDIO_FORMAT_AMR_WB) + { + inFrameCount = inputBufferSize/channelCount/61; + } + } + frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; +#endif // create new record track. The record track uses one track in mHardwareMixerThread by convention. recordTrack = thread->createRecordTrack_l(client, sampleRate, format, channelMask, frameCount, lSessionId, flags, tid, &lStatus); @@ -6849,9 +7147,30 @@ bool AudioFlinger::RecordThread::threadLoop() } } if (framesOut && mFrameCount == mRsmpInIndex) { +#ifdef QCOM_ENHANCED_AUDIO + if (((int) framesOut != mFrameCount) && + ((mFormat != AUDIO_FORMAT_PCM_16_BIT)&& + ((audio_source_t)mInputSource != AUDIO_SOURCE_VOICE_COMMUNICATION))) { + mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, + buffer.frameCount * mFrameSize); + ALOGV("IR mBytesRead = %d",mBytesRead); + if(mBytesRead >= 0 ){ + buffer.frameCount = mBytesRead/mFrameSize; + } + framesOut = 0; + } else +#endif if (framesOut == mFrameCount && +#ifdef QCOM_ENHANCED_AUDIO + ((audio_source_t)mInputSource != AUDIO_SOURCE_VOICE_COMMUNICATION) && +#endif ((int)mChannelCount == mReqChannelCount || mFormat != AUDIO_FORMAT_PCM_16_BIT)) { mBytesRead = mInput->stream->read(mInput->stream, buffer.raw, mInputBytes); +#ifdef QCOM_ENHANCED_AUDIO + if( mBytesRead >= 0 ){ + buffer.frameCount = mBytesRead/mFrameSize; + } +#endif framesOut = 0; } else { mBytesRead = mInput->stream->read(mInput->stream, mRsmpInBuffer, mInputBytes); @@ -6988,7 +7307,11 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR Mutex::Autolock _l(mLock); track = new RecordTrack(this, client, sampleRate, - format, channelMask, frameCount, sessionId); + format, channelMask, frameCount, +#ifdef QCOM_ENHANCED_AUDIO + flags, +#endif + sessionId); if (track->getCblk() == 0) { lStatus = NO_MEMORY; @@ -7796,6 +8119,10 @@ audio_io_handle_t AudioFlinger::openOutput(audio_module_handle_t module, ALOGI("Using module %d has the primary audio interface", module); mPrimaryHardwareDev = outHwDev; +#ifdef SRS_PROCESSING + SRS_Processing::RawDataSet(NULL, "qdsp hook", &mPrimaryHardwareDev, + sizeof(&mPrimaryHardwareDev)); +#endif AutoMutex lock(mHardwareLock); mHardwareStatus = AUDIO_HW_SET_MODE; hwDevHal->set_mode(hwDevHal, mMode); @@ -9289,7 +9616,7 @@ status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, in } else { channels = AUDIO_CHANNEL_OUT_STEREO; } - ALOGV("%s: LPA ON - channels %d", __func__, channels); +// ALOGV("%s: LPA ON - channels %d", __func__, channels); } else { if (thread->channelCount() == 1) { channels = AUDIO_CHANNEL_OUT_MONO; @@ -9347,8 +9674,8 @@ status_t AudioFlinger::EffectModule::configure(bool isForLPA, int sampleRate, in mConfig.inputCfg.buffer.frameCount = thread->frameCount(); mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount; - ALOGV("configure() %p thread %p buffer %p framecount %d", - this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount); +// ALOGV("configure() %p thread %p buffer %p framecount %d", +// this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount); status_t cmdStatus; uint32_t size = sizeof(int); @@ -10037,7 +10364,7 @@ status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode, (cmdCode == EFFECT_CMD_SET_VOLUME) || (cmdCode == EFFECT_CMD_SET_AUDIO_MODE)) ) { // Notify Direct track for the change in Effect module // TODO: check if it is required to send mLPAHandle - ALOGV("Notifying Direct Track for the change in effect config"); + ALOGV("Notifying Direct Track for the change in effect config %d", cmdCode); mClient->audioFlinger()->audioConfigChanged_l(AudioSystem::EFFECT_CONFIG_CHANGED, 0, NULL); } #endif diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index d6a3815..5b718d7 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -245,10 +245,11 @@ public: uint32_t flags); #ifdef QCOM_HARDWARE - void applyEffectsOn(void *token, + bool applyEffectsOn(void *token, int16_t *buffer1, int16_t *buffer2, - int size); + int size, + bool force); #endif // end of IAudioFlinger interface @@ -427,6 +428,9 @@ private: audio_format_t format, audio_channel_mask_t channelMask, int frameCount, +#ifdef QCOM_ENHANCED_AUDIO + uint32_t flags, +#endif const sp<IMemory>& sharedBuffer, int sessionId); virtual ~TrackBase(); @@ -506,6 +510,9 @@ private: // support dynamic rates, the current value is in control block const audio_format_t mFormat; bool mStepServerFailed; +#ifdef QCOM_ENHANCED_AUDIO + uint32_t mFlags; +#endif const int mSessionId; uint8_t mChannelCount; audio_channel_mask_t mChannelMask; @@ -1483,6 +1490,7 @@ private: }; List<BufferInfo> mBufPool; List<BufferInfo> mEffectsPool; + void *mEffectsThreadScratchBuffer; void allocateBufPool(); void deallocateBufPool(); @@ -1521,7 +1529,8 @@ private: sp<AudioFlinger> mAudioFlinger; sp<AudioFlingerDirectTrackClient> mAudioFlingerClient; - void clearPowerManager(); + void clearPowerManager(); + class PMDeathRecipient : public IBinder::DeathRecipient { public: PMDeathRecipient(void *obj){parentClass = (DirectAudioTrack *)obj;} @@ -1592,6 +1601,9 @@ private: audio_format_t format, audio_channel_mask_t channelMask, int frameCount, +#ifdef QCOM_ENHANCED_AUDIO + uint32_t flags, +#endif int sessionId); virtual ~RecordTrack(); @@ -1722,6 +1734,7 @@ private: // when < 0, maximum frames to drop before starting capture even if sync event is // not received ssize_t mFramestoDrop; + int16_t mInputSource; }; // server side of the client's IAudioRecord diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index 967562d..1254962 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -697,6 +697,12 @@ void CameraClient::disableMsgType(int32_t msgType) { bool CameraClient::lockIfMessageWanted(int32_t msgType) { int sleepCount = 0; while (mMsgEnabled & msgType) { + if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && + (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) { + LOG1("lockIfMessageWanted(%d): Don't try to acquire mlock if " + "both Preview and Compressed are enabled", msgType); + return false; + } if (mLock.tryLock() == NO_ERROR) { if (sleepCount > 0) { LOG1("lockIfMessageWanted(%d): waited for %d ms", |