Merge tag 'android-6.0.0_r26' into HEAD
Android 6.0.0 release 26
* tag 'android-6.0.0_r26': (104 commits)
ID3: check possible integer overflow for extendedHeaderSize and paddingSize.
AudioTrack: Prevent stop() from reissuing last marker event
Check NAL size before use
MPEG4Extractor: ensure buffer size is not less than 8 for LastCommentData.
ID3: check possible integer overflow for extendedHeaderSize and paddingSize.
Don't crash when there's no conceal frame
AudioSystem: Fix race condition in accessing ioDescriptors
OMX: allow only secure codec to remotely call allocateBuffer.
MPEG4Extractor: ensure buffer size is not less than 8 for LastCommentData.
Camera3Device: Change HFR request thread priority to 1
Camera3Device: Bookkeeping reprocess shutters separately
CameraService: Use SCHED_FIFO for request queue thread in HFR
CameraService: Use SCHED_FIFO for request queue thread in HFR
DO NOT MERGE stagefright: fix AMessage::FromParcel
stagefright: fix AMessage::FromParcel
stagefright: fix AMessage::FromParcel
SoftAVCDec: Reduced memory requirements
AudioPolicyService: fix race in AudioCommandThread
DO NOT MERGE - Fix build for commit 69ae6a87
audio policy: fix preemtible capture race
...
Conflicts:
media/libmedia/ICrypto.cpp
media/libmedia/IEffect.cpp
media/libmediaplayerservice/nuplayer/GenericSource.cpp
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
media/libstagefright/DataSource.cpp
media/libstagefright/OggExtractor.cpp
media/libstagefright/data/media_codecs_google_video.xml
media/libstagefright/include/OMXNodeInstance.h
media/libstagefright/omx/OMXNodeInstance.cpp
Change-Id: I4e64767638a163004031d2ace602360119349bb5
diff --git a/camera/ICameraClient.cpp b/camera/ICameraClient.cpp
index 179a341..4f43796 100644
--- a/camera/ICameraClient.cpp
+++ b/camera/ICameraClient.cpp
@@ -46,7 +46,12 @@
data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor());
data.writeInt32(msgType);
data.writeInt32(ext1);
- data.writeInt32(ext2);
+ if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) {
+ ALOGD("notifyCallback: CAMERA_MSG_PREVIEW_FRAME fd = %d", ext2);
+ data.writeFileDescriptor(ext2);
+ } else {
+ data.writeInt32(ext2);
+ }
remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -91,8 +96,14 @@
ALOGV("NOTIFY_CALLBACK");
CHECK_INTERFACE(ICameraClient, data, reply);
int32_t msgType = data.readInt32();
- int32_t ext1 = data.readInt32();
- int32_t ext2 = data.readInt32();
+ int32_t ext1 = data.readInt32();
+ int32_t ext2 = 0;
+ if ((msgType == CAMERA_MSG_PREVIEW_FRAME) && (ext1 == CAMERA_FRAME_DATA_FD)) {
+ ext2 = data.readFileDescriptor();
+ ALOGD("onTransact: CAMERA_MSG_PREVIEW_FRAME fd = %d", ext2);
+ } else {
+ ext2 = data.readInt32();
+ }
notifyCallback(msgType, ext1, ext2);
return NO_ERROR;
} break;
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a9c6eda..7413254 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#include <inttypes.h>
@@ -626,6 +645,11 @@
MEDIA_MIMETYPE_AUDIO_MPEG, MEDIA_MIMETYPE_AUDIO_G711_MLAW,
MEDIA_MIMETYPE_AUDIO_G711_ALAW, MEDIA_MIMETYPE_AUDIO_VORBIS,
MEDIA_MIMETYPE_VIDEO_VP8, MEDIA_MIMETYPE_VIDEO_VP9
+#ifdef DOLBY_ENABLE
+ ,
+ MEDIA_MIMETYPE_AUDIO_AC3,
+ MEDIA_MIMETYPE_AUDIO_EAC3
+#endif // DOLBY_END
};
const char *codecType = queryDecoders? "decoder" : "encoder";
diff --git a/drm/libdrmframework/Android.mk b/drm/libdrmframework/Android.mk
index 33f9d3b..b7eb70b 100644
--- a/drm/libdrmframework/Android.mk
+++ b/drm/libdrmframework/Android.mk
@@ -31,7 +31,7 @@
libbinder \
libdl
-LOCAL_STATIC_LIBRARIES := \
+LOCAL_WHOLE_STATIC_LIBRARIES := \
libdrmframeworkcommon
LOCAL_C_INCLUDES += \
diff --git a/include/media/AudioParameter.h b/include/media/AudioParameter.h
index 891bc4b..c769c4b 100644
--- a/include/media/AudioParameter.h
+++ b/include/media/AudioParameter.h
@@ -48,6 +48,7 @@
static const char * const keyFrameCount;
static const char * const keyInputSource;
static const char * const keyScreenState;
+ static const char * const keyDevShutdown;
String8 toString();
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index e02f1b7..191802d 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -31,6 +31,7 @@
struct audio_track_cblk_t;
class AudioTrackClientProxy;
class StaticAudioTrackClientProxy;
+struct ExtendedMediaUtils;
// ----------------------------------------------------------------------------
@@ -623,6 +624,7 @@
*/
status_t obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
struct timespec *elapsed = NULL, size_t *nonContig = NULL);
+ friend struct ExtendedMediaUtils;
public:
/* Public API for TRANSFER_OBTAIN mode.
@@ -940,6 +942,8 @@
// For Device Selection API
// a value of AUDIO_PORT_HANDLE_NONE indicated default (AudioPolicyManager) routing.
audio_port_handle_t mSelectedDeviceId;
+ bool mPlaybackRateSet;
+ bool mTrackOffloaded;
private:
class DeathNotifier : public IBinder::DeathRecipient {
@@ -957,6 +961,7 @@
pid_t mClientPid;
sp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
+ friend struct ExtendedMediaUtils;
};
class TimedAudioTrack : public AudioTrack
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index de82554..745151b 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -46,12 +46,12 @@
template<typename T> class SortedVector;
enum player_type {
- STAGEFRIGHT_PLAYER = 3,
NU_PLAYER = 4,
// Test players are available only in the 'test' and 'eng' builds.
// The shared library with the test player is passed passed as an
// argument to the 'test:' url in the setDataSource call.
TEST_PLAYER = 5,
+ DASH_PLAYER = 6,
};
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index e02918f..b1c7c15 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -56,6 +56,20 @@
CAMCORDER_QUALITY_HIGH_SPEED_1080P = 2004,
CAMCORDER_QUALITY_HIGH_SPEED_2160P = 2005,
CAMCORDER_QUALITY_HIGH_SPEED_LIST_END = 2005,
+
+ CAMCORDER_QUALITY_VENDOR_START = 10000,
+ CAMCORDER_QUALITY_VGA = 10000,
+ CAMCORDER_QUALITY_4KDCI = 10001,
+ CAMCORDER_QUALITY_TIME_LAPSE_VGA = 10002,
+ CAMCORDER_QUALITY_TIME_LAPSE_4KDCI = 10003,
+ CAMCORDER_QUALITY_HIGH_SPEED_CIF = 10004,
+ CAMCORDER_QUALITY_HIGH_SPEED_VGA = 10005,
+ CAMCORDER_QUALITY_HIGH_SPEED_4KDCI = 10006,
+ CAMCORDER_QUALITY_QHD = 10007,
+ CAMCORDER_QUALITY_2k = 10008,
+ CAMCORDER_QUALITY_TIME_LAPSE_QHD = 10009,
+ CAMCORDER_QUALITY_TIME_LAPSE_2k = 10010,
+ CAMCORDER_QUALITY_VENDOR_END = 10010,
};
enum video_decoder {
@@ -392,6 +406,7 @@
static VideoEncoderCap* createDefaultH263VideoEncoderCap();
static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
static AudioEncoderCap* createDefaultAmrNBEncoderCap();
+ static AudioEncoderCap* createDefaultLpcmEncoderCap();
static int findTagForName(const NameToTagMap *map, size_t nMappings, const char *name);
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 3fe749c..1f6ddad 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -53,7 +53,7 @@
MEDIA_ERROR = 100,
MEDIA_INFO = 200,
MEDIA_SUBTITLE_DATA = 201,
- MEDIA_META_DATA = 202,
+ MEDIA_META_DATA = 202
};
// Generic error codes for the media player framework. Errors are fatal, the
@@ -209,7 +209,7 @@
void died();
void disconnect();
- status_t setDataSource(
+ virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
@@ -224,7 +224,7 @@
status_t prepareAsync();
status_t start();
status_t stop();
- status_t pause();
+ virtual status_t pause();
bool isPlaying();
status_t setPlaybackSettings(const AudioPlaybackRate& rate);
status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */);
@@ -234,7 +234,7 @@
float* videoFps /* nonnull */);
status_t getVideoWidth(int *w);
status_t getVideoHeight(int *h);
- status_t seekTo(int msec);
+ virtual status_t seekTo(int msec);
status_t getCurrentPosition(int *msec);
status_t getDuration(int *msec);
status_t reset();
@@ -243,7 +243,7 @@
status_t setLooping(int loop);
bool isLooping();
status_t setVolume(float leftVolume, float rightVolume);
- void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
+ virtual void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
status_t invoke(const Parcel& request, Parcel *reply);
status_t setMetadataFilter(const Parcel& filter);
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
@@ -289,6 +289,7 @@
float mSendLevel;
struct sockaddr_in mRetransmitEndpoint;
bool mRetransmitEndpointValid;
+ friend class QCMediaPlayer;
};
}; // namespace android
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 15ff82d..6ace36d 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -74,6 +74,9 @@
/* VP8/VORBIS data in a WEBM container */
OUTPUT_FORMAT_WEBM = 9,
+ OUTPUT_FORMAT_QCP = 20,
+ OUTPUT_FORMAT_WAVE = 21,
+
OUTPUT_FORMAT_LIST_END // must be last - used to validate format type
};
@@ -86,6 +89,10 @@
AUDIO_ENCODER_AAC_ELD = 5,
AUDIO_ENCODER_VORBIS = 6,
+ AUDIO_ENCODER_EVRC = 10,
+ AUDIO_ENCODER_QCELP = 11,
+ AUDIO_ENCODER_LPCM = 12,
+
AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type
};
@@ -96,7 +103,11 @@
VIDEO_ENCODER_MPEG_4_SP = 3,
VIDEO_ENCODER_VP8 = 4,
- VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type
+ VIDEO_ENCODER_LIST_END, // must be the last - used to validate the video encoder type
+
+ VIDEO_ENCODER_LIST_VENDOR_START = 1000,
+ VIDEO_ENCODER_H265 = 1001,
+ VIDEO_ENCODER_LIST_VENDOR_END,
};
/*
@@ -225,13 +236,13 @@
status_t setOutputFile(int fd, int64_t offset, int64_t length);
status_t setVideoSize(int width, int height);
status_t setVideoFrameRate(int frames_per_second);
- status_t setParameters(const String8& params);
+ virtual status_t setParameters(const String8& params);
status_t setListener(const sp<MediaRecorderListener>& listener);
status_t setClientName(const String16& clientName);
status_t prepare();
status_t getMaxAmplitude(int* max);
- status_t start();
- status_t stop();
+ virtual status_t start();
+ virtual status_t stop();
status_t reset();
status_t init();
status_t close();
@@ -240,7 +251,7 @@
status_t setInputSurface(const sp<PersistentSurface>& surface);
sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer();
-private:
+protected:
void doCleanUp();
status_t doReset();
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 8b5b862..ebfdc7b 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef A_CODEC_H_
@@ -93,8 +112,11 @@
protected:
virtual ~ACodec();
+ virtual status_t setupCustomCodec(
+ status_t err, const char *mime, const sp<AMessage> &msg);
+ virtual status_t GetVideoCodingTypeFromMime(
+ const char *mime, OMX_VIDEO_CODINGTYPE *codingType);
-private:
struct BaseState;
struct UninitializedState;
struct LoadedState;
@@ -152,6 +174,7 @@
};
struct BufferInfo {
+ BufferInfo() : mCustomData(-1) {}
enum Status {
OWNED_BY_US,
OWNED_BY_COMPONENT,
@@ -173,6 +196,7 @@
sp<GraphicBuffer> mGraphicBuffer;
int mFenceFd;
FrameRenderTracker::Info *mRenderInfo;
+ int mCustomData;
// The following field and 4 methods are used for debugging only
bool mIsReadFence;
@@ -271,7 +295,7 @@
status_t setCyclicIntraMacroblockRefresh(const sp<AMessage> &msg, int32_t mode);
status_t allocateBuffersOnPort(OMX_U32 portIndex);
status_t freeBuffersOnPort(OMX_U32 portIndex);
- status_t freeBuffer(OMX_U32 portIndex, size_t i);
+ virtual status_t freeBuffer(OMX_U32 portIndex, size_t i);
status_t handleSetSurface(const sp<Surface> &surface);
status_t setupNativeWindowSizeFormatAndUsage(
@@ -300,8 +324,8 @@
uint32_t portIndex, IOMX::buffer_id bufferID,
ssize_t *index = NULL);
- status_t setComponentRole(bool isEncoder, const char *mime);
- status_t configureCodec(const char *mime, const sp<AMessage> &msg);
+ virtual status_t setComponentRole(bool isEncoder, const char *mime);
+ virtual status_t configureCodec(const char *mime, const sp<AMessage> &msg);
status_t configureTunneledVideoPlayback(int32_t audioHwSync,
const sp<ANativeWindow> &nativeWindow);
@@ -314,10 +338,10 @@
status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);
- status_t setupVideoDecoder(
+ virtual status_t setupVideoDecoder(
const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers);
- status_t setupVideoEncoder(
+ virtual status_t setupVideoEncoder(
const char *mime, const sp<AMessage> &msg);
status_t setVideoFormatOnPort(
@@ -372,7 +396,7 @@
status_t configureBitrate(
int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode);
- status_t setupErrorCorrectionParameters();
+ virtual status_t setupErrorCorrectionParameters();
status_t initNativeWindow();
@@ -408,7 +432,7 @@
bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL);
void sendFormatChange(const sp<AMessage> &reply);
- status_t getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify);
+ virtual status_t getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify);
void signalError(
OMX_ERRORTYPE error = OMX_ErrorUndefined,
@@ -420,11 +444,41 @@
DescribeColorFormatParams &describeParams);
status_t requestIDRFrame();
- status_t setParameters(const sp<AMessage> ¶ms);
+ virtual status_t setParameters(const sp<AMessage> ¶ms);
// Send EOS on input stream.
void onSignalEndOfInputStream();
+ virtual void setBFrames(OMX_VIDEO_PARAM_MPEG4TYPE *mpeg4type) {}
+ virtual void setBFrames(OMX_VIDEO_PARAM_AVCTYPE *h264type,
+ const int32_t iFramesInterval, const int32_t frameRate) {}
+
+ virtual status_t getVQZIPInfo(const sp<AMessage> &msg) {
+ return OK;
+ }
+ virtual bool canAllocateBuffer(OMX_U32 /* portIndex */) {
+ return false;
+ }
+ virtual void enableCustomAllocationMode(const sp<AMessage> &/* msg */) {}
+ virtual status_t allocateBuffer(
+ OMX_U32 portIndex, size_t bufSize, BufferInfo &info);
+
+ virtual status_t setDSModeHint(sp<AMessage>& msg,
+ OMX_U32 flags, int64_t timeUs) {
+ return UNKNOWN_ERROR;
+ }
+
+ virtual bool getDSModeHint(const sp<AMessage>& msg) {
+ return false;
+ }
+
+ sp<IOMXObserver> createObserver();
+#ifdef DOLBY_ENABLE
+ status_t setDolbyParameterOnEndpChange();
+ void setDolbyParameter(const sp<AMessage> &msg);
+ status_t setDolbyParameterOnProcessedAudio(const sp<AMessage> ¶ms);
+#endif // DOLBY_END
+
DISALLOW_EVIL_CONSTRUCTORS(ACodec);
};
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index e0cd965..20ce4a4 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef AUDIO_PLAYER_H_
@@ -138,6 +157,9 @@
AudioPlayer(const AudioPlayer &);
AudioPlayer &operator=(const AudioPlayer &);
+#ifdef DOLBY_ENABLE
+ void setDolbyProcessedAudio(sp<MetaData> &format);
+#endif // DOLBY_END
};
} // namespace android
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 3074910..9750bcd 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -46,6 +46,8 @@
virtual status_t stop() { return reset(); }
virtual sp<MetaData> getFormat();
+ virtual status_t pause() { return ERROR_UNSUPPORTED; }
+
// Returns the maximum amplitude since last call.
int16_t getMaxAmplitude();
@@ -58,9 +60,11 @@
protected:
virtual ~AudioSource();
-private:
+protected:
enum {
- kMaxBufferSize = 2048,
+ //calculated for max duration 80 msec with 48K sampling rate.
+ kMaxBufferSize = 30720,
+
// After the initial mute, we raise the volume linearly
// over kAutoRampDurationUs.
@@ -68,7 +72,7 @@
// This is the initial mute duration to suppress
// the video recording signal tone
- kAutoRampStartUs = 0,
+ kAutoRampStartUs = 500000,
};
Mutex mLock;
@@ -100,10 +104,10 @@
int32_t startFrame, int32_t rampDurationFrames,
uint8_t *data, size_t bytes);
- void queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs);
+ virtual void queueInputBuffer_l(MediaBuffer *buffer, int64_t timeUs);
void releaseQueuedFrames_l();
void waitOutstandingEncodingFrames_l();
- status_t reset();
+ virtual status_t reset();
AudioSource(const AudioSource &);
AudioSource &operator=(const AudioSource &);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 069e897..527ee15 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -92,6 +92,8 @@
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
+ virtual status_t pause() { return ERROR_UNSUPPORTED; }
+
/**
* Check whether a CameraSource object is properly initialized.
* Must call this method before stop().
@@ -189,7 +191,7 @@
void releaseCamera();
-private:
+protected:
friend struct CameraSourceListener;
Mutex mLock;
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index 34213be..f264d98 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -20,6 +20,7 @@
#include <pthread.h>
+#include <media/stagefright/CameraSource.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <utils/String16.h>
@@ -56,7 +57,7 @@
// returning quickly.
void startQuickReadReturns();
-private:
+protected:
// size of the encoded video.
int32_t mVideoWidth;
int32_t mVideoHeight;
@@ -152,7 +153,7 @@
// the frame needs to be encoded, it returns false and also modifies
// the time stamp to be one frame time ahead of the last encoded
// frame's time stamp.
- bool skipFrameAndModifyTimeStamp(int64_t *timestampUs);
+ virtual bool skipFrameAndModifyTimeStamp(int64_t *timestampUs);
// Wrapper to enter threadTimeLapseEntry()
static void *ThreadTimeLapseWrapper(void *me);
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index dcde36f..0c31e72 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -51,7 +51,8 @@
const char *uri,
const KeyedVector<String8, String8> *headers = NULL,
String8 *contentType = NULL,
- HTTPBase *httpSource = NULL);
+ HTTPBase *httpSource = NULL,
+ bool useExtendedCache = false);
static sp<DataSource> CreateMediaHTTP(const sp<IMediaHTTPService> &httpService);
static sp<DataSource> CreateFromIDataSource(const sp<IDataSource> &source);
diff --git a/include/media/stagefright/ExtendedMediaDefs.h b/include/media/stagefright/ExtendedMediaDefs.h
new file mode 100644
index 0000000..18b5e9a
--- /dev/null
+++ b/include/media/stagefright/ExtendedMediaDefs.h
@@ -0,0 +1,69 @@
+/*Copyright (c) 2015, 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 _EXTENDED_MEDIA_DEFS_H_
+#define _EXTENDED_MEDIA_DEFS_H_
+
+namespace android {
+
+extern const char *MEDIA_MIMETYPE_AUDIO_EVRC;
+extern const char *MEDIA_MIMETYPE_VIDEO_WMV;
+extern const char *MEDIA_MIMETYPE_VIDEO_WMV_VC1;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA_PRO;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA_LOSSLESS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_ASF;
+extern const char *MEDIA_MIMETYPE_VIDEO_DIVX;
+extern const char *MEDIA_MIMETYPE_CONTAINER_AAC;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCP;
+extern const char *MEDIA_MIMETYPE_VIDEO_DIVX311;
+extern const char *MEDIA_MIMETYPE_VIDEO_DIVX4;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2;
+extern const char *MEDIA_MIMETYPE_CONTAINER_3G2;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR;
+extern const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS;
+extern const char *MEDIA_MIMETYPE_AUDIO_AIFF;
+extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_APE;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCWAV;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2PS;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG4;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCOGG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QCFLV;
+extern const char *MEDIA_MIMETYPE_VIDEO_VPX;
+extern const char *MEDIA_MIMETYPE_CONTAINER_QTIFLAC;
+extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4_DP;
+
+} // namespace android
+
+#endif // _EXTENDED_MEDIA_DEFS_H_
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index a195fe8..055c079 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -108,6 +108,8 @@
sp<AMessage> mMetaKeys;
+ bool mIsVideoHEVC;
+
void setStartTimestampUs(int64_t timeUs);
int64_t getStartTimestampUs(); // Not const
status_t startTracks(MetaData *params);
@@ -181,6 +183,9 @@
// By default, real time recording is on.
bool isRealTimeRecording() const;
+ // To use 3gp4 box for clips with AMR audio
+ bool mIsAudioAMR;
+
void lock();
void unlock();
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index c10963d..9c489e5 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -51,6 +51,8 @@
BUFFER_FLAG_SYNCFRAME = 1,
BUFFER_FLAG_CODECCONFIG = 2,
BUFFER_FLAG_EOS = 4,
+ BUFFER_FLAG_EXTRADATA = 0x1000,
+ BUFFER_FLAG_DATACORRUPT = 0x2000,
};
enum {
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 71f58a9..d41d87b 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -28,7 +28,7 @@
struct AReplyToken;
class IGraphicBufferProducer;
class IGraphicBufferConsumer;
-class MediaCodec;
+struct MediaCodec;
class MetaData;
struct MediaCodecSource : public MediaSource,
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 21eb04a..21e7704 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef MEDIA_DEFS_H_
@@ -49,6 +68,9 @@
extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM;
extern const char *MEDIA_MIMETYPE_AUDIO_AC3;
extern const char *MEDIA_MIMETYPE_AUDIO_EAC3;
+#ifdef DOLBY_ENABLE
+extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC;
+#endif // DOLBY_END
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
@@ -68,4 +90,6 @@
} // namespace android
+#include <media/stagefright/ExtendedMediaDefs.h>
+
#endif // MEDIA_DEFS_H_
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 183933a..32925ca 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -29,7 +29,8 @@
class MediaExtractor : public RefBase {
public:
static sp<MediaExtractor> Create(
- const sp<DataSource> &source, const char *mime = NULL);
+ const sp<DataSource> &source, const char *mime = NULL,
+ const uint32_t flags = 0);
virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;
@@ -67,6 +68,7 @@
}
virtual void setUID(uid_t uid) {
}
+ virtual void setExtraFlags(uint32_t flag) {}
protected:
MediaExtractor() : mIsDrm(false) {}
diff --git a/include/media/stagefright/MediaHTTP.h b/include/media/stagefright/MediaHTTP.h
index 006d8d8..88683bd 100644
--- a/include/media/stagefright/MediaHTTP.h
+++ b/include/media/stagefright/MediaHTTP.h
@@ -54,7 +54,7 @@
virtual String8 getUri();
virtual String8 getMIMEType() const;
-private:
+protected:
status_t mInitCheck;
sp<IMediaHTTPConnection> mHTTPConnection;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 7fabcb3..5418df2 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef OMX_CODEC_H_
@@ -361,6 +380,10 @@
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
+#ifdef DOLBY_ENABLE
+ static uint32_t getDolbyComponentQuirks(const sp<MediaCodecInfo> &info);
+ void setDolbyProcessedAudio();
+#endif // DOLBY_END
};
struct CodecCapabilities {
diff --git a/media/libavextensions/Android.mk b/media/libavextensions/Android.mk
new file mode 100644
index 0000000..0380135
--- /dev/null
+++ b/media/libavextensions/Android.mk
@@ -0,0 +1,92 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ stagefright/ExtendedMediaDefs.cpp \
+ stagefright/AVUtils.cpp \
+ stagefright/AVFactory.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/av/include/media/ \
+ $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/flac/include \
+ $(TOP)/hardware/qcom/media/mm-core/inc \
+ $(TOP)/frameworks/av/media/libstagefright \
+
+LOCAL_CFLAGS += -Wno-multichar -Werror
+
+ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
+ LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS
+endif
+
+LOCAL_MODULE:= libavextensions
+LOCAL_CLANG := false
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
+########################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ media/AVMediaUtils.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/av/include/media/ \
+ $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/flac/include \
+ $(TOP)/hardware/qcom/media/mm-core/inc
+
+LOCAL_CFLAGS += -Wno-multichar -Werror
+
+ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
+ LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS
+endif
+
+LOCAL_MODULE:= libavmediaextentions
+LOCAL_CLANG := false
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
+########################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ mediaplayerservice/AVMediaServiceFactory.cpp \
+ mediaplayerservice/AVMediaServiceUtils.cpp \
+ mediaplayerservice/AVNuFactory.cpp \
+ mediaplayerservice/AVNuUtils.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(TOP)/frameworks/av/include/media/ \
+ $(TOP)/frameworks/av/media/libmediaplayerservice \
+ $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/av/media/libstagefright/include \
+ $(TOP)/frameworks/av/media/libstagefright/rtsp \
+ $(TOP)/frameworks/native/include/media/hardware \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/external/flac/include \
+ $(TOP)/hardware/qcom/media/mm-core/inc
+
+LOCAL_CFLAGS += -Wno-multichar -Werror
+
+ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
+ LOCAL_CFLAGS += -DENABLE_AV_ENHANCEMENTS
+endif
+
+LOCAL_MODULE:= libavmediaserviceextensions
+LOCAL_CLANG := false
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/media/libavextensions/common/AVExtensionsCommon.h b/media/libavextensions/common/AVExtensionsCommon.h
new file mode 100644
index 0000000..c39872e
--- /dev/null
+++ b/media/libavextensions/common/AVExtensionsCommon.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 _AV_EXTENSIONS_COMMON_H_
+#define _AV_EXTENSIONS_COMMON_H_
+
+namespace android {
+
+typedef void *(*createFunction_t)(void);
+
+template <typename T>
+struct ExtensionsLoader {
+
+ static T *createInstance(const char *createFunctionName);
+
+private:
+ static void loadLib();
+ static createFunction_t loadCreateFunction(const char *createFunctionName);
+ static void *mLibHandle;
+};
+
+/*
+ * Boiler-plate to declare the class as a singleton (with a static getter)
+ * which can be loaded (dlopen'd) via ExtensionsLoader
+ */
+#define DECLARE_LOADABLE_SINGLETON(className) \
+protected: \
+ className(); \
+ virtual ~className(); \
+ static className *sInst; \
+private: \
+ className(const className&); \
+ className &operator=(className &); \
+public: \
+ static className *get() { \
+ return sInst; \
+ } \
+ friend struct ExtensionsLoader<className>;
+
+} //namespace android
+
+#endif // _AV_EXTENSIONS_COMMON_H_
diff --git a/media/libavextensions/common/ExtensionsLoader.hpp b/media/libavextensions/common/ExtensionsLoader.hpp
new file mode 100644
index 0000000..e03979c
--- /dev/null
+++ b/media/libavextensions/common/ExtensionsLoader.hpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 - 2015, 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.
+ */
+#include <dlfcn.h>
+#include <common/AVExtensionsCommon.h>
+
+namespace android {
+
+static const char * CUSTOMIZATION_LIB_NAME = "libavenhancements.so";
+
+/*
+ * Create strongly-typed objects of type T
+ * If the customization library exists and does contain a "named" constructor,
+ * invoke and create an instance
+ * Else create the object of type T itself
+ *
+ * Contains a static instance to dlopen'd library, But may end up
+ * opening the library mutiple times. Following snip from dlopen man page is
+ * reassuring "...Only a single copy of an object file is brought into the
+ * address space, even if dlopen() is invoked multiple times in reference to
+ * the file, and even if different pathnames are used to reference the file.."
+ */
+
+template <typename T>
+T *ExtensionsLoader<T>::createInstance(const char *createFunctionName) {
+ ALOGV("createInstance(%dbit) : %s", sizeof(intptr_t)*8, createFunctionName);
+ // create extended object if extensions-lib is available and
+ // AV_ENHANCEMENTS is enabled
+#if ENABLE_AV_ENHANCEMENTS
+ createFunction_t createFunc = loadCreateFunction(createFunctionName);
+ if (createFunc) {
+ return reinterpret_cast<T *>((*createFunc)());
+ }
+#endif
+ // Else, create the default object
+ return new T;
+}
+
+template <typename T>
+void ExtensionsLoader<T>::loadLib() {
+ if (!mLibHandle) {
+ mLibHandle = ::dlopen(CUSTOMIZATION_LIB_NAME, RTLD_LAZY);
+ if (!mLibHandle) {
+ ALOGV("%s", dlerror());
+ return;
+ }
+ ALOGV("Opened %s", CUSTOMIZATION_LIB_NAME);
+ }
+}
+
+template <typename T>
+createFunction_t ExtensionsLoader<T>::loadCreateFunction(const char *createFunctionName) {
+ loadLib();
+ if (!mLibHandle) {
+ return NULL;
+ }
+ createFunction_t func = (createFunction_t)dlsym(mLibHandle, createFunctionName);
+ if (!func) {
+ ALOGW("symbol %s not found: %s",createFunctionName, dlerror());
+ }
+ return func;
+}
+
+//static
+template <typename T>
+void *ExtensionsLoader<T>::mLibHandle = NULL;
+
+} //namespace android
diff --git a/media/libavextensions/media/AVMediaExtensions.h b/media/libavextensions/media/AVMediaExtensions.h
new file mode 100644
index 0000000..9161fae
--- /dev/null
+++ b/media/libavextensions/media/AVMediaExtensions.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 _AV_MEDIA_EXTENSIONS_H_
+#define _AV_MEDIA_EXTENSIONS_H_
+
+#include <common/AVExtensionsCommon.h>
+#include <hardware/audio.h>
+#include <media/AudioTrack.h>
+
+namespace android {
+
+class MediaRecorder;
+class Parcel;
+/*
+ * Common delegate to the classes in libstagefright
+ */
+struct AVMediaUtils {
+
+ virtual bool AudioTrackIsPcmOffloaded(const audio_format_t /*format*/) {
+ return false;
+ }
+ virtual status_t AudioTrackGetPosition(AudioTrack* /*track*/,
+ uint32_t* /*position*/) {
+ return NO_INIT;
+ }
+
+ virtual status_t AudioTrackGetTimestamp(AudioTrack* /*track*/,
+ AudioTimestamp* /*timestamp*/) {
+ return NO_INIT;
+ }
+
+ virtual size_t AudioTrackGetOffloadFrameCount(size_t frameCount) {
+ return frameCount;
+ }
+
+ virtual bool AudioTrackIsTrackOffloaded(audio_io_handle_t /*output*/) {
+ return false;
+ }
+
+ virtual sp<MediaRecorder> createMediaRecorder(const String16& opPackageName);
+ virtual void writeCustomData(
+ Parcel * /* reply */, void * /* buffer_data */) {}
+ virtual void readCustomData(
+ const Parcel * /* reply */, void ** /*buffer_data */ ) {}
+ virtual void closeFileDescriptor(void * /* buffer_ptr */) {}
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVMediaUtils);
+};
+
+} //namespace android
+
+#endif //_AV_MEDIA_EXTENSIONS_H_
+
diff --git a/media/libavextensions/media/AVMediaUtils.cpp b/media/libavextensions/media/AVMediaUtils.cpp
new file mode 100644
index 0000000..0f9e9eb
--- /dev/null
+++ b/media/libavextensions/media/AVMediaUtils.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 "AVMediaUtils"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/ACodec.h>
+
+#include <media/AudioTrack.h>
+#include <media/mediarecorder.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "media/AVMediaExtensions.h"
+
+namespace android {
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVMediaUtils::AVMediaUtils() {
+}
+
+AVMediaUtils::~AVMediaUtils() {
+}
+
+sp<MediaRecorder> AVMediaUtils::createMediaRecorder(const String16& opPackageName) {
+ return new MediaRecorder(opPackageName);
+}
+
+//static
+AVMediaUtils *AVMediaUtils::sInst =
+ ExtensionsLoader<AVMediaUtils>::createInstance("createExtendedMediaUtils");
+
+} //namespace android
+
diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h b/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h
new file mode 100644
index 0000000..f2c789e
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVMediaServiceExtensions.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 _AV_MEDIA_SERVICE_EXTENSIONS_H_
+#define _AV_MEDIA_SERVICE_EXTENSIONS_H_
+
+#include <common/AVExtensionsCommon.h>
+#include <MediaPlayerFactory.h>
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/String16.h>
+
+#include <media/Metadata.h>
+
+namespace android {
+
+struct StagefrightRecorder;
+struct ARTSPConnection;
+struct ARTPConnection;
+struct AString;
+struct MyHandler;
+struct ABuffer;
+
+/*
+ * Factory to create objects of base-classes in libmediaplayerservice
+ */
+struct AVMediaServiceFactory {
+ virtual StagefrightRecorder *createStagefrightRecorder(const String16 &);
+
+ // RTSP extensions
+ virtual sp<ARTSPConnection> createARTSPConnection(bool uidValid, uid_t uid);
+ virtual sp<ARTPConnection> createARTPConnection();
+
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVMediaServiceFactory);
+};
+
+/*
+ * Common delegate to the classes in libmediaplayerservice
+ */
+struct AVMediaServiceUtils {
+ virtual void getDashPlayerFactory(MediaPlayerFactory::IFactory *&, player_type ) {}
+ // RTSP IPV6 utils
+ virtual bool pokeAHole(sp<MyHandler> handler, int rtpSocket, int rtcpSocket,
+ const AString &transport, const AString &sessionHost);
+ virtual void makePortPair(int *rtpSocket, int *rtcpSocket, unsigned *rtpPort,
+ bool isIPV6);
+ virtual const char* parseURL(AString *host);
+ // RTSP customization utils
+ virtual bool parseTrackURL(AString url, AString val);
+ virtual void appendRange(AString *request);
+ virtual void setServerTimeoutUs(int64_t timeout);
+ virtual void appendMeta(media::Metadata *meta);
+ virtual bool checkNPTMapping(uint32_t *rtpInfoTime, int64_t *playTimeUs,
+ bool *nptValid, uint32_t rtpTime);
+ virtual void addH263AdvancedPacket(const sp<ABuffer> &buffer,
+ List<sp<ABuffer>> *packets, uint32_t rtpTime);
+ virtual bool parseNTPRange(const char *s, float *npt1, float *npt2);
+
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVMediaServiceUtils);
+};
+
+}
+
+#endif // _AV_EXTENSIONS__H_
diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp b/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp
new file mode 100644
index 0000000..10b66f5
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVMediaServiceFactory.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 - 2015, 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_TAG "AVMediaServiceFactory"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include "ARTPConnection.h"
+#include "ARTSPConnection.h"
+
+#include "MediaRecorderClient.h"
+#include "MediaPlayerService.h"
+#include "StagefrightRecorder.h"
+
+#include "common/ExtensionsLoader.hpp"
+#include "mediaplayerservice/AVMediaServiceExtensions.h"
+
+namespace android {
+StagefrightRecorder *AVMediaServiceFactory::createStagefrightRecorder(
+ const String16 &opPackageName) {
+ return new StagefrightRecorder(opPackageName);
+}
+
+sp<ARTSPConnection> AVMediaServiceFactory::createARTSPConnection(
+ bool uidValid, uid_t uid) {
+ return new ARTSPConnection(uidValid, uid);
+}
+
+sp<ARTPConnection> AVMediaServiceFactory::createARTPConnection() {
+ return new ARTPConnection();
+}
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVMediaServiceFactory::AVMediaServiceFactory() {
+}
+
+AVMediaServiceFactory::~AVMediaServiceFactory() {
+}
+
+//static
+AVMediaServiceFactory *AVMediaServiceFactory::sInst =
+ ExtensionsLoader<AVMediaServiceFactory>::createInstance("createExtendedMediaServiceFactory");
+
+} //namespace android
+
diff --git a/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp
new file mode 100644
index 0000000..0e42367
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVMediaServiceUtils.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2013 - 2015, 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_TAG "AVMediaServiceUtils"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include "ARTPConnection.h"
+#include "ASessionDescription.h"
+#include "MyHandler.h"
+
+#include "common/ExtensionsLoader.hpp"
+#include "mediaplayerservice/AVMediaServiceExtensions.h"
+
+namespace android {
+
+bool AVMediaServiceUtils::pokeAHole(sp<MyHandler> handler, int rtpSocket, int rtcpSocket,
+ const AString &transport, const AString &/*sessionHost*/) {
+ if (handler == NULL) {
+ ALOGW("MyHandler is NULL");
+ return false;
+ }
+ return handler->pokeAHole(rtpSocket, rtcpSocket, transport);
+}
+
+void AVMediaServiceUtils::makePortPair(int *rtpSocket, int *rtcpSocket, unsigned *rtpPort,
+ bool /*isIPV6*/) {
+ return ARTPConnection::MakePortPair(rtpSocket, rtcpSocket, rtpPort);
+}
+
+const char* AVMediaServiceUtils::parseURL(AString *host) {
+ return strchr(host->c_str(), ':');
+}
+
+bool AVMediaServiceUtils::parseTrackURL(AString /*url*/, AString /*val*/) {
+ return false;
+}
+
+void AVMediaServiceUtils::appendRange(AString * /*request*/) {
+ return;
+}
+
+void AVMediaServiceUtils::setServerTimeoutUs(int64_t /*timeout*/) {
+ return;
+}
+
+void AVMediaServiceUtils::addH263AdvancedPacket(const sp<ABuffer> &/*buffer*/,
+ List<sp<ABuffer>> * /*packets*/, uint32_t /*rtpTime*/) {
+ return;
+}
+
+void AVMediaServiceUtils::appendMeta(media::Metadata * /*meta*/) {
+ return;
+}
+
+bool AVMediaServiceUtils::checkNPTMapping(uint32_t * /*rtpInfoTime*/, int64_t * /*playTimeUs*/,
+ bool * /*nptValid*/, uint32_t /*rtpTime*/) {
+ return false;
+}
+
+bool AVMediaServiceUtils::parseNTPRange(const char *s, float *npt1, float *npt2) {
+ return ASessionDescription::parseNTPRange(s, npt1, npt2);
+}
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVMediaServiceUtils::AVMediaServiceUtils() {
+}
+
+AVMediaServiceUtils::~AVMediaServiceUtils() {
+}
+
+//static
+AVMediaServiceUtils *AVMediaServiceUtils::sInst =
+ ExtensionsLoader<AVMediaServiceUtils>::createInstance("createExtendedMediaServiceUtils");
+
+} //namespace android
+
diff --git a/media/libavextensions/mediaplayerservice/AVNuExtensions.h b/media/libavextensions/mediaplayerservice/AVNuExtensions.h
new file mode 100644
index 0000000..d7e29d1
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVNuExtensions.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 _AV_NU_EXTENSIONS_H_
+#define _AV_NU_EXTENSIONS_H_
+
+#include <common/AVExtensionsCommon.h>
+
+namespace android {
+
+struct NuPlayer;
+/*
+ * Factory to create extended NuPlayer objects
+ */
+struct AVNuFactory {
+ virtual sp<NuPlayer> createNuPlayer(pid_t pid);
+
+ virtual sp<NuPlayer::DecoderBase> createPassThruDecoder(
+ const sp<AMessage> ¬ify,
+ const sp<NuPlayer::Source> &source,
+ const sp<NuPlayer::Renderer> &renderer);
+
+ virtual sp<NuPlayer::DecoderBase> createDecoder(
+ const sp<AMessage> ¬ify,
+ const sp<NuPlayer::Source> &source,
+ pid_t pid,
+ const sp<NuPlayer::Renderer> &renderer);
+
+ virtual sp<NuPlayer::Renderer> createRenderer(
+ const sp<MediaPlayerBase::AudioSink> &sink,
+ const sp<AMessage> ¬ify,
+ uint32_t flags);
+
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVNuFactory);
+};
+
+/*
+ * Common delegate to the classes in NuPlayer
+ */
+struct AVNuUtils {
+
+ virtual sp<MetaData> createPCMMetaFromSource(const sp<MetaData> &);
+ virtual bool pcmOffloadException(const sp<MetaData> &);
+ virtual bool isRAWFormat(const sp<MetaData> &);
+ virtual bool isRAWFormat(const sp<AMessage> &);
+ virtual bool isVorbisFormat(const sp<MetaData> &);
+ virtual int updateAudioBitWidth(audio_format_t audioFormat,
+ const sp<AMessage> &);
+ virtual audio_format_t getKeyPCMFormat(const sp<MetaData> &);
+ virtual void setKeyPCMFormat(const sp<MetaData> &, audio_format_t audioFormat);
+ virtual audio_format_t getPCMFormat(const sp<AMessage> &);
+ virtual void setPCMFormat(const sp<AMessage> &, audio_format_t audioFormat);
+ virtual void setSourcePCMFormat(const sp<MetaData> &);
+ virtual void setDecodedPCMFormat(const sp<AMessage> &);
+ virtual status_t convertToSinkFormatIfNeeded(const sp<ABuffer> &, sp<ABuffer> &,
+ audio_format_t sinkFormat, bool isOffload);
+ virtual uint32_t getFlags();
+ virtual bool canUseSetBuffers(const sp<MetaData> &Meta);
+
+ virtual void printFileName(int fd);
+ virtual void checkFormatChange(bool *formatChange, const sp<ABuffer> &accessUnit);
+ virtual void addFlagsInMeta(const sp<ABuffer> &buffer, int32_t flags, bool isAudio);
+ virtual bool dropCorruptFrame();
+
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVNuUtils);
+};
+
+}
+
+#endif // _AV_EXTENSIONS__H_
diff --git a/media/libavextensions/mediaplayerservice/AVNuFactory.cpp b/media/libavextensions/mediaplayerservice/AVNuFactory.cpp
new file mode 100644
index 0000000..ff7c074
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVNuFactory.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 "AVNuFactory"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <nuplayer/NuPlayer.h>
+#include <nuplayer/NuPlayerDecoderBase.h>
+#include <nuplayer/NuPlayerDecoderPassThrough.h>
+#include <nuplayer/NuPlayerDecoder.h>
+#include <nuplayer/NuPlayerCCDecoder.h>
+#include <gui/Surface.h>
+#include <nuplayer/NuPlayerSource.h>
+#include <nuplayer/NuPlayerRenderer.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "mediaplayerservice/AVNuExtensions.h"
+
+namespace android {
+
+sp<NuPlayer> AVNuFactory::createNuPlayer(pid_t pid) {
+ return new NuPlayer(pid);
+}
+
+sp<NuPlayer::DecoderBase> AVNuFactory::createPassThruDecoder(
+ const sp<AMessage> ¬ify,
+ const sp<NuPlayer::Source> &source,
+ const sp<NuPlayer::Renderer> &renderer) {
+ return new NuPlayer::DecoderPassThrough(notify, source, renderer);
+}
+
+sp<NuPlayer::DecoderBase> AVNuFactory::createDecoder(
+ const sp<AMessage> ¬ify,
+ const sp<NuPlayer::Source> &source,
+ pid_t pid,
+ const sp<NuPlayer::Renderer> &renderer) {
+ return new NuPlayer::Decoder(notify, source, pid, renderer);
+}
+
+sp<NuPlayer::Renderer> AVNuFactory::createRenderer(
+ const sp<MediaPlayerBase::AudioSink> &sink,
+ const sp<AMessage> ¬ify,
+ uint32_t flags) {
+ return new NuPlayer::Renderer(sink, notify, flags);
+}
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVNuFactory::AVNuFactory() {
+}
+
+AVNuFactory::~AVNuFactory() {
+}
+
+//static
+AVNuFactory *AVNuFactory::sInst =
+ ExtensionsLoader<AVNuFactory>::createInstance("createExtendedNuFactory");
+
+} //namespace android
+
diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
new file mode 100644
index 0000000..6f1fa4d
--- /dev/null
+++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2013 - 2015, 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_TAG "AVNuUtils"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <nuplayer/NuPlayer.h>
+#include <nuplayer/NuPlayerDecoderBase.h>
+#include <nuplayer/NuPlayerDecoderPassThrough.h>
+#include <nuplayer/NuPlayerSource.h>
+#include <nuplayer/NuPlayerRenderer.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "mediaplayerservice/AVNuExtensions.h"
+
+namespace android {
+
+sp<MetaData> AVNuUtils::createPCMMetaFromSource(const sp<MetaData> &sMeta) {
+ return sMeta;
+}
+
+bool AVNuUtils::pcmOffloadException(const sp<MetaData> &) {
+ return true;
+}
+
+bool AVNuUtils::isRAWFormat(const sp<MetaData> &) {
+ return false;
+}
+
+bool AVNuUtils::isRAWFormat(const sp<AMessage> &) {
+ return false;
+}
+
+bool AVNuUtils::isVorbisFormat(const sp<MetaData> &) {
+ return false;
+}
+
+int AVNuUtils::updateAudioBitWidth(audio_format_t /*audioFormat*/,
+ const sp<AMessage> &){
+ return 16;
+}
+
+audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &) {
+ return AUDIO_FORMAT_INVALID;
+}
+
+void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &, audio_format_t /*audioFormat*/) {
+
+}
+
+audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &) {
+ return AUDIO_FORMAT_PCM_16_BIT;
+}
+
+void AVNuUtils::setPCMFormat(const sp<AMessage> &, audio_format_t /*audioFormat*/) {
+
+}
+
+void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &) {
+
+}
+
+void AVNuUtils::setDecodedPCMFormat(const sp<AMessage> &) {
+
+}
+
+status_t AVNuUtils::convertToSinkFormatIfNeeded(const sp<ABuffer> &, sp<ABuffer> &,
+ audio_format_t /*sinkFormat*/, bool /*isOffload*/) {
+ return INVALID_OPERATION;
+}
+
+void AVNuUtils::printFileName(int) {}
+
+void AVNuUtils::checkFormatChange(bool * /*formatChange*/,
+ const sp<ABuffer> & /*accessUnit*/) {
+}
+
+void AVNuUtils::addFlagsInMeta(const sp<ABuffer> & /*buffer*/,
+ int32_t /*flags*/, bool /*isAudio*/) {
+}
+
+uint32_t AVNuUtils::getFlags() {
+ return 0;
+}
+
+bool AVNuUtils::canUseSetBuffers(const sp<MetaData> &/*Meta*/) {
+ return false;
+}
+
+bool AVNuUtils::dropCorruptFrame() { return false; }
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVNuUtils::AVNuUtils() {}
+
+AVNuUtils::~AVNuUtils() {}
+
+//static
+AVNuUtils *AVNuUtils::sInst =
+ ExtensionsLoader<AVNuUtils>::createInstance("createExtendedNuUtils");
+
+} //namespace android
+
diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h
new file mode 100644
index 0000000..bb3f51a
--- /dev/null
+++ b/media/libavextensions/stagefright/AVExtensions.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2013 - 2015, 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 _AV_EXTENSIONS_H_
+#define _AV_EXTENSIONS_H_
+
+#include <media/stagefright/DataSource.h>
+#include <common/AVExtensionsCommon.h>
+#include <system/audio.h>
+#include <camera/ICamera.h>
+#include <media/mediarecorder.h>
+#include <media/IOMX.h>
+
+namespace android {
+
+class AudioParameter;
+class MetaData;
+class MediaExtractor;
+class MPEG4Writer;
+struct ABuffer;
+struct ACodec;
+struct ALooper;
+struct IMediaHTTPConnection;
+struct MediaCodec;
+struct MediaHTTP;
+struct NuCachedSource2;
+class CameraParameters;
+class MediaBuffer;
+struct AudioSource;
+class CameraSource;
+class CameraSourceTimeLapse;
+class ICamera;
+class ICameraRecordingProxy;
+class String16;
+class IGraphicBufferProducer;
+struct Size;
+
+/*
+ * Factory to create objects of base-classes in libstagefright
+ */
+struct AVFactory {
+ virtual sp<ACodec> createACodec();
+ virtual MediaExtractor* createExtendedExtractor(
+ const sp<DataSource> &source, const char *mime,
+ const sp<AMessage> &meta, const uint32_t flags);
+ virtual sp<MediaExtractor> updateExtractor(
+ sp<MediaExtractor> ext, const sp<DataSource> &source,
+ const char *mime, const sp<AMessage> &meta, const uint32_t flags);
+ virtual sp<NuCachedSource2> createCachedSource(
+ const sp<DataSource> &source,
+ const char *cacheConfig = NULL,
+ bool disconnectAtHighwatermark = false);
+ virtual MediaHTTP* createMediaHTTP(
+ const sp<IMediaHTTPConnection> &conn);
+
+ virtual AudioSource* createAudioSource(
+ audio_source_t inputSource,
+ const String16 &opPackageName,
+ uint32_t sampleRate,
+ uint32_t channels,
+ uint32_t outSampleRate = 0);
+
+ virtual CameraSource *CreateCameraSourceFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ const String16& clientName,
+ uid_t clientUid,
+ Size videoSize,
+ int32_t frameRate,
+ const sp<IGraphicBufferProducer>& surface,
+ bool storeMetaDataInVideoBuffers = true);
+
+ virtual CameraSourceTimeLapse *CreateCameraSourceTimeLapseFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ const String16& clientName,
+ uid_t clientUid,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<IGraphicBufferProducer>& surface,
+ int64_t timeBetweenFrameCaptureUs,
+ bool storeMetaDataInVideoBuffers = true);
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVFactory);
+};
+
+/*
+ * Common delegate to the classes in libstagefright
+ */
+struct AVUtils {
+
+ virtual status_t convertMetaDataToMessage(
+ const sp<MetaData> &meta, sp<AMessage> *format);
+ virtual DataSource::SnifferFunc getExtendedSniffer();
+ virtual status_t mapMimeToAudioFormat( audio_format_t& format, const char* mime);
+ virtual status_t sendMetaDataToHal(const sp<MetaData>& meta, AudioParameter *param);
+
+ virtual sp<MediaCodec> createCustomComponentByName(const sp<ALooper> &looper,
+ const char* mime, bool encoder, const sp<AMessage> &format);
+ virtual bool isEnhancedExtension(const char *extension);
+
+ virtual bool is24bitPCMOffloadEnabled();
+ virtual bool is16bitPCMOffloadEnabled();
+ virtual int getAudioSampleBits(const sp<MetaData> &);
+ virtual int getAudioSampleBits(const sp<AMessage> &);
+ virtual void setPcmSampleBits(const sp<MetaData> &, int32_t /*bitWidth*/);
+ virtual void setPcmSampleBits(const sp<AMessage> &, int32_t /*bitWidth*/);
+
+ virtual audio_format_t updateAudioFormat(audio_format_t audioFormat,
+ const sp<MetaData> &);
+
+ virtual audio_format_t updateAudioFormat(audio_format_t audioFormat,
+ const sp<AMessage> &);
+
+ virtual bool canOffloadAPE(const sp<MetaData> &meta);
+
+ virtual int32_t getAudioMaxInputBufferSize(audio_format_t audioFormat,
+ const sp<AMessage> &);
+
+ virtual bool mapAACProfileToAudioFormat(const sp<MetaData> &,
+ audio_format_t &,
+ uint64_t /*eAacProfile*/);
+
+ virtual bool mapAACProfileToAudioFormat(const sp<AMessage> &,
+ audio_format_t &,
+ uint64_t /*eAacProfile*/);
+
+ virtual void extractCustomCameraKeys(
+ const CameraParameters& /*params*/, sp<MetaData> &/*meta*/) {}
+ virtual void printFileName(int /*fd*/) {}
+ virtual void addDecodingTimesFromBatch(MediaBuffer * /*buf*/,
+ List<int64_t> &/*decodeTimeQueue*/) {}
+
+ virtual bool useQCHWEncoder(const sp<AMessage> &, AString &) { return false; }
+
+ virtual bool canDeferRelease(const sp<MetaData> &/*meta*/) { return false; }
+ virtual void setDeferRelease(sp<MetaData> &/*meta*/) {}
+
+ struct HEVCMuxer {
+
+ virtual bool reassembleHEVCCSD(const AString &mime, sp<ABuffer> csd0, sp<MetaData> &meta);
+
+ virtual void writeHEVCFtypBox(MPEG4Writer *writer);
+
+ virtual status_t makeHEVCCodecSpecificData(const uint8_t *data,
+ size_t size, void** codecSpecificData,
+ size_t *codecSpecificDataSize);
+
+ virtual const char *getFourCCForMime(const char *mime);
+
+ virtual void writeHvccBox(MPEG4Writer *writer,
+ void* codecSpecificData, size_t codecSpecificDataSize,
+ bool useNalLengthFour);
+
+ virtual bool isVideoHEVC(const char* mime);
+
+ virtual void getHEVCCodecSpecificDataFromInputFormatIfPossible(
+ sp<MetaData> meta, void **codecSpecificData,
+ size_t *codecSpecificDataSize, bool *gotAllCodecSpecificData);
+
+ protected:
+ HEVCMuxer() {};
+ virtual ~HEVCMuxer() {};
+ friend struct AVUtils;
+ };
+
+ virtual inline HEVCMuxer& HEVCMuxerUtils() {
+ return mHEVCMuxer;
+ }
+
+ virtual bool isAudioMuxFormatSupported(const char *mime);
+ virtual void cacheCaptureBuffers(sp<ICamera> camera, video_encoder encoder);
+ virtual const char *getCustomCodecsLocation();
+ virtual const char *getCustomCodecsPerformanceLocation();
+
+ virtual void setIntraPeriod(
+ int nPFrames, int nBFrames, const sp<IOMX> OMXhandle,
+ IOMX::node_id nodeID);
+
+private:
+ HEVCMuxer mHEVCMuxer;
+ // ----- NO TRESSPASSING BEYOND THIS LINE ------
+ DECLARE_LOADABLE_SINGLETON(AVUtils);
+};
+
+}
+
+#endif // _AV_EXTENSIONS__H_
diff --git a/media/libavextensions/stagefright/AVFactory.cpp b/media/libavextensions/stagefright/AVFactory.cpp
new file mode 100644
index 0000000..2a3810d
--- /dev/null
+++ b/media/libavextensions/stagefright/AVFactory.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013 - 2015, 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_TAG "AVFactory"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/ACodec.h>
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MediaHTTP.h>
+#include <media/stagefright/AudioSource.h>
+#include <media/stagefright/CameraSource.h>
+#include <media/stagefright/CameraSourceTimeLapse.h>
+#include <camera/CameraParameters.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "stagefright/AVExtensions.h"
+#include "include/NuCachedSource2.h"
+
+namespace android {
+
+sp<ACodec> AVFactory::createACodec() {
+ return new ACodec;
+}
+
+MediaExtractor* AVFactory::createExtendedExtractor(
+ const sp<DataSource> &, const char *, const sp<AMessage> &,
+ const uint32_t) {
+ return NULL;
+}
+
+sp<MediaExtractor> AVFactory::updateExtractor(
+ sp<MediaExtractor> ext, const sp<DataSource> &,
+ const char *, const sp<AMessage> &, const uint32_t) {
+ return ext;
+}
+
+sp<NuCachedSource2> AVFactory::createCachedSource(
+ const sp<DataSource> &source,
+ const char *cacheConfig,
+ bool disconnectAtHighwatermark) {
+ return new NuCachedSource2(source, cacheConfig, disconnectAtHighwatermark);
+}
+
+MediaHTTP* AVFactory::createMediaHTTP(
+ const sp<IMediaHTTPConnection> &conn) {
+ return new MediaHTTP(conn);
+}
+
+AudioSource* AVFactory::createAudioSource(
+ audio_source_t inputSource,
+ const String16 &opPackageName,
+ uint32_t sampleRate,
+ uint32_t channels,
+ uint32_t outSampleRate) {
+ return new AudioSource(inputSource, opPackageName, sampleRate,
+ channels, outSampleRate);
+}
+
+CameraSource* AVFactory::CreateCameraSourceFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ const String16& clientName,
+ uid_t clientUid,
+ Size videoSize,
+ int32_t frameRate,
+ const sp<IGraphicBufferProducer>& surface,
+ bool storeMetaDataInVideoBuffers) {
+ return CameraSource::CreateFromCamera(camera, proxy, cameraId,
+ clientName, clientUid, videoSize, frameRate, surface,
+ storeMetaDataInVideoBuffers);
+}
+
+CameraSourceTimeLapse* AVFactory::CreateCameraSourceTimeLapseFromCamera(
+ const sp<ICamera> &camera,
+ const sp<ICameraRecordingProxy> &proxy,
+ int32_t cameraId,
+ const String16& clientName,
+ uid_t clientUid,
+ Size videoSize,
+ int32_t videoFrameRate,
+ const sp<IGraphicBufferProducer>& surface,
+ int64_t timeBetweenFrameCaptureUs,
+ bool storeMetaDataInVideoBuffers) {
+ return CameraSourceTimeLapse::CreateFromCamera(camera, proxy, cameraId,
+ clientName, clientUid, videoSize, videoFrameRate, surface,
+ timeBetweenFrameCaptureUs, storeMetaDataInVideoBuffers);
+}
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVFactory::AVFactory() {
+}
+
+AVFactory::~AVFactory() {
+}
+
+//static
+AVFactory *AVFactory::sInst =
+ ExtensionsLoader<AVFactory>::createInstance("createExtendedFactory");
+
+} //namespace android
+
diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp
new file mode 100644
index 0000000..bf46aca
--- /dev/null
+++ b/media/libavextensions/stagefright/AVUtils.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2013 - 2015, 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_TAG "AVUtils"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/ACodec.h>
+#include <media/stagefright/MediaCodec.h>
+
+#include "common/ExtensionsLoader.hpp"
+#include "stagefright/AVExtensions.h"
+
+namespace android {
+
+status_t AVUtils::convertMetaDataToMessage(
+ const sp<MetaData> &, sp<AMessage> *) {
+ return OK;
+}
+
+status_t AVUtils::mapMimeToAudioFormat(
+ audio_format_t&, const char* ) {
+ return OK;
+}
+
+status_t AVUtils::sendMetaDataToHal(
+ const sp<MetaData>&, AudioParameter *){
+ return OK;
+}
+
+bool AVUtils::is24bitPCMOffloadEnabled() {return false;}
+bool AVUtils::is16bitPCMOffloadEnabled() {return false;}
+
+int AVUtils::getAudioSampleBits(const sp<MetaData> &) {
+ return 16;
+}
+
+int AVUtils::getAudioSampleBits(const sp<AMessage> &) {
+ return 16;
+}
+
+void AVUtils::setPcmSampleBits(const sp<AMessage> &, int32_t /*bitWidth*/) {
+}
+
+void AVUtils::setPcmSampleBits(const sp<MetaData> &, int32_t /*bitWidth*/) {
+}
+
+audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat,
+ const sp<MetaData> &){
+ return audioFormat;
+}
+
+audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat,
+ const sp<AMessage> &){
+ return audioFormat;
+}
+
+static bool dumbSniffer(
+ const sp<DataSource> &, String8 *,
+ float *, sp<AMessage> *) {
+ return false;
+}
+
+DataSource::SnifferFunc AVUtils::getExtendedSniffer() {
+ return dumbSniffer;
+}
+
+sp<MediaCodec> AVUtils::createCustomComponentByName(
+ const sp<ALooper> &, const char* , bool, const sp<AMessage> &) {
+ return NULL;
+}
+
+bool AVUtils::canOffloadAPE(const sp<MetaData> &) {
+ return true;
+}
+
+int32_t AVUtils::getAudioMaxInputBufferSize(audio_format_t, const sp<AMessage> &) {
+ return 0;
+}
+
+bool AVUtils::mapAACProfileToAudioFormat(const sp<MetaData> &, audio_format_t &,
+ uint64_t /*eAacProfile*/) {
+ return false ;
+}
+
+bool AVUtils::mapAACProfileToAudioFormat(const sp<AMessage> &, audio_format_t &,
+ uint64_t /*eAacProfile*/) {
+ return false ;
+}
+
+bool AVUtils::isEnhancedExtension(const char *) {
+ return false;
+}
+
+bool AVUtils::HEVCMuxer::reassembleHEVCCSD(const AString &/*mime*/, sp<ABuffer> /*csd0*/, sp<MetaData> &/*meta*/) {
+ return false;
+}
+
+void AVUtils::HEVCMuxer::writeHEVCFtypBox(MPEG4Writer * /*writer*/) {
+ return;
+}
+
+status_t AVUtils::HEVCMuxer::makeHEVCCodecSpecificData(const uint8_t * /*data*/,
+ size_t /*size*/, void ** /*codecSpecificData*/,
+ size_t * /*codecSpecificDataSize*/) {
+ return UNKNOWN_ERROR;
+}
+
+const char *AVUtils::HEVCMuxer::getFourCCForMime(const char * /*mime*/) {
+ return NULL;
+}
+
+void AVUtils::HEVCMuxer::writeHvccBox(MPEG4Writer * /*writer*/,
+ void * /*codecSpecificData*/, size_t /*codecSpecificDataSize*/,
+ bool /*useNalLengthFour*/) {
+ return;
+}
+
+bool AVUtils::HEVCMuxer::isVideoHEVC(const char * /*mime*/) {
+ return false;
+}
+
+void AVUtils::HEVCMuxer::getHEVCCodecSpecificDataFromInputFormatIfPossible(
+ sp<MetaData> /*meta*/, void ** /*codecSpecificData*/,
+ size_t * /*codecSpecificDataSize*/, bool * /*gotAllCodecSpecificData*/) {
+ return;
+}
+
+bool AVUtils::isAudioMuxFormatSupported(const char *) {
+ return true;
+}
+
+void AVUtils::cacheCaptureBuffers(sp<ICamera>, video_encoder) {
+ return;
+}
+
+const char *AVUtils::getCustomCodecsLocation() {
+ return "/etc/media_codecs.xml";
+}
+
+void AVUtils::setIntraPeriod(
+ int, int, const sp<IOMX>,
+ IOMX::node_id) {
+ return;
+}
+
+const char *AVUtils::getCustomCodecsPerformanceLocation() {
+ return "/etc/media_codecs_performance.xml";
+}
+
+// ----- NO TRESSPASSING BEYOND THIS LINE ------
+AVUtils::AVUtils() {}
+
+AVUtils::~AVUtils() {}
+
+//static
+AVUtils *AVUtils::sInst =
+ ExtensionsLoader<AVUtils>::createInstance("createExtendedUtils");
+
+} //namespace android
+
diff --git a/media/libavextensions/stagefright/ExtendedMediaDefs.cpp b/media/libavextensions/stagefright/ExtendedMediaDefs.cpp
new file mode 100644
index 0000000..cf2683c
--- /dev/null
+++ b/media/libavextensions/stagefright/ExtendedMediaDefs.cpp
@@ -0,0 +1,68 @@
+/*Copyright (c) 2012 - 2015, 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.
+ *
+ */
+
+#include <stagefright/ExtendedMediaDefs.h>
+
+namespace android {
+
+const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
+const char *MEDIA_MIMETYPE_VIDEO_WMV = "video/x-ms-wmv";
+const char *MEDIA_MIMETYPE_VIDEO_WMV_VC1 = "video/wvc1";
+const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
+const char *MEDIA_MIMETYPE_AUDIO_WMA_PRO = "audio/x-ms-wma-pro";
+const char *MEDIA_MIMETYPE_AUDIO_WMA_LOSSLESS = "audio/x-ms-wma-lossless";
+const char *MEDIA_MIMETYPE_CONTAINER_ASF = "video/x-ms-asf";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX = "video/divx";
+const char *MEDIA_MIMETYPE_CONTAINER_AAC = "audio/aac";
+const char *MEDIA_MIMETYPE_CONTAINER_QCP = "audio/vnd.qcelp";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX311 = "video/divx311";
+const char *MEDIA_MIMETYPE_VIDEO_DIVX4 = "video/divx4";
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG2 = "video/mp2";
+const char *MEDIA_MIMETYPE_CONTAINER_3G2 = "video/3g2";
+const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/dts";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_LBR = "audio/dts-lbr";
+const char *MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS = "audio/amr-wb-plus";
+const char *MEDIA_MIMETYPE_AUDIO_AIFF = "audio/x-aiff";
+const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
+const char *MEDIA_MIMETYPE_AUDIO_APE = "audio/x-ape";
+const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_NB = "audio/qc-amr";
+const char *MEDIA_MIMETYPE_CONTAINER_QCAMR_WB = "audio/qc-amr-wb";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG = "audio/qc-mpeg";
+const char *MEDIA_MIMETYPE_CONTAINER_QCWAV = "audio/qc-wav";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2TS = "video/qc-mp2ts";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG2PS = "video/qc-mp2ps";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMPEG4 = "video/qc-mp4";
+const char *MEDIA_MIMETYPE_CONTAINER_QCMATROSKA = "video/qc-matroska";
+const char *MEDIA_MIMETYPE_CONTAINER_QCOGG = "video/qc-ogg";
+const char *MEDIA_MIMETYPE_CONTAINER_QCFLV = "video/qc-flv";
+const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8"; //backward compatibility
+const char *MEDIA_MIMETYPE_CONTAINER_QTIFLAC = "audio/qti-flac";
+const char *MEDIA_MIMETYPE_VIDEO_MPEG4_DP = "video/mp4v-esdp";
+
+} // namespace android
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
index c3c4b67..5ae93d3 100644
--- a/media/libeffects/data/audio_effects.conf
+++ b/media/libeffects/data/audio_effects.conf
@@ -1,3 +1,22 @@
+#
+# This file was modified by Dolby Laboratories, Inc. The portions of the
+# code that are surrounded by "DOLBY..." are copyrighted and
+# licensed separately, as follows:
+#
+# (C) 2012-2015 Dolby Laboratories, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
# List of effect libraries to load. Each library element must contain a "path" element
# giving the full path of the library .so file.
# libraries {
@@ -38,6 +57,14 @@
loudness_enhancer {
path /system/lib/soundfx/libldnhncr.so
}
+#DOLBY_DAP
+ ds_sw {
+ path /system/vendor/lib/soundfx/libswdap.so
+ }
+ ds_hw {
+ path /system/vendor/lib/soundfx/libhwdap.so
+ }
+#DOLBY_END
}
# Default pre-processing library. Add to audio_effect.conf "libraries" section if
@@ -129,6 +156,22 @@
library loudness_enhancer
uuid fa415329-2034-4bea-b5dc-5b381c8d1e2c
}
+#DOLBY_DAP
+ ds {
+ library proxy
+ uuid 9d4921da-8225-4f29-aefa-39537a04bcaa
+
+ libsw {
+ library ds_sw
+ uuid 6ab06da4-c516-4611-8166-452799218539
+ }
+
+ libhw {
+ library ds_hw
+ uuid a0c30891-8246-4aef-b8ad-d53e26da0253
+ }
+ }
+#DOLBY_END
}
# Default pre-processing effects. Add to audio_effect.conf "effects" section if
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 4a41037..18059b2 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -624,9 +624,12 @@
pDownmixer->apply_volume_correction = false;
pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
} else {
- // when configuring the effect, do not allow a blank channel mask
- if (pConfig->inputCfg.channels == 0) {
- ALOGE("Downmix_Configure error: input channel mask can't be 0");
+ // when configuring the effect, do not allow a blank or unsupported channel mask
+ if ((pConfig->inputCfg.channels == 0) ||
+ (Downmix_foldGeneric(pConfig->inputCfg.channels,
+ NULL, NULL, 0, false) == false)) {
+ ALOGE("Downmix_Configure error: input channel mask(0x%x) not supported",
+ pConfig->inputCfg.channels);
return -EINVAL;
}
pDownmixer->input_channel_count =
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index af904a6..e01c414 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -29,6 +29,7 @@
#include "EffectBundle.h"
#include "math.h"
+#include <media/stagefright/foundation/ADebug.h>
// effect_handle_t interface implementation for bass boost
extern "C" const struct effect_interface_s gLvmEffectInterface;
@@ -226,7 +227,7 @@
pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
pContext->pBundledContext->nOutputDevice = AUDIO_DEVICE_NONE;
pContext->pBundledContext->nVirtualizerForcedDevice = AUDIO_DEVICE_NONE;
- pContext->pBundledContext->NumberEffectsEnabled = 0;
+ pContext->pBundledContext->EffectsBitMap = 0;
pContext->pBundledContext->NumberEffectsCalled = 0;
pContext->pBundledContext->firstVolume = LVM_TRUE;
pContext->pBundledContext->volume = 0;
@@ -366,28 +367,28 @@
ALOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
pSessionContext->bBassInstantiated = LVM_FALSE;
if(pContext->pBundledContext->SamplesToExitCountBb > 0){
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_BASS_BOOST);
}
pContext->pBundledContext->SamplesToExitCountBb = 0;
} else if(pContext->EffectType == LVM_VIRTUALIZER) {
ALOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
pSessionContext->bVirtualizerInstantiated = LVM_FALSE;
if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VIRTUALIZER);
}
pContext->pBundledContext->SamplesToExitCountVirt = 0;
} else if(pContext->EffectType == LVM_EQUALIZER) {
ALOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
pSessionContext->bEqualizerInstantiated =LVM_FALSE;
if(pContext->pBundledContext->SamplesToExitCountEq > 0){
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_EQUALIZER);
}
pContext->pBundledContext->SamplesToExitCountEq = 0;
} else if(pContext->EffectType == LVM_VOLUME) {
ALOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
pSessionContext->bVolumeInstantiated = LVM_FALSE;
if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VOLUME);
}
} else {
ALOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
@@ -563,6 +564,7 @@
for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
if (MemTab.Region[i].Size != 0){
MemTab.Region[i].pBaseAddress = malloc(MemTab.Region[i].Size);
+ CHECK(MemTab.Region[i].pBaseAddress != NULL);
if (MemTab.Region[i].pBaseAddress == LVM_NULL){
ALOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %" PRIu32
@@ -729,6 +731,7 @@
}
pContext->pBundledContext->workBuffer =
(LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+ CHECK(pContext->pBundledContext->workBuffer != NULL);
pContext->pBundledContext->frameCount = frameCount;
}
pOutTmp = pContext->pBundledContext->workBuffer;
@@ -2753,7 +2756,7 @@
return -EINVAL;
}
if(pContext->pBundledContext->SamplesToExitCountBb <= 0){
- pContext->pBundledContext->NumberEffectsEnabled++;
+ pContext->pBundledContext->EffectsBitMap |= (1 << LVM_BASS_BOOST);
}
pContext->pBundledContext->SamplesToExitCountBb =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
@@ -2766,7 +2769,7 @@
return -EINVAL;
}
if(pContext->pBundledContext->SamplesToExitCountEq <= 0){
- pContext->pBundledContext->NumberEffectsEnabled++;
+ pContext->pBundledContext->EffectsBitMap |= (1 << LVM_EQUALIZER);
}
pContext->pBundledContext->SamplesToExitCountEq =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
@@ -2778,7 +2781,7 @@
return -EINVAL;
}
if(pContext->pBundledContext->SamplesToExitCountVirt <= 0){
- pContext->pBundledContext->NumberEffectsEnabled++;
+ pContext->pBundledContext->EffectsBitMap |= (1 << LVM_VIRTUALIZER);
}
pContext->pBundledContext->SamplesToExitCountVirt =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
@@ -2790,7 +2793,7 @@
ALOGV("\tEffect_setEnabled() LVM_VOLUME is already enabled");
return -EINVAL;
}
- pContext->pBundledContext->NumberEffectsEnabled++;
+ pContext->pBundledContext->EffectsBitMap |= (1 << LVM_VOLUME);
pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
break;
default:
@@ -2807,6 +2810,9 @@
ALOGV("\tEffect_setEnabled() LVM_BASS_BOOST is already disabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountBb <= 0) {
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_BASS_BOOST);
+ }
pContext->pBundledContext->bBassEnabled = LVM_FALSE;
break;
case LVM_EQUALIZER:
@@ -2814,6 +2820,9 @@
ALOGV("\tEffect_setEnabled() LVM_EQUALIZER is already disabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountEq <= 0) {
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_EQUALIZER);
+ }
pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
break;
case LVM_VIRTUALIZER:
@@ -2821,6 +2830,9 @@
ALOGV("\tEffect_setEnabled() LVM_VIRTUALIZER is already disabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountVirt <= 0) {
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VIRTUALIZER);
+ }
pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
break;
case LVM_VOLUME:
@@ -2828,6 +2840,7 @@
ALOGV("\tEffect_setEnabled() LVM_VOLUME is already disabled");
return -EINVAL;
}
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VOLUME);
pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
break;
default:
@@ -2877,7 +2890,7 @@
LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
//ALOGV("\tEffect_process Start : Enabled = %d Called = %d (%8d %8d %8d)",
-//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled,
+//popcount(pContext->pBundledContext->EffectsBitMap), pContext->pBundledContext->NumberEffectsCalled,
// pContext->pBundledContext->SamplesToExitCountBb,
// pContext->pBundledContext->SamplesToExitCountVirt,
// pContext->pBundledContext->SamplesToExitCountEq);
@@ -2911,7 +2924,7 @@
}
if(pContext->pBundledContext->SamplesToExitCountBb <= 0) {
status = -ENODATA;
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_BASS_BOOST);
ALOGV("\tEffect_process() this is the last frame for LVM_BASS_BOOST");
}
}
@@ -2919,7 +2932,7 @@
(pContext->EffectType == LVM_VOLUME)){
//ALOGV("\tEffect_process() LVM_VOLUME Effect is not enabled");
status = -ENODATA;
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VOLUME);
}
if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_EQUALIZER)){
@@ -2931,7 +2944,7 @@
}
if(pContext->pBundledContext->SamplesToExitCountEq <= 0) {
status = -ENODATA;
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_EQUALIZER);
ALOGV("\tEffect_process() this is the last frame for LVM_EQUALIZER");
}
}
@@ -2945,7 +2958,7 @@
}
if(pContext->pBundledContext->SamplesToExitCountVirt <= 0) {
status = -ENODATA;
- pContext->pBundledContext->NumberEffectsEnabled--;
+ pContext->pBundledContext->EffectsBitMap &= ~(1 << LVM_VIRTUALIZER);
ALOGV("\tEffect_process() this is the last frame for LVM_VIRTUALIZER");
}
}
@@ -2955,9 +2968,9 @@
}
if(pContext->pBundledContext->NumberEffectsCalled ==
- pContext->pBundledContext->NumberEffectsEnabled){
+ popcount(pContext->pBundledContext->EffectsBitMap)){
//ALOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
- //pContext->pBundledContext->NumberEffectsEnabled,
+ //popcount(pContext->pBundledContext->EffectsBitMap),
//pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
if(status == -ENODATA){
@@ -2976,7 +2989,7 @@
}
} else {
//ALOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
- //pContext->pBundledContext->NumberEffectsEnabled,
+ //popcount(pContext->pBundledContext->EffectsBitMap),
//pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
// 2 is for stereo input
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
@@ -3028,9 +3041,9 @@
// called the number of effect called could be greater
// pContext->pBundledContext->NumberEffectsCalled = 0;
- //ALOGV("\tEffect_command NumberEffectsCalled = %d, NumberEffectsEnabled = %d",
- // pContext->pBundledContext->NumberEffectsCalled,
- // pContext->pBundledContext->NumberEffectsEnabled);
+ //ALOGV("\tEffect_command: Enabled = %d Called = %d",
+ // popcount(pContext->pBundledContext->EffectsBitMap),
+ // pContext->pBundledContext->NumberEffectsCalled);
switch (cmdCode){
case EFFECT_CMD_INIT:
@@ -3311,7 +3324,7 @@
(device == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)){
ALOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
*(int32_t *)pCmdData);
- ALOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
+ ALOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BASS_BOOST");
// If a device doesnt support bassboost the effect must be temporarily disabled
// the effect must still report its original state as this can only be changed
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 9459b87..5fa5668 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -75,8 +75,8 @@
bool bVirtualizerTempDisabled; /* Flag for effect to be re-enabled */
audio_devices_t nOutputDevice; /* Output device for the effect */
audio_devices_t nVirtualizerForcedDevice; /* Forced device virtualization mode*/
- int NumberEffectsEnabled; /* Effects in this session */
int NumberEffectsCalled; /* Effects called so far */
+ uint32_t EffectsBitMap; /* Effects enable bit mask */
bool firstVolume; /* No smoothing on first Vol change */
// Saved parameters for each effect */
// Bass Boost
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index a3c3d3c..74e4eb1 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -69,12 +69,21 @@
StringArray.cpp \
AudioPolicy.cpp
+
+#QTI Resampler
+ifeq ($(call is-vendor-board-platform,QCOM), true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
+endif
+#QTI Resampler
+
LOCAL_SHARED_LIBRARIES := \
libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \
libcamera_client libstagefright_foundation \
libgui libdl libaudioutils libnbaio
-LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
+LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper libavmediaextentions
LOCAL_MODULE:= libmedia
@@ -84,6 +93,7 @@
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/frameworks/av/include/media/ \
$(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/av/media/libavextensions \
$(call include-path-for, audio-effects) \
$(call include-path-for, audio-utils)
diff --git a/media/libmedia/AudioParameter.cpp b/media/libmedia/AudioParameter.cpp
index 8c8cf45..535f459 100644
--- a/media/libmedia/AudioParameter.cpp
+++ b/media/libmedia/AudioParameter.cpp
@@ -32,6 +32,7 @@
const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyDevShutdown = AUDIO_PARAMETER_KEY_DEV_SHUTDOWN;
AudioParameter::AudioParameter(const String8& keyValuePairs)
{
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 011b31f..e84a770 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -26,6 +26,7 @@
#include <utils/Log.h>
#include <private/media/AudioTrackShared.h>
#include <media/IAudioFlinger.h>
+#include "SeempLog.h"
#define WAIT_PERIOD_MS 10
@@ -293,6 +294,7 @@
status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
{
ALOGV("start, sync event %d trigger session %d", event, triggerSession);
+ SEEMPLOG_RECORD(71,"");
AutoMutex lock(mLock);
if (mActive) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ab3d66a..e5f1f5f 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -30,6 +30,8 @@
#include <media/IAudioFlinger.h>
#include <media/AudioPolicyHelper.h>
#include <media/AudioResamplerPublic.h>
+#include "media/AVMediaExtensions.h"
+#include <cutils/properties.h>
#define WAIT_PERIOD_MS 10
#define WAIT_STREAM_END_TIMEOUT_SEC 120
@@ -167,7 +169,8 @@
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mPlaybackRateSet(false)
{
mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -197,7 +200,8 @@
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mPlaybackRateSet(false)
{
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
@@ -227,7 +231,8 @@
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
mPausedPosition(0),
- mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
+ mPlaybackRateSet(false)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -541,6 +546,12 @@
// force refresh of remaining frames by processAudioBuffer() as last
// write before stop could be partial.
mRefreshRemaining = true;
+
+ // for static track, clear the old flags when start from stopped state
+ if (mSharedBuffer != 0)
+ android_atomic_and(
+ ~(CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END),
+ &mCblk->mFlags);
}
mNewPosition = mPosition + mUpdatePeriod;
int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
@@ -846,6 +857,14 @@
//set effective rates
mProxy->setPlaybackRate(playbackRateTemp);
mProxy->setSampleRate(effectiveRate); // FIXME: not quite "atomic" with setPlaybackRate
+
+ // fallback out of Direct PCM if setPlaybackRate is called on a track offloaded
+ // session. Do this by setting mPlaybackRateSet to true
+ if (mTrackOffloaded) {
+ mPlaybackRateSet = true;
+ android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
+ }
+
return NO_ERROR;
}
@@ -1001,10 +1020,18 @@
return NO_ERROR;
}
+ if (AVMediaUtils::get()->AudioTrackIsPcmOffloaded(mFormat) &&
+ AVMediaUtils::get()->AudioTrackGetPosition(this, position) == NO_ERROR) {
+ return NO_ERROR;
+ }
+
if (mOutput != AUDIO_IO_HANDLE_NONE) {
uint32_t halFrames; // actually unused
- (void) AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
- // FIXME: on getRenderPosition() error, we return OK with frame position 0.
+ status_t status = AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
+ if (status != NO_ERROR) {
+ ALOGW("failed to getRenderPosition for offload session status %d", status);
+ return INVALID_OPERATION;
+ }
}
// FIXME: dspFrames may not be zero in (mState == STATE_STOPPED || mState == STATE_FLUSHED)
// due to hardware latency. We leave this behavior for now.
@@ -1129,11 +1156,16 @@
audio_stream_type_t streamType = mStreamType;
audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
- status_t status;
- status = AudioSystem::getOutputForAttr(attr, &output,
+ audio_offload_info_t tOffloadInfo = AUDIO_INFO_INITIALIZER;
+ if (mPlaybackRateSet == true && mOffloadInfo == NULL && mFormat == AUDIO_FORMAT_PCM_16_BIT) {
+ mOffloadInfo = &tOffloadInfo;
+ }
+ status_t status = AudioSystem::getOutputForAttr(attr, &output,
(audio_session_t)mSessionId, &streamType, mClientUid,
mSampleRate, mFormat, mChannelMask,
mFlags, mSelectedDeviceId, mOffloadInfo);
+ //reset offload info if forced
+ mOffloadInfo = (mOffloadInfo == &tOffloadInfo) ? NULL : mOffloadInfo;
if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u, format %#x,"
@@ -1141,6 +1173,7 @@
mSessionId, streamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
return BAD_VALUE;
}
+ mTrackOffloaded = AVMediaUtils::get()->AudioTrackIsTrackOffloaded(output);
{
// Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
// we must release it ourselves if anything goes wrong.
@@ -1203,6 +1236,7 @@
frameCount = mSharedBuffer->size();
} else if (frameCount == 0) {
frameCount = mAfFrameCount;
+ frameCount = AVMediaUtils::get()->AudioTrackGetOffloadFrameCount(frameCount);
}
if (mNotificationFramesAct != frameCount) {
mNotificationFramesAct = frameCount;
@@ -1838,40 +1872,6 @@
// get anchor time to account for callbacks.
const nsecs_t timeBeforeCallbacks = systemTime();
- if (waitStreamEnd) {
- // FIXME: Instead of blocking in proxy->waitStreamEndDone(), Callback thread
- // should wait on proxy futex and handle CBLK_STREAM_END_DONE within this function
- // (and make sure we don't callback for more data while we're stopping).
- // This helps with position, marker notifications, and track invalidation.
- struct timespec timeout;
- timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
- timeout.tv_nsec = 0;
-
- status_t status = proxy->waitStreamEndDone(&timeout);
- switch (status) {
- case NO_ERROR:
- case DEAD_OBJECT:
- case TIMED_OUT:
- mCbf(EVENT_STREAM_END, mUserData, NULL);
- {
- AutoMutex lock(mLock);
- // The previously assigned value of waitStreamEnd is no longer valid,
- // since the mutex has been unlocked and either the callback handler
- // or another thread could have re-started the AudioTrack during that time.
- waitStreamEnd = mState == STATE_STOPPING;
- if (waitStreamEnd) {
- mState = STATE_STOPPED;
- mReleased = 0;
- }
- }
- if (waitStreamEnd && status != DEAD_OBJECT) {
- return NS_INACTIVE;
- }
- break;
- }
- return 0;
- }
-
// perform callbacks while unlocked
if (newUnderrun) {
mCbf(EVENT_UNDERRUN, mUserData, NULL);
@@ -1902,6 +1902,46 @@
}
}
+ if (waitStreamEnd) {
+ // FIXME: Instead of blocking in proxy->waitStreamEndDone(), Callback thread
+ // should wait on proxy futex and handle CBLK_STREAM_END_DONE within this function
+ // (and make sure we don't callback for more data while we're stopping).
+ // This helps with position, marker notifications, and track invalidation.
+ struct timespec timeout;
+ timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
+ timeout.tv_nsec = 0;
+
+ status_t status = proxy->waitStreamEndDone(&timeout);
+ switch (status) {
+ case NO_ERROR:
+ case DEAD_OBJECT:
+ case TIMED_OUT:
+ if (isOffloaded_l()) {
+ if (mCblk->mFlags & (CBLK_INVALID)){
+ // will trigger EVENT_STREAM_END in next iteration
+ return 0;
+ }
+ }
+ mCbf(EVENT_STREAM_END, mUserData, NULL);
+ {
+ AutoMutex lock(mLock);
+ // The previously assigned value of waitStreamEnd is no longer valid,
+ // since the mutex has been unlocked and either the callback handler
+ // or another thread could have re-started the AudioTrack during that time.
+ waitStreamEnd = mState == STATE_STOPPING;
+ if (waitStreamEnd) {
+ mState = STATE_STOPPED;
+ mReleased = 0;
+ }
+ }
+ if (waitStreamEnd && status != DEAD_OBJECT) {
+ return NS_INACTIVE;
+ }
+ break;
+ }
+ return 0;
+ }
+
// if inactive, then don't run me again until re-started
if (!active) {
return NS_INACTIVE;
@@ -2232,14 +2272,22 @@
}
}
- // The presented frame count must always lag behind the consumed frame count.
- // To avoid a race, read the presented frames first. This ensures that presented <= consumed.
- status_t status = mAudioTrack->getTimestamp(timestamp);
- if (status != NO_ERROR) {
- ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
- return status;
+ status_t status = UNKNOWN_ERROR;
+ //call Timestamp only if its NOT PCM offloaded and NOT Track Offloaded
+ if (!AVMediaUtils::get()->AudioTrackIsPcmOffloaded(mFormat) && !mTrackOffloaded) {
+ // The presented frame count must always lag behind the consumed frame count.
+ // To avoid a race, read the presented frames first. This ensures that presented <= consumed.
+
+ status = mAudioTrack->getTimestamp(timestamp);
+ if (status != NO_ERROR) {
+ ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
+ return status;
+ }
+
}
- if (isOffloadedOrDirect_l()) {
+
+ if (isOffloadedOrDirect_l() && !AVMediaUtils::get()->AudioTrackIsPcmOffloaded(mFormat)
+ && !mTrackOffloaded) {
if (isOffloaded_l() && (mState == STATE_PAUSED || mState == STATE_PAUSED_STOPPING)) {
// use cached paused position in case another offloaded track is running.
timestamp.mPosition = mPausedPosition;
@@ -2297,6 +2345,11 @@
}
} else {
// Update the mapping between local consumed (mPosition) and server consumed (mServer)
+
+ if (AVMediaUtils::get()->AudioTrackGetTimestamp(this, ×tamp) == NO_ERROR) {
+ return NO_ERROR;
+ }
+
(void) updateAndGetPosition_l();
// Server consumed (mServer) and presented both use the same server time base,
// and server consumed is always >= presented.
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index a398ff7..24e027e 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -24,6 +24,7 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
+#include <media/AVMediaExtensions.h>
namespace android {
@@ -136,6 +137,7 @@
if (secure) {
data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
+ AVMediaUtils::get()->writeCustomData(&data, dstPtr);
}
remote()->transact(DECRYPT, data, &reply);
@@ -235,6 +237,7 @@
if (opaqueSize > 0) {
opaqueData = malloc(opaqueSize);
+ CHECK(opaqueData != NULL);
data.read(opaqueData, opaqueSize);
}
@@ -296,8 +299,10 @@
void *secureBufferId, *dstPtr;
if (secure) {
secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
+ AVMediaUtils::get()->readCustomData(&data, &secureBufferId);
} else {
dstPtr = calloc(1, totalSize);
+ CHECK(dstPtr != NULL);
}
AString errorDetailMsg;
@@ -348,6 +353,8 @@
}
free(dstPtr);
dstPtr = NULL;
+ } else {
+ AVMediaUtils::get()->closeFileDescriptor(secureBufferId);
}
delete[] subSamples;
diff --git a/media/libmedia/IEffectClient.cpp b/media/libmedia/IEffectClient.cpp
index 1322e72..531f767 100644
--- a/media/libmedia/IEffectClient.cpp
+++ b/media/libmedia/IEffectClient.cpp
@@ -22,6 +22,8 @@
#include <sys/types.h>
#include <media/IEffectClient.h>
+#include <media/stagefright/foundation/ADebug.h>
+
namespace android {
enum {
@@ -117,12 +119,14 @@
char *cmd = NULL;
if (cmdSize) {
cmd = (char *)malloc(cmdSize);
+ CHECK(cmd != NULL);
data.read(cmd, cmdSize);
}
uint32_t replySize = data.readInt32();
char *resp = NULL;
if (replySize) {
resp = (char *)malloc(replySize);
+ CHECK(resp != NULL);
data.read(resp, replySize);
}
commandExecuted(cmdCode, cmdSize, cmd, replySize, resp);
diff --git a/media/libmedia/IMediaHTTPConnection.cpp b/media/libmedia/IMediaHTTPConnection.cpp
index 0dda0be..23fa084 100644
--- a/media/libmedia/IMediaHTTPConnection.cpp
+++ b/media/libmedia/IMediaHTTPConnection.cpp
@@ -124,6 +124,14 @@
ALOGE("got %zu, but memory has %zu", len, mMemory->size());
return ERROR_OUT_OF_RANGE;
}
+ if(buffer == NULL) {
+ ALOGE("readAt got a NULL buffer");
+ return UNKNOWN_ERROR;
+ }
+ if (mMemory->pointer() == NULL) {
+ ALOGE("readAt got a NULL mMemory->pointer()");
+ return UNKNOWN_ERROR;
+ }
memcpy(buffer, mMemory->pointer(), len);
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 5423c2a..5356494 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -22,6 +22,7 @@
#include <binder/Parcel.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/AVMediaExtensions.h>
namespace android {
@@ -472,6 +473,7 @@
*buffer = (buffer_id)reply.readInt32();
*buffer_data = (void *)reply.readInt64();
+ AVMediaUtils::get()->readCustomData(&reply, buffer_data);
return err;
}
@@ -980,6 +982,7 @@
if (err == OK) {
reply->writeInt32((int32_t)buffer);
reply->writeInt64((uintptr_t)buffer_data);
+ AVMediaUtils::get()->writeCustomData(reply, buffer_data);
}
return NO_ERROR;
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index c5790fb..bb13aed 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -37,7 +37,8 @@
const MediaProfiles::NameToTagMap MediaProfiles::sVideoEncoderNameMap[] = {
{"h263", VIDEO_ENCODER_H263},
{"h264", VIDEO_ENCODER_H264},
- {"m4v", VIDEO_ENCODER_MPEG_4_SP}
+ {"m4v", VIDEO_ENCODER_MPEG_4_SP},
+ {"h265", VIDEO_ENCODER_H265}
};
const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
@@ -45,7 +46,8 @@
{"amrwb", AUDIO_ENCODER_AMR_WB},
{"aac", AUDIO_ENCODER_AAC},
{"heaac", AUDIO_ENCODER_HE_AAC},
- {"aaceld", AUDIO_ENCODER_AAC_ELD}
+ {"aaceld", AUDIO_ENCODER_AAC_ELD},
+ {"lpcm", AUDIO_ENCODER_LPCM},
};
const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
@@ -88,6 +90,19 @@
{"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P},
{"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P},
{"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P},
+
+ // Vendor-specific profiles
+ {"vga", CAMCORDER_QUALITY_VGA},
+ {"4kdci", CAMCORDER_QUALITY_4KDCI},
+ {"timelapsevga", CAMCORDER_QUALITY_TIME_LAPSE_VGA},
+ {"timelapse4kdci", CAMCORDER_QUALITY_TIME_LAPSE_4KDCI},
+ {"highspeedcif", CAMCORDER_QUALITY_HIGH_SPEED_CIF},
+ {"highspeedvga", CAMCORDER_QUALITY_HIGH_SPEED_VGA},
+ {"highspeed4kdci", CAMCORDER_QUALITY_HIGH_SPEED_4KDCI},
+ {"qhd", CAMCORDER_QUALITY_QHD},
+ {"2k", CAMCORDER_QUALITY_2k},
+ {"timelapseqhd", CAMCORDER_QUALITY_TIME_LAPSE_QHD},
+ {"timelapse2k", CAMCORDER_QUALITY_TIME_LAPSE_2k},
};
#if LOG_NDEBUG
@@ -423,8 +438,10 @@
}
static bool isCamcorderProfile(camcorder_quality quality) {
- return quality >= CAMCORDER_QUALITY_LIST_START &&
- quality <= CAMCORDER_QUALITY_LIST_END;
+ return (quality >= CAMCORDER_QUALITY_LIST_START &&
+ quality <= CAMCORDER_QUALITY_LIST_END) ||
+ (quality >= CAMCORDER_QUALITY_VENDOR_START &&
+ quality <= CAMCORDER_QUALITY_VENDOR_END);
}
static bool isTimelapseProfile(camcorder_quality quality) {
@@ -778,6 +795,7 @@
MediaProfiles::createDefaultAudioEncoders(MediaProfiles *profiles)
{
profiles->mAudioEncoders.add(createDefaultAmrNBEncoderCap());
+ profiles->mAudioEncoders.add(createDefaultLpcmEncoderCap());
}
/*static*/ void
@@ -812,6 +830,14 @@
AUDIO_ENCODER_AMR_NB, 5525, 12200, 8000, 8000, 1, 1);
}
+
+/*static*/ MediaProfiles::AudioEncoderCap*
+MediaProfiles::createDefaultLpcmEncoderCap()
+{
+ return new MediaProfiles::AudioEncoderCap(
+ AUDIO_ENCODER_LPCM, 768000, 4608000, 8000, 48000, 1, 6);
+}
+
/*static*/ void
MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
{
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index dcbb769..dac0a9e 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -24,6 +24,8 @@
#include <sys/stat.h>
#include <dirent.h>
+#include <media/stagefright/foundation/ADebug.h>
+
namespace android {
MediaScanner::MediaScanner()
@@ -240,6 +242,7 @@
MediaAlbumArt *MediaAlbumArt::clone() {
size_t byte_size = this->size() + sizeof(MediaAlbumArt);
MediaAlbumArt *result = reinterpret_cast<MediaAlbumArt *>(malloc(byte_size));
+ CHECK(result != NULL);
result->mSize = this->size();
memcpy(&result->mData[0], &this->mData[0], this->size());
return result;
@@ -253,6 +256,7 @@
MediaAlbumArt *MediaAlbumArt::fromData(int32_t dataSize, const void* data) {
size_t byte_size = sizeof(MediaAlbumArt) + dataSize;
MediaAlbumArt *result = reinterpret_cast<MediaAlbumArt *>(malloc(byte_size));
+ CHECK(result != NULL);
init(result, dataSize, data);
return result;
}
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 6da5348..53b229e 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -804,6 +804,12 @@
ALOGE("Unable to marshal AudioFlinger");
return;
}
+
+ if (mSamplingRate > 48000) {
+ ALOGW("mSamplingRate %d . limit to 48k", mSamplingRate);
+ mSamplingRate = 48000;
+ }
+
mThreadCanCallJava = threadCanCallJava;
mStreamType = streamType;
mVolume = volume;
@@ -1046,7 +1052,7 @@
ALOGV("Create Track: %p", mpAudioTrack.get());
mpAudioTrack->set(mStreamType,
- 0, // sampleRate
+ mSamplingRate,
AUDIO_FORMAT_PCM_16_BIT,
AUDIO_CHANNEL_OUT_MONO,
0, // frameCount
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 4d1b587..c4c5b47 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -18,7 +18,6 @@
MetadataRetrieverClient.cpp \
RemoteDisplay.cpp \
SharedLibrary.cpp \
- StagefrightPlayer.cpp \
StagefrightRecorder.cpp \
TestPlayerStub.cpp \
@@ -46,6 +45,9 @@
libstagefright_nuplayer \
libstagefright_rtsp \
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+ libavmediaserviceextensions \
+
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/av/media/libstagefright/include \
$(TOP)/frameworks/av/media/libstagefright/rtsp \
@@ -53,13 +55,14 @@
$(TOP)/frameworks/av/media/libstagefright/webm \
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/external/tremolo/Tremolo \
+ $(TOP)/frameworks/av/media/libavextensions \
LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
LOCAL_CLANG := true
LOCAL_MODULE:= libmediaplayerservice
-LOCAL_32_BIT_ONLY := true
+#LOCAL_32_BIT_ONLY := true
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
index d5d12f7..f0afc5a 100644
--- a/media/libmediaplayerservice/MediaPlayerFactory.cpp
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -31,8 +31,8 @@
#include "MediaPlayerFactory.h"
#include "TestPlayerStub.h"
-#include "StagefrightPlayer.h"
#include "nuplayer/NuPlayerDriver.h"
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
namespace android {
@@ -64,12 +64,6 @@
}
static player_type getDefaultPlayerType() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.use-awesome", value, NULL)
- && (!strcmp("1", value) || !strcasecmp("true", value))) {
- return STAGEFRIGHT_PLAYER;
- }
-
return NU_PLAYER;
}
@@ -87,7 +81,7 @@
#define GET_PLAYER_TYPE_IMPL(a...) \
Mutex::Autolock lock_(&sLock); \
\
- player_type ret = STAGEFRIGHT_PLAYER; \
+ player_type ret = NU_PLAYER; \
float bestScore = 0.0; \
\
for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
@@ -176,63 +170,6 @@
* *
*****************************************************************************/
-class StagefrightPlayerFactory :
- public MediaPlayerFactory::IFactory {
- public:
- virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
- int fd,
- int64_t offset,
- int64_t length,
- float /*curScore*/) {
- if (legacyDrm()) {
- sp<DataSource> source = new FileSource(dup(fd), offset, length);
- String8 mimeType;
- float confidence;
- if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
- return 1.0;
- }
- }
-
- if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
- char buf[20];
- lseek(fd, offset, SEEK_SET);
- read(fd, buf, sizeof(buf));
- lseek(fd, offset, SEEK_SET);
-
- uint32_t ident = *((uint32_t*)buf);
-
- // Ogg vorbis?
- if (ident == 0x5367674f) // 'OggS'
- return 1.0;
- }
-
- return 0.0;
- }
-
- virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
- const char* url,
- float /*curScore*/) {
- if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
- return 1.0;
- }
- return 0.0;
- }
-
- virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
- ALOGV(" create StagefrightPlayer");
- return new StagefrightPlayer();
- }
- private:
- bool legacyDrm() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("persist.sys.media.legacy-drm", value, NULL)
- && (!strcmp("1", value) || !strcasecmp("true", value))) {
- return true;
- }
- return false;
- }
-};
-
class NuPlayerFactory : public MediaPlayerFactory::IFactory {
public:
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
@@ -305,14 +242,20 @@
};
void MediaPlayerFactory::registerBuiltinFactories() {
+
+ MediaPlayerFactory::IFactory* pCustomFactory = NULL;
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
- registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
+ AVMediaServiceUtils::get()->getDashPlayerFactory(pCustomFactory, DASH_PLAYER);
+ if(pCustomFactory != NULL) {
+ ALOGV("Registering DASH_PLAYER");
+ registerFactory_l(pCustomFactory, DASH_PLAYER);
+ }
sInitComplete = true;
}
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index bcfd83a..820b3c3 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
// Proxy for media player implementations
@@ -21,6 +40,7 @@
#define LOG_TAG "MediaPlayerService"
#include <utils/Log.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
@@ -73,7 +93,6 @@
#include "MediaPlayerFactory.h"
#include "TestPlayerStub.h"
-#include "StagefrightPlayer.h"
#include "nuplayer/NuPlayerDriver.h"
#include <OMX.h>
@@ -83,6 +102,9 @@
#include "HDCP.h"
#include "HTTPBase.h"
#include "RemoteDisplay.h"
+#ifdef DOLBY_ENABLE
+#include "DolbyMediaPlayerServiceExtImpl.h"
+#endif // DOLBY_END
namespace {
using android::media::Metadata;
@@ -148,7 +170,7 @@
if (p.dataAvail() < size)
{
- ALOGE("Filter too short expected %d but got %d", size, p.dataAvail());
+ ALOGE("Filter too short expected %zu but got %zu", size, p.dataAvail());
*status = NOT_ENOUGH_DATA;
return false;
}
@@ -733,7 +755,7 @@
status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64_t length)
{
- ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+ ALOGV("setDataSource fd=%d, offset=%" PRId64 ", length=%" PRId64 "", fd, offset, length);
struct stat sb;
int ret = fstat(fd, &sb);
if (ret != 0) {
@@ -741,11 +763,11 @@
return UNKNOWN_ERROR;
}
- ALOGV("st_dev = %llu", static_cast<uint64_t>(sb.st_dev));
+ ALOGV("st_dev = %" PRIu64 "", static_cast<uint64_t>(sb.st_dev));
ALOGV("st_mode = %u", sb.st_mode);
ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
- ALOGV("st_size = %llu", sb.st_size);
+ ALOGV("st_size = %" PRId64 "", sb.st_size);
if (offset >= sb.st_size) {
ALOGE("offset error");
@@ -754,7 +776,7 @@
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
- ALOGV("calculated length = %lld", length);
+ ALOGV("calculated length = %" PRId64 "", length);
}
player_type playerType = MediaPlayerFactory::getPlayerType(this,
@@ -1249,8 +1271,17 @@
if (msg == MEDIA_PLAYBACK_COMPLETE && client->mNextClient != NULL) {
if (client->mAudioOutput != NULL)
client->mAudioOutput->switchToNextOutput();
- client->mNextClient->start();
- client->mNextClient->mClient->notify(MEDIA_INFO, MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
+ ALOGD("gapless:current track played back");
+ ALOGD("gapless:try to do a gapless switch to next track");
+ status_t ret;
+ ret = client->mNextClient->start();
+ if (ret == NO_ERROR) {
+ client->mNextClient->mClient->notify(MEDIA_INFO,
+ MEDIA_INFO_STARTED_AS_NEXT, 0, obj);
+ } else {
+ client->mClient->notify(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN , 0, obj);
+ ALOGW("gapless:start playback for next track failed");
+ }
}
}
@@ -1366,6 +1397,10 @@
}
setMinBufferCount();
+ mBitWidth = 16;
+#ifdef DOLBY_ENABLE
+ mProcessedAudio = false;
+#endif // DOLBY_END
}
MediaPlayerService::AudioOutput::~AudioOutput()
@@ -1465,6 +1500,9 @@
status_t MediaPlayerService::AudioOutput::setParameters(const String8& keyValuePairs)
{
Mutex::Autolock lock(mLock);
+#ifdef DOLBY_ENABLE
+ setDolbyParameters(keyValuePairs);
+#endif // DOLBY_END
if (mTrack == 0) return NO_INIT;
return mTrack->setParameters(keyValuePairs);
}
@@ -1622,6 +1660,15 @@
} else if (mRecycledTrack->format() != format) {
reuse = false;
}
+
+ if (bothOffloaded) {
+ if (mBitWidth != offloadInfo->bit_width) {
+ ALOGV("output bit width differs %d v/s %d",
+ mBitWidth, offloadInfo->bit_width);
+ reuse = false;
+ }
+ }
+
} else {
ALOGV("no track available to recycle");
}
@@ -1702,7 +1749,7 @@
if (!bothOffloaded) {
if (mRecycledTrack->frameCount() != t->frameCount()) {
- ALOGV("framecount differs: %u/%u frames",
+ ALOGV("framecount differs: %zu/%zu frames",
mRecycledTrack->frameCount(), t->frameCount());
reuse = false;
}
@@ -1717,6 +1764,9 @@
mCallbackData->setOutput(this);
}
delete newcbd;
+#ifdef DOLBY_ENABLE
+ updateTrackOnAudioProcessed(mTrack, reuse);
+#endif // DOLBY_END
return OK;
}
}
@@ -1737,6 +1787,13 @@
mFlags = flags;
mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
mFrameSize = t->frameSize();
+
+ if (offloadInfo) {
+ mBitWidth = offloadInfo->bit_width;
+ } else {
+ mBitWidth = 16;
+ }
+
uint32_t pos;
if (t->getPosition(&pos) == OK) {
mBytesWritten = uint64_t(pos) * mFrameSize;
@@ -1753,6 +1810,9 @@
res = t->attachAuxEffect(mAuxEffectId);
}
}
+#ifdef DOLBY_ENABLE
+ updateTrackOnAudioProcessed(t, false);
+#endif // DOLBY_END
ALOGV("open() DONE status %d", res);
return res;
}
@@ -1837,6 +1897,7 @@
mNextOutput->mBytesWritten = mBytesWritten;
mNextOutput->mFlags = mFlags;
mNextOutput->mFrameSize = mFrameSize;
+ mNextOutput->mBitWidth = mBitWidth;
close_l();
mCallbackData = NULL; // destruction handled by mNextOutput
} else {
@@ -2101,6 +2162,7 @@
if (mBuffer == NULL) {
mBufferSize = sink->bufferSize();
mBuffer = malloc(mBufferSize);
+ CHECK(mBuffer != NULL);
}
size_t actualSize =
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 60d4617..e92c0d3 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
#ifndef ANDROID_MEDIAPLAYERSERVICE_H
@@ -133,6 +152,11 @@
int event, void *me, void *info);
void deleteRecycledTrack_l();
void close_l();
+#ifdef DOLBY_ENABLE
+ void setDolbyParameters(const String8& keyValuePairs);
+ void updateTrackOnAudioProcessed(sp<AudioTrack> t, bool trackReused);
+ bool mProcessedAudio;
+#endif // DOLBY_END
sp<AudioTrack> mTrack;
sp<AudioTrack> mRecycledTrack;
@@ -160,6 +184,7 @@
// static variables below not protected by mutex
static bool mIsOnEmulator;
static int mMinBufferCount; // 12 for emulator; otherwise 4
+ uint16_t mBitWidth;
// CallbackData is what is passed to the AudioTrack as the "user" data.
// We need to be able to target this to a different Output on the fly,
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index f761dec..6f242e5 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -18,6 +18,7 @@
#define LOG_TAG "MediaRecorderService"
#include <utils/Log.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -39,6 +40,7 @@
#include "StagefrightRecorder.h"
#include <gui/IGraphicBufferProducer.h>
+#include "mediaplayerservice/AVMediaServiceExtensions.h"
namespace android {
@@ -166,7 +168,7 @@
status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
{
- ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+ ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
@@ -305,7 +307,7 @@
{
ALOGV("Client constructor");
mPid = pid;
- mRecorder = new StagefrightRecorder(opPackageName);
+ mRecorder = AVMediaServiceFactory::get()->createStagefrightRecorder(opPackageName);
mMediaPlayerService = service;
}
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index a5a1fa5..894a855 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -19,6 +19,7 @@
#define LOG_TAG "MetadataRetrieverClient"
#include <utils/Log.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -84,7 +85,6 @@
{
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
- case STAGEFRIGHT_PLAYER:
case NU_PLAYER:
{
p = new StagefrightMetadataRetriever;
@@ -133,7 +133,7 @@
status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
{
- ALOGV("setDataSource fd=%d, offset=%lld, length=%lld", fd, offset, length);
+ ALOGV("setDataSource fd=%d, offset=%" PRId64 ", length=%" PRId64 "", fd, offset, length);
Mutex::Autolock lock(mLock);
struct stat sb;
int ret = fstat(fd, &sb);
@@ -141,20 +141,20 @@
ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
return BAD_VALUE;
}
- ALOGV("st_dev = %llu", static_cast<uint64_t>(sb.st_dev));
+ ALOGV("st_dev = %" PRIu64 "", static_cast<uint64_t>(sb.st_dev));
ALOGV("st_mode = %u", sb.st_mode);
ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
- ALOGV("st_size = %llu", sb.st_size);
+ ALOGV("st_size = %" PRIu64 "", sb.st_size);
if (offset >= sb.st_size) {
- ALOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
+ ALOGE("offset (%" PRId64 ") bigger than file size (%" PRIu64 ")", offset, sb.st_size);
::close(fd);
return BAD_VALUE;
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
- ALOGV("calculated length = %lld", length);
+ ALOGV("calculated length = %" PRId64 "", length);
}
player_type playerType =
@@ -195,7 +195,7 @@
sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option)
{
- ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option);
+ ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option);
Mutex::Autolock lock(mLock);
Mutex::Autolock glock(sLock);
mThumbnail.clear();
@@ -217,7 +217,7 @@
}
mThumbnail = new MemoryBase(heap, 0, size);
if (mThumbnail == NULL) {
- ALOGE("not enough memory for VideoFrame size=%u", size);
+ ALOGE("not enough memory for VideoFrame size=%zu", size);
delete frame;
return NULL;
}
@@ -258,7 +258,7 @@
}
mAlbumArt = new MemoryBase(heap, 0, size);
if (mAlbumArt == NULL) {
- ALOGE("not enough memory for MediaAlbumArt size=%u", size);
+ ALOGE("not enough memory for MediaAlbumArt size=%zu", size);
delete albumArt;
return NULL;
}
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
deleted file mode 100644
index 3fedd9b..0000000
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "StagefrightPlayer"
-#include <utils/Log.h>
-
-#include "StagefrightPlayer.h"
-
-#include "AwesomePlayer.h"
-
-#include <media/Metadata.h>
-#include <media/stagefright/MediaExtractor.h>
-
-namespace android {
-
-StagefrightPlayer::StagefrightPlayer()
- : mPlayer(new AwesomePlayer) {
- ALOGV("StagefrightPlayer");
-
- mPlayer->setListener(this);
-}
-
-StagefrightPlayer::~StagefrightPlayer() {
- ALOGV("~StagefrightPlayer");
- reset();
-
- delete mPlayer;
- mPlayer = NULL;
-}
-
-status_t StagefrightPlayer::initCheck() {
- ALOGV("initCheck");
- return OK;
-}
-
-status_t StagefrightPlayer::setUID(uid_t uid) {
- mPlayer->setUID(uid);
-
- return OK;
-}
-
-status_t StagefrightPlayer::setDataSource(
- const sp<IMediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers) {
- return mPlayer->setDataSource(httpService, url, headers);
-}
-
-// Warning: The filedescriptor passed into this method will only be valid until
-// the method returns, if you want to keep it, dup it!
-status_t StagefrightPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
- ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
- return mPlayer->setDataSource(dup(fd), offset, length);
-}
-
-status_t StagefrightPlayer::setDataSource(const sp<IStreamSource> &source) {
- return mPlayer->setDataSource(source);
-}
-
-status_t StagefrightPlayer::setVideoSurfaceTexture(
- const sp<IGraphicBufferProducer> &bufferProducer) {
- ALOGV("setVideoSurfaceTexture");
-
- return mPlayer->setSurfaceTexture(bufferProducer);
-}
-
-status_t StagefrightPlayer::prepare() {
- return mPlayer->prepare();
-}
-
-status_t StagefrightPlayer::prepareAsync() {
- return mPlayer->prepareAsync();
-}
-
-status_t StagefrightPlayer::start() {
- ALOGV("start");
-
- return mPlayer->play();
-}
-
-status_t StagefrightPlayer::stop() {
- ALOGV("stop");
-
- return pause(); // what's the difference?
-}
-
-status_t StagefrightPlayer::pause() {
- ALOGV("pause");
-
- return mPlayer->pause();
-}
-
-bool StagefrightPlayer::isPlaying() {
- ALOGV("isPlaying");
- return mPlayer->isPlaying();
-}
-
-status_t StagefrightPlayer::seekTo(int msec) {
- ALOGV("seekTo %.2f secs", msec / 1E3);
-
- status_t err = mPlayer->seekTo((int64_t)msec * 1000);
-
- return err;
-}
-
-status_t StagefrightPlayer::getCurrentPosition(int *msec) {
- ALOGV("getCurrentPosition");
-
- int64_t positionUs;
- status_t err = mPlayer->getPosition(&positionUs);
-
- if (err != OK) {
- return err;
- }
-
- *msec = (positionUs + 500) / 1000;
-
- return OK;
-}
-
-status_t StagefrightPlayer::getDuration(int *msec) {
- ALOGV("getDuration");
-
- int64_t durationUs;
- status_t err = mPlayer->getDuration(&durationUs);
-
- if (err != OK) {
- *msec = 0;
- return OK;
- }
-
- *msec = (durationUs + 500) / 1000;
-
- return OK;
-}
-
-status_t StagefrightPlayer::reset() {
- ALOGV("reset");
-
- mPlayer->reset();
-
- return OK;
-}
-
-status_t StagefrightPlayer::setLooping(int loop) {
- ALOGV("setLooping");
-
- return mPlayer->setLooping(loop);
-}
-
-player_type StagefrightPlayer::playerType() {
- ALOGV("playerType");
- return STAGEFRIGHT_PLAYER;
-}
-
-status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) {
- ALOGV("invoke()");
- return mPlayer->invoke(request, reply);
-}
-
-void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
- MediaPlayerInterface::setAudioSink(audioSink);
-
- mPlayer->setAudioSink(audioSink);
-}
-
-status_t StagefrightPlayer::setParameter(int key, const Parcel &request) {
- ALOGV("setParameter(key=%d)", key);
- return mPlayer->setParameter(key, request);
-}
-
-status_t StagefrightPlayer::getParameter(int key, Parcel *reply) {
- ALOGV("getParameter");
- return mPlayer->getParameter(key, reply);
-}
-
-status_t StagefrightPlayer::setPlaybackSettings(const AudioPlaybackRate &rate) {
- return mPlayer->setPlaybackSettings(rate);
-}
-
-status_t StagefrightPlayer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
- return mPlayer->getPlaybackSettings(rate);
-}
-
-status_t StagefrightPlayer::getMetadata(
- const media::Metadata::Filter& /* ids */, Parcel *records) {
- using media::Metadata;
-
- uint32_t flags = mPlayer->flags();
-
- Metadata metadata(records);
-
- metadata.appendBool(
- Metadata::kPauseAvailable,
- flags & MediaExtractor::CAN_PAUSE);
-
- metadata.appendBool(
- Metadata::kSeekBackwardAvailable,
- flags & MediaExtractor::CAN_SEEK_BACKWARD);
-
- metadata.appendBool(
- Metadata::kSeekForwardAvailable,
- flags & MediaExtractor::CAN_SEEK_FORWARD);
-
- metadata.appendBool(
- Metadata::kSeekAvailable,
- flags & MediaExtractor::CAN_SEEK);
-
- return OK;
-}
-
-status_t StagefrightPlayer::dump(int fd, const Vector<String16> &args) const {
- return mPlayer->dump(fd, args);
-}
-
-} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
deleted file mode 100644
index 96013df..0000000
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-**
-** Copyright 2009, 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.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_STAGEFRIGHTPLAYER_H
-#define ANDROID_STAGEFRIGHTPLAYER_H
-
-#include <media/MediaPlayerInterface.h>
-
-namespace android {
-
-struct AwesomePlayer;
-
-class StagefrightPlayer : public MediaPlayerInterface {
-public:
- StagefrightPlayer();
- virtual ~StagefrightPlayer();
-
- virtual status_t initCheck();
-
- virtual status_t setUID(uid_t uid);
-
- virtual status_t setDataSource(
- const sp<IMediaHTTPService> &httpService,
- const char *url,
- const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-
- virtual status_t setDataSource(const sp<IStreamSource> &source);
-
- virtual status_t setVideoSurfaceTexture(
- const sp<IGraphicBufferProducer> &bufferProducer);
- virtual status_t prepare();
- virtual status_t prepareAsync();
- virtual status_t start();
- virtual status_t stop();
- virtual status_t pause();
- virtual bool isPlaying();
- virtual status_t seekTo(int msec);
- virtual status_t getCurrentPosition(int *msec);
- virtual status_t getDuration(int *msec);
- virtual status_t reset();
- virtual status_t setLooping(int loop);
- virtual player_type playerType();
- virtual status_t invoke(const Parcel &request, Parcel *reply);
- virtual void setAudioSink(const sp<AudioSink> &audioSink);
- virtual status_t setParameter(int key, const Parcel &request);
- virtual status_t getParameter(int key, Parcel *reply);
- virtual status_t setPlaybackSettings(const AudioPlaybackRate &rate);
- virtual status_t getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */);
-
- virtual status_t getMetadata(
- const media::Metadata::Filter& ids, Parcel *records);
-
- virtual status_t dump(int fd, const Vector<String16> &args) const;
-
-private:
- AwesomePlayer *mPlayer;
-
- StagefrightPlayer(const StagefrightPlayer &);
- StagefrightPlayer &operator=(const StagefrightPlayer &);
-};
-
-} // namespace android
-
-#endif // ANDROID_STAGEFRIGHTPLAYER_H
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index e521fae..80d5ac2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -19,6 +19,7 @@
#include <inttypes.h>
#include <utils/Log.h>
+#include <inttypes.h>
#include "WebmWriter.h"
#include "StagefrightRecorder.h"
@@ -55,9 +56,12 @@
#include <system/audio.h>
#include "ARTPWriter.h"
+#include <stagefright/AVExtensions.h>
namespace android {
+static const int64_t kMax32BitFileSize = 0x00ffffffffLL; // 4GB
+
// To collect the encoder usage for the battery app
static void addBatteryData(uint32_t params) {
sp<IBinder> binder =
@@ -249,7 +253,7 @@
}
status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
- ALOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
+ ALOGV("setOutputFile: %d, %" PRId64 ", %" PRId64 "", fd, offset, length);
// These don't make any sense, do they?
CHECK_EQ(offset, 0ll);
CHECK_EQ(length, 0ll);
@@ -364,7 +368,7 @@
status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
ALOGV("setParamAudioNumberOfChannels: %d", channels);
- if (channels <= 0 || channels >= 3) {
+ if (channels <= 0 || channels >= 7) {
ALOGE("Invalid number of audio channels: %d", channels);
return BAD_VALUE;
}
@@ -416,42 +420,46 @@
}
status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
- ALOGV("setParamMaxFileDurationUs: %lld us", timeUs);
+ ALOGV("setParamMaxFileDurationUs: %" PRId64 " us", timeUs);
// This is meant for backward compatibility for MediaRecorder.java
if (timeUs <= 0) {
- ALOGW("Max file duration is not positive: %lld us. Disabling duration limit.", timeUs);
+ ALOGW("Max file duration is not positive: %" PRId64 " us. Disabling duration limit.", timeUs);
timeUs = 0; // Disable the duration limit for zero or negative values.
} else if (timeUs <= 100000LL) { // XXX: 100 milli-seconds
- ALOGE("Max file duration is too short: %lld us", timeUs);
+ ALOGE("Max file duration is too short: %" PRId64 " us", timeUs);
return BAD_VALUE;
}
if (timeUs <= 15 * 1000000LL) {
- ALOGW("Target duration (%lld us) too short to be respected", timeUs);
+ ALOGW("Target duration (%" PRId64 " us) too short to be respected", timeUs);
}
mMaxFileDurationUs = timeUs;
return OK;
}
status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
- ALOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
+ ALOGV("setParamMaxFileSizeBytes: %" PRId64 " bytes", bytes);
// This is meant for backward compatibility for MediaRecorder.java
if (bytes <= 0) {
- ALOGW("Max file size is not positive: %lld bytes. "
+ ALOGW("Max file size is not positive: %" PRId64 " bytes. "
"Disabling file size limit.", bytes);
bytes = 0; // Disable the file size limit for zero or negative values.
} else if (bytes <= 1024) { // XXX: 1 kB
- ALOGE("Max file size is too small: %lld bytes", bytes);
+ ALOGE("Max file size is too small: %" PRId64 " bytes", bytes);
return BAD_VALUE;
}
if (bytes <= 100 * 1024) {
- ALOGW("Target file size (%lld bytes) is too small to be respected", bytes);
+ ALOGW("Target file size (%" PRId64 " bytes) is too small to be respected", bytes);
}
mMaxFileSizeBytes = bytes;
+
+ // If requested size is >4GB, force 64-bit offsets
+ mUse64BitFileOffset |= (bytes >= kMax32BitFileSize);
+
return OK;
}
@@ -500,9 +508,9 @@
}
status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
- ALOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
+ ALOGV("setParamTrackTimeStatus: %" PRId64 "", timeDurationUs);
if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms?
- ALOGE("Tracking time duration too short: %lld us", timeDurationUs);
+ ALOGE("Tracking time duration too short: %" PRId64 " us", timeDurationUs);
return BAD_VALUE;
}
mTrackEveryTimeDurationUs = timeDurationUs;
@@ -581,11 +589,11 @@
status_t StagefrightRecorder::setParamCaptureFps(float fps) {
ALOGV("setParamCaptureFps: %.2f", fps);
- int64_t timeUs = (int64_t) (1000000.0 / fps + 0.5f);
+ int64_t timeUs = (int64_t) (1000000.0f / fps + 0.5f);
// Not allowing time more than a day
if (timeUs <= 0 || timeUs > 86400*1E6) {
- ALOGE("Time between frame capture (%lld) is out of range [0, 1 Day]", timeUs);
+ ALOGE("Time between frame capture (%" PRId64 ") is out of range [0, 1 Day]", timeUs);
return BAD_VALUE;
}
@@ -814,8 +822,10 @@
break;
default:
- ALOGE("Unsupported output file format: %d", mOutputFormat);
- status = UNKNOWN_ERROR;
+ if (handleCustomRecording() != OK) {
+ ALOGE("Unsupported output file format: %d", mOutputFormat);
+ status = UNKNOWN_ERROR;
+ }
break;
}
@@ -879,8 +889,10 @@
default:
{
- ALOGE("Unsupported output file format: %d", mOutputFormat);
- status = UNKNOWN_ERROR;
+ if (handleCustomOutputFormats() != OK) {
+ ALOGE("Unsupported output file format: %d", mOutputFormat);
+ status = UNKNOWN_ERROR;
+ }
break;
}
}
@@ -927,13 +939,12 @@
}
}
- sp<AudioSource> audioSource =
- new AudioSource(
- mAudioSource,
- mOpPackageName,
- sourceSampleRate,
- mAudioChannels,
- mSampleRate);
+ sp<AudioSource> audioSource = AVFactory::get()->createAudioSource(
+ mAudioSource,
+ mOpPackageName,
+ sourceSampleRate,
+ mAudioChannels,
+ mSampleRate);
status_t err = audioSource->initCheck();
@@ -965,8 +976,10 @@
break;
default:
- ALOGE("Unknown audio encoder: %d", mAudioEncoder);
- return NULL;
+ if (handleCustomAudioSource(format) != OK) {
+ ALOGE("Unknown audio encoder: %d", mAudioEncoder);
+ return NULL;
+ }
}
int32_t maxInputSize;
@@ -984,6 +997,13 @@
sp<MediaSource> audioEncoder =
MediaCodecSource::Create(mLooper, format, audioSource);
+ // If encoder could not be created (as in LPCM), then
+ // use the AudioSource directly as the MediaSource.
+ if (audioEncoder == NULL &&
+ mAudioEncoder == AUDIO_ENCODER_LPCM) {
+ ALOGD("No encoder is needed for linear PCM format");
+ audioEncoder = audioSource;
+ }
mAudioSourceNode = audioSource;
if (audioEncoder == NULL) {
@@ -1440,22 +1460,23 @@
videoSize.height = mVideoHeight;
if (mCaptureFpsEnable) {
if (mTimeBetweenCaptureUs < 0) {
- ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld",
+ ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %" PRId64 "",
mTimeBetweenCaptureUs);
return BAD_VALUE;
}
- mCameraSourceTimeLapse = CameraSourceTimeLapse::CreateFromCamera(
+ mCameraSourceTimeLapse = AVFactory::get()->CreateCameraSourceTimeLapseFromCamera(
mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
videoSize, mFrameRate, mPreviewSurface,
mTimeBetweenCaptureUs);
*cameraSource = mCameraSourceTimeLapse;
} else {
- *cameraSource = CameraSource::CreateFromCamera(
+ *cameraSource = AVFactory::get()->CreateCameraSourceFromCamera(
mCamera, mCameraProxy, mCameraId, mClientName, mClientUid,
videoSize, mFrameRate,
mPreviewSurface);
}
+ AVUtils::get()->cacheCaptureBuffers(mCamera, mVideoEncoder);
mCamera.clear();
mCameraProxy.clear();
if (*cameraSource == NULL) {
@@ -1487,6 +1508,11 @@
return OK;
}
+bool StagefrightRecorder::setCustomVideoEncoderMime(const video_encoder /*videoEncoder*/,
+ sp<AMessage> /*format*/) {
+ return false;
+}
+
status_t StagefrightRecorder::setupVideoEncoder(
sp<MediaSource> cameraSource,
sp<MediaSource> *source) {
@@ -1512,6 +1538,9 @@
break;
default:
+ if (setCustomVideoEncoderMime(mVideoEncoder, format)) {
+ break;
+ }
CHECK(!"Should not be here, unsupported video encoding.");
break;
}
@@ -1541,7 +1570,7 @@
// set up time lapse/slow motion for surface source
if (mCaptureFpsEnable) {
if (mTimeBetweenCaptureUs <= 0) {
- ALOGE("Invalid mTimeBetweenCaptureUs value: %lld",
+ ALOGE("Invalid mTimeBetweenCaptureUs value: %" PRId64 "",
mTimeBetweenCaptureUs);
return BAD_VALUE;
}
@@ -1549,6 +1578,8 @@
}
}
+ setupCustomVideoEncoderParams(cameraSource, format);
+
format->setInt32("bitrate", mVideoBitRate);
format->setInt32("frame-rate", mFrameRate);
format->setInt32("i-frame-interval", mIFramesIntervalSec);
@@ -1614,8 +1645,10 @@
break;
default:
- ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
- return UNKNOWN_ERROR;
+ if (handleCustomAudioEncoder() != OK) {
+ ALOGE("Unsupported audio encoder: %d", mAudioEncoder);
+ return UNKNOWN_ERROR;
+ }
}
sp<MediaSource> audioEncoder = createAudioSource();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index da00bc7..d2ff62d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -39,6 +39,7 @@
class IGraphicBufferProducer;
class SurfaceMediaSource;
struct ALooper;
+struct AMessage;
struct StagefrightRecorder : public MediaRecorderBase {
StagefrightRecorder(const String16 &opPackageName);
@@ -70,7 +71,7 @@
// Querying a SurfaceMediaSourcer
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const;
-private:
+protected:
sp<ICamera> mCamera;
sp<ICameraRecordingProxy> mCameraProxy;
sp<IGraphicBufferProducer> mPreviewSurface;
@@ -131,7 +132,7 @@
static const int kMaxHighSpeedFps = 1000;
- status_t prepareInternal();
+ virtual status_t prepareInternal();
status_t setupMPEG4orWEBMRecording();
void setupMPEG4orWEBMMetaData(sp<MetaData> *meta);
status_t setupAMRRecording();
@@ -139,8 +140,8 @@
status_t setupRawAudioRecording();
status_t setupRTPRecording();
status_t setupMPEG2TSRecording();
- sp<MediaSource> createAudioSource();
- status_t checkVideoEncoderCapabilities();
+ virtual sp<MediaSource> createAudioSource();
+ virtual status_t checkVideoEncoderCapabilities();
status_t checkAudioEncoderCapabilities();
// Generic MediaSource set-up. Returns the appropriate
// source (CameraSource or SurfaceMediaSource)
@@ -148,10 +149,13 @@
status_t setupMediaSource(sp<MediaSource> *mediaSource);
status_t setupCameraSource(sp<CameraSource> *cameraSource);
status_t setupAudioEncoder(const sp<MediaWriter>& writer);
- status_t setupVideoEncoder(sp<MediaSource> cameraSource, sp<MediaSource> *source);
+ virtual status_t setupVideoEncoder(sp<MediaSource> cameraSource, sp<MediaSource> *source);
+ virtual void setupCustomVideoEncoderParams(sp<MediaSource> /*cameraSource*/,
+ sp<AMessage> &/*format*/) {}
+ virtual bool setCustomVideoEncoderMime(const video_encoder videoEncoder, sp<AMessage> format);
// Encoding parameter handling utilities
- status_t setParameter(const String8 &key, const String8 &value);
+ virtual status_t setParameter(const String8 &key, const String8 &value);
status_t setParamAudioEncodingBitRate(int32_t bitRate);
status_t setParamAudioNumberOfChannels(int32_t channles);
status_t setParamAudioSamplingRate(int32_t sampleRate);
@@ -181,7 +185,11 @@
void clipAudioSampleRate();
void clipNumberOfAudioChannels();
void setDefaultProfileIfNecessary();
- void setDefaultVideoEncoderIfNecessary();
+ virtual void setDefaultVideoEncoderIfNecessary();
+ virtual status_t handleCustomOutputFormats() {return UNKNOWN_ERROR;}
+ virtual status_t handleCustomRecording() {return UNKNOWN_ERROR;}
+ virtual status_t handleCustomAudioSource(sp<AMessage> /*format*/) {return UNKNOWN_ERROR;}
+ virtual status_t handleCustomAudioEncoder() {return UNKNOWN_ERROR;}
StagefrightRecorder(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index cd20837..005cb4b 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -23,7 +23,8 @@
$(TOP)/frameworks/av/media/libstagefright/rtsp \
$(TOP)/frameworks/av/media/libstagefright/timedtext \
$(TOP)/frameworks/av/media/libmediaplayerservice \
- $(TOP)/frameworks/native/include/media/openmax
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/av/media/libavextensions \
LOCAL_CFLAGS += -Werror -Wall
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index b3eb5fd..b29c5b8 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -37,6 +37,7 @@
#include "../../libstagefright/include/NuCachedSource2.h"
#include "../../libstagefright/include/WVMExtractor.h"
#include "../../libstagefright/include/HTTPBase.h"
+#include "mediaplayerservice/AVNuExtensions.h"
namespace android {
@@ -60,6 +61,7 @@
mAudioIsVorbis(false),
mIsWidevine(false),
mIsSecure(false),
+ mUseSetBuffers(false),
mIsStreaming(false),
mUIDValid(uidValid),
mUID(uid),
@@ -172,7 +174,8 @@
extractor = mWVMExtractor;
} else {
extractor = MediaExtractor::Create(mDataSource,
- mimeType.isEmpty() ? NULL : mimeType.string());
+ mimeType.isEmpty() ? NULL : mimeType.string(),
+ mIsStreaming ? 0 : AVNuUtils::get()->getFlags());
}
if (extractor == NULL) {
@@ -202,6 +205,11 @@
}
}
+ if (AVNuUtils::get()->canUseSetBuffers(mFileMeta)) {
+ mUseSetBuffers = true;
+ ALOGI("setBuffers mode enabled");
+ }
+
int32_t totalBitrate = 0;
size_t numtracks = extractor->countTracks();
@@ -318,7 +326,7 @@
status_t NuPlayer::GenericSource::setBuffers(
bool audio, Vector<MediaBuffer *> &buffers) {
- if (mIsSecure && !audio) {
+ if ((mIsSecure || mUseSetBuffers) && !audio) {
return mVideoTrack.mSource->setBuffers(buffers);
}
return INVALID_OPERATION;
@@ -374,7 +382,8 @@
mDataSource = DataSource::CreateFromURI(
mHTTPService, uri, &mUriHeaders, &contentType,
- static_cast<HTTPBase *>(mHttpSource.get()));
+ static_cast<HTTPBase *>(mHttpSource.get()),
+ true /*use extended cache*/);
} else {
mIsWidevine = false;
@@ -427,7 +436,8 @@
| FLAG_CAN_PAUSE
| FLAG_CAN_SEEK_BACKWARD
| FLAG_CAN_SEEK_FORWARD
- | FLAG_CAN_SEEK);
+ | FLAG_CAN_SEEK
+ | (mUseSetBuffers ? FLAG_USE_SET_BUFFERS : 0));
if (mIsSecure) {
// secure decoders must be instantiated before starting widevine source
@@ -1022,7 +1032,8 @@
// start pulling in more buffers if we only have one (or no) buffer left
// so that decoder has less chance of being starved
- if (track->mPackets->getAvailableBufferCount(&finalResult) < 2) {
+ if ((track->mPackets->getAvailableBufferCount(&finalResult) < 2)
+ && !mUseSetBuffers) {
postReadBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO);
}
@@ -1366,7 +1377,7 @@
}
sp<ABuffer> ab;
- if (mIsSecure && !audio) {
+ if ((mIsSecure || mUseSetBuffers) && !audio) {
// data is already provided in the buffer
ab = new ABuffer(NULL, mb->range_length());
mb->add_ref();
@@ -1481,7 +1492,9 @@
break;
case MEDIA_TRACK_TYPE_AUDIO:
track = &mAudioTrack;
- if (mIsWidevine) {
+ if (mHttpSource != NULL && getTrackCount() == 1) {
+ maxBuffers = 16;
+ } else if (mIsWidevine || (mHttpSource != NULL)) {
maxBuffers = 8;
} else {
maxBuffers = 64;
@@ -1512,9 +1525,10 @@
if (seekTimeUs >= 0) {
options.setSeekTo(seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
seeking = true;
+ track->mPackets->clear();
}
- if (mIsWidevine) {
+ if (mIsWidevine || mUseSetBuffers) {
options.setNonBlocking();
}
@@ -1536,7 +1550,8 @@
queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
sp<ABuffer> buffer = mediaBufferToABuffer(
- mbuf, trackType, seekTimeUs, actualTimeUs);
+ mbuf, trackType, seekTimeUs,
+ numBuffers == 0 ? actualTimeUs : NULL);
track->mPackets->queueAccessUnit(buffer);
formatChange = false;
seeking = false;
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h
index ac980ef..bdcf706 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.h
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.h
@@ -42,7 +42,7 @@
struct NuPlayer::GenericSource : public NuPlayer::Source {
GenericSource(const sp<AMessage> ¬ify, bool uidValid, uid_t uid);
- status_t setDataSource(
+ virtual status_t setDataSource(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
@@ -84,7 +84,7 @@
virtual sp<MetaData> getFormatMeta(bool audio);
-private:
+protected:
enum {
kWhatPrepareAsync,
kWhatFetchSubtitleData,
@@ -126,6 +126,7 @@
bool mAudioIsVorbis;
bool mIsWidevine;
bool mIsSecure;
+ bool mUseSetBuffers;
bool mIsStreaming;
bool mUIDValid;
uid_t mUID;
@@ -164,7 +165,7 @@
int64_t getLastReadPosition();
void setDrmPlaybackStatusIfNeeded(int playbackStatus, int64_t position);
- void notifyPreparedAndCleanup(status_t err);
+ virtual void notifyPreparedAndCleanup(status_t err);
void onSecureDecodersInstantiated(status_t err);
void finishPrepareAsync();
status_t startSources();
@@ -181,7 +182,7 @@
void onSeek(sp<AMessage> msg);
status_t doSeek(int64_t seekTimeUs);
- void onPrepareAsync();
+ virtual void onPrepareAsync();
void fetchTextData(
uint32_t what, media_track_type type,
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 126625a..a57fdc1 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -30,6 +30,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/Utils.h>
+
namespace android {
@@ -118,6 +120,19 @@
return format;
}
+sp<MetaData> NuPlayer::HTTPLiveSource::getFormatMeta(bool audio) {
+ sp<AMessage> format = getFormat(audio);
+
+ if (format == NULL) {
+ return NULL;
+ }
+
+ sp<MetaData> meta = new MetaData;
+ convertMessageToMetaData(format, meta);
+ return meta;
+}
+
+
status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
return OK;
}
@@ -197,7 +212,11 @@
}
status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
- return mLiveSession->seekTo(seekTimeUs);
+ if (mLiveSession->isSeekable()) {
+ return mLiveSession->seekTo(seekTimeUs);
+ } else {
+ return INVALID_OPERATION;
+ }
}
void NuPlayer::HTTPLiveSource::pollForRawData(
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 9e0ec2f..388156c 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -39,6 +39,7 @@
virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
virtual sp<AMessage> getFormat(bool audio);
+ virtual sp<MetaData> getFormatMeta(bool audio);
virtual status_t feedMoreTSData();
virtual status_t getDuration(int64_t *durationUs);
@@ -53,7 +54,6 @@
virtual void onMessageReceived(const sp<AMessage> &msg);
-private:
enum Flags {
// Don't log any URLs.
kFlagIncognito = 1,
@@ -78,7 +78,7 @@
bool mHasMetadata;
bool mMetadataSelected;
- void onSessionNotify(const sp<AMessage> &msg);
+ virtual void onSessionNotify(const sp<AMessage> &msg);
void pollForRawData(
const sp<AMessage> &msg, int32_t currentGeneration,
LiveSession::StreamType fetchType, int32_t pushWhat);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index c0146d5..ccbfc75 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -56,6 +75,10 @@
#include "ESDS.h"
#include <media/stagefright/Utils.h>
+#include "mediaplayerservice/AVNuExtensions.h"
+#ifdef DOLBY_ENABLE
+#include "DolbyNuPlayerExtImpl.h"
+#endif // DOLBY_END
namespace android {
@@ -130,6 +153,23 @@
DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction);
};
+struct NuPlayer::InstantiateDecoderAction : public Action {
+ InstantiateDecoderAction(bool audio, sp<DecoderBase> *decoder)
+ : mAudio(audio),
+ mdecoder(decoder) {
+ }
+
+ virtual void execute(NuPlayer *player) {
+ player->instantiateDecoder(mAudio, mdecoder);
+ }
+
+private:
+ bool mAudio;
+ sp<DecoderBase> *mdecoder;
+
+ DISALLOW_EVIL_CONSTRUCTORS(InstantiateDecoderAction);
+};
+
struct NuPlayer::PostMessageAction : public Action {
PostMessageAction(const sp<AMessage> &msg)
: mMessage(msg) {
@@ -188,6 +228,7 @@
mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
mVideoFpsHint(-1.f),
mStarted(false),
+ mResetting(false),
mSourceStarted(false),
mPaused(false),
mPausedByClient(false),
@@ -216,7 +257,7 @@
msg->post();
}
-static bool IsHTTPLiveURL(const char *url) {
+bool NuPlayer::IsHTTPLiveURL(const char *url) {
if (!strncasecmp("http://", url, 7)
|| !strncasecmp("https://", url, 8)
|| !strncasecmp("file://", url, 7)) {
@@ -1019,6 +1060,10 @@
break; // Finish anyways.
}
notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+#ifdef DOLBY_ENABLE
+ } else if (what == kWhatDlbCpProc) {
+ onDolbyMessageReceived();
+#endif // DOLBY_END
} else {
ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
what,
@@ -1092,40 +1137,7 @@
int32_t reason;
CHECK(msg->findInt32("reason", &reason));
ALOGV("Tear down audio with reason %d.", reason);
- mAudioDecoder.clear();
- ++mAudioDecoderGeneration;
- bool needsToCreateAudioDecoder = true;
- if (mFlushingAudio == FLUSHING_DECODER) {
- mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
- mFlushingAudio = FLUSHED;
- finishFlushIfPossible();
- } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
- || mFlushingAudio == SHUTTING_DOWN_DECODER) {
- mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
- mFlushingAudio = SHUT_DOWN;
- finishFlushIfPossible();
- needsToCreateAudioDecoder = false;
- }
- if (mRenderer == NULL) {
- break;
- }
- closeAudioSink();
- mRenderer->flush(
- true /* audio */, false /* notifyComplete */);
- if (mVideoDecoder != NULL) {
- mRenderer->flush(
- false /* audio */, false /* notifyComplete */);
- }
-
- int64_t positionUs;
- if (!msg->findInt64("positionUs", &positionUs)) {
- positionUs = mPreviousSeekTimeUs;
- }
- performSeek(positionUs);
-
- if (reason == Renderer::kDueToError && needsToCreateAudioDecoder) {
- instantiateDecoder(true /* audio */, &mAudioDecoder);
- }
+ performTearDown(msg);
}
break;
}
@@ -1139,12 +1151,17 @@
{
ALOGV("kWhatReset");
+ mResetting = true;
+
mDeferredActions.push_back(
new FlushDecoderAction(
FLUSH_CMD_SHUTDOWN /* audio */,
FLUSH_CMD_SHUTDOWN /* video */));
mDeferredActions.push_back(
+ new SimpleAction(&NuPlayer::closeAudioSink));
+
+ mDeferredActions.push_back(
new SimpleAction(&NuPlayer::performReset));
processDeferredActions();
@@ -1221,7 +1238,8 @@
}
void NuPlayer::onResume() {
- if (!mPaused) {
+ if (!mPaused || mResetting) {
+ ALOGD_IF(mResetting, "resetting, onResume discarded");
return;
}
mPaused = false;
@@ -1295,6 +1313,7 @@
}
sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
+ AVNuUtils::get()->setSourcePCMFormat(audioMeta);
audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
if (mAudioSink != NULL) {
streamType = mAudioSink->getAudioStreamType();
@@ -1304,6 +1323,10 @@
mOffloadAudio =
canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType);
+ if (!mOffloadAudio) {
+ mOffloadAudio = canOffloadDecodedPCMStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType);
+ }
+
if (mOffloadAudio) {
flags |= Renderer::FLAG_OFFLOAD_AUDIO;
}
@@ -1311,7 +1334,7 @@
sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
++mRendererGeneration;
notify->setInt32("generation", mRendererGeneration);
- mRenderer = new Renderer(mAudioSink, notify, flags);
+ mRenderer = AVNuFactory::get()->createRenderer(mAudioSink, notify, flags);
mRendererLooper = new ALooper;
mRendererLooper->setName("NuPlayerRenderer");
mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
@@ -1440,7 +1463,7 @@
// is possible; otherwise the decoders call the renderer openAudioSink directly.
status_t err = mRenderer->openAudioSink(
- format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio);
+ format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mSource->isStreaming());
if (err != OK) {
// Any failure we turn off mOffloadAudio.
mOffloadAudio = false;
@@ -1470,8 +1493,11 @@
sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
const bool hasVideo = (videoFormat != NULL);
- const bool canOffload = canOffloadStream(
+ bool canOffload = canOffloadStream(
audioMeta, hasVideo, mSource->isStreaming(), streamType);
+ if (!canOffload) {
+ canOffload = canOffloadDecodedPCMStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType);
+ }
if (canOffload) {
if (!mOffloadAudio) {
mRenderer->signalEnableOffloadAudio();
@@ -1483,6 +1509,7 @@
if (mOffloadAudio) {
mRenderer->signalDisableOffloadAudio();
mOffloadAudio = false;
+ setDecodedPcmOffload(false);
}
}
}
@@ -1493,7 +1520,10 @@
if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
return OK;
}
-
+ if (mSource == NULL) {
+ ALOGD("%s Ignore instantiate decoder after clearing source", __func__);
+ return INVALID_OPERATION;
+ }
sp<AMessage> format = mSource->getFormat(audio);
if (format == NULL) {
@@ -1531,12 +1561,17 @@
notify->setInt32("generation", mAudioDecoderGeneration);
determineAudioModeChange();
- if (mOffloadAudio) {
+
+ if (AVNuUtils::get()->isRAWFormat(format)) {
+ AVNuUtils::get()->setPCMFormat(format,
+ AVNuUtils::get()->getKeyPCMFormat(mSource->getFormatMeta(true /* audio */)));
+ }
+ if (mOffloadAudio && !ifDecodedPCMOffload()) {
const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);
format->setInt32("has-video", hasVideo);
- *decoder = new DecoderPassThrough(notify, mSource, mRenderer);
+ *decoder = AVNuFactory::get()->createPassThruDecoder(notify, mSource, mRenderer);
} else {
- *decoder = new Decoder(notify, mSource, mPID, mRenderer);
+ *decoder = AVNuFactory::get()->createDecoder(notify, mSource, mPID, mRenderer);
}
} else {
sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
@@ -1561,7 +1596,8 @@
(*decoder)->configure(format);
// allocate buffers to decrypt widevine source buffers
- if (!audio && (mSourceFlags & Source::FLAG_SECURE)) {
+ if (!audio && ((mSourceFlags & Source::FLAG_SECURE) ||
+ (mSourceFlags & Source::FLAG_USE_SET_BUFFERS))) {
Vector<sp<ABuffer> > inputBufs;
CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK);
@@ -1924,6 +1960,7 @@
}
mStarted = false;
+ mResetting = false;
mSourceStarted = false;
}
@@ -2217,6 +2254,13 @@
break;
}
+ case Source::kWhatRTCPByeReceived:
+ {
+ ALOGV("notify the client that Bye message is received");
+ notifyListener(MEDIA_INFO, 2000, 0);
+ break;
+ }
+
default:
TRESPASS();
}
@@ -2362,4 +2406,51 @@
TRESPASS();
}
+//
+// There is a flush from within the decoder's onFlush handling.
+// Without it, it is still possible that a buffer can be queueued
+// after NuPlayer issues a flush on the renderer's audio queue.
+//
+void NuPlayer::performTearDown(const sp<AMessage> &msg) {
+ int32_t reason;
+ CHECK(msg->findInt32("reason", &reason));
+
+ if (mAudioDecoder != NULL) {
+ switch (mFlushingAudio) {
+ case NONE:
+ case FLUSHING_DECODER:
+ mDeferredActions.push_back(
+ new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
+ FLUSH_CMD_NONE /* video */));
+
+ if (reason == Renderer::kDueToError) {
+ mDeferredActions.push_back(
+ new InstantiateDecoderAction(true /* audio */, &mAudioDecoder));
+ }
+
+ int64_t positionUs;
+ if (!msg->findInt64("positionUs", &positionUs)) {
+ positionUs = mPreviousSeekTimeUs;
+ }
+ mDeferredActions.push_back(new SeekAction(positionUs));
+ break;
+ default:
+ ALOGW("performTearDown while flushing audio in %d", mFlushingAudio);
+ break;
+ }
+ }
+
+ if (mRenderer != NULL) {
+ closeAudioSink();
+ // see comment at beginning of function
+ mRenderer->flush(
+ true /* audio */, false /* notifyComplete */);
+ if (mVideoDecoder != NULL) {
+ mRenderer->flush(
+ false /* audio */, false /* notifyComplete */);
+ }
+ }
+ processDeferredActions();
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index c9f0bbd..9a7e81a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef NU_PLAYER_H_
@@ -41,7 +60,7 @@
void setDataSourceAsync(const sp<IStreamSource> &source);
- void setDataSourceAsync(
+ virtual void setDataSourceAsync(
const sp<IMediaHTTPService> &httpService,
const char *url,
const KeyedVector<String8, String8> *headers);
@@ -86,12 +105,15 @@
virtual ~NuPlayer();
virtual void onMessageReceived(const sp<AMessage> &msg);
-
+ virtual bool ifDecodedPCMOffload() {return false;}
+ virtual void setDecodedPcmOffload(bool /*decodePcmOffload*/) {}
+ virtual bool canOffloadDecodedPCMStream(const sp<MetaData> /*meta*/,
+ bool /*hasVideo*/, bool /*isStreaming*/, audio_stream_type_t /*streamType*/) {return false;}
+ static bool IsHTTPLiveURL(const char *url);
public:
struct NuPlayerStreamListener;
struct Source;
-private:
struct Decoder;
struct DecoderBase;
struct DecoderPassThrough;
@@ -106,9 +128,11 @@
struct SetSurfaceAction;
struct ResumeDecoderAction;
struct FlushDecoderAction;
+ struct InstantiateDecoderAction;
struct PostMessageAction;
struct SimpleAction;
+protected:
enum {
kWhatSetDataSource = '=DaS',
kWhatPrepare = 'prep',
@@ -197,6 +221,7 @@
AVSyncSettings mSyncSettings;
float mVideoFpsHint;
bool mStarted;
+ bool mResetting;
bool mSourceStarted;
// Actual pause state, either as requested by client or due to buffering.
@@ -221,11 +246,11 @@
mFlushComplete[1][1] = false;
}
- void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
+ virtual void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
void closeAudioSink();
void determineAudioModeChange();
- status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
+ virtual status_t instantiateDecoder(bool audio, sp<DecoderBase> *decoder);
status_t onInstantiateSecureDecoders();
@@ -233,13 +258,13 @@
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat = NULL);
- void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);
+ virtual void notifyListener(int msg, int ext1, int ext2, const Parcel *in = NULL);
void handleFlushComplete(bool audio, bool isDecoder);
void finishFlushIfPossible();
void onStart(int64_t startPositionUs = -1);
- void onResume();
+ virtual void onResume();
void onPause();
bool audioDecoderStillNeeded();
@@ -256,14 +281,14 @@
void processDeferredActions();
- void performSeek(int64_t seekTimeUs);
+ virtual void performSeek(int64_t seekTimeUs);
void performDecoderFlush(FlushCommand audio, FlushCommand video);
void performReset();
void performScanSources();
void performSetSurface(const sp<Surface> &wrapper);
void performResumeDecoders(bool needNotify);
- void onSourceNotify(const sp<AMessage> &msg);
+ virtual void onSourceNotify(const sp<AMessage> &msg);
void onClosedCaptionNotify(const sp<AMessage> &msg);
void queueDecoderShutdown(
@@ -275,6 +300,12 @@
void writeTrackInfo(Parcel* reply, const sp<AMessage> format) const;
+ void performTearDown(const sp<AMessage> &msg);
+
+#ifdef DOLBY_ENABLE
+ void onDolbyMessageReceived();
+#endif // DOLBY_END
+
DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 3646828..fbd0b12 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -34,10 +53,15 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
+#include <stagefright/AVExtensions.h>
#include <gui/Surface.h>
#include "avc_utils.h"
#include "ATSParser.h"
+#include "mediaplayerservice/AVNuExtensions.h"
+#ifdef DOLBY_ENABLE
+#include "DolbyNuPlayerDecoderExtImpl.h"
+#endif // DOLBY_END
namespace android {
@@ -78,7 +102,9 @@
}
NuPlayer::Decoder::~Decoder() {
- mCodec->release();
+ if (mCodec != NULL) {
+ mCodec->release();
+ }
releaseAndResetMediaBuffers();
}
@@ -251,8 +277,10 @@
mComponentName.append(" decoder");
ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
- mCodec = MediaCodec::CreateByType(
- mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid);
+ mCodec = AVUtils::get()->createCustomComponentByName(mCodecLooper, mime.c_str(), false /* encoder */, format);
+ if (mCodec == NULL) {
+ mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
+ }
int32_t secure = 0;
if (format->findInt32("secure", &secure) && secure != 0) {
if (mCodec != NULL) {
@@ -313,6 +341,9 @@
sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
mCodec->setCallback(reply);
+#ifdef DOLBY_ENABLE
+ setDolbyMessage();
+#endif // DOLBY_END
err = mCodec->start();
if (err != OK) {
@@ -357,7 +388,14 @@
if (notifyComplete) {
mResumePending = true;
}
- mCodec->start();
+
+ if (mCodec != NULL) {
+ mCodec->start();
+ } else {
+ ALOGW("Decoder %s onResume without a valid codec object",
+ mComponentName.c_str());
+ handleError(NO_INIT);
+ }
}
void NuPlayer::Decoder::doFlush(bool notifyComplete) {
@@ -558,6 +596,11 @@
sp<ABuffer> buffer;
mCodec->getOutputBuffer(index, &buffer);
+ if (buffer == NULL) {
+ handleError(UNKNOWN_ERROR);
+ return false;
+ }
+
if (index >= mOutputBuffers.size()) {
for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
mOutputBuffers.add();
@@ -569,6 +612,8 @@
buffer->setRange(offset, size);
buffer->meta()->clear();
buffer->meta()->setInt64("timeUs", timeUs);
+ setPcmFormat(buffer->meta());
+ AVNuUtils::get()->addFlagsInMeta(buffer, flags, mIsAudio);
bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
// we do not expect CODECCONFIG or SYNCFRAME for decoder
@@ -577,6 +622,14 @@
reply->setSize("buffer-ix", index);
reply->setInt32("generation", mBufferGeneration);
+ if ((flags & MediaCodec::BUFFER_FLAG_DATACORRUPT) &&
+ AVNuUtils::get()->dropCorruptFrame()) {
+ ALOGV("[%s] dropping corrupt buffer at time %lld as requested.",
+ mComponentName.c_str(), (long long)timeUs);
+ reply->post();
+ return true;
+ }
+
if (eos) {
ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
@@ -636,7 +689,7 @@
}
mRenderer->openAudioSink(
- format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
+ format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */, mSource->isStreaming());
}
}
@@ -708,6 +761,7 @@
// treat seamless format change separately
formatChange = !seamlessFormatChange;
}
+ AVNuUtils::get()->checkFormatChange(&formatChange, accessUnit);
// For format or time change, return EOS to queue EOS input,
// then wait for EOS on output.
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index eeb4af4..1999615 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef NUPLAYER_DECODER_H_
@@ -49,8 +68,8 @@
virtual void onFlush();
virtual void onShutdown(bool notifyComplete);
virtual bool doRequestBuffers();
+ virtual void setPcmFormat(const sp<AMessage> & /*format*/) {}
-private:
enum {
kWhatCodecNotify = 'cdcN',
kWhatRenderBuffer = 'rndr',
@@ -103,7 +122,7 @@
size_t size,
int64_t timeUs,
int32_t flags);
- void handleOutputFormatChange(const sp<AMessage> &format);
+ virtual void handleOutputFormatChange(const sp<AMessage> &format);
void releaseAndResetMediaBuffers();
void requestCodecNotification();
@@ -121,6 +140,9 @@
void finishHandleDiscontinuity(bool flushOnTimeChange);
void notifyResumeCompleteIfNecessary();
+#ifdef DOLBY_ENABLE
+ void setDolbyMessage();
+#endif // DOLBY_END
DISALLOW_EVIL_CONSTRUCTORS(Decoder);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
index 30146c4..937936d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -29,14 +29,12 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
+#include "mediaplayerservice/AVNuExtensions.h"
#include "ATSParser.h"
namespace android {
-// TODO optimize buffer size for power consumption
-// The offload read buffer size is 32 KB but 24 KB uses less power.
-static const size_t kAggregateBufferSizeBytes = 24 * 1024;
static const size_t kMaxCachedBytes = 200000;
NuPlayer::DecoderPassThrough::DecoderPassThrough(
@@ -46,6 +44,9 @@
: DecoderBase(notify),
mSource(source),
mRenderer(renderer),
+ // TODO optimize buffer size for power consumption
+ // The offload read buffer size is 32 KB but 24 KB uses less power.
+ mAggregateBufferSizeBytes(24 * 1024),
mSkipRenderingUntilMediaTimeUs(-1ll),
mPaused(false),
mReachedEOS(true),
@@ -76,7 +77,7 @@
// format is different.
status_t err = mRenderer->openAudioSink(
format, true /* offloadOnly */, hasVideo,
- AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */);
+ AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */, mSource->isStreaming());
if (err != OK) {
handleError(err);
}
@@ -173,9 +174,9 @@
size_t smallSize = accessUnit->size();
if ((mAggregateBuffer == NULL)
// Don't bother if only room for a few small buffers.
- && (smallSize < (kAggregateBufferSizeBytes / 3))) {
+ && (smallSize < (mAggregateBufferSizeBytes / 3))) {
// Create a larger buffer for combining smaller buffers from the extractor.
- mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
+ mAggregateBuffer = new ABuffer(mAggregateBufferSizeBytes);
mAggregateBuffer->setRange(0, 0); // start empty
}
@@ -201,6 +202,7 @@
if ((bigSize == 0) && smallTimestampValid) {
mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
}
+ setPcmFormat(mAggregateBuffer->meta());
// Append small buffer to the bigger buffer.
memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
bigSize += smallSize;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
index db33e87..629e266 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h
@@ -43,25 +43,27 @@
virtual void onFlush();
virtual void onShutdown(bool notifyComplete);
virtual bool doRequestBuffers();
+ virtual void setPcmFormat(const sp<AMessage> & /*format*/) {}
+ virtual sp<ABuffer> aggregateBuffer(const sp<ABuffer> &accessUnit);
-private:
enum {
kWhatBufferConsumed = 'bufC',
};
sp<Source> mSource;
sp<Renderer> mRenderer;
+ size_t mAggregateBufferSizeBytes;
int64_t mSkipRenderingUntilMediaTimeUs;
bool mPaused;
-
- bool mReachedEOS;
+ bool mReachedEOS;
// Used by feedDecoderInputData to aggregate small buffers into
// one large buffer.
+ status_t mPendingAudioErr;
sp<ABuffer> mPendingAudioAccessUnit;
- status_t mPendingAudioErr;
sp<ABuffer> mAggregateBuffer;
+private:
// mPendingBuffersToDrain are only for debugging. It can be removed
// when the power investigation is done.
size_t mPendingBuffersToDrain;
@@ -72,7 +74,6 @@
bool isDoneFetching() const;
status_t dequeueAccessUnit(sp<ABuffer> *accessUnit);
- sp<ABuffer> aggregateBuffer(const sp<ABuffer> &accessUnit);
status_t fetchInputData(sp<AMessage> &reply);
void doFlush(bool notifyComplete);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index 7370224..a294d36 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -31,6 +31,9 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
+#include "mediaplayerservice/AVNuExtensions.h"
+#include "mediaplayerservice/AVMediaServiceExtensions.h"
+
namespace android {
NuPlayerDriver::NuPlayerDriver(pid_t pid)
@@ -55,7 +58,7 @@
true, /* canCallJava */
PRIORITY_AUDIO);
- mPlayer = new NuPlayer(pid);
+ mPlayer = AVNuFactory::get()->createNuPlayer(pid);
mLooper->registerHandler(mPlayer);
mPlayer->setDriver(this);
@@ -114,6 +117,7 @@
mCondition.wait(mLock);
}
+ AVNuUtils::get()->printFileName(fd);
return mAsyncResult;
}
@@ -607,6 +611,8 @@
Metadata::kSeekAvailable,
mPlayerFlags & NuPlayer::Source::FLAG_CAN_SEEK);
+ AVMediaServiceUtils::get()->appendMeta(&meta);
+
return OK;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 776dba8..c92309b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -32,6 +32,8 @@
#include <media/stagefright/VideoFrameScheduler.h>
#include <inttypes.h>
+#include "mediaplayerservice/AVNuExtensions.h"
+#include "stagefright/AVExtensions.h"
namespace android {
@@ -81,6 +83,16 @@
// static
const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
+static bool sFrameAccurateAVsync = false;
+
+static void readProperties() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("persist.sys.media.avsync", value, NULL)) {
+ sFrameAccurateAVsync =
+ !strcmp("1", value) || !strcasecmp("true", value);
+ }
+}
+
NuPlayer::Renderer::Renderer(
const sp<MediaPlayerBase::AudioSink> &sink,
const sp<AMessage> ¬ify,
@@ -102,6 +114,7 @@
mVideoLateByUs(0ll),
mHasAudio(false),
mHasVideo(false),
+ mFoundAudioEOS(false),
mNotifyCompleteAudio(false),
mNotifyCompleteVideo(false),
mSyncQueues(false),
@@ -122,6 +135,7 @@
mMediaClock = new MediaClock;
mPlaybackRate = mPlaybackSettings.mSpeed;
mMediaClock->setPlaybackRate(mPlaybackRate);
+ readProperties();
}
NuPlayer::Renderer::~Renderer() {
@@ -312,7 +326,8 @@
// Called on any threads.
status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
- return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
+ return mMediaClock->getMediaTime(
+ ALooper::GetNowUs(), mediaUs, (mHasAudio && mFoundAudioEOS));
}
void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
@@ -348,18 +363,20 @@
bool offloadOnly,
bool hasVideo,
uint32_t flags,
- bool *isOffloaded) {
+ bool *isOffloaded,
+ bool isStreaming) {
sp<AMessage> msg = new AMessage(kWhatOpenAudioSink, this);
msg->setMessage("format", format);
msg->setInt32("offload-only", offloadOnly);
msg->setInt32("has-video", hasVideo);
msg->setInt32("flags", flags);
+ msg->setInt32("isStreaming", isStreaming);
sp<AMessage> response;
- msg->postAndAwaitResponse(&response);
+ status_t postStatus = msg->postAndAwaitResponse(&response);
int32_t err;
- if (!response->findInt32("err", &err)) {
+ if (postStatus != OK || !response->findInt32("err", &err)) {
err = INVALID_OPERATION;
} else if (err == OK && isOffloaded != NULL) {
int32_t offload;
@@ -392,7 +409,10 @@
uint32_t flags;
CHECK(msg->findInt32("flags", (int32_t *)&flags));
- status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags);
+ uint32_t isStreaming;
+ CHECK(msg->findInt32("isStreaming", (int32_t *)&isStreaming));
+
+ status_t err = onOpenAudioSink(format, offloadOnly, hasVideo, flags, isStreaming);
sp<AMessage> response = new AMessage;
response->setInt32("err", err);
@@ -435,9 +455,10 @@
if (onDrainAudioQueue()) {
uint32_t numFramesPlayed;
- CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed),
- (status_t)OK);
-
+ if (mAudioSink->getPosition(&numFramesPlayed) != OK) {
+ ALOGW("mAudioSink->getPosition failed");
+ break;
+ }
uint32_t numFramesPendingPlayout =
mNumFramesWritten - numFramesPlayed;
@@ -1074,6 +1095,11 @@
ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
// post 2 display refreshes before rendering is due
+ // FIXME currently this increases power consumption, so unless frame-accurate
+ // AV sync is requested, post closer to required render time (at 0.63 vsyncs)
+ if (!sFrameAccurateAVsync) {
+ twoVsyncsUs >>= 4;
+ }
msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
mDrainVideoQueuePending = true;
@@ -1164,6 +1190,9 @@
}
void NuPlayer::Renderer::notifyEOS(bool audio, status_t finalResult, int64_t delayUs) {
+ if (audio) {
+ mFoundAudioEOS = true;
+ }
sp<AMessage> notify = mNotify->dup();
notify->setInt32("what", kWhatEOS);
notify->setInt32("audio", static_cast<int32_t>(audio));
@@ -1479,6 +1508,7 @@
mDrainAudioQueuePending = false;
mDrainVideoQueuePending = false;
+ mVideoRenderingStarted = false; // force-notify NOTE_INFO MEDIA_INFO_RENDERING_START after resume
if (mHasAudio) {
mAudioSink->pause();
@@ -1490,6 +1520,8 @@
}
void NuPlayer::Renderer::onResume() {
+ readProperties();
+
if (!mPaused) {
return;
}
@@ -1559,6 +1591,7 @@
int64_t numFramesPlayedAt;
AudioTimestamp ts;
static const int64_t kStaleTimestamp100ms = 100000;
+ int64_t durationUs;
status_t res = mAudioSink->getTimestamp(ts);
if (res == OK) { // case 1: mixing audio tracks and offloaded tracks.
@@ -1585,14 +1618,20 @@
// numFramesPlayed, (long long)numFramesPlayedAt);
} else { // case 3: transitory at new track or audio fast tracks.
res = mAudioSink->getPosition(&numFramesPlayed);
- CHECK_EQ(res, (status_t)OK);
- numFramesPlayedAt = nowUs;
- numFramesPlayedAt += 1000LL * mAudioSink->latency() / 2; /* XXX */
+ if (res != OK) {
+ //query to getPosition fails, use media clock to simulate render position
+ getCurrentPosition(&durationUs);
+ durationUs = durationUs - mAnchorTimeMediaUs;
+ return durationUs;
+ } else {
+ numFramesPlayedAt = nowUs;
+ numFramesPlayedAt += 1000LL * mAudioSink->latency() / 2; /* XXX */
+ }
//ALOGD("getPosition: %u %lld", numFramesPlayed, (long long)numFramesPlayedAt);
}
//CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
- int64_t durationUs = getDurationUsIfPlayedAtSampleRate(numFramesPlayed)
+ durationUs = getDurationUsIfPlayedAtSampleRate(numFramesPlayed)
+ nowUs - numFramesPlayedAt;
if (durationUs < 0) {
// Occurs when numFramesPlayed position is very small and the following:
@@ -1650,7 +1689,8 @@
const sp<AMessage> &format,
bool offloadOnly,
bool hasVideo,
- uint32_t flags) {
+ uint32_t flags,
+ bool isStreaming) {
ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)",
offloadOnly, offloadingAudio());
bool audioSinkChanged = false;
@@ -1678,9 +1718,13 @@
"audio_format", mime.c_str());
onDisableOffloadAudio();
} else {
+ int32_t bitWidth = 16;
ALOGV("Mime \"%s\" mapped to audio_format 0x%x",
mime.c_str(), audioFormat);
+ audioFormat = AVUtils::get()->updateAudioFormat(audioFormat, format);
+
+ bitWidth = AVUtils::get()->getAudioSampleBits(format);
int avgBitRate = -1;
format->findInt32("bit-rate", &avgBitRate);
@@ -1688,12 +1732,24 @@
if (audioFormat == AUDIO_FORMAT_AAC
&& format->findInt32("aac-profile", &aacProfile)) {
// Redefine AAC format as per aac profile
- mapAACProfileToAudioFormat(
- audioFormat,
- aacProfile);
+ int32_t isADTSSupported;
+ isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(format,
+ audioFormat,
+ aacProfile);
+ if (!isADTSSupported) {
+ mapAACProfileToAudioFormat(audioFormat,
+ aacProfile);
+ } else {
+ ALOGV("Format is AAC ADTS\n");
+ }
}
+ int32_t offloadBufferSize =
+ AVUtils::get()->getAudioMaxInputBufferSize(
+ audioFormat,
+ format);
audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER;
+
offloadInfo.duration_us = -1;
format->findInt64(
"durationUs", &offloadInfo.duration_us);
@@ -1703,7 +1759,9 @@
offloadInfo.stream_type = AUDIO_STREAM_MUSIC;
offloadInfo.bit_rate = avgBitRate;
offloadInfo.has_video = hasVideo;
- offloadInfo.is_streaming = true;
+ offloadInfo.is_streaming = isStreaming;
+ offloadInfo.bit_width = bitWidth;
+ offloadInfo.offload_buffer_size = offloadBufferSize;
if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) {
ALOGV("openAudioSink: no change in offload mode");
@@ -1767,7 +1825,7 @@
const PcmInfo info = {
(audio_channel_mask_t)channelMask,
(audio_output_flags_t)pcmFlags,
- AUDIO_FORMAT_PCM_16_BIT, // TODO: change to audioFormat
+ AVNuUtils::get()->getPCMFormat(format),
numChannels,
sampleRate
};
@@ -1802,7 +1860,7 @@
sampleRate,
numChannels,
(audio_channel_mask_t)channelMask,
- AUDIO_FORMAT_PCM_16_BIT,
+ AVNuUtils::get()->getPCMFormat(format),
0 /* bufferCount - unused */,
mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL,
mUseAudioCallback ? this : NULL,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 87bcbf9..50bd0a9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -73,12 +73,15 @@
status_t getCurrentPosition(int64_t *mediaUs);
int64_t getVideoLateByUs();
+ virtual audio_stream_type_t getAudioStreamType(){return AUDIO_STREAM_DEFAULT;}
+
status_t openAudioSink(
const sp<AMessage> &format,
bool offloadOnly,
bool hasVideo,
uint32_t flags,
- bool *isOffloaded);
+ bool *isOffloaded,
+ bool isStreaming);
void closeAudioSink();
enum {
@@ -101,7 +104,6 @@
virtual void onMessageReceived(const sp<AMessage> &msg);
-private:
enum {
kWhatDrainAudioQueue = 'draA',
kWhatDrainVideoQueue = 'draV',
@@ -162,6 +164,7 @@
int64_t mVideoLateByUs;
bool mHasAudio;
bool mHasVideo;
+ bool mFoundAudioEOS;
bool mNotifyCompleteAudio;
bool mNotifyCompleteVideo;
@@ -228,7 +231,7 @@
void prepareForMediaRenderingStart_l();
void notifyIfMediaRenderingStarted_l();
- void onQueueBuffer(const sp<AMessage> &msg);
+ virtual void onQueueBuffer(const sp<AMessage> &msg);
void onQueueEOS(const sp<AMessage> &msg);
void onFlush(const sp<AMessage> &msg);
void onAudioSinkChanged();
@@ -250,7 +253,8 @@
const sp<AMessage> &format,
bool offloadOnly,
bool hasVideo,
- uint32_t flags);
+ uint32_t flags,
+ bool isStreaming);
void onCloseAudioSink();
void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 11a6a9f..b248316 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -39,6 +39,7 @@
FLAG_DYNAMIC_DURATION = 16,
FLAG_SECURE = 32,
FLAG_PROTECTED = 64,
+ FLAG_USE_SET_BUFFERS = 128,
};
enum {
@@ -57,6 +58,7 @@
kWhatQueueDecoderShutdown,
kWhatDrmNoLicense,
kWhatInstantiateSecureDecoders,
+ kWhatRTCPByeReceived,
};
// The provides message is used to notify the player about various
@@ -132,10 +134,10 @@
void notifyFlagsChanged(uint32_t flags);
void notifyVideoSizeChanged(const sp<AMessage> &format = NULL);
void notifyInstantiateSecureDecoders(const sp<AMessage> &reply);
- void notifyPrepared(status_t err = OK);
+ virtual void notifyPrepared(status_t err = OK);
-private:
sp<AMessage> mNotify;
+private:
DISALLOW_EVIL_CONSTRUCTORS(Source);
};
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index af0351e..35567a5 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -27,6 +27,7 @@
#include <media/IMediaHTTPService.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
namespace android {
@@ -131,6 +132,10 @@
// Check if EOS or ERROR is received
if (source != NULL && source->isFinished(mediaDurationUs)) {
+ if (mHandler != NULL) {
+ ALOGI("Nearing EOS...No Pause is issued");
+ mHandler->cancelTimeoutCheck();
+ }
return;
}
}
@@ -476,8 +481,11 @@
if (!info->mNPTMappingValid) {
// This is a live stream, we didn't receive any normal
// playtime mapping. We won't map to npt time.
- source->queueAccessUnit(accessUnit);
- break;
+ if (!AVMediaServiceUtils::get()->checkNPTMapping(&info->mRTPTime,
+ &info->mNormalPlaytimeUs, &info->mNPTMappingValid, rtpTime)) {
+ source->queueAccessUnit(accessUnit);
+ break;
+ }
}
int64_t nptUs =
@@ -563,6 +571,14 @@
break;
}
+ case MyHandler::kWhatByeReceived:
+ {
+ sp<AMessage> msg = dupNotify();
+ msg->setInt32("what", kWhatRTCPByeReceived);
+ msg->post();
+ break;
+ }
+
case SDPLoader::kWhatSDPLoaded:
{
onSDPLoaded(msg);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 8d9bd21..677e2d7 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -54,6 +73,11 @@
#include "include/avc_utils.h"
+#include <stagefright/AVExtensions.h>
+#ifdef DOLBY_ENABLE
+#include "DolbyACodecExtImpl.h"
+#endif // DOLBY_END
+
namespace android {
// OMX errors are directly mapped into status_t range if
@@ -539,6 +563,10 @@
ACodec::~ACodec() {
}
+status_t ACodec::setupCustomCodec(status_t err, const char *, const sp<AMessage> &) {
+ return err;
+}
+
void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
mNotify = msg;
}
@@ -613,8 +641,8 @@
msg->setInt32("keepComponentAllocated", keepComponentAllocated);
msg->post();
if (!keepComponentAllocated) {
- // ensure shutdown completes in 3 seconds
- (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
+ // ensure shutdown completes in 30 seconds
+ (new AMessage(kWhatReleaseCodecInstance, this))->post(30000000);
}
}
@@ -828,15 +856,11 @@
: OMXCodec::kRequiresAllocateBufferOnOutputPorts;
if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
- || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) {
+ || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())
+ || canAllocateBuffer(portIndex)) {
mem.clear();
- void *ptr;
- err = mOMX->allocateBuffer(
- mNode, portIndex, bufSize, &info.mBufferID,
- &ptr);
-
- info.mData = new ABuffer(ptr, bufSize);
+ err = allocateBuffer(portIndex, bufSize, info);
} else if (mQuirks & requiresAllocateBufferBit) {
err = mOMX->allocateBufferWithBackup(
mNode, portIndex, mem, &info.mBufferID, allottedSize);
@@ -1574,6 +1598,10 @@
"audio_decoder.ac3", "audio_encoder.ac3" },
{ MEDIA_MIMETYPE_AUDIO_EAC3,
"audio_decoder.eac3", "audio_encoder.eac3" },
+#ifdef DOLBY_UDC
+ { MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+ "audio_decoder.eac3_joc", NULL },
+#endif // DOLBY_END
};
static const size_t kNumMimeToRole =
@@ -1639,6 +1667,8 @@
return err;
}
+ enableCustomAllocationMode(msg);
+
int32_t bitRate = 0;
// FLAC encoder doesn't need a bitrate, other encoders do
if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
@@ -2069,7 +2099,11 @@
}
err = setupG711Codec(encoder, sampleRate, numChannels);
}
+#ifdef QTI_FLAC_DECODER
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) && encoder) {
+#else
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
+#endif
int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
@@ -2125,6 +2159,8 @@
} else {
err = setupEAC3Codec(encoder, numChannels, sampleRate);
}
+ } else {
+ err = setupCustomCodec(err, mime, msg);
}
if (err != OK) {
@@ -2835,13 +2871,14 @@
{ MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
{ MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4_DP, OMX_VIDEO_CodingMPEG4 },
{ MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
{ MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
{ MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
{ MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
};
-static status_t GetVideoCodingTypeFromMime(
+status_t ACodec::GetVideoCodingTypeFromMime(
const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
for (size_t i = 0;
i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
@@ -3228,6 +3265,7 @@
mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
}
+ setBFrames(&mpeg4type);
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
@@ -3425,6 +3463,8 @@
err = verifySupportForProfileAndLevel(profile, level);
if (err != OK) {
+ ALOGE("%s does not support profile %x @ level %x",
+ mComponentName.c_str(), profile, level);
return err;
}
@@ -3433,11 +3473,14 @@
}
// XXX
+ // Allow higher profiles to be set since the encoder seems to support
+#if 0
if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
ALOGW("Use baseline profile instead of %d for AVC recording",
h264type.eProfile);
h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
}
+#endif
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
h264type.nSliceHeaderSpacing = 0;
@@ -3458,6 +3501,7 @@
h264type.nCabacInitIdc = 0;
}
+ setBFrames(&h264type, iFrameInterval, frameRate);
if (h264type.nBFrames != 0) {
h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
}
@@ -3498,6 +3542,8 @@
frameRate = (float)tmp;
}
+ AVUtils::get()->setIntraPeriod(setPFramesSpacing(iFrameInterval, frameRate), 0, mOMX, mNode);
+
OMX_VIDEO_PARAM_HEVCTYPE hevcType;
InitOMXParams(&hevcType);
hevcType.nPortIndex = kPortIndexOutput;
@@ -4179,7 +4225,8 @@
if (params.nChannels <= 0
|| (params.nChannels != 1 && !params.bInterleaved)
- || params.nBitPerSample != 16u
+ || (params.nBitPerSample != 16u
+ && params.nBitPerSample != 24u)// we support 16/24 bit s/w decoding
|| params.eNumData != OMX_NumericalDataSigned
|| params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
@@ -4194,7 +4241,7 @@
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSamplingRate);
-
+ notify->setInt32("bit-width", params.nBitPerSample);
if (mChannelMaskPresent) {
notify->setInt32("channel-mask", mChannelMask);
}
@@ -4448,6 +4495,8 @@
mEncoderPadding * frameSize);
}
+ getVQZIPInfo(notify);
+
notify->post();
mSentFormat = true;
@@ -4596,6 +4645,7 @@
ALOGI("[%s] forcing the release of codec",
mCodec->mComponentName.c_str());
status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
+ mCodec->changeState(mCodec->mUninitializedState);
ALOGE_IF("[%s] failed to release codec instance: err=%d",
mCodec->mComponentName.c_str(), err);
sp<AMessage> notify = mCodec->mNotify->dup();
@@ -5180,6 +5230,7 @@
mCodec->mSkipCutBuffer->submit(info->mData);
}
info->mData->meta()->setInt64("timeUs", timeUs);
+ info->mData->meta()->setObject("graphic-buffer", info->mGraphicBuffer);
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
@@ -5189,6 +5240,8 @@
reply->setInt32("buffer-id", info->mBufferID);
+ (void)mCodec->setDSModeHint(reply, flags, timeUs);
+
notify->setMessage("reply", reply);
notify->post();
@@ -5243,8 +5296,9 @@
ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
}
+ bool skip = mCodec->getDSModeHint(msg);
int32_t render;
- if (mCodec->mNativeWindow != NULL
+ if (!skip && mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
&& info->mData != NULL && info->mData->size() != 0) {
ATRACE_NAME("render");
@@ -5665,6 +5719,15 @@
handled = true;
break;
}
+#ifdef DOLBY_ENABLE
+ case ACodec::kWhatSetParameters:
+ {
+ mCodec->setDolbyParameter(msg);
+
+ handled = true;
+ break;
+ }
+#endif // DOLBY_END
default:
return BaseState::onMessageReceived(msg);
@@ -5697,6 +5760,7 @@
{
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatComponentConfigured);
+ notify->setString("componentName", mCodec->mComponentName.c_str());
notify->setMessage("input-format", mCodec->mInputFormat);
notify->setMessage("output-format", mCodec->mOutputFormat);
notify->post();
@@ -5871,6 +5935,9 @@
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
} else {
+#ifdef DOLBY_ENABLE
+ mCodec->setDolbyParameterOnEndpChange();
+#endif // DOLBY_END
mCodec->changeState(mCodec->mLoadedToIdleState);
}
}
@@ -6344,6 +6411,9 @@
return err;
}
}
+#ifdef DOLBY_ENABLE
+ return setDolbyParameterOnProcessedAudio(params);
+#endif // DOLBY_END
return OK;
}
@@ -6359,6 +6429,23 @@
notify->post();
}
+sp<IOMXObserver> ACodec::createObserver() {
+ sp<CodecObserver> observer = new CodecObserver;
+ sp<AMessage> notify = new AMessage(kWhatOMXMessageList, this);
+ observer->setNotificationMessage(notify);
+ return observer;
+}
+
+status_t ACodec::allocateBuffer(
+ OMX_U32 portIndex, size_t bufSize, BufferInfo &info) {
+ void *ptr;
+ status_t err = mOMX->allocateBuffer(
+ mNode, portIndex, bufSize, &info.mBufferID, &ptr);
+
+ info.mData = new ABuffer(ptr, bufSize);
+ return err;
+}
+
bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
mCodec->onFrameRendered(mediaTimeUs, systemNano);
return true;
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 2529aa7..9687c7d 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -72,6 +72,7 @@
LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/av/include/media/ \
+ $(TOP)/frameworks/av/media/libavextensions \
$(TOP)/frameworks/av/include/media/stagefright/timedtext \
$(TOP)/frameworks/native/include/media/hardware \
$(TOP)/frameworks/native/include/media/openmax \
@@ -104,7 +105,7 @@
libutils \
libvorbisidec \
libz \
- libpowermanager
+ libpowermanager \
LOCAL_STATIC_LIBRARIES := \
libstagefright_color_conversion \
@@ -120,6 +121,8 @@
libFLAC \
libmedia_helper \
+LOCAL_WHOLE_STATIC_LIBRARIES := libavextensions
+
LOCAL_SHARED_LIBRARIES += \
libstagefright_enc_common \
libstagefright_avc_common \
@@ -129,11 +132,22 @@
LOCAL_CFLAGS += -Wno-multichar -Werror -Wno-error=deprecated-declarations -Wall
+ifeq ($(TARGET_USES_QCOM_BSP), true)
+ LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+ LOCAL_CFLAGS += -DQTI_BSP
+endif
+
# enable experiments only in userdebug and eng builds
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DENABLE_STAGEFRIGHT_EXPERIMENTS
endif
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
+ LOCAL_CFLAGS += -DQTI_FLAC_DECODER
+endif
+endif
+
LOCAL_CLANG := true
LOCAL_MODULE:= libstagefright
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index dd9d393..69a1562 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#include <inttypes.h>
@@ -34,6 +53,9 @@
#include <media/stagefright/Utils.h>
#include "include/AwesomePlayer.h"
+#ifdef DOLBY_ENABLE
+#include "DolbyAudioPlayerExtImpl.h"
+#endif // DOLBY_END
namespace android {
@@ -256,6 +278,9 @@
mStarted = true;
mPlaying = true;
+#ifdef DOLBY_ENABLE
+ setDolbyProcessedAudio(format);
+#endif // DOLBY_END
mPinnedTimeUs = -1ll;
return OK;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 6e4a1dd..dc9c37b 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -61,7 +61,7 @@
mNumClientOwnedBuffers(0) {
ALOGV("sampleRate: %u, outSampleRate: %u, channelCount: %u",
sampleRate, outSampleRate, channelCount);
- CHECK(channelCount == 1 || channelCount == 2);
+ CHECK(channelCount == 1 || channelCount == 2 || channelCount == 6);
CHECK(sampleRate > 0);
size_t minFrameCount;
@@ -124,6 +124,8 @@
int64_t startTimeUs;
if (params && params->findInt64(kKeyTime, &startTimeUs)) {
mStartTimeUs = startTimeUs;
+ } else {
+ mStartTimeUs = systemTime() / 1000ll;
}
status_t err = mRecord->start();
if (err == OK) {
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 66280da..27a6086 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -33,6 +33,8 @@
#include <utils/String8.h>
#include <cutils/properties.h>
+#include <stagefright/AVExtensions.h>
+
#if LOG_NDEBUG
#define UNUSED_UNLESS_VERBOSE(x) (void)(x)
#else
@@ -98,6 +100,11 @@
}
static int32_t getColorFormat(const char* colorFormat) {
+ if (!colorFormat) {
+ ALOGE("Invalid color format");
+ return -1;
+ }
+
if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420P)) {
return OMX_COLOR_FormatYUV420Planar;
}
@@ -298,6 +305,12 @@
return OK;
}
+static int32_t getHighSpeedFrameRate(const CameraParameters& params) {
+ const char* hsr = params.get("video-hsr");
+ int32_t rate = (hsr != NULL && strncmp(hsr, "off", 3)) ? atoi(hsr) : 0;
+ return rate > 240 ? 240 : rate;
+}
+
/*
* Configure the camera to use the requested video size
* (width and height) and/or frame rate. If both width and
@@ -350,6 +363,10 @@
params->get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES);
CHECK(supportedFrameRates != NULL);
ALOGV("Supported frame rates: %s", supportedFrameRates);
+ if (getHighSpeedFrameRate(*params)) {
+ ALOGI("Use default 30fps for HighSpeed %dfps", frameRate);
+ frameRate = 30;
+ }
char buf[4];
snprintf(buf, 4, "%d", frameRate);
if (strstr(supportedFrameRates, buf) == NULL) {
@@ -451,6 +468,8 @@
ALOGE("Failed to retrieve preview frame rate (%d)", frameRateActual);
return UNKNOWN_ERROR;
}
+ int32_t highSpeedRate = getHighSpeedFrameRate(params);
+ frameRateActual = highSpeedRate ? highSpeedRate : frameRateActual;
// Check the actual video frame rate against the target/requested
// video frame rate.
@@ -575,6 +594,8 @@
mMeta->setInt32(kKeyStride, mVideoSize.width);
mMeta->setInt32(kKeySliceHeight, mVideoSize.height);
mMeta->setInt32(kKeyFrameRate, mVideoFrameRate);
+ AVUtils::get()->extractCustomCameraKeys(params, mMeta);
+
return OK;
}
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 0acd9d0..926e95c 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -279,7 +279,8 @@
// The first 2 output frames from the encoder are: decoder specific info and
// the compressed video frame data for the first input video frame.
if (mNumFramesEncoded >= 1 && *timestampUs <
- (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs)) {
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenFrameCaptureUs) &&
+ (mTimeBetweenFrameCaptureUs > mTimeBetweenTimeLapseVideoFramesUs + 1)) {
// Skip all frames from last encoded frame until
// sufficient time (mTimeBetweenFrameCaptureUs) has passed.
// Tell the camera to release its recording frame and return.
@@ -294,6 +295,12 @@
mLastTimeLapseFrameRealTimestampUs = *timestampUs;
*timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+ // Update start-time once the captured-time reaches the expected start-time.
+ // Not doing so will result in CameraSource always dropping frames since
+ // updated-timestamp will never intersect start-timestamp
+ if ((mNumFramesReceived == 0 && mLastTimeLapseFrameRealTimestampUs >= mStartTimeUs)) {
+ mStartTimeUs = *timestampUs;
+ }
return false;
}
return false;
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 5020c6c..b5e7a6e 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -48,6 +48,8 @@
#include <cutils/properties.h>
+#include <stagefright/AVExtensions.h>
+
namespace android {
bool DataSource::getUInt16(off64_t offset, uint16_t *x) {
@@ -175,6 +177,7 @@
RegisterSniffer_l(SniffMPEG2PS);
RegisterSniffer_l(SniffWVM);
RegisterSniffer_l(SniffMidi);
+ RegisterSniffer_l(AVUtils::get()->getExtendedSniffer());
char value[PROPERTY_VALUE_MAX];
if (property_get("drm.service.enabled", value, NULL)
@@ -190,7 +193,8 @@
const char *uri,
const KeyedVector<String8, String8> *headers,
String8 *contentType,
- HTTPBase *httpSource) {
+ HTTPBase *httpSource,
+ bool useExtendedCache) {
if (contentType != NULL) {
*contentType = "";
}
@@ -214,7 +218,7 @@
ALOGE("Failed to make http connection from http service!");
return NULL;
}
- httpSource = new MediaHTTP(conn);
+ httpSource = AVFactory::get()->createMediaHTTP(conn);
}
String8 tmp;
@@ -246,10 +250,17 @@
*contentType = httpSource->getMIMEType();
}
- source = NuCachedSource2::Create(
- httpSource,
- cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
- disconnectAtHighwatermark);
+ if (useExtendedCache) {
+ source = AVFactory::get()->createCachedSource(
+ httpSource,
+ cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ disconnectAtHighwatermark);
+ } else {
+ source = NuCachedSource2::Create(
+ httpSource,
+ cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ disconnectAtHighwatermark);
+ }
} else {
// We do not want that prefetching, caching, datasource wrapper
// in the widevine:// case.
@@ -278,7 +289,7 @@
if (conn == NULL) {
return NULL;
} else {
- return new MediaHTTP(conn);
+ return AVFactory::get()->createMediaHTTP(conn);
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index a1af3aa..c5112cc 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -47,6 +66,11 @@
#ifndef UINT32_MAX
#define UINT32_MAX (4294967295U)
#endif
+#if defined(DOLBY_ENABLE) && defined(DEBUG_LOG_DDP_DECODER_EXTRA)
+#define DLOGD ALOGD
+#else
+#define DLOGD(...) ((void)0)
+#endif // DOLBY_END
namespace android {
@@ -203,6 +227,9 @@
mCachedOffset(0),
mCachedSize(0),
mCache(NULL) {
+#ifdef DOLBY_ENABLE
+ DLOGD("@DDP MPEG4DataSource::MPEG4DataSource");
+#endif // DOLBY_END
}
MPEG4DataSource::~MPEG4DataSource() {
@@ -311,6 +338,9 @@
}
static const char *FourCC2MIME(uint32_t fourcc) {
+#ifdef DOLBY_ENABLE
+ DLOGD("@DDP FourCC2MIME");
+#endif // DOLBY_END
switch (fourcc) {
case FOURCC('m', 'p', '4', 'a'):
return MEDIA_MIMETYPE_AUDIO_AAC;
@@ -335,7 +365,18 @@
case FOURCC('h', 'v', 'c', '1'):
case FOURCC('h', 'e', 'v', '1'):
return MEDIA_MIMETYPE_VIDEO_HEVC;
+#ifdef DOLBY_ENABLE
+ case FOURCC('a', 'c', '-', '3'):
+ DLOGD("@DDP Track FOURCC = 'ac-3'");
+ return MEDIA_MIMETYPE_AUDIO_AC3;
+ case FOURCC('e', 'c', '-', '3'):
+ DLOGD("@DDP Track FOURCC = 'ec-3'");
+ return MEDIA_MIMETYPE_AUDIO_EAC3;
+#endif // DOLBY_END
default:
+#ifdef DOLBY_ENABLE
+ ALOGD("@DDP FourCC2Mime default (not found)");
+#endif // DOLBY_END
CHECK(!"should not be here.");
return NULL;
}
@@ -369,6 +410,9 @@
mFileMetaData(new MetaData),
mFirstSINF(NULL),
mIsDrm(false) {
+#ifdef DOLBY_ENABLE
+ DLOGD("@DDP MPEG4Extractor::MPEG4Extractor");
+#endif // DOLBY_END
}
MPEG4Extractor::~MPEG4Extractor() {
@@ -535,6 +579,7 @@
}
if (psshsize > 0 && psshsize <= UINT32_MAX) {
char *buf = (char*)malloc(psshsize);
+ CHECK(buf != NULL);
char *ptr = buf;
for (size_t i = 0; i < mPssh.size(); i++) {
memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
@@ -1319,6 +1364,10 @@
case FOURCC('e', 'n', 'c', 'a'):
case FOURCC('s', 'a', 'm', 'r'):
case FOURCC('s', 'a', 'w', 'b'):
+#ifdef DOLBY_ENABLE
+ case FOURCC('a', 'c', '-', '3'):
+ case FOURCC('e', 'c', '-', '3'):
+#endif // DOLBY_END
{
uint8_t buffer[8 + 20];
if (chunk_data_size < (ssize_t)sizeof(buffer)) {
@@ -1342,7 +1391,20 @@
if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
// if the chunk type is enca, we'll get the type from the sinf/frma box later
+#ifdef DOLBY_ENABLE
+ const char *mime;
+ CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ //Track mime-type should have been set at 'trak'
+ //Only set the mimetype here to the chunk type if it hasn't changed
+ //Eg. EC3SpecificBox may already have set it to a more appropriate value
+ if (!strcmp(mime, "application/octet-stream")) {
+ DLOGD("@DDP Set mimetype from %s to %s", mime, FourCC2MIME(chunk_type));
+#endif // DOLBY_END
mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
+#ifdef DOLBY_ENABLE
+ DLOGD("@DDP FourCC:'%s'", FourCC2MIME(chunk_type));
+ }
+#endif // DOLBY_END
AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
}
ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
@@ -1365,6 +1427,96 @@
break;
}
+#ifdef DOLBY_ENABLE
+ case FOURCC('d', 'a', 'c', '3'):
+ {
+ uint8_t buffer[3];
+ if (chunk_data_size < (ssize_t)sizeof(buffer)) {
+ // 3 bytes for AC3Specific.
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
+ return ERROR_IO;
+ }
+ uint32_t acmod = (buffer[1] >> 3) & 0x3; //acmod presents channels of DD
+ if (acmod > 2) {
+ mLastTrack->meta->setInt32(kKeyChannelCount, 6); //5.1 case
+ }
+ *offset += chunk_size;
+ break;
+ }
+
+ case FOURCC('d', 'e', 'c', '3'):
+ {
+ //Only allowed on E-AC3 tracks
+ if (!(mPath.size() >= 2 && (
+ mPath[mPath.size() - 2] == FOURCC('e', 'c', '-', '3')))) {
+ return ERROR_MALFORMED;
+ }
+
+ //Minimum EC3SpecificBox Length
+ if (chunk_data_size < 5) {
+ return ERROR_MALFORMED;
+ }
+
+ //JOC Extensions allow EC3SpecificBox to be boundless in size
+ //Impose a realistic limit of 256 bytes
+ uint8_t buffer[256];
+ if (chunk_data_size > (off64_t)sizeof(buffer)) {
+ return ERROR_BUFFER_TOO_SMALL;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+ DLOGD("@DDP - Valid EC3SpecificBox detected");
+
+ uint8_t data_offset = 1;
+ uint32_t num_channels = 2;
+ uint8_t num_ind_sub = (buffer[data_offset] & 0x7) + 1; //0 = One I substream
+ DLOGD("@DDP - EC3SpecificBox reports num_ind_sub = %d", num_ind_sub);
+
+ for (uint8_t i = 0; i < num_ind_sub; i++) {
+ data_offset += 2;
+ uint32_t acmod = (buffer[data_offset] >> 1) & 0x3;
+ if(acmod > 2) {
+ num_channels = 6;
+ }
+ data_offset++;
+ uint8_t num_dep_sub = (buffer[data_offset] >> 1) & 0xF;
+
+ DLOGD("@DDP - I%d : num_dep_sub = %d", i, num_dep_sub);
+ if (num_dep_sub > 0) {
+ data_offset++; //chan_loc byte
+ if ((buffer[data_offset]>>1) & 0x1) { // Only support Lrs/Rrs case
+ num_channels = 8;
+ }
+ }
+ }
+
+ if (num_channels != 2) {
+ mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
+ }
+ if (chunk_data_size - (data_offset + 1) >= 2) {
+ //JOC requires at least 2 bytes extension data
+ data_offset++;
+ if (buffer[data_offset] & 0x1) {
+ mLastTrack->meta->setCString(
+ kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_EAC3_JOC);
+ DLOGD("@DDP - flag_eac3_extension_type_a = 1 - Set EAC3/JOC mimetype");
+ }
+ }
+ else if (chunk_data_size > (data_offset +1)){
+ ALOGE("@DDP - Invalid EC3SpecificBox extension data");
+ return ERROR_MALFORMED;
+ }
+ *offset += chunk_size;
+ break;
+ }
+#endif // DOLBY_END
case FOURCC('m', 'p', '4', 'v'):
case FOURCC('e', 'n', 'c', 'v'):
case FOURCC('s', '2', '6', '3'):
@@ -1590,13 +1742,21 @@
return ERROR_MALFORMED;
*offset += chunk_size;
+ // Ignore stss block for audio even if its present
+ // All audio sample are sync samples itself,
+ // self decodeable and playable.
+ // Parsing this block for audio restricts audio seek to few entries
+ // available in this block, sometimes 0, which is undesired.
+ const char *mime;
+ CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
+ if (strncasecmp("audio/", mime, 6)) {
+ status_t err =
+ mLastTrack->sampleTable->setSyncSampleParams(
+ data_offset, chunk_data_size);
- status_t err =
- mLastTrack->sampleTable->setSyncSampleParams(
- data_offset, chunk_data_size);
-
- if (err != OK) {
- return err;
+ if (err != OK) {
+ return err;
+ }
}
break;
@@ -3129,7 +3289,7 @@
extensionFlag, objectType);
}
- if (numChannels == 0) {
+ if (numChannels == 0 && (br.numBitsLeft() > 0)) {
int32_t channelsEffectiveNum = 0;
int32_t channelsNum = 0;
if (br.numBitsLeft() < 32) {
@@ -3267,6 +3427,9 @@
mBuffer(NULL),
mWantsNALFragments(false),
mSrcBuffer(NULL) {
+#ifdef DOLBY_ENABLE
+ DLOGD("@DDP MPEG4Source::MPEG4Source");
+#endif // DOLBY_END
memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 47f114a..1f43117 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -38,10 +38,11 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>
#include <media/mediarecorder.h>
+#include <stagefright/AVExtensions.h>
#include <cutils/properties.h>
#include "include/ESDS.h"
-
+#include <stagefright/AVExtensions.h>
#ifndef __predict_false
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
@@ -91,6 +92,7 @@
bool isAvc() const { return mIsAvc; }
bool isAudio() const { return mIsAudio; }
bool isMPEG4() const { return mIsMPEG4; }
+ bool isHEVC() const { return mIsHEVC; }
void addChunkOffset(off64_t offset);
int32_t getTrackId() const { return mTrackId; }
status_t dump(int fd, const Vector<String16>& args) const;
@@ -236,6 +238,7 @@
bool mIsAvc;
bool mIsAudio;
bool mIsMPEG4;
+ bool mIsHEVC;
int32_t mTrackId;
int64_t mTrackDurationUs;
int64_t mMaxChunkDurationUs;
@@ -385,7 +388,9 @@
mLongitudex10000(0),
mAreGeoTagsAvailable(false),
mStartTimeOffsetMs(-1),
- mMetaKeys(new AMessage()) {
+ mMetaKeys(new AMessage()),
+ mIsVideoHEVC(false),
+ mIsAudioAMR(false) {
addDeviceMeta();
// Verify mFd is seekable
@@ -463,6 +468,8 @@
return "s263";
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
return "avc1";
+ } else {
+ return AVUtils::get()->HEVCMuxerUtils().getFourCCForMime(mime);
}
} else {
ALOGE("Track (%s) other than video or audio is not supported", mime);
@@ -488,10 +495,23 @@
const char *mime;
source->getFormat()->findCString(kKeyMIMEType, &mime);
bool isAudio = !strncasecmp(mime, "audio/", 6);
+ bool isVideo = !strncasecmp(mime, "video/", 6);
if (Track::getFourCCForMime(mime) == NULL) {
ALOGE("Unsupported mime '%s'", mime);
return ERROR_UNSUPPORTED;
}
+ mIsAudioAMR = isAudio && (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mime) ||
+ !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime));
+
+
+ if (isVideo) {
+ mIsVideoHEVC = AVUtils::get()->HEVCMuxerUtils().isVideoHEVC(mime);
+ }
+
+ if (isAudio && !AVUtils::get()->isAudioMuxFormatSupported(mime)) {
+ ALOGE("Muxing is not supported for %s", mime);
+ return ERROR_UNSUPPORTED;
+ }
// At this point, we know the track to be added is either
// video or audio. Thus, we only need to check whether it
@@ -580,7 +600,7 @@
// If the estimation is wrong, we will pay the price of wasting
// some reserved space. This should not happen so often statistically.
- static const int32_t factor = mUse32BitOffset? 1: 2;
+ int32_t factor = mUse32BitOffset? 1: 2;
static const int64_t MIN_MOOV_BOX_SIZE = 3 * 1024; // 3 KB
static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
int64_t size = MIN_MOOV_BOX_SIZE;
@@ -677,8 +697,6 @@
mIsRealTimeRecording = isRealTimeRecording;
}
- mStartTimestampUs = -1;
-
if (mStarted) {
if (mPaused) {
mPaused = false;
@@ -687,6 +705,8 @@
return OK;
}
+ mStartTimestampUs = -1;
+
if (!param ||
!param->findInt32(kKeyTimeScale, &mTimeScale)) {
mTimeScale = 1000;
@@ -1047,8 +1067,10 @@
beginBox("ftyp");
int32_t fileType;
- if (param && param->findInt32(kKeyFileType, &fileType) &&
- fileType != OUTPUT_FORMAT_MPEG_4) {
+ if (mIsVideoHEVC) {
+ AVUtils::get()->HEVCMuxerUtils().writeHEVCFtypBox(this);
+ } else if (mIsAudioAMR || (param && param->findInt32(kKeyFileType, &fileType) &&
+ fileType != OUTPUT_FORMAT_MPEG_4)) {
writeFourcc("3gp4");
writeInt32(0);
writeFourcc("isom");
@@ -1464,6 +1486,12 @@
mIsAudio = !strncasecmp(mime, "audio/", 6);
mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
+ mIsHEVC = AVUtils::get()->HEVCMuxerUtils().isVideoHEVC(mime);
+
+ if (mIsHEVC) {
+ AVUtils::get()->HEVCMuxerUtils().getHEVCCodecSpecificDataFromInputFormatIfPossible(
+ mMeta, &mCodecSpecificData, &mCodecSpecificDataSize, &mGotAllCodecSpecificData);
+ }
setTimeScale();
}
@@ -1562,6 +1590,7 @@
size_t size;
if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
mCodecSpecificData = malloc(size);
+ CHECK(mCodecSpecificData != NULL);
mCodecSpecificDataSize = size;
memcpy(mCodecSpecificData, data, size);
mGotAllCodecSpecificData = true;
@@ -1575,6 +1604,7 @@
ESDS esds(data, size);
if (esds.getCodecSpecificInfo(&data, &size) == OK) {
mCodecSpecificData = malloc(size);
+ CHECK(mCodecSpecificData != NULL);
mCodecSpecificDataSize = size;
memcpy(mCodecSpecificData, data, size);
mGotAllCodecSpecificData = true;
@@ -1657,7 +1687,7 @@
while (!chunk->mSamples.empty()) {
List<MediaBuffer *>::iterator it = chunk->mSamples.begin();
- off64_t offset = chunk->mTrack->isAvc()
+ off64_t offset = (chunk->mTrack->isAvc() || chunk->mTrack->isHEVC())
? addLengthPrefixedSample_l(*it)
: addSample_l(*it);
@@ -1881,6 +1911,10 @@
status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
+ if (mOwner->exceedsFileSizeLimit() && mStszTableEntries->count() == 0) {
+ ALOGE(" Filesize limit exceeded and zero samples written ");
+ return ERROR_END_OF_STREAM;
+ }
return err;
}
@@ -1971,6 +2005,7 @@
mCodecSpecificDataSize = size;
mCodecSpecificData = malloc(size);
+ CHECK(mCodecSpecificData != NULL);
memcpy(mCodecSpecificData, data, size);
return OK;
}
@@ -2093,6 +2128,7 @@
// ISO 14496-15: AVC file format
mCodecSpecificDataSize += 7; // 7 more bytes in the header
mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ CHECK(mCodecSpecificData != NULL);
uint8_t *header = (uint8_t *)mCodecSpecificData;
header[0] = 1; // version
header[1] = mProfileIdc; // profile indication
@@ -2195,7 +2231,9 @@
MediaBuffer *buffer;
const char *trackName = mIsAudio ? "Audio" : "Video";
while (!mDone && (err = mSource->read(&buffer)) == OK) {
- if (buffer->range_length() == 0) {
+ if (buffer == NULL) {
+ continue;
+ } else if (buffer->range_length() == 0) {
buffer->release();
buffer = NULL;
++nZeroLengthFrames;
@@ -2227,10 +2265,18 @@
} else if (mIsMPEG4) {
mCodecSpecificDataSize = buffer->range_length();
mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ CHECK(mCodecSpecificData != NULL);
memcpy(mCodecSpecificData,
(const uint8_t *)buffer->data()
+ buffer->range_offset(),
buffer->range_length());
+ } else if (mIsHEVC) {
+ status_t err = AVUtils::get()->HEVCMuxerUtils().makeHEVCCodecSpecificData(
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length(), &mCodecSpecificData, &mCodecSpecificDataSize);
+ if ((status_t)OK != err) {
+ return err;
+ }
}
buffer->release();
@@ -2240,20 +2286,28 @@
continue;
}
- // Make a deep copy of the MediaBuffer and Metadata and release
- // the original as soon as we can
- MediaBuffer *copy = new MediaBuffer(buffer->range_length());
- memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
- buffer->range_length());
- copy->set_range(0, buffer->range_length());
- meta_data = new MetaData(*buffer->meta_data().get());
- buffer->release();
- buffer = NULL;
+ MediaBuffer *copy = NULL;
+ // Check if the upstream source hints it is OK to hold on to the
+ // buffer without releasing immediately and avoid cloning the buffer
+ if (AVUtils::get()->canDeferRelease(buffer->meta_data())) {
+ copy = buffer;
+ meta_data = new MetaData(*buffer->meta_data().get());
+ } else {
+ // Make a deep copy of the MediaBuffer and Metadata and release
+ // the original as soon as we can
+ copy = new MediaBuffer(buffer->range_length());
+ memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+ copy->set_range(0, buffer->range_length());
+ meta_data = new MetaData(*buffer->meta_data().get());
+ buffer->release();
+ buffer = NULL;
+ }
- if (mIsAvc) StripStartcode(copy);
+ if (mIsAvc || mIsHEVC) StripStartcode(copy);
size_t sampleSize = copy->range_length();
- if (mIsAvc) {
+ if (mIsAvc || mIsHEVC) {
if (mOwner->useNalLengthFour()) {
sampleSize += 4;
} else {
@@ -2287,6 +2341,7 @@
previousPausedDurationUs = mStartTimestampUs;
}
+#if 0
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
@@ -2303,6 +2358,7 @@
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
+#endif
timestampUs -= previousPausedDurationUs;
if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
@@ -2320,8 +2376,8 @@
CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
decodingTimeUs -= previousPausedDurationUs;
cttsOffsetTimeUs =
- timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
- if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+ timestampUs - decodingTimeUs;
+ if (WARN_UNLESS(kMaxCttsOffsetTimeUs >= decodingTimeUs - timestampUs, "for %s track", trackName)) {
copy->release();
return ERROR_MALFORMED;
}
@@ -2347,7 +2403,11 @@
cttsSampleCount = 0; // No sample in ctts box is pending
} else {
if (currCttsOffsetTimeTicks != lastCttsOffsetTimeTicks) {
- addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+ // cttsSampleCount is 0 after writing the initial ctts entry
+ // Avoid writing entry with 0 sample count
+ if (cttsSampleCount != 0) {
+ addOneCttsTableEntry(cttsSampleCount, lastCttsOffsetTimeTicks);
+ }
lastCttsOffsetTimeTicks = currCttsOffsetTimeTicks;
cttsSampleCount = 1; // One sample in ctts box is pending
} else {
@@ -2453,7 +2513,7 @@
trackProgressStatus(timestampUs);
}
if (!hasMultipleTracks) {
- off64_t offset = mIsAvc? mOwner->addLengthPrefixedSample_l(copy)
+ off64_t offset = (mIsAvc || mIsHEVC)? mOwner->addLengthPrefixedSample_l(copy)
: mOwner->addSample_l(copy);
uint32_t count = (mOwner->use32BitFileOffset()
@@ -2546,8 +2606,13 @@
if (mIsAudio) {
ALOGI("Audio track drift time: %" PRId64 " us", mOwner->getDriftTimeUs());
}
-
- if (err == ERROR_END_OF_STREAM) {
+ // if err is ERROR_IO (ex: during SSR), return OK to save the
+ // recorded file successfully. Session tear down will happen as part of
+ // client callback
+ if (mIsAudio && (err == ERROR_IO)) {
+ return OK;
+ }
+ else if (err == ERROR_END_OF_STREAM) {
return OK;
}
return err;
@@ -2705,7 +2770,8 @@
CHECK(mMeta->findCString(kKeyMIMEType, &mime));
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime) ||
!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime) ||
- !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
+ !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime) ||
+ mIsHEVC) {
if (!mCodecSpecificData ||
mCodecSpecificDataSize <= 0) {
ALOGE("Missing codec specific data");
@@ -2726,6 +2792,11 @@
ALOGV("%s track time scale: %d",
mIsAudio? "Audio": "Video", mTimeScale);
+ if (mMdatSizeBytes == 0) {
+ ALOGW("Track data is not available.");
+ return;
+ }
+
uint32_t now = getMpeg4Time();
mOwner->beginBox("trak");
writeTkhdBox(now);
@@ -2803,17 +2874,22 @@
mOwner->writeInt16(0x18); // depth
mOwner->writeInt16(-1); // predefined
- CHECK_LT(23 + mCodecSpecificDataSize, 128);
-
if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
writeMp4vEsdsBox();
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_H263, mime)) {
writeD263Box();
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
writeAvccBox();
+ } else if (mIsHEVC) {
+ AVUtils::get()->HEVCMuxerUtils().writeHvccBox(mOwner, mCodecSpecificData,
+ mCodecSpecificDataSize,
+ mOwner->useNalLengthFour());
}
- writePaspBox();
+ if (!mIsHEVC) {
+ writePaspBox();
+ }
+
mOwner->endBox(); // mp4v, s263 or avc1
}
@@ -2898,6 +2974,9 @@
CHECK_GT(mCodecSpecificDataSize, 0);
mOwner->beginBox("esds");
+ // Make sure all sizes encode to a single byte.
+ CHECK_LT(mCodecSpecificDataSize + 23, 128);
+
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt8(0x03); // ES_DescrTag
@@ -3086,7 +3165,7 @@
int32_t MPEG4Writer::Track::getStartTimeOffsetScaledTime() const {
int64_t trackStartTimeOffsetUs = 0;
int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
- if (mStartTimestampUs != moovStartTimeUs) {
+ if (mStartTimestampUs != moovStartTimeUs && mStszTableEntries->count() != 0) {
CHECK_GT(mStartTimestampUs, moovStartTimeUs);
trackStartTimeOffsetUs = mStartTimestampUs - moovStartTimeUs;
}
diff --git a/media/libstagefright/MediaBuffer.cpp b/media/libstagefright/MediaBuffer.cpp
index 1f80a47..525a156 100644
--- a/media/libstagefright/MediaBuffer.cpp
+++ b/media/libstagefright/MediaBuffer.cpp
@@ -54,6 +54,7 @@
mOwnsData(true),
mMetaData(new MetaData),
mOriginal(NULL) {
+ CHECK(mData != NULL);
}
MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7019537..0780a3c 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -51,6 +51,7 @@
#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/Singleton.h>
+#include <stagefright/AVExtensions.h>
namespace android {
@@ -306,7 +307,7 @@
// queue.
if (nameIsType || !strncasecmp(name.c_str(), "omx.", 4)) {
- mCodec = new ACodec;
+ mCodec = AVFactory::get()->createACodec();
} else if (!nameIsType
&& !strncasecmp(name.c_str(), "android.filter.", 15)) {
mCodec = new MediaFilter;
@@ -871,6 +872,8 @@
}
*format = info.mFormat;
}
+ } else {
+ return BAD_INDEX;
}
return OK;
}
@@ -984,6 +987,12 @@
if (omxFlags & OMX_BUFFERFLAG_EOS) {
flags |= BUFFER_FLAG_EOS;
}
+ if (omxFlags & OMX_BUFFERFLAG_EXTRADATA) {
+ flags |= BUFFER_FLAG_EXTRADATA;
+ }
+ if (omxFlags & OMX_BUFFERFLAG_DATACORRUPT) {
+ flags |= BUFFER_FLAG_DATACORRUPT;
+ }
response->setInt32("flags", flags);
response->postReply(replyID);
@@ -1177,6 +1186,7 @@
// reset input surface flag
mHaveInputSurface = false;
+ CHECK(msg->findString("componentName", &mComponentName));
CHECK(msg->findMessage("input-format", &mInputFormat));
CHECK(msg->findMessage("output-format", &mOutputFormat));
@@ -2269,6 +2279,7 @@
uint32_t bufferID;
CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
+ Mutex::Autolock al(mBufferLock);
Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
@@ -2628,6 +2639,9 @@
if (omxFlags & OMX_BUFFERFLAG_EOS) {
flags |= BUFFER_FLAG_EOS;
}
+ if (omxFlags & OMX_BUFFERFLAG_DATACORRUPT) {
+ flags |= BUFFER_FLAG_DATACORRUPT;
+ }
msg->setInt32("flags", flags);
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 5edc04c..83bf58a 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -40,6 +40,7 @@
#include <cutils/properties.h>
#include <libexpat/expat.h>
+#include <stagefright/AVExtensions.h>
namespace android {
@@ -174,8 +175,9 @@
: mInitCheck(NO_INIT),
mUpdate(false),
mGlobalSettings(new AMessage()) {
- parseTopLevelXMLFile("/etc/media_codecs.xml");
- parseTopLevelXMLFile("/etc/media_codecs_performance.xml", true/* ignore_errors */);
+ parseTopLevelXMLFile(AVUtils::get()->getCustomCodecsLocation());
+ parseTopLevelXMLFile(AVUtils::get()->getCustomCodecsPerformanceLocation(),
+ true/* ignore_errors */);
parseTopLevelXMLFile(kProfilingResults, true/* ignore_errors */);
}
@@ -939,7 +941,13 @@
// complexity: range + default
bool found;
- if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
+ // VT specific limits
+ if (name.find("vt-") == 0) {
+ AString value;
+ if (msg->findString("value", &value) && value.size()) {
+ mCurrentInfo->addDetail(name, value);
+ }
+ } else if (name == "aspect-ratio" || name == "bitrate" || name == "block-count"
|| name == "blocks-per-second" || name == "complexity"
|| name == "frame-rate" || name == "quality" || name == "size"
|| name == "measured-blocks-per-second" || name.startsWith("measured-frame-rate-")) {
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 7f9f824..925be14 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -36,6 +36,8 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/Utils.h>
+#include <OMX_Core.h>
+#include <stagefright/AVExtensions.h>
namespace android {
@@ -399,10 +401,14 @@
}
AString outputMIME;
+ AString role;
CHECK(mOutputFormat->findString("mime", &outputMIME));
-
- mEncoder = MediaCodec::CreateByType(
+ if (AVUtils::get()->useQCHWEncoder(mOutputFormat, role)) {
+ mEncoder = MediaCodec::CreateByComponentName(mCodecLooper, role.c_str());
+ } else {
+ mEncoder = MediaCodec::CreateByType(
mCodecLooper, outputMIME.c_str(), true /* encoder */);
+ }
if (mEncoder == NULL) {
return NO_INIT;
@@ -514,6 +520,9 @@
mOutputBufferQueue.clear();
mEncoderReachedEOS = true;
mErrorCode = err;
+ if (err == OMX_ErrorHardware) {
+ mErrorCode = ERROR_IO;
+ }
mOutputBufferCond.signal();
}
@@ -572,6 +581,9 @@
// push decoding time for video, or drift time for audio
if (mIsVideo) {
mDecodingTimeQueue.push_back(timeUs);
+ if (mFlags & FLAG_USE_METADATA_INPUT) {
+ AVUtils::get()->addDecodingTimesFromBatch(mbuf, mDecodingTimeQueue);
+ }
} else {
#if DEBUG_DRIFT_TIME
if (mFirstSampleTimeUs < 0ll) {
@@ -591,7 +603,7 @@
status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
if (err != OK || inbuf == NULL) {
mbuf->release();
- signalEOS();
+ signalEOS(err);
break;
}
@@ -633,6 +645,9 @@
resume();
} else {
CHECK(mPuller != NULL);
+ if (mIsVideo) {
+ mEncoder->requestIDRFrame();
+ }
mPuller->resume();
}
return OK;
@@ -738,12 +753,14 @@
sp<ABuffer> outbuf;
status_t err = mEncoder->getOutputBuffer(index, &outbuf);
if (err != OK || outbuf == NULL) {
- signalEOS();
+ signalEOS(err);
break;
}
MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
memcpy(mbuf->data(), outbuf->data(), outbuf->size());
+ sp<MetaData> meta = mbuf->meta_data();
+ AVUtils::get()->setDeferRelease(meta);
if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
if (mIsVideo) {
@@ -799,7 +816,7 @@
CHECK(msg->findInt32("err", &err));
ALOGE("Encoder (%s) reported error : 0x%x",
mIsVideo ? "video" : "audio", err);
- signalEOS();
+ signalEOS(err);
}
break;
}
@@ -852,7 +869,7 @@
}
case kWhatPause:
{
- if (mFlags && FLAG_USE_SURFACE_INPUT) {
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
suspend();
} else {
CHECK(mPuller != NULL);
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 2a50692..4077bd3 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#include <media/stagefright/MediaDefs.h>
@@ -47,6 +66,9 @@
const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm";
const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3";
const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3";
+#ifdef DOLBY_ENABLE
+const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC = "audio/eac3-joc";
+#endif // DOLBY_END
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index e21fe6e..bfb2a16 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -40,6 +40,8 @@
#include <media/stagefright/MetaData.h>
#include <utils/String8.h>
+#include <stagefright/AVExtensions.h>
+
namespace android {
sp<MetaData> MediaExtractor::getMetaData() {
@@ -52,7 +54,8 @@
// static
sp<MediaExtractor> MediaExtractor::Create(
- const sp<DataSource> &source, const char *mime) {
+ const sp<DataSource> &source, const char *mime,
+ const uint32_t flags) {
sp<AMessage> meta;
String8 tmp;
@@ -91,8 +94,9 @@
}
}
- MediaExtractor *ret = NULL;
- if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
+ sp<MediaExtractor> ret = NULL;
+ if ((ret = AVFactory::get()->createExtendedExtractor(source, mime, meta, flags)) != NULL) {
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4)
|| !strcasecmp(mime, "audio/mp4")) {
ret = new MPEG4Extractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
@@ -121,6 +125,7 @@
ret = new MidiExtractor(source);
}
+ ret = AVFactory::get()->updateExtractor(ret, source, mime, meta, flags);
if (ret != NULL) {
if (isDrm) {
ret->setDrmFlag(true);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index b1dde80..4762217 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#include <inttypes.h>
@@ -55,6 +74,9 @@
#include <OMX_AsString.h>
#include "include/avc_utils.h"
+#ifdef DOLBY_ENABLE
+#include "DolbyOMXCodecExtImpl.h"
+#endif // DOLBY_END
namespace android {
@@ -150,6 +172,11 @@
}
static bool IsSoftwareCodec(const char *componentName) {
+#ifdef DOLBY_ENABLE
+ if (!strncmp("OMX.dolby.", componentName, 10)) {
+ return true;
+ }
+#endif // DOLBY_END
if (!strncmp("OMX.google.", componentName, 11)) {
return true;
}
@@ -264,6 +291,9 @@
if (info->hasQuirk("output-buffers-are-unreadable")) {
quirks |= kOutputBuffersAreUnreadable;
}
+#ifdef DOLBY_ENABLE
+ quirks |= getDolbyComponentQuirks(info);
+#endif // DOLBY_END
return quirks;
}
@@ -1510,6 +1540,12 @@
"video_decoder.mpeg2", "video_encoder.mpeg2" },
{ MEDIA_MIMETYPE_AUDIO_AC3,
"audio_decoder.ac3", "audio_encoder.ac3" },
+#ifdef DOLBY_ENABLE
+ { MEDIA_MIMETYPE_AUDIO_EAC3,
+ "audio_decoder.eac3", NULL },
+ { MEDIA_MIMETYPE_AUDIO_EAC3_JOC,
+ "audio_decoder.eac3_joc", NULL },
+#endif // DOLBY_END
};
static const size_t kNumMimeToRole =
@@ -4114,6 +4150,9 @@
? numChannels : params.nChannels);
mOutputFormat->setInt32(kKeySampleRate, params.nSamplingRate);
+#ifdef DOLBY_ENABLE
+ setDolbyProcessedAudio();
+#endif // DOLBY_END
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAMR) {
OMX_AUDIO_PARAM_AMRTYPE amr;
InitOMXParams(&amr);
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index db33e83..a757181 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -28,6 +28,8 @@
#include <media/mediametadataretriever.h>
#include <private/media/VideoFrame.h>
+#include <stagefright/AVExtensions.h>
+
namespace android {
StagefrightMediaScanner::StagefrightMediaScanner() {}
@@ -75,7 +77,8 @@
return MEDIA_SCAN_RESULT_SKIPPED;
}
- if (!FileHasAcceptableExtension(extension)) {
+ if (!FileHasAcceptableExtension(extension)
+ && !AVUtils::get()->isEnhancedExtension(extension)) {
return MEDIA_SCAN_RESULT_SKIPPED;
}
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index e37e909..5a8f6a5 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -23,6 +23,7 @@
#include <gui/Surface.h>
#include "include/StagefrightMetadataRetriever.h"
+#include "include/HTTPBase.h"
#include <media/ICrypto.h>
#include <media/IMediaHTTPService.h>
@@ -44,6 +45,8 @@
#include <CharacterEncodingDetector.h>
+#include <stagefright/AVExtensions.h>
+
namespace android {
static const int64_t kBufferTimeOutUs = 30000ll; // 30 msec
@@ -62,6 +65,12 @@
ALOGV("~StagefrightMetadataRetriever()");
clearMetadata();
mClient.disconnect();
+
+ if (mSource != NULL &&
+ (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
+ mExtractor.clear();
+ static_cast<HTTPBase *>(mSource.get())->disconnect();
+ }
}
status_t StagefrightMetadataRetriever::setDataSource(
@@ -97,6 +106,7 @@
fd = dup(fd);
ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
+ AVUtils::get()->printFileName(fd);
clearMetadata();
mSource = new FileSource(fd, offset, length);
@@ -154,6 +164,8 @@
// TODO: Use Flexible color instead
videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
+ videoFormat->setInt32("thumbnail-mode", 1);
+
status_t err;
sp<ALooper> looper = new ALooper;
looper->start();
@@ -214,6 +226,7 @@
err = decoder->getInputBuffers(&inputBuffers);
if (err != OK) {
ALOGW("failed to get input buffers: %d (%s)", err, asString(err));
+ source->stop();
decoder->release();
return NULL;
}
@@ -222,6 +235,7 @@
err = decoder->getOutputBuffers(&outputBuffers);
if (err != OK) {
ALOGW("failed to get output buffers: %d (%s)", err, asString(err));
+ source->stop();
decoder->release();
return NULL;
}
@@ -346,9 +360,11 @@
}
}
- int32_t width, height;
+ int32_t width, height, stride, slice_height;
CHECK(outputFormat->findInt32("width", &width));
CHECK(outputFormat->findInt32("height", &height));
+ CHECK(outputFormat->findInt32("stride", &stride));
+ CHECK(outputFormat->findInt32("slice-height", &slice_height));
int32_t crop_left, crop_top, crop_right, crop_bottom;
if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
@@ -386,7 +402,7 @@
if (converter.isValid()) {
err = converter.convert(
(const uint8_t *)videoFrameBuffer->data(),
- width, height,
+ stride, slice_height,
crop_left, crop_top, crop_right, crop_bottom,
frame->mData,
frame->mWidth,
@@ -481,7 +497,7 @@
mime,
false, /* encoder */
NULL, /* matchComponentName */
- OMXCodec::kPreferSoftwareCodecs,
+ 0 /* OMXCodec::kPreferSoftwareCodecs */,
&matchingCodecs);
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
@@ -661,9 +677,12 @@
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
const char *lang;
- trackMeta->findCString(kKeyMediaLanguage, &lang);
- timedTextLang.append(String8(lang));
- timedTextLang.append(String8(":"));
+ if (trackMeta->findCString(kKeyMediaLanguage, &lang)) {
+ timedTextLang.append(String8(lang));
+ timedTextLang.append(String8(":"));
+ } else {
+ ALOGE("No language found for timed text");
+ }
}
}
}
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index e8abf48..147eb45 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -35,6 +35,9 @@
#include <utils/String8.h>
#include <private/gui/ComposerService.h>
+#if QTI_BSP
+#include <gralloc_priv.h>
+#endif
namespace android {
@@ -59,8 +62,12 @@
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER |
- GRALLOC_USAGE_HW_TEXTURE);
+ mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER
+ | GRALLOC_USAGE_HW_TEXTURE
+#if QTI_BSP
+ | GRALLOC_USAGE_PRIVATE_WFD
+#endif
+ );
sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -360,7 +367,11 @@
mNumFramesEncoded++;
// Pass the data to the MediaBuffer. Pass in only the metadata
-
+ if (mSlots[mCurrentSlot].mGraphicBuffer == NULL) {
+ ALOGV("Read: SurfaceMediaSource mGraphicBuffer is null. Returning"
+ "ERROR_END_OF_STREAM.");
+ return ERROR_END_OF_STREAM;
+ }
passMetadataBuffer(buffer, mSlots[mCurrentSlot].mGraphicBuffer->handle);
(*buffer)->setObserver(this);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 17f0201..42d87f6 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -35,6 +54,8 @@
#include <media/stagefright/Utils.h>
#include <media/AudioParameter.h>
+#include <stagefright/AVExtensions.h>
+
namespace android {
uint16_t U16_AT(const uint8_t *ptr) {
@@ -453,6 +474,7 @@
msg->setBuffer("csd-2", buffer);
}
+ AVUtils::get()->convertMetaDataToMessage(meta, &msg);
*format = msg;
return OK;
@@ -685,6 +707,8 @@
// for transporting the CSD to muxers.
reassembleESDS(csd0, esds);
meta->setData(kKeyESDS, kKeyESDS, esds, sizeof(esds));
+ } else {
+ AVUtils::get()->HEVCMuxerUtils().reassembleHEVCCSD(mime, csd0, meta);
}
}
@@ -744,6 +768,7 @@
param.addInt(String8(AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES), paddingSamples);
}
+ AVUtils::get()->sendMetaDataToHal(meta, ¶m);
ALOGV("sendMetaDataToHal: bitRate %d, sampleRate %d, chanMask %d,"
"delaySample %d, paddingSample %d", bitRate, sampleRate,
channelMask, delaySamples, paddingSamples);
@@ -765,6 +790,11 @@
{ MEDIA_MIMETYPE_AUDIO_AAC, AUDIO_FORMAT_AAC },
{ MEDIA_MIMETYPE_AUDIO_VORBIS, AUDIO_FORMAT_VORBIS },
{ MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS},
+#ifdef DOLBY_ENABLE
+ { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3},
+ { MEDIA_MIMETYPE_AUDIO_EAC3, AUDIO_FORMAT_E_AC3},
+ { MEDIA_MIMETYPE_AUDIO_EAC3_JOC, AUDIO_FORMAT_E_AC3},
+#endif // DOLBY_END
{ 0, AUDIO_FORMAT_INVALID }
};
@@ -779,7 +809,7 @@
++p;
}
- return BAD_VALUE;
+ return AVUtils::get()->mapMimeToAudioFormat(format, mime);
}
struct aac_format_conv_t {
@@ -833,18 +863,27 @@
} else {
ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info.format);
}
-
+ info.format = AVUtils::get()->updateAudioFormat(info.format, meta);
if (AUDIO_FORMAT_INVALID == info.format) {
// can't offload if we don't know what the source format is
ALOGE("mime type \"%s\" not a known audio format", mime);
return false;
}
+ if (AVUtils::get()->canOffloadAPE(meta) != true) {
+ return false;
+ }
+
// Redefine aac format according to its profile
// Offloading depends on audio DSP capabilities.
int32_t aacaot = -1;
if (meta->findInt32(kKeyAACAOT, &aacaot)) {
- mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+ bool isADTSSupported = false;
+ isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(meta, info.format,
+ (OMX_AUDIO_AACPROFILETYPE) aacaot);
+ if (!isADTSSupported) {
+ mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot);
+ }
}
int32_t srate = -1;
diff --git a/media/libstagefright/VideoFrameScheduler.cpp b/media/libstagefright/VideoFrameScheduler.cpp
index 5fe9bf9..02b8783 100644
--- a/media/libstagefright/VideoFrameScheduler.cpp
+++ b/media/libstagefright/VideoFrameScheduler.cpp
@@ -257,8 +257,7 @@
mPhase = firstTime;
}
}
- ALOGV("priming[%zu] phase:%lld period:%lld",
- numSamplesToUse, (long long)mPhase, (long long)mPeriod);
+ ALOGV("priming[%zu] phase:%lld period:%lld ", numSamplesToUse, (long long)mPhase, (long long)mPeriod);
}
nsecs_t VideoFrameScheduler::PLL::addSample(nsecs_t time) {
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 8ef2dca..98b5c0e 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
#include <utils/misc.h>
@@ -393,7 +394,7 @@
meta->setInt32(kKeyWidth, width);
meta->setInt32(kKeyHeight, height);
- if (sarWidth > 1 || sarHeight > 1) {
+ if (sarWidth > 1 && sarHeight > 1) {
// We treat 0:0 (unspecified) as 1:1.
meta->setInt32(kKeySARWidth, sarWidth);
@@ -443,25 +444,34 @@
}
bool IsAVCReferenceFrame(const sp<ABuffer> &accessUnit) {
- const uint8_t *data = accessUnit->data();
+ MediaBuffer *mediaBuffer =
+ (MediaBuffer *)(accessUnit->getMediaBufferBase());
+ const uint8_t *data =
+ (mediaBuffer != NULL) ? (uint8_t *) mediaBuffer->data() : accessUnit->data();
size_t size = accessUnit->size();
const uint8_t *nalStart;
size_t nalSize;
+ bool bIsReferenceFrame = true;
while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
CHECK_GT(nalSize, 0u);
unsigned nalType = nalStart[0] & 0x1f;
if (nalType == 5) {
- return true;
+ bIsReferenceFrame = true;
+ break;
} else if (nalType == 1) {
unsigned nal_ref_idc = (nalStart[0] >> 5) & 3;
- return nal_ref_idc != 0;
+ bIsReferenceFrame = (nal_ref_idc != 0);
+ break;
}
}
- return true;
+ if (mediaBuffer != NULL) {
+ mediaBuffer->release();
+ }
+ return bIsReferenceFrame;
}
sp<MetaData> MakeAACCodecSpecificData(
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 965c55e..c945305 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -68,6 +68,8 @@
mOutputBufferCount(0),
mSignalledError(false),
mLastInHeader(NULL),
+ mLastHeaderTimeUs(-1),
+ mNextOutBufferTimeUs(0),
mOutputPortSettingsChange(NONE) {
initPorts();
CHECK_EQ(initDecoder(), (status_t)OK);
@@ -492,6 +494,27 @@
return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable();
}
+void SoftAAC2::updateTimeStamp(int64_t inHeaderTimeUs) {
+ // use new input buffer timestamp as Anchor Time if its
+ // a) first buffer or
+ // b) first buffer post seek or
+ // c) different from last buffer timestamp
+ //If input buffer timestamp is same as last input buffer timestamp then
+ //treat this as a erroneous timestamp and ignore new input buffer
+ //timestamp and use last output buffer timestamp as Anchor Time.
+ int64_t anchorTimeUs = 0;
+ if ((mLastHeaderTimeUs != inHeaderTimeUs)) {
+ anchorTimeUs = inHeaderTimeUs;
+ mLastHeaderTimeUs = inHeaderTimeUs;
+ //Store current buffer's timestamp so that it can used as reference
+ //in cases where first frame/buffer is skipped/dropped.
+ //e.g to compensate decoder delay
+ mNextOutBufferTimeUs = inHeaderTimeUs;
+ } else {
+ anchorTimeUs = mNextOutBufferTimeUs;
+ }
+ mBufferTimestamps.add(anchorTimeUs);
+}
void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) {
if (mSignalledError || mOutputPortSettingsChange != NONE) {
@@ -618,7 +641,7 @@
// insert buffer size and time stamp
mBufferSizes.add(inBufferLength[0]);
if (mLastInHeader != inHeader) {
- mBufferTimestamps.add(inHeader->nTimeStamp);
+ updateTimeStamp(inHeader->nTimeStamp);
mLastInHeader = inHeader;
} else {
int64_t currentTime = mBufferTimestamps.top();
@@ -630,7 +653,7 @@
inBuffer[0] = inHeader->pBuffer + inHeader->nOffset;
inBufferLength[0] = inHeader->nFilledLen;
mLastInHeader = inHeader;
- mBufferTimestamps.add(inHeader->nTimeStamp);
+ updateTimeStamp(inHeader->nTimeStamp);
mBufferSizes.add(inHeader->nFilledLen);
}
@@ -755,6 +778,14 @@
if (inHeader && inHeader->nFilledLen == 0) {
inInfo->mOwnedByUs = false;
mInputBufferCount++;
+
+ //During Port reconfiguration current frames is skipped and next frame
+ //is sent for decoding.
+ //Update mNextOutBufferTimeUs with current frame's timestamp if port reconfiguration is
+ //happening in last frame of current buffer otherwise LastOutBufferTimeUs
+ //will be zero(post seek).
+ mNextOutBufferTimeUs = mBufferTimestamps.top() + mStreamInfo->aacSamplesPerFrame *
+ 1000000ll / mStreamInfo->aacSampleRate;
inQueue.erase(inQueue.begin());
mLastInHeader = NULL;
inInfo = NULL;
@@ -875,6 +906,7 @@
*currentBufLeft -= decodedSize;
*nextTimeStamp += mStreamInfo->aacSamplesPerFrame *
1000000ll / mStreamInfo->aacSampleRate;
+ mNextOutBufferTimeUs = *nextTimeStamp;
ALOGV("adjusted nextTimeStamp/size to %lld/%d",
(long long) *nextTimeStamp, *currentBufLeft);
} else {
@@ -882,6 +914,7 @@
if (mBufferTimestamps.size() > 0) {
mBufferTimestamps.removeAt(0);
nextTimeStamp = &mBufferTimestamps.editItemAt(0);
+ mNextOutBufferTimeUs = *nextTimeStamp;
mBufferSizes.removeAt(0);
currentBufLeft = &mBufferSizes.editItemAt(0);
ALOGV("moved to next time/size: %lld/%d",
@@ -976,6 +1009,8 @@
mDecodedSizes.clear();
mLastInHeader = NULL;
mEndOfInput = false;
+ mLastHeaderTimeUs = -1;
+ mNextOutBufferTimeUs = 0;
} else {
int avail;
while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) {
@@ -1038,6 +1073,8 @@
mBufferSizes.clear();
mDecodedSizes.clear();
mLastInHeader = NULL;
+ mLastHeaderTimeUs = -1;
+ mNextOutBufferTimeUs = 0;
// To make the codec behave the same before and after a reset, we need to invalidate the
// streaminfo struct. This does that:
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h
index c3e4459..3fe958e 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.h
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h
@@ -59,6 +59,8 @@
size_t mOutputBufferCount;
bool mSignalledError;
OMX_BUFFERHEADERTYPE *mLastInHeader;
+ int64_t mLastHeaderTimeUs;
+ int64_t mNextOutBufferTimeUs;
Vector<int32_t> mBufferSizes;
Vector<int32_t> mDecodedSizes;
Vector<int64_t> mBufferTimestamps;
@@ -90,6 +92,7 @@
int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
int32_t outputDelayRingBufferSamplesAvailable();
int32_t outputDelayRingBufferSpaceLeft();
+ void updateTimeStamp(int64_t inHeaderTimesUs);
DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2);
};
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 76a7f40..21109d9 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -80,6 +80,7 @@
libstagefright_amrnb_common
LOCAL_MODULE := libstagefright_soft_amrdec
+LOCAL_CLANG := false
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index a9723ea..f8316fd 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -352,7 +352,14 @@
}
size_t frameSize = getFrameSize(mode);
- CHECK_GE(inHeader->nFilledLen, frameSize);
+ if (inHeader->nFilledLen < frameSize) {
+ ALOGE("Filled length vs frameSize %u vs %lu. Corrupt clip?",
+ inHeader->nFilledLen, frameSize);
+
+ notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
+ mSignalledError = true;
+ return;
+ }
int16_t *outPtr = (int16_t *)outHeader->pBuffer;
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index f743b1c..4c4da60 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -51,7 +51,9 @@
mSignalledError(false),
mSawInputEos(false),
mSignalledOutputEos(false),
- mOutputPortSettingsChange(NONE) {
+ mOutputPortSettingsChange(NONE),
+ mLastAnchorTimeUs(-1),
+ mNextOutBufferTimeUs(0) {
initPorts();
initDecoder();
}
@@ -112,7 +114,7 @@
void SoftMP3::initDecoder() {
mConfig->equalizerType = flat;
mConfig->crcEnabled = false;
-
+ mConfig->samplingRate = mSamplingRate;
uint32_t memRequirements = pvmp3_decoderMemRequirements();
mDecoderBuf = malloc(memRequirements);
@@ -212,7 +214,7 @@
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
-
+ int64_t tmpTime = 0;
while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
BufferInfo *inInfo = NULL;
OMX_BUFFERHEADERTYPE *inHeader = NULL;
@@ -227,7 +229,20 @@
if (inHeader) {
if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
- mAnchorTimeUs = inHeader->nTimeStamp;
+ // use new input buffer timestamp as Anchor Time if its
+ // a) first buffer or
+ // b) first buffer post seek or
+ // c) different from last buffer timestamp
+ //If input buffer timestamp is same as last input buffer timestamp then
+ //treat this as a erroneous timestamp and ignore new input buffer
+ //timestamp and use last output buffer timestamp as Anchor Time.
+ if ((mLastAnchorTimeUs != inHeader->nTimeStamp)) {
+ mAnchorTimeUs = inHeader->nTimeStamp;
+ mLastAnchorTimeUs = inHeader->nTimeStamp;
+ } else {
+ mAnchorTimeUs = mNextOutBufferTimeUs;
+ }
+
mNumFramesOutput = 0;
}
@@ -259,10 +274,13 @@
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) {
@@ -323,7 +341,7 @@
outHeader->nTimeStamp =
mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
-
+ tmpTime = outHeader->nTimeStamp;
if (inHeader) {
CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
@@ -348,6 +366,10 @@
notifyFillBufferDone(outHeader);
outHeader = NULL;
}
+
+ if (tmpTime > 0) {
+ mNextOutBufferTimeUs = tmpTime;
+ }
}
void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
@@ -359,6 +381,8 @@
mSignalledError = false;
mSawInputEos = false;
mSignalledOutputEos = false;
+ mLastAnchorTimeUs = -1;
+ mNextOutBufferTimeUs = 0;
}
}
@@ -395,6 +419,8 @@
mSawInputEos = false;
mSignalledOutputEos = false;
mOutputPortSettingsChange = NONE;
+ mLastAnchorTimeUs = -1;
+ mNextOutBufferTimeUs = 0;
}
} // namespace android
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h
index f9e7b53..c769795 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.h
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h
@@ -70,6 +70,9 @@
AWAITING_ENABLED
} mOutputPortSettingsChange;
+ int64_t mLastAnchorTimeUs;
+ int64_t mNextOutBufferTimeUs;
+
void initPorts();
void initDecoder();
diff --git a/media/libstagefright/codecs/raw/SoftRaw.cpp b/media/libstagefright/codecs/raw/SoftRaw.cpp
index 9d514a6..b78b36f 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.cpp
+++ b/media/libstagefright/codecs/raw/SoftRaw.cpp
@@ -58,7 +58,7 @@
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 32 * 1024;
+ def.nBufferSize = 192 * 1024;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
@@ -76,7 +76,7 @@
def.eDir = OMX_DirOutput;
def.nBufferCountMin = kNumBuffers;
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = 32 * 1024;
+ def.nBufferSize = 192 * 1024;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
diff --git a/media/libstagefright/codecs/raw/SoftRaw.h b/media/libstagefright/codecs/raw/SoftRaw.h
index 015c4a3..94b0ef1 100644
--- a/media/libstagefright/codecs/raw/SoftRaw.h
+++ b/media/libstagefright/codecs/raw/SoftRaw.h
@@ -43,7 +43,7 @@
private:
enum {
- kNumBuffers = 4
+ kNumBuffers = 8
};
bool mSignalledError;
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index c559682..3dc549e 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -419,6 +419,8 @@
mNumFramesOutput = 0;
vorbis_dsp_restart(mState);
+ mSawInputEos = false;
+ mSignalledOutputEos = false;
}
}
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index 81a6d00..ea4cd2b 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -16,7 +16,14 @@
<Included>
<Decoders>
- <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es">
+ <MediaCodec name="OMX.google.mpeg4.decoder">
+ <Type name="video/mp4v-es" />
+ <!--
+ Use Google mpeg4 decoder for mpeg4 DP content which is not
+ supported by HW. A component can be used to support several
+ mimetypes, so non-DP mpeg4 usecases will not be affected by this.
+ -->
+ <Type name="video/mp4v-esdp" />
<!-- profiles and levels: ProfileSimple : Level3 -->
<Limit name="size" min="2x2" max="352x288" />
<Limit name="alignment" value="2x2" />
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
index a5b81a8..3ebbbd9 100644
--- a/media/libstagefright/foundation/ABuffer.cpp
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -29,13 +29,9 @@
mInt32Data(0),
mOwnsData(true) {
mData = malloc(capacity);
- if (mData == NULL) {
- mCapacity = 0;
- mRangeLength = 0;
- } else {
- mCapacity = capacity;
- mRangeLength = capacity;
- }
+ CHECK(mData != NULL);
+ mCapacity = capacity;
+ mRangeLength = capacity;
}
ABuffer::ABuffer(void *data, size_t capacity)
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 1557401..1b0b1c5 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -54,7 +54,7 @@
const int64_t LiveSession::kPrepareMarkUs = 1500000ll;
const int64_t LiveSession::kUnderflowMarkUs = 1000000ll;
-struct LiveSession::BandwidthEstimator : public RefBase {
+struct LiveSession::BandwidthEstimator : public LiveSession::BandwidthBaseEstimator {
BandwidthEstimator();
void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
@@ -1064,6 +1064,7 @@
itemsWithVideo.push(item);
}
}
+#if 0
// remove the audio-only variants if we have at least one with video
if (!itemsWithVideo.empty()
&& itemsWithVideo.size() < mBandwidthItems.size()) {
@@ -1072,7 +1073,7 @@
mBandwidthItems.push(itemsWithVideo[i]);
}
}
-
+#endif
CHECK_GT(mBandwidthItems.size(), 0u);
initialBandwidth = mBandwidthItems[0].mBandwidth;
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index 90d56d0..0d504e4 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -73,7 +73,7 @@
const sp<IMediaHTTPService> &httpService);
int64_t calculateMediaTimeUs(int64_t firstTimeUs, int64_t timeUs, int32_t discontinuitySeq);
- status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit);
+ virtual status_t dequeueAccessUnit(StreamType stream, sp<ABuffer> *accessUnit);
status_t getStreamFormat(StreamType stream, sp<AMessage> *format);
@@ -117,7 +117,6 @@
virtual void onMessageReceived(const sp<AMessage> &msg);
-private:
friend struct PlaylistFetcher;
enum {
@@ -142,6 +141,14 @@
static const int64_t kPrepareMarkUs;
static const int64_t kUnderflowMarkUs;
+ struct BandwidthBaseEstimator : public RefBase {
+ virtual void addBandwidthMeasurement(size_t numBytes, int64_t delayUs) = 0;
+ virtual bool estimateBandwidth(
+ int32_t *bandwidth,
+ bool *isStable = NULL,
+ int32_t *shortTermBps = NULL) = 0;
+ };
+
struct BandwidthEstimator;
struct BandwidthItem {
size_t mPlaylistIndex;
@@ -201,7 +208,7 @@
ssize_t mOrigBandwidthIndex;
int32_t mLastBandwidthBps;
bool mLastBandwidthStable;
- sp<BandwidthEstimator> mBandwidthEstimator;
+ sp<BandwidthBaseEstimator> mBandwidthEstimator;
sp<M3UParser> mPlaylist;
int32_t mMaxWidth;
@@ -251,10 +258,10 @@
KeyedVector<size_t, int64_t> mDiscontinuityAbsStartTimesUs;
KeyedVector<size_t, int64_t> mDiscontinuityOffsetTimesUs;
- sp<PlaylistFetcher> addFetcher(const char *uri);
+ virtual sp<PlaylistFetcher> addFetcher(const char *uri);
void onConnect(const sp<AMessage> &msg);
- void onMasterPlaylistFetched(const sp<AMessage> &msg);
+ virtual void onMasterPlaylistFetched(const sp<AMessage> &msg);
void onSeek(const sp<AMessage> &msg);
bool UriIsSameAsIndex( const AString &uri, int32_t index, bool newUri);
@@ -269,7 +276,7 @@
float getAbortThreshold(
ssize_t currentBWIndex, ssize_t targetBWIndex) const;
void addBandwidthMeasurement(size_t numBytes, int64_t delayUs);
- size_t getBandwidthIndex(int32_t bandwidthBps);
+ virtual size_t getBandwidthIndex(int32_t bandwidthBps);
ssize_t getLowestValidBandwidthIndex() const;
HLSTime latestMediaSegmentStartTime() const;
@@ -284,7 +291,7 @@
void onChangeConfiguration2(const sp<AMessage> &msg);
void onChangeConfiguration3(const sp<AMessage> &msg);
- void swapPacketSource(StreamType stream);
+ virtual void swapPacketSource(StreamType stream);
void tryToFinishBandwidthSwitch(const AString &oldUri);
void cancelBandwidthSwitch(bool resume = false);
bool checkSwitchProgress(
@@ -296,7 +303,7 @@
void schedulePollBuffering();
void cancelPollBuffering();
void restartPollBuffering();
- void onPollBuffering();
+ virtual void onPollBuffering();
bool checkBuffering(bool &underflow, bool &ready, bool &down, bool &up);
void startBufferingIfNecessary();
void stopBufferingIfNecessary();
@@ -304,7 +311,7 @@
void finishDisconnect();
- void postPrepared(status_t err);
+ virtual void postPrepared(status_t err);
void postError(status_t err);
DISALLOW_EVIL_CONSTRUCTORS(LiveSession);
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 72d832e..023de93 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -975,7 +975,9 @@
if (mSegmentStartTimeUs < 0) {
if (!mPlaylist->isComplete() && !mPlaylist->isEvent()) {
// If this is a live session, start 3 segments from the end on connect
- mSeqNumber = lastSeqNumberInPlaylist - 3;
+ if (!getSeqNumberInLiveStreaming()) {
+ mSeqNumber = lastSeqNumberInPlaylist - 3;
+ }
if (mSeqNumber < firstSeqNumberInPlaylist) {
mSeqNumber = firstSeqNumberInPlaylist;
}
@@ -1418,6 +1420,10 @@
}
}
+ if (checkSwitchBandwidth()) {
+ return;
+ }
+
++mSeqNumber;
// if adapting, pause after found the next starting point
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index c8ca457..6b60b65 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -89,7 +89,6 @@
virtual ~PlaylistFetcher();
virtual void onMessageReceived(const sp<AMessage> &msg);
-private:
enum {
kMaxNumRetries = 5,
};
@@ -249,6 +248,8 @@
void updateDuration();
void updateTargetDuration();
+ virtual bool checkSwitchBandwidth() { return false; }
+ virtual bool getSeqNumberInLiveStreaming() { return false; }
DISALLOW_EVIL_CONSTRUCTORS(PlaylistFetcher);
};
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 4410579..76d65f0 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -503,8 +503,9 @@
void ID3::Iterator::getstring(String8 *id, bool otherdata) const {
id->setTo("");
- const uint8_t *frameData = mFrameData;
- if (frameData == NULL) {
+ size_t size;
+ const uint8_t *frameData = getData(&size);
+ if ((size == 0) || (frameData == NULL)) {
return;
}
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index a29bdf9..afa91ae 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -69,7 +69,7 @@
protected:
virtual ~NuCachedSource2();
-private:
+protected:
friend struct AHandlerReflector<NuCachedSource2>;
NuCachedSource2(
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index e5fb45b..1ca7ad2 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -145,7 +145,7 @@
OMX::node_id mNodeID;
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
- bool mDying;
+ atomic_bool mDying;
bool mIsSecure;
// Lock only covers mGraphicBufferSource. We can't always use mLock
diff --git a/media/libstagefright/include/SimpleSoftOMXComponent.h b/media/libstagefright/include/SimpleSoftOMXComponent.h
index 591b38e..6a0a958 100644
--- a/media/libstagefright/include/SimpleSoftOMXComponent.h
+++ b/media/libstagefright/include/SimpleSoftOMXComponent.h
@@ -140,6 +140,7 @@
void onPortFlush(OMX_U32 portIndex, bool sendFlushComplete);
void checkTransitions();
+ void onTransitionError();
DISALLOW_EVIL_CONSTRUCTORS(SimpleSoftOMXComponent);
};
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index e3c3e80..3645424 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -628,6 +647,12 @@
mQueue = new ElementaryStreamQueue(
ElementaryStreamQueue::AC3);
break;
+#ifdef DOLBY_ENABLE
+ case STREAMTYPE_EAC3:
+ mQueue = new ElementaryStreamQueue(
+ ElementaryStreamQueue::EAC3);
+ break;
+#endif // DOLBY_END
case STREAMTYPE_METADATA:
mQueue = new ElementaryStreamQueue(
@@ -752,6 +777,9 @@
case STREAMTYPE_MPEG2_AUDIO_ADTS:
case STREAMTYPE_LPCM_AC3:
case STREAMTYPE_AC3:
+#ifdef DOLBY_ENABLE
+ case STREAMTYPE_EAC3:
+#endif // DOLBY_END
return true;
default:
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 430a8d5..366a861 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef A_TS_PARSER_H_
@@ -134,6 +153,9 @@
// Stream type 0x83 is non-standard,
// it could be LPCM or TrueHD AC3
STREAMTYPE_LPCM_AC3 = 0x83,
+#ifdef DOLBY_ENABLE
+ STREAMTYPE_EAC3 = 0x87,
+#endif // DOLBY_END
};
protected:
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 36ec367..770e94b 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -33,6 +52,9 @@
#include <inttypes.h>
#include <netinet/in.h>
+#ifdef DOLBY_ENABLE
+#include "DolbyESQueueExtImpl.h"
+#endif // DOLBY_END
namespace android {
@@ -40,6 +62,9 @@
: mMode(mode),
mFlags(flags),
mEOSReached(false) {
+#ifdef DOLBY_ENABLE
+ independent_streams_processed = 0;
+#endif // DOLBY_END
}
sp<MetaData> ElementaryStreamQueue::getFormat() {
@@ -388,6 +413,35 @@
size -= startOffset;
break;
}
+#ifdef DOLBY_ENABLE
+ case EAC3:
+ {
+ uint8_t *ptr = (uint8_t *)data;
+
+ ssize_t startOffset = -1;
+ for (size_t i = 0; i < size; ++i) {
+ if (IsSeeminglyValidEAC3AudioHeader(&ptr[i], size - i)) {
+ startOffset = i;
+ break;
+ }
+ }
+
+ if (startOffset < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ if (startOffset > 0) {
+ ALOGI("found something resembling a DDP audio "
+ "syncword at offset %zd",
+ startOffset);
+ }
+
+ data = &ptr[startOffset];
+ size -= startOffset;
+ break;
+ }
+
+#endif // DOLBY_END
case MPEG_AUDIO:
{
@@ -496,6 +550,10 @@
return dequeueAccessUnitAAC();
case AC3:
return dequeueAccessUnitAC3();
+#ifdef DOLBY_ENABLE
+ case EAC3:
+ return dequeueAccessUnitEAC3();
+#endif // DOLBY_END
case MPEG_VIDEO:
return dequeueAccessUnitMPEGVideo();
case MPEG4_VIDEO:
diff --git a/media/libstagefright/mpeg2ts/ESQueue.h b/media/libstagefright/mpeg2ts/ESQueue.h
index e9f96b7..e86a36d 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.h
+++ b/media/libstagefright/mpeg2ts/ESQueue.h
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
#ifndef ES_QUEUE_H_
@@ -33,6 +52,9 @@
H264,
AAC,
AC3,
+#ifdef DOLBY_ENABLE
+ EAC3,
+#endif // DOLBY_END
MPEG_AUDIO,
MPEG_VIDEO,
MPEG4_VIDEO,
@@ -77,6 +99,11 @@
sp<ABuffer> dequeueAccessUnitMPEG4Video();
sp<ABuffer> dequeueAccessUnitPCMAudio();
sp<ABuffer> dequeueAccessUnitMetadata();
+#ifdef DOLBY_ENABLE
+ sp<ABuffer> dequeueAccessUnitEAC3();
+ unsigned independent_streams_processed;
+ unsigned independent_stream_num_channels;
+#endif // DOLBY_END
// consume a logical (compressed) access unit of size "size",
// returns its timestamp in us (or -1 if no time information).
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index 6d9fe9d..86645d5 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -607,6 +626,14 @@
mode = ElementaryStreamQueue::MPEG_AUDIO;
break;
+#ifdef DOLBY_ENABLE
+ case ATSParser::STREAMTYPE_AC3:
+ mode = ElementaryStreamQueue::AC3;
+ break;
+ case ATSParser::STREAMTYPE_EAC3:
+ mode = ElementaryStreamQueue::EAC3;
+ break;
+#endif // DOLBY_END
case ATSParser::STREAMTYPE_MPEG1_VIDEO:
case ATSParser::STREAMTYPE_MPEG2_VIDEO:
mode = ElementaryStreamQueue::MPEG_VIDEO;
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 5f0f567..d16d5df 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -30,6 +30,12 @@
libstagefright_foundation \
libdl
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
+ LOCAL_CFLAGS += -DQTI_FLAC_DECODER
+endif
+endif
+
LOCAL_MODULE:= libstagefright_omx
LOCAL_CFLAGS += -Werror -Wall
LOCAL_CLANG := true
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 7f357c9..efb1a1c 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -468,6 +468,10 @@
findInstance(node)->onEvent(eEvent, nData1, nData2);
sp<OMX::CallbackDispatcher> dispatcher = findDispatcher(node);
+ if (dispatcher == NULL) {
+ ALOGW("OnEvent Callback dispatcher NULL, skip post");
+ return OMX_ErrorNone;
+ }
// output rendered events are not processed as regular events until they hit the observer
if (eEvent == OMX_EventOutputRendered) {
@@ -513,7 +517,12 @@
msg.fenceFd = fenceFd;
msg.u.buffer_data.buffer = buffer;
- findDispatcher(node)->post(msg);
+ sp<OMX::CallbackDispatcher> callbackDispatcher = findDispatcher(node);
+ if (callbackDispatcher != NULL) {
+ callbackDispatcher->post(msg);
+ } else {
+ ALOGW("OnEmptyBufferDone Callback dispatcher NULL, skip post");
+ }
return OMX_ErrorNone;
}
@@ -532,7 +541,12 @@
msg.u.extended_buffer_data.flags = pBuffer->nFlags;
msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
- findDispatcher(node)->post(msg);
+ sp<OMX::CallbackDispatcher> callbackDispatcher = findDispatcher(node);
+ if (callbackDispatcher != NULL) {
+ callbackDispatcher->post(msg);
+ } else {
+ ALOGW("OnFillBufferDone Callback dispatcher NULL, skip post");
+ }
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 94a213a..9795580 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -122,7 +122,8 @@
}
// check component returns proper range
- sp<ABuffer> codec = getBuffer(header, false /* backup */, true /* limit */);
+ sp<ABuffer> codec = getBuffer(header, false /* backup */,
+ !(header->nFlags & OMX_BUFFERFLAG_EXTRADATA));
memcpy((OMX_U8 *)mMem->pointer() + header->nOffset, codec->data(), codec->size());
}
@@ -132,9 +133,11 @@
return;
}
+ size_t bytesToCopy = header->nFlags & OMX_BUFFERFLAG_EXTRADATA ?
+ header->nAllocLen - header->nOffset : header->nFilledLen;
memcpy(header->pBuffer + header->nOffset,
(const OMX_U8 *)mMem->pointer() + header->nOffset,
- header->nFilledLen);
+ bytesToCopy);
}
// return either the codec or the backup buffer
@@ -190,7 +193,6 @@
mNodeID(0),
mHandle(NULL),
mObserver(observer),
- mDying(false),
mBufferIDCount(0)
{
mName = ADebug::GetDebugName(name);
@@ -203,6 +205,7 @@
mDebugLevelBumpPendingBuffers[1] = 0;
mMetadataType[0] = kMetadataBufferTypeInvalid;
mMetadataType[1] = kMetadataBufferTypeInvalid;
+ atomic_store(&mDying, false);
mIsSecure = AString(name).endsWith(".secure");
}
@@ -274,11 +277,12 @@
// The code below may trigger some more events to be dispatched
// by the OMX component - we want to ignore them as our client
// does not expect them.
- mDying = true;
+ atomic_store(&mDying, true);
OMX_STATETYPE state;
CHECK_EQ(OMX_GetState(mHandle, &state), OMX_ErrorNone);
switch (state) {
+ case OMX_StatePause:
case OMX_StateExecuting:
{
ALOGV("forcing Executing->Idle");
@@ -1457,6 +1461,9 @@
ALOGE("!!! Observer died. Quickly, do something, ... anything...");
// Try to force shutdown of the node and hope for the best.
+ // But allow the component to observe mDying = true first
+ atomic_store(&mDying, true);
+ sleep(2);
freeNode(master);
}
@@ -1524,7 +1531,7 @@
OMX_IN OMX_U32 nData2,
OMX_IN OMX_PTR pEventData) {
OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
- if (instance->mDying) {
+ if (atomic_load(&instance->mDying)) {
return OMX_ErrorNone;
}
return instance->owner()->OnEvent(
@@ -1537,7 +1544,7 @@
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
- if (instance->mDying) {
+ if (atomic_load(&instance->mDying)) {
return OMX_ErrorNone;
}
int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
@@ -1551,7 +1558,7 @@
OMX_IN OMX_PTR pAppData,
OMX_IN OMX_BUFFERHEADERTYPE* pBuffer) {
OMXNodeInstance *instance = static_cast<OMXNodeInstance *>(pAppData);
- if (instance->mDying) {
+ if (atomic_load(&instance->mDying)) {
return OMX_ErrorNone;
}
int fenceFd = instance->retrieveFenceFromMeta_l(pBuffer, kPortIndexOutput);
diff --git a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
index e6a0c49..1fd0641 100644
--- a/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SimpleSoftOMXComponent.cpp
@@ -417,16 +417,43 @@
}
}
+void SimpleSoftOMXComponent::onTransitionError() {
+ mState = OMX_StateInvalid;
+ mTargetState = OMX_StateInvalid;
+ notify(OMX_EventError, OMX_CommandStateSet, OMX_StateInvalid, 0);
+}
+
void SimpleSoftOMXComponent::onChangeState(OMX_STATETYPE state) {
+ bool skipTransitions = false;
+
// We shouldn't be in a state transition already.
- CHECK_EQ((int)mState, (int)mTargetState);
+ if (mState != mTargetState) {
+ // Workaround to prevent assertion
+ // XXX CHECK_EQ((int)mState, (int)mTargetState);
+ ALOGW("mState %d != mTargetState %d", mState, mTargetState);
+ skipTransitions = true;
+ onTransitionError();
+ }
switch (mState) {
case OMX_StateLoaded:
- CHECK_EQ((int)state, (int)OMX_StateIdle);
+ if (state != OMX_StateIdle) {
+ // Workaround to prevent assertion
+ // XXX CHECK_EQ((int)state, (int)OMX_StateIdle);
+ ALOGW("In OMX_StateLoaded, state %d != OMX_StateIdle", state);
+ skipTransitions = true;
+ onTransitionError();
+ }
break;
case OMX_StateIdle:
- CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting);
+ if (!(state == OMX_StateLoaded || state == OMX_StateExecuting)) {
+ // Workaround to prevent assertion
+ // XXX CHECK(state == OMX_StateLoaded || state == OMX_StateExecuting);
+ ALOGW("In OMX_StateIdle, state %d != OMX_StateLoaded||OMX_StateExecuting",
+ state);
+ skipTransitions = true;
+ onTransitionError();
+ }
break;
case OMX_StateExecuting:
{
@@ -440,11 +467,20 @@
notify(OMX_EventCmdComplete, OMX_CommandStateSet, state, NULL);
break;
}
-
+ case OMX_StateInvalid: {
+ ALOGW("In OMX_StateInvalid, ignore state transition to %d", state);
+ skipTransitions = true;
+ onTransitionError();
+ break;
+ }
default:
TRESPASS();
}
+ if (skipTransitions) {
+ return;
+ }
+
mTargetState = state;
checkTransitions();
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 0f9c00c..5117ddd 100755
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -12,6 +12,25 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2011-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
//#define LOG_NDEBUG 0
@@ -59,6 +78,14 @@
{ "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },
{ "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },
{ "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" },
+#ifdef QTI_FLAC_DECODER
+ { "OMX.qti.audio.decoder.flac", "flacdec", "audio_decoder.flac" },
+#endif
+#ifdef DOLBY_ENABLE
+ { "OMX.dolby.ac3.decoder", "ddpdec", "audio_decoder.ac3" },
+ { "OMX.dolby.eac3.decoder", "ddpdec", "audio_decoder.eac3" },
+ { "OMX.dolby.eac3_joc.decoder", "ddpdec", "audio_decoder.eac3_joc" },
+#endif // DOLBY_END
};
static const size_t kNumComponents =
diff --git a/media/libstagefright/rtsp/AH263Assembler.cpp b/media/libstagefright/rtsp/AH263Assembler.cpp
index 75cd911..28594e2 100644
--- a/media/libstagefright/rtsp/AH263Assembler.cpp
+++ b/media/libstagefright/rtsp/AH263Assembler.cpp
@@ -27,6 +27,8 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/Utils.h>
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
+
namespace android {
AH263Assembler::AH263Assembler(const sp<AMessage> ¬ify)
@@ -63,7 +65,8 @@
if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
break;
}
-
+ AVMediaServiceUtils::get()->addH263AdvancedPacket(
+ *it, &mPackets, mAccessUnitRTPTime);
it = queue->erase(it);
}
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
index a1a6576..d239e7b 100644
--- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -420,6 +420,11 @@
CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
offset += mOtherDataLenBits / 8;
}
+
+ if (i < mNumSubFrames && offset >= buffer->size()) {
+ ALOGW("Skip subframes after %d, total %d", (int)i, (int)mNumSubFrames);
+ break;
+ }
}
if (offset < buffer->size()) {
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
index a86ab74..e021b29 100644
--- a/media/libstagefright/rtsp/ARTPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -81,7 +81,8 @@
const sp<ASessionDescription> &sessionDesc,
size_t index,
const sp<AMessage> ¬ify,
- bool injected) {
+ bool injected,
+ bool isIPV6) {
sp<AMessage> msg = new AMessage(kWhatAddStream, this);
msg->setInt32("rtp-socket", rtpSocket);
msg->setInt32("rtcp-socket", rtcpSocket);
@@ -89,6 +90,7 @@
msg->setSize("index", index);
msg->setMessage("notify", notify);
msg->setInt32("injected", injected);
+ msg->setInt32("isIPV6", isIPV6);
msg->post();
}
@@ -145,6 +147,10 @@
TRESPASS();
}
+size_t ARTPConnection::sockAddrSize() {
+ return sizeof(struct sockaddr_in);
+}
+
void ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatAddStream:
@@ -345,7 +351,7 @@
n = sendto(
s->mRTCPSocket, buffer->data(), buffer->size(), 0,
(const struct sockaddr *)&s->mRemoteRTCPAddr,
- sizeof(s->mRemoteRTCPAddr));
+ sockAddrSize());
} while (n < 0 && errno == EINTR);
if (n <= 0) {
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
index edbcc35..057007b 100644
--- a/media/libstagefright/rtsp/ARTPConnection.h
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -38,7 +38,8 @@
int rtpSocket, int rtcpSocket,
const sp<ASessionDescription> &sessionDesc, size_t index,
const sp<AMessage> ¬ify,
- bool injected);
+ bool injected,
+ bool isIPV6 = false);
void removeStream(int rtpSocket, int rtcpSocket);
@@ -53,8 +54,8 @@
protected:
virtual ~ARTPConnection();
virtual void onMessageReceived(const sp<AMessage> &msg);
+ virtual size_t sockAddrSize();
-private:
enum {
kWhatAddStream,
kWhatRemoveStream,
@@ -72,7 +73,7 @@
bool mPollEventPending;
int64_t mLastReceiverReportTimeUs;
- void onAddStream(const sp<AMessage> &msg);
+ virtual void onAddStream(const sp<AMessage> &msg);
void onRemoveStream(const sp<AMessage> &msg);
void onPollStreams();
void onInjectPacket(const sp<AMessage> &msg);
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 855ffdc..b2c1fd1 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -26,6 +26,7 @@
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
#include <arpa/inet.h>
#include <fcntl.h>
@@ -170,7 +171,7 @@
}
}
- const char *colonPos = strchr(host->c_str(), ':');
+ const char *colonPos = AVMediaServiceUtils::get()->parseURL(host);
if (colonPos != NULL) {
unsigned long x;
@@ -252,6 +253,11 @@
ALOGV("user = '%s', pass = '%s'", mUser.c_str(), mPass.c_str());
}
+ performConnect(reply, host, port);
+}
+
+void ARTSPConnection::performConnect(const sp<AMessage> &reply,
+ AString host, unsigned port) {
struct hostent *ent = gethostbyname(host.c_str());
if (ent == NULL) {
ALOGE("Unknown host %s", host.c_str());
@@ -381,7 +387,12 @@
socklen_t optionLen = sizeof(err);
CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
CHECK_EQ(optionLen, (socklen_t)sizeof(err));
+ performCompleteConnection(msg, err);
+}
+void ARTSPConnection::performCompleteConnection(const sp<AMessage> &msg, int err) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
if (err != 0) {
ALOGE("err = %d (%s)", err, strerror(err));
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
index 1fe9c99..c4ebe1d 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.h
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -42,6 +42,8 @@
void observeBinaryData(const sp<AMessage> &reply);
+ virtual bool isIPV6() { return false; }
+
static bool ParseURL(
const char *url, AString *host, unsigned *port, AString *path,
AString *user, AString *pass);
@@ -49,8 +51,11 @@
protected:
virtual ~ARTSPConnection();
virtual void onMessageReceived(const sp<AMessage> &msg);
+ virtual void performConnect(const sp<AMessage> &reply,
+ AString host, unsigned port);
+ virtual void performCompleteConnection(const sp<AMessage> &msg,
+ int err);
-private:
enum State {
DISCONNECTED,
CONNECTING,
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
index 98498e9..92ad1ec 100644
--- a/media/libstagefright/rtsp/ASessionDescription.cpp
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -22,7 +22,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
-
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
#include <stdlib.h>
namespace android {
@@ -264,7 +264,8 @@
}
float from, to;
- if (!parseNTPRange(value.c_str() + 4, &from, &to)) {
+ if (!AVMediaServiceUtils::get()->parseNTPRange(
+ value.c_str() + 4, &from, &to)) {
return false;
}
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
index c5e8c35..8bc4295 100644
--- a/media/libstagefright/rtsp/Android.mk
+++ b/media/libstagefright/rtsp/Android.mk
@@ -22,8 +22,10 @@
LOCAL_SHARED_LIBRARIES += libcrypto
LOCAL_C_INCLUDES:= \
- $(TOP)/frameworks/av/media/libstagefright \
- $(TOP)/frameworks/native/include/media/openmax
+ $(TOP)/frameworks/av/media/libstagefright \
+ $(TOP)/frameworks/av/media/libavextensions \
+ $(TOP)/frameworks/native/include/media/openmax \
+ $(TOP)/frameworks/av/media/libmediaplayerservice \
LOCAL_MODULE:= libstagefright_rtsp
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 0d0baf3..7290ee2 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -32,6 +32,7 @@
#include "ASessionDescription.h"
#include <ctype.h>
+#include <cutils/properties.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -39,6 +40,7 @@
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/Utils.h>
+#include <mediaplayerservice/AVMediaServiceExtensions.h>
#include <arpa/inet.h>
#include <sys/socket.h>
@@ -64,6 +66,8 @@
static int64_t kPauseDelayUs = 3000000ll;
+static int64_t kTearDownTimeoutUs = 3000000ll;
+
namespace android {
static bool GetAttribute(const char *s, const char *key, AString *value) {
@@ -105,6 +109,8 @@
kWhatEOS = 'eos!',
kWhatSeekDiscontinuity = 'seeD',
kWhatNormalPlayTimeMapping = 'nptM',
+ kWhatCancelCheck = 'canC',
+ kWhatByeReceived = 'byeR',
};
MyHandler(
@@ -115,8 +121,6 @@
mUIDValid(uidValid),
mUID(uid),
mNetLooper(new ALooper),
- mConn(new ARTSPConnection(mUIDValid, mUID)),
- mRTPConn(new ARTPConnection),
mOriginalSessionURL(url),
mSessionURL(url),
mSetupTracksSuccessful(false),
@@ -140,11 +144,22 @@
mPausing(false),
mPauseGeneration(0),
mPlayResponseParsed(false) {
+ mConn = AVMediaServiceFactory::get()->createARTSPConnection(
+ mUIDValid, uid);
+ mRTPConn = AVMediaServiceFactory::get()->createARTPConnection();
mNetLooper->setName("rtsp net");
mNetLooper->start(false /* runOnCallingThread */,
false /* canCallJava */,
PRIORITY_HIGHEST);
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("rtsp.transport.TCP", value, "false");
+ if (!strcasecmp(value, "true")) {
+ mTryTCPInterleaving = true;
+ } else {
+ mTryTCPInterleaving = false;
+ }
+
// Strip any authentication info from the session url, we don't
// want to transmit user/pass in cleartext.
AString host, path, user, pass;
@@ -244,6 +259,11 @@
msg->post();
}
+ void cancelTimeoutCheck() {
+ sp<AMessage> msg = new AMessage('canC', this);
+ msg->post();
+ }
+
static void addRR(const sp<ABuffer> &buf) {
uint8_t *ptr = buf->data() + buf->size();
ptr[0] = 0x80 | 0;
@@ -703,6 +723,7 @@
timeoutSecs);
}
}
+ AVMediaServiceUtils::get()->setServerTimeoutUs(mKeepAliveTimeoutUs);
i = mSessionID.find(";");
if (i >= 0) {
@@ -722,16 +743,19 @@
// We are going to continue even if we were
// unable to poke a hole into the firewall...
- pokeAHole(
+ AVMediaServiceUtils::get()->pokeAHole(
+ this,
track->mRTPSocket,
track->mRTCPSocket,
- transport);
+ transport,
+ mSessionHost);
}
mRTPConn->addStream(
track->mRTPSocket, track->mRTCPSocket,
mSessionDesc, index,
- notify, track->mUsingInterleavedTCP);
+ notify, track->mUsingInterleavedTCP,
+ mConn->isIPV6());
mSetupTracksSuccessful = true;
} else {
@@ -774,6 +798,7 @@
request.append(mSessionID);
request.append("\r\n");
+ AVMediaServiceUtils::get()->appendRange(&request);
request.append("\r\n");
sp<AMessage> reply = new AMessage('play', this);
@@ -922,6 +947,15 @@
request.append("\r\n");
mConn->sendRequest(request.c_str(), reply);
+
+ // If the response of teardown hasn't been received in 3 seconds,
+ // post 'tear' message to avoid ANR.
+ if (!msg->findInt32("reconnect", &reconnect) || !reconnect) {
+ sp<AMessage> teardown = new AMessage('tear', this);
+ teardown->setInt32("result", -ECONNABORTED);
+ teardown->post(kTearDownTimeoutUs);
+ }
+
break;
}
@@ -1020,6 +1054,13 @@
int32_t eos;
if (msg->findInt32("eos", &eos)) {
ALOGI("received BYE on track index %zu", trackIndex);
+ char value[PROPERTY_VALUE_MAX] = {0};
+ if (property_get("rtcp.bye.notify", value, "false")
+ && !strcasecmp(value, "true")) {
+ sp<AMessage> msg = mNotify->dup();
+ msg->setInt32("what", kWhatByeReceived);
+ msg->post();
+ }
if (!mAllTracksHaveTime && dataReceivedOnAllChannels()) {
ALOGI("No time established => fake existing data");
@@ -1386,6 +1427,13 @@
break;
}
+ case 'canC':
+ {
+ ALOGV("cancel checking timeout");
+ mCheckGeneration++;
+ break;
+ }
+
default:
TRESPASS();
break;
@@ -1471,7 +1519,9 @@
size_t trackIndex = 0;
while (trackIndex < mTracks.size()
- && !(val == mTracks.editItemAt(trackIndex).mURL)) {
+ && !(AVMediaServiceUtils::get()->parseTrackURL(
+ mTracks.editItemAt(trackIndex).mURL, val)
+ || val == mTracks.editItemAt(trackIndex).mURL)) {
++trackIndex;
}
CHECK_LT(trackIndex, mTracks.size());
@@ -1648,8 +1698,9 @@
request.append(interleaveIndex + 1);
} else {
unsigned rtpPort;
- ARTPConnection::MakePortPair(
- &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
+ AVMediaServiceUtils::get()->makePortPair(
+ &info->mRTPSocket, &info->mRTCPSocket, &rtpPort,
+ mConn->isIPV6());
if (mUIDValid) {
HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID,
@@ -1860,7 +1911,7 @@
mLastMediaTimeUs = mediaTimeUs;
}
- if (mediaTimeUs < 0) {
+ if (mediaTimeUs < 0 && !mSeekable) {
ALOGV("dropping early accessUnit.");
return false;
}
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index b6de0d9..fec0629 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -50,6 +50,12 @@
frameworks/av/services/radio \
external/sonic
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_LISTEN)),true)
+LOCAL_SHARED_LIBRARIES += liblisten
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-listen
+LOCAL_CFLAGS += -DAUDIO_LISTEN_ENABLED
+endif
+
LOCAL_MODULE:= mediaserver
LOCAL_32_BIT_ONLY := true
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 4a485ed..f6aed5f 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -38,6 +38,9 @@
#include "service/AudioPolicyService.h"
#include "SoundTriggerHwService.h"
#include "RadioService.h"
+#ifdef AUDIO_LISTEN_ENABLED
+#include "ListenService.h"
+#endif
using namespace android;
@@ -136,6 +139,10 @@
AudioPolicyService::instantiate();
SoundTriggerHwService::instantiate();
RadioService::instantiate();
+#ifdef AUDIO_LISTEN_ENABLED
+ ALOGI("ListenService instantiated");
+ ListenService::instantiate();
+#endif
registerExtensions();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 9b4ba79..3ea586e 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -60,6 +60,14 @@
libcpustats \
libmedia_helper
+#QTI Resampler
+ifeq ($(call is-vendor-board-platform,QCOM), true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
+endif
+#QTI Resampler
+
LOCAL_MODULE:= libaudioflinger
LOCAL_32_BIT_ONLY := true
@@ -123,7 +131,26 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
- liblog
+ liblog \
+ libaudioutils
+
+#QTI Resampler
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)),true)
+ifdef TARGET_2ND_ARCH
+LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm
+LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
+LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler
+LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER
+else
+LOCAL_SRC_FILES += AudioResamplerQTI.cpp.arm
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
+LOCAL_SHARED_LIBRARIES += libqct_resampler
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
+endif
+endif
+#QTI Resampler
LOCAL_MODULE := libaudioresampler
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9ec5802..eed3bb2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
@@ -80,6 +99,9 @@
#define ALOGVV(a...) do { } while(0)
#endif
+#ifdef DOLBY_ENABLE
+#include "EffectDapController_impl.h"
+#endif // DOLBY_END
namespace android {
static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
@@ -131,6 +153,14 @@
case AUDIO_FORMAT_OPUS: return "opus";
case AUDIO_FORMAT_AC3: return "ac-3";
case AUDIO_FORMAT_E_AC3: return "e-ac-3";
+ case AUDIO_FORMAT_PCM_OFFLOAD:
+ switch (format) {
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD: return "pcm-16bit-offload";
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD: return "pcm-24bit-offload";
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -210,6 +240,9 @@
mTeeSinkTrackEnabled = true;
}
#endif
+#ifdef DOLBY_ENABLE
+ EffectDapController::mInstance = new EffectDapController(this);
+#endif // DOLBY_END
}
void AudioFlinger::onFirstRef()
@@ -239,6 +272,9 @@
AudioFlinger::~AudioFlinger()
{
+#ifdef DOLBY_ENABLE
+ delete EffectDapController::mInstance;
+#endif // DOLBY_END
while (!mRecordThreads.isEmpty()) {
// closeInput_nonvirtual() will remove specified entry from mRecordThreads
closeInput_nonvirtual(mRecordThreads.keyAt(0));
@@ -1053,9 +1089,24 @@
}
mHardwareStatus = AUDIO_HW_IDLE;
}
- // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
+
AudioParameter param = AudioParameter(keyValuePairs);
- String8 value;
+ String8 value, key;
+ key = String8("SND_CARD_STATUS");
+ if (param.get(key, value) == NO_ERROR) {
+ ALOGV("Set keySoundCardStatus:%s", value.string());
+ if ((value.find("OFFLINE", 0) != -1) ) {
+ ALOGV("OFFLINE detected - call InvalidateTracks()");
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ if( thread->getOutput()->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ){
+ thread->invalidateTracks(AUDIO_STREAM_MUSIC);
+ }
+ }
+ }
+ }
+
+ // disable AEC and NS if the device is a BT SCO headset supporting those pre processings
if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) {
bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF);
if (mBtNrecIsOff != btNrecIsOff) {
@@ -1353,11 +1404,10 @@
: RefBase(),
mAudioFlinger(audioFlinger),
// FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below
- mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
+ mMemoryDealer(new MemoryDealer(4100*1024, "AudioFlinger::Client")), //4MB + 1 more 4k page
mPid(pid),
mTimedTrackCount(0)
{
- // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
}
// Client destructor must be called with AudioFlinger::mClientLock held
@@ -1818,7 +1868,11 @@
|| !isValidPcmSinkFormat(config->format)
|| !isValidPcmSinkChannelMask(config->channel_mask)) {
thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
- ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread);
+ ALOGV("openOutput_l() created direct output: ID %d thread %p ", *output, thread);
+ //Check if this is DirectPCM, if so
+ if (flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
+ thread->mIsDirectPcm = true;
+ }
} else {
thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread);
@@ -2694,6 +2748,11 @@
Mutex::Autolock _dl(dstThread->mLock);
Mutex::Autolock _sl(srcThread->mLock);
+#ifdef DOLBY_ENABLE
+ if (sessionId == DOLBY_MOVE_EFFECT_SIGNAL) {
+ return EffectDapController::instance()->moveEffect(AUDIO_SESSION_OUTPUT_MIX, srcThread, dstThread);
+ }
+#endif // DOLBY_END
return moveEffectChain_l(sessionId, srcThread, dstThread, false);
}
@@ -2775,6 +2834,9 @@
if (status != NO_ERROR) {
for (size_t i = 0; i < removed.size(); i++) {
srcThread->addEffect_l(removed[i]);
+#ifdef DOLBY_ENABLE
+ EffectDapController::instance()->restartEffect(effect);
+#endif // DOLBY_END
if (dstChain != 0 && reRegister) {
AudioSystem::unregisterEffect(removed[i]->id());
AudioSystem::registerEffect(&removed[i]->desc(),
@@ -2960,6 +3022,7 @@
bool firstRead = true;
#define TEE_SINK_READ 1024 // frames per I/O operation
void *buffer = malloc(TEE_SINK_READ * frameSize);
+ CHECK (buffer != NULL);
for (;;) {
size_t count = TEE_SINK_READ;
ssize_t actual = teeSource->read(buffer, count,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 20c34ef..afcc61f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
#ifndef ANDROID_AUDIO_FLINGER_H
@@ -64,6 +83,9 @@
#include <media/nbaio/NBLog.h>
#include <private/media/AudioTrackShared.h>
+#ifdef DOLBY_ENABLE
+#include "ds_config.h"
+#endif // DOLBY_END
namespace android {
@@ -764,6 +786,9 @@
sp<PatchPanel> mPatchPanel;
bool mSystemReady;
+#ifdef DOLBY_ENABLE
+#include "EffectDapController.h"
+#endif // DOLBY_END
};
#undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 8a9a837..27a2f65 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -85,6 +85,9 @@
// Set to default copy buffer size in frames for input processing.
static const size_t kCopyBufferFrameCount = 256;
+#ifdef QTI_RESAMPLER
+#define QTI_RESAMPLER_MAX_SAMPLERATE 192000
+#endif
namespace android {
// ----------------------------------------------------------------------------
@@ -779,6 +782,13 @@
// but if none exists, it is the channel count (1 for mono).
const int resamplerChannelCount = downmixerBufferProvider != NULL
? mMixerChannelCount : channelCount;
+#ifdef QTI_RESAMPLER
+ if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) &&
+ (trackSampleRate > devSampleRate * 2) &&
+ ((devSampleRate == 48000)||(devSampleRate == 44100))) {
+ quality = AudioResampler::QTI_QUALITY;
+ }
+#endif
ALOGVV("Creating resampler:"
" format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n",
mMixerInFormat, resamplerChannelCount, devSampleRate, quality);
@@ -1644,6 +1654,9 @@
// Note: In case of later int16_t sink output,
// conversion and clamping is done by memcpy_to_i16_from_float().
} while (--outFrames);
+ //assign fout to out, when no more frames are available, so that 0s
+ //can be filled at the right place
+ out = (int32_t *)fout;
break;
case AUDIO_FORMAT_PCM_16_BIT:
if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index e49b7b1..ab3294a 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -28,6 +28,10 @@
#include "AudioResamplerCubic.h"
#include "AudioResamplerDyn.h"
+#ifdef QTI_RESAMPLER
+#include "AudioResamplerQTI.h"
+#endif
+
#ifdef __arm__
#define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
#endif
@@ -90,6 +94,9 @@
case DYN_LOW_QUALITY:
case DYN_MED_QUALITY:
case DYN_HIGH_QUALITY:
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+#endif
return true;
default:
return false;
@@ -110,7 +117,11 @@
if (*endptr == '\0') {
defaultQuality = (src_quality) l;
ALOGD("forcing AudioResampler quality to %d", defaultQuality);
+#ifdef QTI_RESAMPLER
+ if (defaultQuality < DEFAULT_QUALITY || defaultQuality > QTI_QUALITY) {
+#else
if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) {
+#endif
defaultQuality = DEFAULT_QUALITY;
}
}
@@ -129,6 +140,9 @@
case HIGH_QUALITY:
return 20;
case VERY_HIGH_QUALITY:
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY: //for QTI_QUALITY, currently assuming same as VHQ
+#endif
return 34;
case DYN_LOW_QUALITY:
return 4;
@@ -204,6 +218,11 @@
case DYN_HIGH_QUALITY:
quality = DYN_MED_QUALITY;
break;
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+ quality = DYN_HIGH_QUALITY;
+ break;
+#endif
}
}
pthread_mutex_unlock(&mutex);
@@ -250,6 +269,12 @@
}
}
break;
+#ifdef QTI_RESAMPLER
+ case QTI_QUALITY:
+ ALOGV("Create QTI_QUALITY Resampler = %d",quality);
+ resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate);
+ break;
+#endif
}
// initialize resampler
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index a8e3e6f..6669a85 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -47,6 +47,9 @@
DYN_LOW_QUALITY=5,
DYN_MED_QUALITY=6,
DYN_HIGH_QUALITY=7,
+#ifdef QTI_RESAMPLER
+ QTI_QUALITY=8,
+#endif
};
static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f;
diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp
new file mode 100644
index 0000000..44b741e
--- /dev/null
+++ b/services/audioflinger/AudioResamplerQTI.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All rights reserved.
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioResamplerQTI.h"
+#include "QCT_Resampler.h"
+#include <sys/time.h>
+#include <audio_utils/primitives.h>
+
+namespace android {
+AudioResamplerQTI::AudioResamplerQTI(int format,
+ int inChannelCount, int32_t sampleRate)
+ :AudioResampler(inChannelCount, sampleRate, QTI_QUALITY),
+ mOutFrameCount(0), mTmpBuf(0), mResamplerOutBuf(0), mFrameIndex(0)
+{
+ stateSize = QCT_Resampler::MemAlloc(format, inChannelCount, sampleRate, sampleRate);
+ mState = new int16_t[stateSize];
+ mVolume[0] = mVolume[1] = 0;
+ mBuffer.frameCount = 0;
+}
+
+AudioResamplerQTI::~AudioResamplerQTI()
+{
+ if (mState) {
+ delete [] mState;
+ }
+ if (mTmpBuf) {
+ delete [] mTmpBuf;
+ }
+ if(mResamplerOutBuf) {
+ delete [] mResamplerOutBuf;
+ }
+}
+
+size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider)
+{
+ int16_t vl = mVolume[0];
+ int16_t vr = mVolume[1];
+ int16_t *pBuf;
+
+ size_t inFrameRequest;
+ size_t inFrameCount = getNumInSample(outFrameCount);
+ size_t index = 0;
+ size_t frameIndex = mFrameIndex;
+ size_t out_count = outFrameCount * 2;
+ float *fout = reinterpret_cast<float *>(out);
+
+ if (mChannelCount == 1) {
+ inFrameRequest = inFrameCount;
+ } else {
+ inFrameRequest = inFrameCount * 2;
+ }
+
+ if (mOutFrameCount < outFrameCount) {
+ mOutFrameCount = outFrameCount;
+ if (mTmpBuf) {
+ delete [] mTmpBuf;
+ }
+ if(mResamplerOutBuf) {
+ delete [] mResamplerOutBuf;
+ }
+ mTmpBuf = new int16_t[inFrameRequest + 16];
+ mResamplerOutBuf = new int32_t[out_count];
+ }
+
+ if (mChannelCount == 1) {
+ // buffer is empty, fetch a new one
+ while (index < inFrameCount) {
+ if (!mBuffer.frameCount) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer);
+ frameIndex = 0;
+ }
+
+ if (mBuffer.raw == NULL) {
+ while (index < inFrameCount) {
+ mTmpBuf[index++] = 0;
+ }
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ goto resample_exit;
+ }
+
+ mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+
+ if (frameIndex >= mBuffer.frameCount) {
+ provider->releaseBuffer(&mBuffer);
+ }
+ }
+
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ } else {
+ pBuf = &mTmpBuf[inFrameCount];
+ // buffer is empty, fetch a new one
+ while (index < inFrameCount) {
+ if (!mBuffer.frameCount) {
+ mBuffer.frameCount = inFrameCount;
+ provider->getNextBuffer(&mBuffer);
+ frameIndex = 0;
+ }
+ if (mBuffer.raw == NULL) {
+ while (index < inFrameCount) {
+ mTmpBuf[index] = 0;
+ pBuf[index++] = 0;
+ }
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ goto resample_exit;
+ }
+
+ mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ if (frameIndex >= mBuffer.frameCount * 2) {
+ provider->releaseBuffer(&mBuffer);
+ }
+ }
+
+ QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount);
+ }
+
+resample_exit:
+ for (int i = 0; i < out_count; i += 2) {
+ fout[i] += float_from_q4_27(mResamplerOutBuf[i] * vl);
+ fout[i+1] += float_from_q4_27(mResamplerOutBuf[i+1] * vr);
+ }
+
+ mFrameIndex = frameIndex;
+ return index;
+}
+
+void AudioResamplerQTI::setSampleRate(int32_t inSampleRate)
+{
+ if (mInSampleRate != inSampleRate) {
+ mInSampleRate = inSampleRate;
+ init();
+ }
+}
+
+void AudioResamplerQTI::init()
+{
+ QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate);
+}
+
+size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount)
+{
+ size_t size = (size_t)QCT_Resampler::GetNumInSamp(mState, outFrameCount);
+ return size;
+}
+
+void AudioResamplerQTI::reset()
+{
+ AudioResampler::reset();
+}
+
+}; // namespace android
diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h
new file mode 100644
index 0000000..0b30a9f
--- /dev/null
+++ b/services/audioflinger/AudioResamplerQTI.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All rights reserved.
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResamplerQTI : public AudioResampler {
+public:
+ AudioResamplerQTI(int format, int inChannelCount, int32_t sampleRate);
+ ~AudioResamplerQTI();
+ size_t resample(int32_t* out, size_t outFrameCount,
+ AudioBufferProvider* provider);
+ void setSampleRate(int32_t inSampleRate);
+ size_t getNumInSample(size_t outFrameCount);
+
+ int16_t *mState;
+ int16_t *mTmpBuf;
+ int32_t *mResamplerOutBuf;
+ size_t mFrameIndex;
+ size_t stateSize;
+ size_t mOutFrameCount;
+
+ static const int kNumTmpBufSize = 1024;
+
+ void init();
+ void reset();
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index a8be206..434a514 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -24,6 +24,7 @@
#include <media/EffectsFactoryApi.h>
#include <utils/Log.h>
+#include <media/stagefright/foundation/ADebug.h>
#include "Configuration.h"
#include "BufferProviders.h"
@@ -205,6 +206,7 @@
const int downmixParamSize =
sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
+ CHECK(param != NULL);
param->psize = sizeof(downmix_params_t);
const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
memcpy(param->data, &downmixParam, param->psize);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 949c91d..2249c6e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
@@ -318,6 +337,7 @@
status_t AudioFlinger::EffectModule::configure()
{
status_t status;
+ status_t cmdStatus = 0;
sp<ThreadBase> thread;
uint32_t size;
audio_channel_mask_t channelMask;
@@ -383,7 +403,6 @@
ALOGV("configure() %p thread %p buffer %p framecount %d",
this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
- status_t cmdStatus;
size = sizeof(int);
status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_SET_CONFIG,
@@ -434,7 +453,7 @@
if (mEffectInterface == NULL) {
return NO_INIT;
}
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status_t status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_INIT,
@@ -476,7 +495,7 @@
if (mStatus != NO_ERROR) {
return mStatus;
}
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status_t status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_ENABLE,
@@ -677,7 +696,7 @@
if (isProcessEnabled() &&
((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
(mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t volume[2];
uint32_t *pVolume = NULL;
uint32_t size = sizeof(volume);
@@ -712,7 +731,7 @@
}
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE :
EFFECT_CMD_SET_INPUT_DEVICE;
@@ -734,7 +753,7 @@
}
status_t status = NO_ERROR;
if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
- status_t cmdStatus;
+ status_t cmdStatus = 0;
uint32_t size = sizeof(status_t);
status = (*mEffectInterface)->command(mEffectInterface,
EFFECT_CMD_SET_AUDIO_MODE,
@@ -770,6 +789,9 @@
void AudioFlinger::EffectModule::setSuspended(bool suspended)
{
+#ifdef DOLBY_ENABLE
+ EffectDapController::instance()->effectSuspended(this, suspended);
+#endif // DOLBY_END
Mutex::Autolock _l(mLock);
mSuspended = suspended;
}
@@ -1113,7 +1135,8 @@
mEnabled = false;
} else {
if (thread != 0) {
- if (thread->type() == ThreadBase::OFFLOAD) {
+ if ((thread->type() == ThreadBase::OFFLOAD) ||
+ (thread->type() == ThreadBase::DIRECT && thread->mIsDirectPcm)) {
PlaybackThread *t = (PlaybackThread *)thread.get();
Mutex::Autolock _l(t->mLock);
t->broadcast_l();
@@ -1583,8 +1606,12 @@
ALOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this,
idx_insert);
}
+#ifdef DOLBY_ENABLE
+ return effect->configure();
+#else // DOLBY_END
effect->configure();
return NO_ERROR;
+#endif // LINE_ADDED_BY_DOLBY
}
// removeEffect_l() must be called with PlaybackThread::mLock held
@@ -1614,6 +1641,11 @@
mEffects.removeAt(i);
ALOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(),
this, i);
+#ifdef DOLBY_ENABLE
+ if (effect->suspended() && EffectDapController::instance()->isDapEffect(effect)) {
+ effect->setSuspended(false);
+ }
+#endif // DOLBY_END
break;
}
}
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f586291..3406260 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+**
+** This file was modified by Dolby Laboratories, Inc. The portions of the
+** code that are surrounded by "DOLBY..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2011-2015 Dolby Laboratories, Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+**
*/
@@ -544,6 +563,7 @@
mSystemReady(systemReady)
{
memset(&mPatch, 0, sizeof(struct audio_patch));
+ mIsDirectPcm = false;
}
AudioFlinger::ThreadBase::~ThreadBase()
@@ -1154,7 +1174,8 @@
// Reject any effect on Direct output threads for now, since the format of
// mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo).
- if (mType == DIRECT) {
+ // Exception: allow effects for Direct PCM
+ if (mType == DIRECT && !mIsDirectPcm) {
ALOGW("createEffect_l() Cannot add effect %s on Direct output type thread %s",
desc->name, mThreadName);
lStatus = BAD_VALUE;
@@ -1171,12 +1192,17 @@
}
// Allow global effects only on offloaded and mixer threads
+ // Exception: allow effects for Direct PCM
if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
switch (mType) {
case MIXER:
case OFFLOAD:
break;
case DIRECT:
+ if (mIsDirectPcm) {
+ // Allow effects when direct PCM enabled on Direct output
+ break;
+ }
case DUPLICATING:
case RECORD:
default:
@@ -1229,7 +1255,13 @@
if (lStatus != NO_ERROR) {
goto Exit;
}
- effect->setOffloaded(mType == OFFLOAD, mId);
+
+ bool setVal = false;
+ if (mType == OFFLOAD || (mType == DIRECT && mIsDirectPcm)) {
+ setVal = true;
+ }
+
+ effect->setOffloaded(setVal, mId);
lStatus = chain->addEffect_l(effect);
if (lStatus != NO_ERROR) {
@@ -1241,6 +1273,9 @@
effect->setDevice(mInDevice);
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
+#ifdef DOLBY_ENABLE
+ EffectDapController::instance()->effectCreated(effect, this);
+#endif // DOLBY_END
}
// create effect handle and connect it to effect module
handle = new EffectHandle(effect, client, effectClient, priority);
@@ -1313,7 +1348,13 @@
return BAD_VALUE;
}
- effect->setOffloaded(mType == OFFLOAD, mId);
+ bool setval = false;
+
+ if ((mType == OFFLOAD) || (mType == DIRECT && mIsDirectPcm)) {
+ setval = true;
+ }
+
+ effect->setOffloaded(setval, mId);
status_t status = chain->addEffect_l(effect);
if (status != NO_ERROR) {
@@ -1327,6 +1368,9 @@
effect->setDevice(mInDevice);
effect->setMode(mAudioFlinger->getMode());
effect->setAudioSource(mAudioSource);
+#ifdef DOLBY_ENABLE
+ EffectDapController::instance()->updateOffload(this);
+#endif // DOLBY_END
return NO_ERROR;
}
@@ -2443,6 +2487,9 @@
bytesWritten = framesWritten;
}
mLatchDValid = false;
+#ifdef DOLBY_ENABLE
+ EffectDapController::instance()->dumpBuffer((char *)mSinkBuffer + offset, count);
+#endif // DOLBY_END
status_t status = mNormalSink->getTimestamp(mLatchD.mTimestamp);
if (status == NO_ERROR) {
size_t totalFramesWritten = mNormalSink->framesWritten();
@@ -2506,6 +2553,10 @@
track->invalidate();
}
}
+#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
+ // When a thread is closed set associated volume to 0
+ EffectDapController::instance()->updatePregain(mType, mOutput->flags, 0);
+#endif // DOLBY_END
}
/*
@@ -2840,6 +2891,13 @@
}
// mMixerStatusIgnoringFastTracks is also updated internally
mMixerStatus = prepareTracks_l(&tracksToRemove);
+#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
+ // If there are no active tracks, then reset volume to zero for this thread.
+ if (mMixerStatus == MIXER_IDLE) {
+ ALOGV("EffectDapController: Reset volumes to zeros for threadType = %d flags = %d", mType, mOutput->flags);
+ EffectDapController::instance()->updatePregain(mType, mOutput->flags, 0);
+ }
+#endif // DOLBY_END
// compare with previously applied list
if (lastGeneration != mActiveTracksGeneration) {
@@ -3662,6 +3720,10 @@
float masterVolume = mMasterVolume;
bool masterMute = mMasterMute;
+#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
+ // The maximum volume of left channel and right channel for pregain calculation.
+ uint32_t max_vol = 0;
+#endif // DOLBY_END
if (masterMute) {
masterVolume = 0;
@@ -3999,6 +4061,12 @@
}
track->mHasVolumeController = false;
}
+#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
+ // Select the maximum volume by scanning all the active audio tracks but not the output one.
+ if (!track->isOutputTrack()) {
+ max_vol = max(max_vol, max(vl, vr));
+ }
+#endif // DOLBY_END
// XXX: these things DON'T need to be done each time
mAudioMixer->setBufferProvider(name, track);
@@ -4116,6 +4184,11 @@
if (track->isStopped()) {
track->reset();
}
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+ // Since this track is being removed from active tracks, check if we
+ // should re-enable content processing in DAP.
+ EffectDapController::instance()->trackStateChanged(track->mId, track->mState);
+#endif // DOLBY_END
tracksToRemove->add(track);
}
} else {
@@ -4226,6 +4299,18 @@
if (fastTracks > 0) {
mixerStatus = MIXER_TRACKS_READY;
}
+#ifdef DOLBY_ENABLE
+ // DOLBY_DAP_BYPASS_SOUND_TYPES
+ EffectDapController::instance()->checkForBypass(mActiveTracks, mOutput->flags);
+ // DOLBY_DAP_PREGAIN
+ // Skip the DS pregain setting if there're no active tracks, or all the active tracks are pausing ones,
+ // so that the last pregain will be adopted and zero volume level will not be sent in the 2 cases above.
+ if (mMixerStatusIgnoringFastTracks == MIXER_TRACKS_READY) {
+ EffectDapController::instance()->updatePregain(mType, mOutput->flags, max_vol);
+ }
+ // DOLBY_AUDIO_DUMP
+ EffectDapController::instance()->checkDumpEnable();
+#endif // DOLBY_END
return mixerStatus;
}
@@ -4493,6 +4578,10 @@
if (mOutput->stream->set_volume) {
mOutput->stream->set_volume(mOutput->stream, left, right);
}
+#ifdef DOLBY_ENABLE // DOLBY_DAP_PREGAIN
+ // Update the volume set for the current thread
+ EffectDapController::instance()->updatePregain(mType, mOutput->flags, max(vl, vr));
+#endif // DOLBY_END
}
}
}
@@ -5295,6 +5384,8 @@
} else {
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
+ } else if (mEffectBufferValid) {
+ memset(mEffectBuffer, 0, mEffectBufferSize);
} else {
memset(mSinkBuffer, 0, mSinkBufferSize);
}
@@ -5316,7 +5407,11 @@
} else if (mBytesWritten != 0) {
if (mMixerStatus == MIXER_TRACKS_ENABLED) {
writeFrames = mNormalFrameCount;
- memset(mSinkBuffer, 0, mSinkBufferSize);
+ if (mMixerBufferValid) {
+ memset(mMixerBuffer, 0, mMixerBufferSize);
+ } else {
+ memset(mSinkBuffer, 0, mSinkBufferSize);
+ }
} else {
// flush remaining overflow buffers in output tracks
writeFrames = 0;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 46ac300..9e32ea1 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -457,6 +457,7 @@
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
+ bool mIsDirectPcm; // flag to indicate unique Direct thread
};
// --- PlaybackThread ---
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b3fac0b..a95801a 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -13,6 +13,25 @@
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
*/
@@ -24,6 +43,7 @@
#include <math.h>
#include <sys/syscall.h>
#include <utils/Log.h>
+#include <media/stagefright/foundation/ADebug.h>
#include <private/media/AudioTrackShared.h>
@@ -37,6 +57,10 @@
#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>
#include <audio_utils/minifloat.h>
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+#include <media/AudioParameter.h>
+#include "ds_config.h"
+#endif // DOLBY_END
// ----------------------------------------------------------------------------
@@ -459,6 +483,9 @@
if (mSharedBuffer != 0) {
mSharedBuffer.clear();
}
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+ EffectDapController::instance()->trackDestroyed(mId);
+#endif // DOLBY_END
}
status_t AudioFlinger::PlaybackThread::Track::initCheck() const
@@ -706,6 +733,14 @@
mState = state;
}
}
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+ if (mState != state) {
+ // This call will disable content processing in global DAP if this track
+ // is carrying processed audio. The content processing will be re-enabled
+ // when this track has been exhausted by MixerThread::prepareTracks_l()
+ EffectDapController::instance()->trackStateChanged(mId, mState);
+ }
+#endif // DOLBY_END
// track was already in the active list, not a problem
if (status == ALREADY_EXISTS) {
status = NO_ERROR;
@@ -870,6 +905,22 @@
status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
{
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+ AudioParameter ap(keyValuePairs);
+ int value = 0;
+ if (ap.getInt(String8(DOLBY_PARAM_PROCESSED_AUDIO), value) == NO_ERROR) {
+ if (value) {
+ // Bypass content processing if processed audio is flowing through this track.
+ ALOGI("%s(): Marking track %d as containing processed audio", __FUNCTION__, mId);
+ EffectDapController::instance()->trackContainsProcessedAudio(mId, mState);
+ } else {
+ // Remove the track if it is no longer carrying processed audio.
+ ALOGI("%s(): Clearing track %d processed audio mark", __FUNCTION__, mId);
+ EffectDapController::instance()->trackDestroyed(mId);
+ }
+ return NO_ERROR;
+ }
+#endif // DOLBY_END
sp<ThreadBase> thread = mThread.promote();
if (thread == 0) {
ALOGE("thread is dead");
@@ -931,6 +982,14 @@
status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
{
+#ifdef DOLBY_ENABLE // DOLBY_UDC_VIRTUALIZE_AUDIO
+ // The track contains processed audio if EffectId is DOLBY_PROCESSED_AUDIO_EFFECT_ID
+ if (EffectId == DOLBY_PROCESSED_AUDIO_EFFECT_ID) {
+ ALOGI("%s(): Marking track %d as containing processed audio", __FUNCTION__, mId);
+ EffectDapController::instance()->trackContainsProcessedAudio(mId, mState);
+ return NO_ERROR;
+ }
+#endif // DOLBY_END
status_t status = DEAD_OBJECT;
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
@@ -1774,6 +1833,7 @@
if (mBufferQueue.size() < kMaxOverFlowBuffers) {
pInBuffer = new Buffer;
pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
+ CHECK(pInBuffer->mBuffer != NULL);
pInBuffer->frameCount = inBuffer.frameCount;
pInBuffer->raw = pInBuffer->mBuffer;
memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 8728ff3..8c6a53c 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -31,6 +31,27 @@
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH)/include
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true)
+LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
+endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
+LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
+endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_WMA_OFFLOAD)),true)
+LOCAL_CFLAGS += -DWMA_OFFLOAD_ENABLED
+endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_ALAC_OFFLOAD)),true)
+LOCAL_CFLAGS += -DALAC_OFFLOAD_ENABLED
+endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_APE_OFFLOAD)),true)
+LOCAL_CFLAGS += -DAPE_OFFLOAD_ENABLED
+endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AAC_ADTS_OFFLOAD)),true)
+LOCAL_CFLAGS += -DAAC_ADTS_OFFLOAD_ENABLED
+endif
+endif
+
LOCAL_MODULE := libaudiopolicycomponents
include $(BUILD_STATIC_LIBRARY)
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 50f622d..e1c2999 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -72,6 +72,7 @@
sp<AudioPort> mPort;
audio_devices_t mDevice; // current device this output is routed to
audio_patch_handle_t mPatchHandle;
+ audio_io_handle_t mIoHandle; // output handle
uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
nsecs_t mStopTime[AUDIO_STREAM_CNT];
float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
@@ -116,7 +117,6 @@
virtual void toAudioPort(struct audio_port *port) const;
const sp<IOProfile> mProfile; // I/O profile this output derives from
- audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
audio_output_flags_t mFlags; //
AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index 78d2cdf..3cb61db 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -74,6 +74,9 @@
STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP),
+#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
+ STRING_TO_ENUM(AUDIO_DEVICE_OUT_PROXY),
+#endif
STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -153,6 +156,7 @@
const StringToEnum sOutputFlagNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
@@ -162,6 +166,7 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
};
const StringToEnum sInputFlagNameToEnumTable[] = {
@@ -198,6 +203,33 @@
STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
STRING_TO_ENUM(AUDIO_FORMAT_DTS),
STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
+#ifdef FLAC_OFFLOAD_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
+#endif
+#ifdef WMA_OFFLOAD_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA),
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
+#endif
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
+#ifdef ALAC_OFFLOAD_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
+#endif
+#ifdef APE_OFFLOAD_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_APE),
+#endif
+#ifdef AAC_ADTS_OFFLOAD_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LD),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD),
+#endif
};
const StringToEnum sOutChannelsNameToEnumTable[] = {
@@ -206,12 +238,17 @@
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
+ STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
};
const StringToEnum sInChannelsNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_5POINT1),
};
const StringToEnum sIndexChannelsNameToEnumTable[] = {
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index c9783a1..396541b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -21,6 +21,7 @@
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
+#include <utils/Thread.h>
namespace android {
@@ -66,6 +67,8 @@
* Maximum memory allocated to audio effects in KB
*/
static const uint32_t MAX_EFFECTS_MEMORY = 512;
+
+ Mutex mLock;
};
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index a278375..5ddeaed 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -33,7 +33,7 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
- : mPort(port), mDevice(AUDIO_DEVICE_NONE),
+ : mPort(port), mDevice(AUDIO_DEVICE_NONE), mIoHandle(0),
mPatchHandle(0), mClientInterface(clientInterface), mId(0)
{
// clear usage count for all stream types
@@ -223,7 +223,7 @@
SwAudioOutputDescriptor::SwAudioOutputDescriptor(
const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface)
: AudioOutputDescriptor(profile, clientInterface),
- mProfile(profile), mIoHandle(0), mLatency(0),
+ mProfile(profile), mLatency(0),
mFlags((audio_output_flags_t)0), mPolicyMix(NULL),
mOutput1(0), mOutput2(0), mDirectOpenCount(0), mGlobalRefCount(0)
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 33d838d..6a0d079 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -56,6 +56,7 @@
int session,
int id)
{
+ Mutex::Autolock _l(mLock);
if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
desc->name, desc->memoryUsage);
@@ -80,6 +81,7 @@
status_t EffectDescriptorCollection::unregisterEffect(int id)
{
+ Mutex::Autolock _l(mLock);
ssize_t index = indexOfKey(id);
if (index < 0) {
ALOGW("unregisterEffect() unknown effect ID %d", id);
@@ -106,6 +108,7 @@
status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
{
+ Mutex::Autolock _l(mLock);
ssize_t index = indexOfKey(id);
if (index < 0) {
ALOGW("unregisterEffect() unknown effect ID %d", id);
@@ -148,6 +151,7 @@
bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
{
+ Mutex::Autolock _l(mLock);
for (size_t i = 0; i < size(); i++) {
sp<EffectDescriptor> effectDesc = valueAt(i);
if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
@@ -172,6 +176,7 @@
status_t EffectDescriptorCollection::dump(int fd)
{
+ Mutex::Autolock _l(mLock);
const size_t SIZE = 256;
char buffer[SIZE];
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 8d43b89..de84e96 100755
--- a/services/audiopolicy/enginedefault/Android.mk
+++ b/services/audiopolicy/enginedefault/Android.mk
@@ -31,6 +31,11 @@
$(call include-path-for, bionic) \
$(TOPDIR)frameworks/av/services/audiopolicy/common/include
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true)
+LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED
+endif
+endif
LOCAL_MODULE := libaudiopolicyenginedefault
LOCAL_MODULE_TAGS := optional
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 0686414..8b4a085 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -408,9 +408,10 @@
if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
if (device) break;
- device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
- if (device) break;
}
+ // Allow voice call on USB ANLG DOCK headset
+ device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE;
if (device) break;
device = mApmObserver->getDefaultOutputDevice()->type();
@@ -450,6 +451,13 @@
}
break;
}
+
+ if (isInCall() && (device == AUDIO_DEVICE_NONE)) {
+ // when in call, get the device for Phone strategy
+ device = getDeviceForStrategy(STRATEGY_PHONE);
+ break;
+ }
+
break;
case STRATEGY_SONIFICATION:
@@ -498,6 +506,13 @@
case STRATEGY_REROUTING:
case STRATEGY_MEDIA: {
uint32_t device2 = AUDIO_DEVICE_NONE;
+
+ if (isInCall() && (device == AUDIO_DEVICE_NONE)) {
+ // when in call, get the device for Phone strategy
+ device = getDeviceForStrategy(STRATEGY_PHONE);
+ break;
+ }
+
if (strategy != STRATEGY_SONIFICATION) {
// no sonification on remote submix (e.g. WFD)
if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) {
@@ -541,14 +556,23 @@
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
}
- if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
+ if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE)
+ && (device2 == AUDIO_DEVICE_NONE)) {
// no sonification on aux digital (e.g. HDMI)
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
}
if ((device2 == AUDIO_DEVICE_NONE) &&
- (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
+ (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)
+ && (strategy != STRATEGY_SONIFICATION)) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
}
+#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED
+ if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE)
+ && (device2 == AUDIO_DEVICE_NONE)) {
+ // no sonification on WFD sink
+ device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_PROXY;
+ }
+#endif
if (device2 == AUDIO_DEVICE_NONE) {
device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
}
@@ -671,6 +695,8 @@
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
device = AUDIO_DEVICE_IN_USB_DEVICE;
+ } else if (availableDeviceTypes & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET) {
+ device = AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) {
device = AUDIO_DEVICE_IN_BUILTIN_MIC;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8419ed5..ba468e2 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -12,6 +12,24 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#define LOG_TAG "APM::AudioPolicyManager"
@@ -40,6 +58,9 @@
#include "audio_policy_conf.h"
#include <ConfigParsingUtils.h>
#include <policy.h>
+#ifdef DOLBY_ENABLE
+#include "DolbyAudioPolicy_impl.h"
+#endif // DOLBY_END
namespace android {
@@ -171,6 +192,11 @@
}
updateDevicesAndOutputs();
+#ifdef DOLBY_ENABLE // DOLBY_UDC
+ // Before closing the opened outputs, update endpoint property with device capabilities
+ audio_devices_t audioOutputDevice = getDeviceForStrategy(getStrategy(AUDIO_STREAM_MUSIC), true);
+ mDolbyAudioPolicy.setEndpointSystemProperty(audioOutputDevice, mHwModules);
+#endif // DOLBY_END
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, false /*fromCache*/);
updateCallRouting(newDevice);
@@ -351,6 +377,14 @@
AUDIO_OUTPUT_FLAG_NONE,
AUDIO_FORMAT_INVALID);
if (output != AUDIO_IO_HANDLE_NONE) {
+ // close active input (if any) before opening new input
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
+ if (activeInput != 0) {
+ ALOGV("updateCallRouting() close active input before opening new input");
+ sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
+ stopInput(activeInput, activeDesc->mSessions.itemAt(0));
+ releaseInput(activeInput, activeDesc->mSessions.itemAt(0));
+ }
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
ALOG_ASSERT(!outputDesc->isDuplicated(),
"updateCallRouting() RX device output is duplicated");
@@ -588,7 +622,8 @@
// only retain flags that will drive the direct output profile selection
// if explicitly requested
static const uint32_t kRelevantFlags =
- (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
+ (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+ AUDIO_OUTPUT_FLAG_VOIP_RX);
flags =
(audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
@@ -914,7 +949,23 @@
addOutput(output, outputDesc);
audio_io_handle_t dstOutput = getOutputForEffect();
if (dstOutput == output) {
+#ifdef DOLBY_ENABLE
+ status_t status = mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
+ if (status == NO_ERROR) {
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ sp<EffectDescriptor> desc = mEffects.valueAt(i);
+ if (desc->mSession == AUDIO_SESSION_OUTPUT_MIX) {
+ // update the mIo member of EffectDescriptor for the global effect
+ ALOGV("%s updating mIo", __FUNCTION__);
+ desc->mIo = dstOutput;
+ }
+ }
+ } else {
+ ALOGW("%s moveEffects from %d to %d failed", __FUNCTION__, srcOutput, dstOutput);
+ }
+#else // DOLBY_END
mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, srcOutput, dstOutput);
+#endif // LINE_ADDED_BY_DOLBY
}
mPreviousOutputs = mOutputs;
ALOGV("getOutput() returns new direct output %d", output);
@@ -1051,6 +1102,26 @@
if (delayMs != 0) {
usleep(delayMs * 1000);
}
+#ifdef DOLBY_ENABLE
+ // DOLBY_UDC
+ // It is observed that in some use-cases where multiple outputs are present eg. bluetooth and headphone,
+ // the output for particular stream type is decided in this routine. Hence we must call
+ // getDeviceForStrategy in order to get the current active output for this stream type and update
+ // the dolby system property.
+ if (stream == AUDIO_STREAM_MUSIC)
+ {
+ audio_devices_t audioOutputDevice = getDeviceForStrategy(getStrategy(AUDIO_STREAM_MUSIC), true);
+ mDolbyAudioPolicy.setEndpointSystemProperty(audioOutputDevice, mHwModules);
+ }
+ // DOLBY_DAP_MOVE_EFFECT
+ // Note: The global effect can't be taken away from the deep-buffered output (source output) if there're still
+ // music playing on the deep-buffered output.
+ sp<SwAudioOutputDescriptor> srcOutputDesc = mOutputs.valueFor(mDolbyAudioPolicy.output());
+ if ((stream == AUDIO_STREAM_MUSIC) && mDolbyAudioPolicy.shouldMoveToOutput(output, outputDesc->mFlags) && srcOutputDesc != NULL &&
+ ((srcOutputDesc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) == 0 || srcOutputDesc->mRefCount[AUDIO_STREAM_MUSIC] == 0)) {
+ mDolbyAudioPolicy.movedToOutput(mpClientInterface, output);
+ }
+#endif //DOLBY_END
return status;
}
@@ -1272,8 +1343,25 @@
// output by default: move them back to the appropriate output.
audio_io_handle_t dstOutput = getOutputForEffect();
if (hasPrimaryOutput() && dstOutput != mPrimaryOutput->mIoHandle) {
+#ifdef DOLBY_ENABLE
+ status_t status = mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX,
+ mPrimaryOutput->mIoHandle, dstOutput);
+ if (status == NO_ERROR) {
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ sp<EffectDescriptor> desc = mEffects.valueAt(i);
+ if (desc->mSession == AUDIO_SESSION_OUTPUT_MIX) {
+ // update the mIo member of EffectDescriptor for the global effect
+ ALOGV("%s updating mIo", __FUNCTION__);
+ desc->mIo = dstOutput;
+ }
+ }
+ } else {
+ ALOGW("%s moveEffects from %d to %d failed", __FUNCTION__, mPrimaryOutput->mIoHandle, dstOutput);
+ }
+#else // DOLBY_END
mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX,
mPrimaryOutput->mIoHandle, dstOutput);
+#endif // LINE_ADDED_BY_DOLBY
}
mpClientInterface->onAudioPortListUpdate();
}
@@ -1336,6 +1424,12 @@
ALOGW("getInputForAttr() could not find device for source %d", inputSource);
return BAD_VALUE;
}
+ // block request to open input on USB during voice call
+ if((AUDIO_MODE_IN_CALL == mEngine->getPhoneState()) &&
+ (device == AUDIO_DEVICE_IN_USB_DEVICE)) {
+ ALOGV("getInputForAttr(): blocking the request to open input on USB device");
+ return BAD_VALUE;
+ }
if (policyMix != NULL) {
address = policyMix->mRegistrationId;
if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
@@ -1356,20 +1450,6 @@
} else {
*inputType = API_INPUT_LEGACY;
}
- // adapt channel selection to input source
- switch (inputSource) {
- case AUDIO_SOURCE_VOICE_UPLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
- break;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- case AUDIO_SOURCE_VOICE_CALL:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- default:
- break;
- }
if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
@@ -1773,6 +1853,7 @@
audio_io_handle_t outputOffloaded = 0;
audio_io_handle_t outputDeepBuffer = 0;
+ audio_io_handle_t outputDirectPcm = 0;
for (size_t i = 0; i < outputs.size(); i++) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]);
@@ -1780,6 +1861,9 @@
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
outputOffloaded = outputs[i];
}
+ if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) != 0) {
+ outputDirectPcm = outputs[i];
+ }
if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
outputDeepBuffer = outputs[i];
}
@@ -1790,6 +1874,9 @@
if (outputOffloaded != 0) {
return outputOffloaded;
}
+ if (outputDirectPcm != 0) {
+ return outputDirectPcm;
+ }
if (outputDeepBuffer != 0) {
return outputDeepBuffer;
}
@@ -1826,7 +1913,16 @@
return INVALID_OPERATION;
}
}
+#ifdef DOLBY_ENABLE
+ status_t status = mEffects.registerEffect(desc, io, strategy, session, id);
+ if (status == NO_ERROR) {
+ sp<EffectDescriptor> effectDesc = mEffects.valueFor(id);
+ mDolbyAudioPolicy.effectRegistered(effectDesc);
+ }
+ return status;
+#else // DOLBY_END
return mEffects.registerEffect(desc, io, strategy, session, id);
+#endif // LINE_ADDED_BY_DOLBY
}
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
@@ -3781,7 +3877,7 @@
{
audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);
audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/);
- SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs);
+ SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mOutputs);
SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
// also take into account external policy-related changes: add all outputs which are
@@ -3825,8 +3921,17 @@
if (moved.indexOf(effectDesc->mIo) < 0) {
ALOGV("checkOutputForStrategy() moving effect %d to output %d",
mEffects.keyAt(i), fxOutput);
+#ifdef DOLBY_ENABLE
+ status_t status = mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, effectDesc->mIo,
+ fxOutput);
+ if (status != NO_ERROR) {
+ ALOGW("%s moveEffects from %d to %d failed", __FUNCTION__, effectDesc->mIo, fxOutput);
+ continue;
+ }
+#else // DOLBY_END
mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, effectDesc->mIo,
fxOutput);
+#endif // LINE_ADDED_BY_DOLBY
moved.add(effectDesc->mIo);
}
effectDesc->mIo = fxOutput;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bbdf396..a4af97f 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -12,6 +12,24 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * This file was modified by Dolby Laboratories, Inc. The portions of the
+ * code that are surrounded by "DOLBY..." are copyrighted and
+ * licensed separately, as follows:
+ *
+ * (C) 2014-2015 Dolby Laboratories, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#pragma once
@@ -173,6 +191,10 @@
int id);
virtual status_t unregisterEffect(int id)
{
+#ifdef DOLBY_ENABLE
+ sp<EffectDescriptor> effectDesc = mEffects.valueFor(id);
+ mDolbyAudioPolicy.effectRemoved(effectDesc);
+#endif // DOLBY_END
return mEffects.unregisterEffect(id);
}
virtual status_t setEffectEnabled(int id, bool enabled)
@@ -350,7 +372,7 @@
// handle special cases for sonification strategy while in call: mute streams or replace by
// a special tone in the device used for communication
- void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
+ virtual void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
audio_mode_t getPhoneState();
@@ -397,7 +419,7 @@
// must be called every time a condition that affects the device choice for a given output is
// changed: connected device, phone state, force use, output start, output stop..
// see getDeviceForStrategy() for the use of fromCache parameter
- audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
+ virtual audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
bool fromCache);
// updates cache of device used by all strategies (mDeviceForStrategy[])
@@ -484,11 +506,11 @@
// if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force
// the re-evaluation of the output device.
- status_t startSource(sp<AudioOutputDescriptor> outputDesc,
+ virtual status_t startSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t *delayMs);
- status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
+ virtual status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate);
@@ -571,7 +593,7 @@
// Audio Policy Engine Interface.
AudioPolicyManagerInterface *mEngine;
-private:
+protected:
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
@@ -586,7 +608,7 @@
SortedVector<audio_io_handle_t>& outputs /*out*/);
uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
// internal method to return the output handle for the given device and format
- audio_io_handle_t getOutputForDevice(
+ virtual audio_io_handle_t getOutputForDevice(
audio_devices_t device,
audio_session_t session,
audio_stream_type_t stream,
@@ -610,10 +632,15 @@
AudioMix **policyMix = NULL);
// Called by setDeviceConnectionState().
- status_t setDeviceConnectionStateInt(audio_devices_t device,
+ virtual status_t setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name);
+#ifdef DOLBY_ENABLE
+protected:
+#include "DolbyAudioPolicy.h"
+ DolbyAudioPolicy mDolbyAudioPolicy;
+#endif // DOLBY_END
};
};
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 282ddeb..e71d7a5 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -442,6 +442,7 @@
size_t curSize = sizeof(effect_param_t);
size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
+ CHECK(fx_param != NULL);
param = config_find(root, PARAM_TAG);
value = config_find(root, VALUE_TAG);
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 3dec437..3845050 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -27,6 +27,8 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
+#include <media/stagefright/foundation/ADebug.h>
+
namespace android {
// ----------------------------------------------------------------------------
@@ -102,6 +104,7 @@
((origParam->psize + 3) & ~3) +
((origParam->vsize + 3) & ~3);
effect_param_t *dupParam = (effect_param_t *) malloc(origSize);
+ CHECK(dupParam != NULL);
memcpy(dupParam, origParam, origSize);
// This works because the param buffer allocation is also done by
// multiples of 4 bytes originally. In theory we should memcpy only
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ca365a5..a228798 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -463,6 +463,7 @@
if (mAudioPolicyManager == NULL) {
return AUDIO_DEVICE_NONE;
}
+ Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getDevicesForStream(stream);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index c77cc45..41dd40c 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -899,10 +899,12 @@
} else {
data2->mKeyValuePairs = param2.toString();
}
- command->mTime = command2->mTime;
- // force delayMs to non 0 so that code below does not request to wait for
- // command status as the command is now delayed
- delayMs = 1;
+ if (!data2->mKeyValuePairs.compare(data->mKeyValuePairs)) {
+ command->mTime = command2->mTime;
+ // force delayMs to non 0 so that code below does not request to wait for
+ // command status as the command is now delayed
+ delayMs = 1;
+ }
} break;
case SET_VOLUME: {
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index 280bb9d..fd23ef9 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -99,7 +99,8 @@
status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
if (!mFlashlightMapInitialized) {
- ALOGE("%s: findFlashUnits() must be called before this method.");
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
return NO_INIT;
}
@@ -200,7 +201,8 @@
bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
if (!mFlashlightMapInitialized) {
- ALOGE("%s: findFlashUnits() must be called before this method.");
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
return false;
}
@@ -219,7 +221,8 @@
Mutex::Autolock l(mLock);
if (!mFlashlightMapInitialized) {
- ALOGE("%s: findFlashUnits() must be called before this method.");
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
return NO_INIT;
}
@@ -256,7 +259,8 @@
Mutex::Autolock l(mLock);
if (!mFlashlightMapInitialized) {
- ALOGE("%s: findFlashUnits() must be called before this method.");
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
return NO_INIT;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2aaefe9..db6272b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2082,7 +2082,11 @@
void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
const CaptureResultExtras& resultExtras) {
- mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+ if (mRemoteCallback != NULL) {
+ mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0);
+ } else {
+ ALOGE("mRemoteCallback is NULL!!");
+ }
}
// NOTE: function is idempotent
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 38e35cd..9ff843a 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -56,6 +56,9 @@
mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mLegacyMode = legacyMode;
mPlayShutterSound = true;
+
+ mLongshotEnabled = false;
+ mBurstCnt = 0;
LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
}
@@ -553,6 +556,10 @@
CAMERA_MSG_COMPRESSED_IMAGE);
enableMsgType(picMsgType);
+ mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter");
+ if(mBurstCnt <= 0)
+ mBurstCnt = 1;
+ LOG1("mBurstCnt = %d", mBurstCnt);
return mHardware->takePicture();
}
@@ -655,6 +662,20 @@
} else if (cmd == CAMERA_CMD_PING) {
// If mHardware is 0, checkPidAndHardware will return error.
return OK;
+ } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) {
+ enableMsgType(CAMERA_MSG_STATS_DATA);
+ } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) {
+ disableMsgType(CAMERA_MSG_STATS_DATA);
+ } else if (cmd == CAMERA_CMD_METADATA_ON) {
+ enableMsgType(CAMERA_MSG_META_DATA);
+ } else if (cmd == CAMERA_CMD_METADATA_OFF) {
+ disableMsgType(CAMERA_MSG_META_DATA);
+ } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) {
+ mLongshotEnabled = true;
+ } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) {
+ mLongshotEnabled = false;
+ disableMsgType(CAMERA_MSG_SHUTTER);
+ disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
}
return mHardware->sendCommand(cmd, arg1, arg2);
@@ -797,7 +818,9 @@
c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
}
- disableMsgType(CAMERA_MSG_SHUTTER);
+ if ( !mLongshotEnabled ) {
+ disableMsgType(CAMERA_MSG_SHUTTER);
+ }
// Shutters only happen in response to takePicture, so mark device as
// idle now, until preview is restarted
@@ -882,7 +905,13 @@
// picture callback - compressed picture ready
void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
- disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+ if (mBurstCnt)
+ mBurstCnt--;
+
+ if (!mBurstCnt && !mLongshotEnabled) {
+ LOG1("handleCompressedPicture mBurstCnt = %d", mBurstCnt);
+ disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+ }
sp<ICameraClient> c = mRemoteCallback;
mLock.unlock();
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 95616b2..9d2d02f 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -162,6 +162,9 @@
// This function keeps trying to grab mLock, or give up if the message
// is found to be disabled. It returns true if mLock is grabbed.
bool lockIfMessageWanted(int32_t msgType);
+
+ bool mLongshotEnabled;
+ int mBurstCnt;
};
}