summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioTrack.h2
-rw-r--r--include/media/IOMX.h34
-rw-r--r--include/media/MediaProfiles.h79
-rw-r--r--include/media/stagefright/ACodec.h23
-rw-r--r--include/media/stagefright/MediaCodec.h2
-rw-r--r--include/media/stagefright/foundation/ADebug.h25
-rw-r--r--media/libmedia/IOMX.cpp53
-rw-r--r--media/libmedia/MediaProfiles.cpp126
-rw-r--r--media/libmediaplayerservice/Android.mk1
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp25
-rw-r--r--media/libstagefright/ACodec.cpp209
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/MediaCodec.cpp130
-rw-r--r--media/libstagefright/MediaCodecList.cpp18
-rw-r--r--media/libstagefright/MediaCodecListOverrides.cpp12
-rw-r--r--media/libstagefright/MediaCodecListOverrides.h3
-rw-r--r--media/libstagefright/OMXClient.cpp30
-rw-r--r--media/libstagefright/OMXCodec.cpp6
-rw-r--r--media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp10
-rw-r--r--media/libstagefright/include/OMX.h12
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h29
-rw-r--r--media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp26
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.cpp74
-rw-r--r--media/libstagefright/omx/GraphicBufferSource.h3
-rw-r--r--media/libstagefright/omx/OMX.cpp20
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp210
-rw-r--r--media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp24
-rw-r--r--media/libstagefright/omx/tests/OMXHarness.cpp2
-rw-r--r--media/libstagefright/tests/MediaCodecListOverrides_test.cpp6
-rw-r--r--media/utils/Android.mk39
-rw-r--r--media/utils/BatteryNotifier.cpp213
-rw-r--r--media/utils/README4
-rw-r--r--media/utils/include/mediautils/BatteryNotifier.h73
-rw-r--r--services/audioflinger/Effects.cpp10
-rw-r--r--services/audioflinger/Threads.cpp34
-rw-r--r--services/camera/libcameraservice/Android.mk1
-rw-r--r--services/camera/libcameraservice/CameraService.cpp96
-rw-r--r--services/camera/libcameraservice/CameraService.h26
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp62
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.h1
-rw-r--r--services/camera/libcameraservice/utils/ClientManager.h133
41 files changed, 1162 insertions, 725 deletions
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index d7b5f97..3efa74c 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -59,9 +59,11 @@ public:
// voluntary invalidation by mediaserver, or mediaserver crash.
EVENT_STREAM_END = 7, // Sent after all the buffers queued in AF and HW are played
// back (after stop is called)
+#if 0 // FIXME not yet implemented
EVENT_NEW_TIMESTAMP = 8, // Delivered periodically and when there's a significant change
// in the mapping from frame position to presentation time.
// See AudioTimestamp for the information included with event.
+#endif
};
/* Client should declare a Buffer and pass the address to obtainBuffer()
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index d33d142..26cc73e 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -25,6 +25,8 @@
#include <utils/List.h>
#include <utils/String8.h>
+#include <media/hardware/MetadataBufferType.h>
+
#include <OMX_Core.h>
#include <OMX_Video.h>
@@ -81,8 +83,10 @@ public:
virtual status_t getState(
node_id node, OMX_STATETYPE* state) = 0;
+ // This will set *type to previous metadata buffer type on OMX error (not on binder error), and
+ // new metadata buffer type on success.
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type = NULL) = 0;
virtual status_t prepareForAdaptivePlayback(
node_id node, OMX_U32 portIndex, OMX_BOOL enable,
@@ -98,9 +102,10 @@ public:
virtual status_t getGraphicBufferUsage(
node_id node, OMX_U32 port_index, OMX_U32* usage) = 0;
+ // Use |params| as an OMX buffer, but limit the size of the OMX buffer to |allottedSize|.
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) = 0;
+ buffer_id *buffer, OMX_U32 allottedSize) = 0;
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -110,17 +115,23 @@ public:
node_id node, OMX_U32 port_index,
const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) = 0;
+ // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
+ // well as on success.
virtual status_t createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer) = 0;
+ sp<IGraphicBufferProducer> *bufferProducer,
+ MetadataBufferType *type = NULL) = 0;
virtual status_t createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
+ // This will set *type to resulting metadata buffer type on OMX error (not on binder error) as
+ // well as on success.
virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer) = 0;
+ const sp<IGraphicBufferConsumer> &bufferConsumer,
+ MetadataBufferType *type) = 0;
virtual status_t signalEndOfInputStream(node_id node) = 0;
@@ -132,9 +143,11 @@ public:
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data) = 0;
+ // Allocate an OMX buffer of size |allotedSize|. Use |params| as the backup buffer, which
+ // may be larger.
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) = 0;
+ buffer_id *buffer, OMX_U32 allottedSize) = 0;
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer) = 0;
@@ -233,4 +246,15 @@ struct CodecProfileLevel {
} // namespace android
+inline static const char *asString(android::MetadataBufferType i, const char *def = "??") {
+ using namespace android;
+ switch (i) {
+ case kMetadataBufferTypeCameraSource: return "CameraSource";
+ case kMetadataBufferTypeGrallocSource: return "GrallocSource";
+ case kMetadataBufferTypeANWBuffer: return "ANWBuffer";
+ case kMetadataBufferTypeInvalid: return "Invalid";
+ default: return def;
+ }
+}
+
#endif // ANDROID_IOMX_H_
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index f061d22..e02918f 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -58,24 +58,6 @@ enum camcorder_quality {
CAMCORDER_QUALITY_HIGH_SPEED_LIST_END = 2005,
};
-/**
- * Set CIF as default maximum import and export resolution of video editor.
- * The maximum import and export resolutions are platform specific,
- * which should be defined in media_profiles.xml.
- * Set default maximum prefetch YUV frames to 6, which means video editor can
- * queue up to 6 YUV frames in the video encoder source.
- * This value is used to limit the amount of memory used by video editor
- * engine when the encoder consumes YUV frames at a lower speed
- * than video editor engine produces.
- */
-enum videoeditor_capability {
- VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH = 352,
- VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT = 288,
- VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH = 352,
- VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT = 288,
- VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES = 6
-};
-
enum video_decoder {
VIDEO_DECODER_WMV,
};
@@ -148,32 +130,6 @@ public:
int getVideoEncoderParamByName(const char *name, video_encoder codec) const;
/**
- * Returns the value for the given param name for the video editor cap
- * param or -1 if error.
- * Supported param name are:
- * videoeditor.input.width.max - max input video frame width
- * videoeditor.input.height.max - max input video frame height
- * videoeditor.output.width.max - max output video frame width
- * videoeditor.output.height.max - max output video frame height
- * maxPrefetchYUVFrames - max prefetch YUV frames in video editor engine. This value is used
- * to limit the memory consumption.
- */
- int getVideoEditorCapParamByName(const char *name) const;
-
- /**
- * Returns the value for the given param name for the video editor export codec format
- * param or -1 if error.
- * Supported param name are:
- * videoeditor.export.profile - export video profile
- * videoeditor.export.level - export video level
- * Supported param codec are:
- * 1 for h263
- * 2 for h264
- * 3 for mpeg4
- */
- int getVideoEditorExportParamByName(const char *name, int codec) const;
-
- /**
* Returns the audio encoders supported.
*/
Vector<audio_encoder> getAudioEncoders() const;
@@ -221,7 +177,7 @@ private:
MediaProfiles& operator=(const MediaProfiles&); // Don't call me
MediaProfiles(const MediaProfiles&); // Don't call me
- MediaProfiles() { mVideoEditorCap = NULL; } // Dummy default constructor
+ MediaProfiles() {} // Dummy default constructor
~MediaProfiles(); // Don't delete me
struct VideoCodec {
@@ -366,31 +322,6 @@ private:
int mCameraId;
Vector<int> mLevels;
};
- struct ExportVideoProfile {
- ExportVideoProfile(int codec, int profile, int level)
- :mCodec(codec),mProfile(profile),mLevel(level) {}
- ~ExportVideoProfile() {}
- int mCodec;
- int mProfile;
- int mLevel;
- };
- struct VideoEditorCap {
- VideoEditorCap(int inFrameWidth, int inFrameHeight,
- int outFrameWidth, int outFrameHeight, int frames)
- : mMaxInputFrameWidth(inFrameWidth),
- mMaxInputFrameHeight(inFrameHeight),
- mMaxOutputFrameWidth(outFrameWidth),
- mMaxOutputFrameHeight(outFrameHeight),
- mMaxPrefetchYUVFrames(frames) {}
-
- ~VideoEditorCap() {}
-
- int mMaxInputFrameWidth;
- int mMaxInputFrameHeight;
- int mMaxOutputFrameWidth;
- int mMaxOutputFrameHeight;
- int mMaxPrefetchYUVFrames;
- };
int getCamcorderProfileIndex(int cameraId, camcorder_quality quality) const;
void initRequiredProfileRefs(const Vector<int>& cameraIds);
@@ -403,7 +334,6 @@ private:
static void logAudioEncoderCap(const AudioEncoderCap& cap);
static void logVideoDecoderCap(const VideoDecoderCap& cap);
static void logAudioDecoderCap(const AudioDecoderCap& cap);
- static void logVideoEditorCap(const VideoEditorCap& cap);
// If the xml configuration file does exist, use the settings
// from the xml
@@ -415,9 +345,6 @@ private:
static VideoDecoderCap* createVideoDecoderCap(const char **atts);
static VideoEncoderCap* createVideoEncoderCap(const char **atts);
static AudioEncoderCap* createAudioEncoderCap(const char **atts);
- static VideoEditorCap* createVideoEditorCap(
- const char **atts, MediaProfiles *profiles);
- static ExportVideoProfile* createExportVideoProfile(const char **atts);
static CamcorderProfile* createCamcorderProfile(
int cameraId, const char **atts, Vector<int>& cameraIds);
@@ -461,8 +388,6 @@ private:
static void createDefaultEncoderOutputFileFormats(MediaProfiles *profiles);
static void createDefaultImageEncodingQualityLevels(MediaProfiles *profiles);
static void createDefaultImageDecodingMaxMemory(MediaProfiles *profiles);
- static void createDefaultVideoEditorCap(MediaProfiles *profiles);
- static void createDefaultExportVideoProfiles(MediaProfiles *profiles);
static VideoEncoderCap* createDefaultH263VideoEncoderCap();
static VideoEncoderCap* createDefaultM4vVideoEncoderCap();
@@ -520,8 +445,6 @@ private:
RequiredProfiles *mRequiredProfileRefs;
Vector<int> mCameraIds;
- VideoEditorCap* mVideoEditorCap;
- Vector<ExportVideoProfile*> mVideoEditorExportProfiles;
};
}; // namespace android
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 4ed97e5..bbecc80 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <android/native_window.h>
+#include <media/hardware/MetadataBufferType.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/AHierarchicalStateMachine.h>
#include <media/stagefright/CodecBase.h>
@@ -123,7 +124,7 @@ private:
kWhatStart = 'star',
kWhatRequestIDRFrame = 'ridr',
kWhatSetParameters = 'setP',
- kWhatSubmitOutputMetaDataBufferIfEOS = 'subm',
+ kWhatSubmitOutputMetadataBufferIfEOS = 'subm',
kWhatOMXDied = 'OMXd',
kWhatReleaseCodecInstance = 'relC',
};
@@ -207,7 +208,6 @@ private:
bool mSentFormat;
bool mIsVideo;
bool mIsEncoder;
- bool mUseMetadataOnEncoderOutput;
bool mShutdownInProgress;
bool mExplicitShutdown;
@@ -222,9 +222,10 @@ private:
bool mChannelMaskPresent;
int32_t mChannelMask;
unsigned mDequeueCounter;
- bool mStoreMetaDataInOutputBuffers;
+ MetadataBufferType mInputMetadataType;
+ MetadataBufferType mOutputMetadataType;
bool mLegacyAdaptiveExperiment;
- int32_t mMetaDataBuffersToSubmit;
+ int32_t mMetadataBuffersToSubmit;
size_t mNumUndequeuedBuffers;
int64_t mRepeatFrameDelayUs;
@@ -249,14 +250,22 @@ private:
status_t configureOutputBuffersFromNativeWindow(
OMX_U32 *nBufferCount, OMX_U32 *nBufferSize,
OMX_U32 *nMinUndequeuedBuffers);
- status_t allocateOutputMetaDataBuffers();
- status_t submitOutputMetaDataBuffer();
- void signalSubmitOutputMetaDataBufferIfEOS_workaround();
+ status_t allocateOutputMetadataBuffers();
+ status_t submitOutputMetadataBuffer();
+ void signalSubmitOutputMetadataBufferIfEOS_workaround();
status_t allocateOutputBuffersFromNativeWindow();
status_t cancelBufferToNativeWindow(BufferInfo *info);
status_t freeOutputBuffersNotOwnedByComponent();
BufferInfo *dequeueBufferFromNativeWindow();
+ inline bool storingMetadataInDecodedBuffers() {
+ return mOutputMetadataType >= 0 && !mIsEncoder;
+ }
+
+ inline bool usingMetadataOnEncoderOutput() {
+ return mOutputMetadataType >= 0 && mIsEncoder;
+ }
+
BufferInfo *findBufferByID(
uint32_t portIndex, IOMX::buffer_id bufferID,
ssize_t *index = NULL);
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 6e14fc5..d62b35d 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -60,8 +60,6 @@ struct MediaCodec : public AHandler {
CB_RESOURCE_RECLAIMED = 5,
};
- struct BatteryNotifier;
-
static sp<MediaCodec> CreateByType(
const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err = NULL);
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index a97dd9b..24df85a 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -24,6 +24,31 @@
#include <media/stagefright/foundation/AString.h>
#include <utils/Log.h>
+inline static const char *asString(android::status_t i, const char *def = "??") {
+ using namespace android;
+ switch (i) {
+ case NO_ERROR: return "NO_ERROR";
+ case UNKNOWN_ERROR: return "UNKNOWN_ERROR";
+ case NO_MEMORY: return "NO_MEMORY";
+ case INVALID_OPERATION: return "INVALID_OPERATION";
+ case BAD_VALUE: return "BAD_VALUE";
+ case BAD_TYPE: return "BAD_TYPE";
+ case NAME_NOT_FOUND: return "NAME_NOT_FOUND";
+ case PERMISSION_DENIED: return "PERMISSION_DENIED";
+ case NO_INIT: return "NO_INIT";
+ case ALREADY_EXISTS: return "ALREADY_EXISTS";
+ case DEAD_OBJECT: return "DEAD_OBJECT";
+ case FAILED_TRANSACTION: return "FAILED_TRANSACTION";
+ case BAD_INDEX: return "BAD_INDEX";
+ case NOT_ENOUGH_DATA: return "NOT_ENOUGH_DATA";
+ case WOULD_BLOCK: return "WOULD_BLOCK";
+ case TIMED_OUT: return "TIMED_OUT";
+ case UNKNOWN_TRANSACTION: return "UNKNOWN_TRANSACTION";
+ case FDS_NOT_ALLOWED: return "FDS_NOT_ALLOWED";
+ default: return def;
+ }
+}
+
namespace android {
#define LITERAL_TO_STRING_INTERNAL(x) #x
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index c14debf..cac2f7f 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -245,12 +245,13 @@ public:
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(params));
+ data.writeInt32(allottedSize);
remote()->transact(USE_BUFFER, data, &reply);
status_t err = reply.readInt32();
@@ -305,7 +306,7 @@ public:
virtual status_t createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer) {
+ sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
Parcel data, reply;
status_t err;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -317,6 +318,12 @@ public:
return err;
}
+ // read type even if createInputSurface failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
err = reply.readInt32();
if (err != OK) {
return err;
@@ -355,7 +362,7 @@ public:
virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer) {
+ const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
status_t err;
@@ -369,6 +376,13 @@ public:
ALOGW("binder transaction failed: %d", err);
return err;
}
+
+ // read type even if setInputSurface failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
return reply.readInt32();
}
@@ -387,7 +401,7 @@ public:
}
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
@@ -395,8 +409,13 @@ public:
data.writeInt32((uint32_t)enable);
remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
- status_t err = reply.readInt32();
- return err;
+ // read type even storeMetaDataInBuffers failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
+ return reply.readInt32();
}
virtual status_t prepareForAdaptivePlayback(
@@ -459,12 +478,13 @@ public:
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(params));
+ data.writeInt32(allottedSize);
remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
status_t err = reply.readInt32();
@@ -757,9 +777,10 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
+ OMX_U32 allottedSize = data.readInt32();
buffer_id buffer;
- status_t err = useBuffer(node, port_index, params, &buffer);
+ status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
reply->writeInt32(err);
if (err == OK) {
@@ -815,9 +836,10 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IGraphicBufferProducer> bufferProducer;
- status_t err = createInputSurface(node, port_index,
- &bufferProducer);
+ MetadataBufferType type;
+ status_t err = createInputSurface(node, port_index, &bufferProducer, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
if (err == OK) {
@@ -856,8 +878,10 @@ status_t BnOMX::onTransact(
sp<IGraphicBufferConsumer> bufferConsumer =
interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
- status_t err = setInputSurface(node, port_index, bufferConsumer);
+ MetadataBufferType type;
+ status_t err = setInputSurface(node, port_index, bufferConsumer, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
return NO_ERROR;
}
@@ -882,7 +906,9 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
- status_t err = storeMetaDataInBuffers(node, port_index, enable);
+ MetadataBufferType type;
+ status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
return NO_ERROR;
@@ -953,10 +979,11 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
+ OMX_U32 allottedSize = data.readInt32();
buffer_id buffer;
status_t err = allocateBufferWithBackup(
- node, port_index, params, &buffer);
+ node, port_index, params, &buffer, allottedSize);
reply->writeInt32(err);
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index ae0061f..c5790fb 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -152,16 +152,6 @@ MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUS
ALOGV("codec = %d", cap.mCodec);
}
-/*static*/ void
-MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap UNUSED)
-{
- ALOGV("videoeditor cap:");
- ALOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth);
- ALOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight);
- ALOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth);
- ALOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight);
-}
-
/*static*/ int
MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings,
const char *name)
@@ -398,42 +388,6 @@ void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts)
ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs);
mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
}
-/*static*/ MediaProfiles::ExportVideoProfile*
-MediaProfiles::createExportVideoProfile(const char **atts)
-{
- CHECK(!strcmp("name", atts[0]) &&
- !strcmp("profile", atts[2]) &&
- !strcmp("level", atts[4]));
-
- const size_t nMappings =
- sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
- const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
-
- MediaProfiles::ExportVideoProfile *profile =
- new MediaProfiles::ExportVideoProfile(
- codec, atoi(atts[3]), atoi(atts[5]));
-
- return profile;
-}
-/*static*/ MediaProfiles::VideoEditorCap*
-MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles)
-{
- CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
- !strcmp("maxInputFrameHeight", atts[2]) &&
- !strcmp("maxOutputFrameWidth", atts[4]) &&
- !strcmp("maxOutputFrameHeight", atts[6]) &&
- !strcmp("maxPrefetchYUVFrames", atts[8]));
-
- MediaProfiles::VideoEditorCap *pVideoEditorCap =
- new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
- atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
-
- logVideoEditorCap(*pVideoEditorCap);
- profiles->mVideoEditorCap = pVideoEditorCap;
-
- return pVideoEditorCap;
-}
/*static*/ void
MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
@@ -465,10 +419,6 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char
createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
} else if (strcmp("ImageEncoding", name) == 0) {
profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
- } else if (strcmp("VideoEditorCap", name) == 0) {
- createVideoEditorCap(atts, profiles);
- } else if (strcmp("ExportVideoProfile", name) == 0) {
- profiles->mVideoEditorExportProfiles.add(createExportVideoProfile(atts));
}
}
@@ -873,32 +823,6 @@ MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
profiles->mImageEncodingQualityLevels.add(levels);
}
-/*static*/ void
-MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles)
-{
- profiles->mVideoEditorCap =
- new MediaProfiles::VideoEditorCap(
- VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
- VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
- VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
- VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT,
- VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES);
-}
-/*static*/ void
-MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles)
-{
- // Create default video export profiles
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_H263,
- OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10));
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_MPEG_4_SP,
- OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1));
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_H264,
- OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13));
-}
-
/*static*/ MediaProfiles*
MediaProfiles::createDefaultInstance()
{
@@ -910,8 +834,6 @@ MediaProfiles::createDefaultInstance()
createDefaultAudioDecoders(profiles);
createDefaultEncoderOutputFileFormats(profiles);
createDefaultImageEncodingQualityLevels(profiles);
- createDefaultVideoEditorCap(profiles);
- createDefaultExportVideoProfiles(profiles);
return profiles;
}
@@ -1009,54 +931,6 @@ int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder co
ALOGE("The given video encoder param name %s is not found", name);
return -1;
}
-int MediaProfiles::getVideoEditorExportParamByName(
- const char *name, int codec) const
-{
- ALOGV("getVideoEditorExportParamByName: name %s codec %d", name, codec);
- ExportVideoProfile *exportProfile = NULL;
- int index = -1;
- for (size_t i =0; i < mVideoEditorExportProfiles.size(); i++) {
- exportProfile = mVideoEditorExportProfiles[i];
- if (exportProfile->mCodec == codec) {
- index = i;
- break;
- }
- }
- if (index == -1) {
- ALOGE("The given video decoder %d is not found", codec);
- return -1;
- }
- if (!strcmp("videoeditor.export.profile", name))
- return exportProfile->mProfile;
- if (!strcmp("videoeditor.export.level", name))
- return exportProfile->mLevel;
-
- ALOGE("The given video editor export param name %s is not found", name);
- return -1;
-}
-int MediaProfiles::getVideoEditorCapParamByName(const char *name) const
-{
- ALOGV("getVideoEditorCapParamByName: %s", name);
-
- if (mVideoEditorCap == NULL) {
- ALOGE("The mVideoEditorCap is not created, then create default cap.");
- createDefaultVideoEditorCap(sInstance);
- }
-
- if (!strcmp("videoeditor.input.width.max", name))
- return mVideoEditorCap->mMaxInputFrameWidth;
- if (!strcmp("videoeditor.input.height.max", name))
- return mVideoEditorCap->mMaxInputFrameHeight;
- if (!strcmp("videoeditor.output.width.max", name))
- return mVideoEditorCap->mMaxOutputFrameWidth;
- if (!strcmp("videoeditor.output.height.max", name))
- return mVideoEditorCap->mMaxOutputFrameHeight;
- if (!strcmp("maxPrefetchYUVFrames", name))
- return mVideoEditorCap->mMaxPrefetchYUVFrames;
-
- ALOGE("The given video editor param name %s is not found", name);
- return -1;
-}
Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
{
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index b52db97..7f0cca2 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -33,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \
libdl \
libgui \
libmedia \
+ libmediautils \
libsonivox \
libstagefright \
libstagefright_foundation \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9c0af4a..7c40121 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -34,7 +34,6 @@
#include <utils/misc.h>
-#include <binder/IBatteryStats.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h>
@@ -60,6 +59,7 @@
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooperRoster.h>
+#include <mediautils/BatteryNotifier.h>
#include <system/audio.h>
@@ -287,17 +287,9 @@ MediaPlayerService::MediaPlayerService()
// reset battery stats
// if the mediaserver has crashed, battery stats could be left
// in bad state, reset the state upon service start.
- const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != NULL) {
- const String16 name("batterystats");
- // use checkService() to avoid blocking if service is not up yet
- sp<IBatteryStats> batteryStats =
- interface_cast<IBatteryStats>(sm->checkService(name));
- if (batteryStats != NULL) {
- batteryStats->noteResetVideo();
- batteryStats->noteResetAudio();
- }
- }
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteResetVideo();
+ notifier.noteResetAudio();
MediaPlayerFactory::registerBuiltinFactories();
}
@@ -1884,6 +1876,15 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
me->mCallbackCookie, CB_EVENT_TEAR_DOWN);
break;
+ case AudioTrack::EVENT_UNDERRUN:
+ // This occurs when there is no data available, typically occurring
+ // when there is a failure to supply data to the AudioTrack. It can also
+ // occur in non-offloaded mode when the audio device comes out of standby.
+ //
+ // If you see this at the start of playback, there probably was a glitch.
+ ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
+ break;
+
default:
ALOGE("received unknown event type: %d inside CallbackWrapper !", event);
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 70480a2..08045d1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -413,7 +413,6 @@ ACodec::ACodec()
mSentFormat(false),
mIsVideo(false),
mIsEncoder(false),
- mUseMetadataOnEncoderOutput(false),
mShutdownInProgress(false),
mExplicitShutdown(false),
mEncoderDelay(0),
@@ -422,9 +421,10 @@ ACodec::ACodec()
mChannelMaskPresent(false),
mChannelMask(0),
mDequeueCounter(0),
- mStoreMetaDataInOutputBuffers(false),
+ mInputMetadataType(kMetadataBufferTypeInvalid),
+ mOutputMetadataType(kMetadataBufferTypeInvalid),
mLegacyAdaptiveExperiment(false),
- mMetaDataBuffersToSubmit(0),
+ mMetadataBuffersToSubmit(0),
mRepeatFrameDelayUs(-1ll),
mMaxPtsGapUs(-1ll),
mMaxFps(-1),
@@ -542,10 +542,10 @@ void ACodec::signalRequestIDRFrame() {
// This causes a halt if we already signaled an EOS on the input
// port. For now keep submitting an output buffer if there was an
// EOS on the input port, but not yet on the output port.
-void ACodec::signalSubmitOutputMetaDataBufferIfEOS_workaround() {
+void ACodec::signalSubmitOutputMetadataBufferIfEOS_workaround() {
if (mPortEOS[kPortIndexInput] && !mPortEOS[kPortIndexOutput] &&
- mMetaDataBuffersToSubmit > 0) {
- (new AMessage(kWhatSubmitOutputMetaDataBufferIfEOS, this))->post();
+ mMetadataBuffersToSubmit > 0) {
+ (new AMessage(kWhatSubmitOutputMetadataBufferIfEOS, this))->post();
}
}
@@ -620,7 +620,7 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
for (size_t i = 0; i < buffers.size(); ++i) {
const BufferInfo &info = buffers[i];
// skip undequeued buffers for meta data mode
- if (mStoreMetaDataInOutputBuffers
+ if (storingMetadataInDecodedBuffers()
&& !mLegacyAdaptiveExperiment
&& info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
@@ -638,7 +638,7 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
}
// cancel undequeued buffers to new surface
- if (!mStoreMetaDataInOutputBuffers || mLegacyAdaptiveExperiment) {
+ if (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment) {
for (size_t i = 0; i < buffers.size(); ++i) {
const BufferInfo &info = buffers[i];
if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
@@ -674,8 +674,8 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
status_t err;
if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
- if (mStoreMetaDataInOutputBuffers) {
- err = allocateOutputMetaDataBuffers();
+ if (storingMetadataInDecodedBuffers()) {
+ err = allocateOutputMetadataBuffers();
} else {
err = allocateOutputBuffersFromNativeWindow();
}
@@ -688,16 +688,33 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
if (err == OK) {
- ALOGV("[%s] Allocating %u buffers of size %u on %s port",
+ MetadataBufferType type =
+ portIndex == kPortIndexOutput ? mOutputMetadataType : mInputMetadataType;
+ int32_t bufSize = def.nBufferSize;
+ if (type == kMetadataBufferTypeGrallocSource) {
+ bufSize = sizeof(VideoGrallocMetadata);
+ } else if (type == kMetadataBufferTypeANWBuffer) {
+ bufSize = sizeof(VideoNativeMetadata);
+ }
+
+ // If using gralloc or native source input metadata buffers, allocate largest
+ // metadata size as we prefer to generate native source metadata, but component
+ // may require gralloc source.
+ int32_t allottedSize = bufSize;
+ if (portIndex == kPortIndexInput && type > 0) {
+ bufSize = max(sizeof(VideoGrallocMetadata), sizeof(VideoNativeMetadata));
+ }
+
+ ALOGV("[%s] Allocating %u buffers of size %d/%d (from %u using %s) on %s port",
mComponentName.c_str(),
- def.nBufferCountActual, def.nBufferSize,
+ def.nBufferCountActual, bufSize, allottedSize, def.nBufferSize, asString(type),
portIndex == kPortIndexInput ? "input" : "output");
- size_t totalSize = def.nBufferCountActual * def.nBufferSize;
+ size_t totalSize = def.nBufferCountActual * bufSize;
mDealer[portIndex] = new MemoryDealer(totalSize, "ACodec");
- for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
- sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
+ for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
+ sp<IMemory> mem = mDealer[portIndex]->allocate(bufSize);
if (mem == NULL || mem->pointer() == NULL) {
return NO_MEMORY;
}
@@ -711,27 +728,27 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
: OMXCodec::kRequiresAllocateBufferOnOutputPorts;
if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
- || mUseMetadataOnEncoderOutput) {
+ || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) {
mem.clear();
void *ptr;
err = mOMX->allocateBuffer(
- mNode, portIndex, def.nBufferSize, &info.mBufferID,
+ mNode, portIndex, bufSize, &info.mBufferID,
&ptr);
- int32_t bufSize = mUseMetadataOnEncoderOutput ?
- (4 + sizeof(buffer_handle_t)) : def.nBufferSize;
-
info.mData = new ABuffer(ptr, bufSize);
} else if (mQuirks & requiresAllocateBufferBit) {
err = mOMX->allocateBufferWithBackup(
- mNode, portIndex, mem, &info.mBufferID);
+ mNode, portIndex, mem, &info.mBufferID, allottedSize);
} else {
- err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID);
+ err = mOMX->useBuffer(mNode, portIndex, mem, &info.mBufferID, allottedSize);
}
if (mem != NULL) {
- info.mData = new ABuffer(mem->pointer(), def.nBufferSize);
+ info.mData = new ABuffer(mem->pointer(), bufSize);
+ if (type == kMetadataBufferTypeANWBuffer) {
+ ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
+ }
}
mBuffers[portIndex].push(info);
@@ -896,7 +913,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
return err;
mNumUndequeuedBuffers = minUndequeuedBuffers;
- if (!mStoreMetaDataInOutputBuffers) {
+ if (!storingMetadataInDecodedBuffers()) {
static_cast<Surface*>(mNativeWindow.get())
->getIGraphicBufferProducer()->allowAllocation(true);
}
@@ -959,7 +976,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
}
}
- if (!mStoreMetaDataInOutputBuffers) {
+ if (!storingMetadataInDecodedBuffers()) {
static_cast<Surface*>(mNativeWindow.get())
->getIGraphicBufferProducer()->allowAllocation(false);
}
@@ -967,7 +984,7 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
return err;
}
-status_t ACodec::allocateOutputMetaDataBuffers() {
+status_t ACodec::allocateOutputMetadataBuffers() {
OMX_U32 bufferCount, bufferSize, minUndequeuedBuffers;
status_t err = configureOutputBuffersFromNativeWindow(
&bufferCount, &bufferSize, &minUndequeuedBuffers);
@@ -978,7 +995,9 @@ status_t ACodec::allocateOutputMetaDataBuffers() {
ALOGV("[%s] Allocating %u meta buffers on output port",
mComponentName.c_str(), bufferCount);
- size_t totalSize = bufferCount * 8;
+ size_t bufSize = mOutputMetadataType == kMetadataBufferTypeANWBuffer ?
+ sizeof(struct VideoNativeMetadata) : sizeof(struct VideoGrallocMetadata);
+ size_t totalSize = bufferCount * bufSize;
mDealer[kPortIndexOutput] = new MemoryDealer(totalSize, "ACodec");
// Dequeue buffers and send them to OMX
@@ -988,16 +1007,18 @@ status_t ACodec::allocateOutputMetaDataBuffers() {
info.mGraphicBuffer = NULL;
info.mDequeuedAt = mDequeueCounter;
- sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
- sizeof(struct VideoDecoderOutputMetaData));
+ sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(bufSize);
if (mem == NULL || mem->pointer() == NULL) {
return NO_MEMORY;
}
+ if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
+ ((VideoNativeMetadata *)mem->pointer())->nFenceFd = -1;
+ }
info.mData = new ABuffer(mem->pointer(), mem->size());
// we use useBuffer for metadata regardless of quirks
err = mOMX->useBuffer(
- mNode, kPortIndexOutput, mem, &info.mBufferID);
+ mNode, kPortIndexOutput, mem, &info.mBufferID, mem->size());
mBuffers[kPortIndexOutput].push(info);
@@ -1044,13 +1065,13 @@ status_t ACodec::allocateOutputMetaDataBuffers() {
->getIGraphicBufferProducer()->allowAllocation(false);
}
- mMetaDataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
+ mMetadataBuffersToSubmit = bufferCount - minUndequeuedBuffers;
return err;
}
-status_t ACodec::submitOutputMetaDataBuffer() {
- CHECK(mStoreMetaDataInOutputBuffers);
- if (mMetaDataBuffersToSubmit == 0)
+status_t ACodec::submitOutputMetadataBuffer() {
+ CHECK(storingMetadataInDecodedBuffers());
+ if (mMetadataBuffersToSubmit == 0)
return OK;
BufferInfo *info = dequeueBufferFromNativeWindow();
@@ -1061,7 +1082,7 @@ status_t ACodec::submitOutputMetaDataBuffer() {
ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
- --mMetaDataBuffersToSubmit;
+ --mMetadataBuffersToSubmit;
status_t err = mOMX->fillBuffer(mNode, info->mBufferID);
if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
@@ -1159,7 +1180,7 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
// same is possible in meta mode, in which case, it will be treated
// as a normal buffer, which is not desirable.
// TODO: fix this.
- if (!stale && (!mStoreMetaDataInOutputBuffers || mLegacyAdaptiveExperiment)) {
+ if (!stale && (!storingMetadataInDecodedBuffers() || mLegacyAdaptiveExperiment)) {
ALOGI("dequeued unrecognized (stale) buffer %p. discarding", buf);
stale = true;
}
@@ -1187,7 +1208,7 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
CHECK(oldest != NULL);
// it is impossible to dequeue an unknown buffer in non-meta mode, as the
// while loop above does not complete
- CHECK(mStoreMetaDataInOutputBuffers);
+ CHECK(storingMetadataInDecodedBuffers());
// discard buffer in LRU info and replace with new buffer
oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
@@ -1197,16 +1218,23 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
mNode, kPortIndexOutput, oldest->mGraphicBuffer,
oldest->mBufferID);
- VideoDecoderOutputMetaData *metaData =
- reinterpret_cast<VideoDecoderOutputMetaData *>(
- oldest->mData->base());
- CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
-
- ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
- (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
- mDequeueCounter - oldest->mDequeuedAt,
- metaData->pHandle,
- oldest->mGraphicBuffer->handle, oldest->mData->base());
+ if (mOutputMetadataType == kMetadataBufferTypeGrallocSource) {
+ VideoGrallocMetadata *grallocMeta =
+ reinterpret_cast<VideoGrallocMetadata *>(oldest->mData->base());
+ ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
+ (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
+ mDequeueCounter - oldest->mDequeuedAt,
+ grallocMeta->hHandle,
+ oldest->mGraphicBuffer->handle, oldest->mData->base());
+ } else if (mOutputMetadataType == kMetadataBufferTypeANWBuffer) {
+ VideoNativeMetadata *nativeMeta =
+ reinterpret_cast<VideoNativeMetadata *>(oldest->mData->base());
+ ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
+ (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
+ mDequeueCounter - oldest->mDequeuedAt,
+ nativeMeta->pBuffer,
+ oldest->mGraphicBuffer->getNativeBuffer(), oldest->mData->base());
+ }
return oldest;
}
@@ -1398,6 +1426,8 @@ status_t ACodec::configureCodec(
mIsEncoder = encoder;
+ mInputMetadataType = kMetadataBufferTypeInvalid;
+ mOutputMetadataType = kMetadataBufferTypeInvalid;
status_t err = setComponentRole(encoder /* isEncoder */, mime);
@@ -1416,15 +1446,19 @@ status_t ACodec::configureCodec(
if (encoder
&& msg->findInt32("store-metadata-in-buffers", &storeMeta)
&& storeMeta != 0) {
- err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE);
-
+ err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexInput, OMX_TRUE, &mInputMetadataType);
if (err != OK) {
- ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
+ ALOGE("[%s] storeMetaDataInBuffers (input) failed w/ err %d",
mComponentName.c_str(), err);
- return err;
- }
- }
+ return err;
+ }
+ // For this specific case we could be using camera source even if storeMetaDataInBuffers
+ // returns Gralloc source. Pretend that we are; this will force us to use nBufferSize.
+ if (mInputMetadataType == kMetadataBufferTypeGrallocSource) {
+ mInputMetadataType = kMetadataBufferTypeCameraSource;
+ }
+ }
int32_t prependSPSPPS = 0;
if (encoder
@@ -1463,14 +1497,10 @@ status_t ACodec::configureCodec(
&& msg->findInt32("store-metadata-in-buffers-output", &storeMeta)
&& storeMeta != 0);
- err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable);
-
+ err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, enable, &mOutputMetadataType);
if (err != OK) {
ALOGE("[%s] storeMetaDataInBuffers (output) failed w/ err %d",
mComponentName.c_str(), err);
- mUseMetadataOnEncoderOutput = 0;
- } else {
- mUseMetadataOnEncoderOutput = enable;
}
if (!msg->findInt64(
@@ -1502,7 +1532,6 @@ status_t ACodec::configureCodec(
sp<RefBase> obj;
bool haveNativeWindow = msg->findObject("native-window", &obj)
&& obj != NULL && video && !encoder;
- mStoreMetaDataInOutputBuffers = false;
mLegacyAdaptiveExperiment = false;
if (video && !encoder) {
inputFormat->setInt32("adaptive-playback", false);
@@ -1588,7 +1617,7 @@ status_t ACodec::configureCodec(
// Always try to enable dynamic output buffers on native surface
err = mOMX->storeMetaDataInBuffers(
- mNode, kPortIndexOutput, OMX_TRUE);
+ mNode, kPortIndexOutput, OMX_TRUE, &mOutputMetadataType);
if (err != OK) {
ALOGE("[%s] storeMetaDataInBuffers failed w/ err %d",
mComponentName.c_str(), err);
@@ -1640,7 +1669,7 @@ status_t ACodec::configureCodec(
} else {
ALOGV("[%s] storeMetaDataInBuffers succeeded",
mComponentName.c_str());
- mStoreMetaDataInOutputBuffers = true;
+ CHECK(storingMetadataInDecodedBuffers());
mLegacyAdaptiveExperiment = ADebug::isExperimentEnabled(
"legacy-adaptive", !msg->contains("no-experiments"));
@@ -1717,9 +1746,10 @@ status_t ACodec::configureCodec(
mNativeWindow.clear();
haveNativeWindow = false;
usingSwRenderer = true;
- if (mStoreMetaDataInOutputBuffers) {
- err = mOMX->storeMetaDataInBuffers(mNode, kPortIndexOutput, OMX_FALSE);
- mStoreMetaDataInOutputBuffers = false;
+ if (storingMetadataInDecodedBuffers()) {
+ err = mOMX->storeMetaDataInBuffers(
+ mNode, kPortIndexOutput, OMX_FALSE, &mOutputMetadataType);
+ mOutputMetadataType = kMetadataBufferTypeInvalid; // just in case
// TODO: implement adaptive-playback support for bytebuffer mode.
// This is done by SW codecs, but most HW codecs don't support it.
inputFormat->setInt32("adaptive-playback", false);
@@ -3536,8 +3566,8 @@ void ACodec::waitUntilAllPossibleNativeWindowBuffersAreReturnedToUs() {
while (countBuffersOwnedByNativeWindow() > mNumUndequeuedBuffers
&& dequeueBufferFromNativeWindow() != NULL) {
// these buffers will be submitted as regular buffers; account for this
- if (mStoreMetaDataInOutputBuffers && mMetaDataBuffersToSubmit > 0) {
- --mMetaDataBuffersToSubmit;
+ if (storingMetadataInDecodedBuffers() && mMetadataBuffersToSubmit > 0) {
+ --mMetadataBuffersToSubmit;
}
}
}
@@ -4628,16 +4658,16 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
mCodec->mBufferStats.add(timeUs, stats);
#endif
- if (mCodec->mStoreMetaDataInOutputBuffers) {
+ if (mCodec->storingMetadataInDecodedBuffers()) {
// try to submit an output buffer for each input buffer
PortMode outputMode = getPortMode(kPortIndexOutput);
- ALOGV("MetaDataBuffersToSubmit=%u portMode=%s",
- mCodec->mMetaDataBuffersToSubmit,
+ ALOGV("MetadataBuffersToSubmit=%u portMode=%s",
+ mCodec->mMetadataBuffersToSubmit,
(outputMode == FREE_BUFFERS ? "FREE" :
outputMode == KEEP_BUFFERS ? "KEEP" : "RESUBMIT"));
if (outputMode == RESUBMIT_BUFFERS) {
- mCodec->submitOutputMetaDataBuffer();
+ mCodec->submitOutputMetadataBuffer();
}
}
status_t err2 = mCodec->mOMX->emptyBuffer(
@@ -4799,10 +4829,17 @@ bool ACodec::BaseState::onOMXFillBufferDone(
if (!mCodec->mSentFormat && rangeLength > 0) {
mCodec->sendFormatChange(reply);
}
-
- if (mCodec->mUseMetadataOnEncoderOutput) {
- native_handle_t* handle =
- *(native_handle_t**)(info->mData->data() + 4);
+ if (mCodec->usingMetadataOnEncoderOutput()) {
+ native_handle_t *handle = NULL;
+ VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)info->mData->data();
+ VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)info->mData->data();
+ if (info->mData->size() >= sizeof(grallocMeta)
+ && grallocMeta.eType == kMetadataBufferTypeGrallocSource) {
+ handle = (native_handle_t *)grallocMeta.hHandle;
+ } else if (info->mData->size() >= sizeof(nativeMeta)
+ && nativeMeta.eType == kMetadataBufferTypeANWBuffer) {
+ handle = (native_handle_t *)nativeMeta.pBuffer->handle;
+ }
info->mData->meta()->setPointer("handle", handle);
info->mData->meta()->setInt32("rangeOffset", rangeOffset);
info->mData->meta()->setInt32("rangeLength", rangeLength);
@@ -4999,7 +5036,8 @@ void ACodec::UninitializedState::stateEntered() {
mCodec->mOMX.clear();
mCodec->mQuirks = 0;
mCodec->mFlags = 0;
- mCodec->mUseMetadataOnEncoderOutput = 0;
+ mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
+ mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
mCodec->mComponentName.clear();
}
@@ -5202,7 +5240,7 @@ void ACodec::LoadedState::stateEntered() {
mCodec->mInputEOSResult = OK;
mCodec->mDequeueCounter = 0;
- mCodec->mMetaDataBuffersToSubmit = 0;
+ mCodec->mMetadataBuffersToSubmit = 0;
mCodec->mRepeatFrameDelayUs = -1ll;
mCodec->mInputFormat.clear();
mCodec->mOutputFormat.clear();
@@ -5431,7 +5469,7 @@ void ACodec::LoadedState::onCreateInputSurface(
sp<IGraphicBufferProducer> bufferProducer;
status_t err = mCodec->mOMX->createInputSurface(
- mCodec->mNode, kPortIndexInput, &bufferProducer);
+ mCodec->mNode, kPortIndexInput, &bufferProducer, &mCodec->mInputMetadataType);
if (err == OK) {
err = setupInputSurface();
@@ -5463,7 +5501,8 @@ void ACodec::LoadedState::onSetInputSurface(
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
status_t err = mCodec->mOMX->setInputSurface(
- mCodec->mNode, kPortIndexInput, surface->getBufferConsumer());
+ mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
+ &mCodec->mInputMetadataType);
if (err == OK) {
err = setupInputSurface();
@@ -5680,13 +5719,13 @@ void ACodec::ExecutingState::submitOutputMetaBuffers() {
BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
- if (mCodec->submitOutputMetaDataBuffer() != OK)
+ if (mCodec->submitOutputMetadataBuffer() != OK)
break;
}
}
// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
- mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
+ mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
}
void ACodec::ExecutingState::submitRegularOutputBuffers() {
@@ -5731,7 +5770,7 @@ void ACodec::ExecutingState::submitRegularOutputBuffers() {
void ACodec::ExecutingState::submitOutputBuffers() {
submitRegularOutputBuffers();
- if (mCodec->mStoreMetaDataInOutputBuffers) {
+ if (mCodec->storingMetadataInDecodedBuffers()) {
submitOutputMetaBuffers();
}
}
@@ -5863,13 +5902,13 @@ bool ACodec::ExecutingState::onMessageReceived(const sp<AMessage> &msg) {
}
// *** NOTE: THE FOLLOWING WORKAROUND WILL BE REMOVED ***
- case kWhatSubmitOutputMetaDataBufferIfEOS:
+ case kWhatSubmitOutputMetadataBufferIfEOS:
{
if (mCodec->mPortEOS[kPortIndexInput] &&
!mCodec->mPortEOS[kPortIndexOutput]) {
- status_t err = mCodec->submitOutputMetaDataBuffer();
+ status_t err = mCodec->submitOutputMetadataBuffer();
if (err == OK) {
- mCodec->signalSubmitOutputMetaDataBufferIfEOS_workaround();
+ mCodec->signalSubmitOutputMetadataBufferIfEOS_workaround();
}
}
return true;
@@ -5980,7 +6019,7 @@ bool ACodec::ExecutingState::onOMXEvent(
CHECK_EQ(data1, (OMX_U32)kPortIndexOutput);
if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
- mCodec->mMetaDataBuffersToSubmit = 0;
+ mCodec->mMetadataBuffersToSubmit = 0;
CHECK_EQ(mCodec->mOMX->sendCommand(
mCodec->mNode,
OMX_CommandPortDisable, kPortIndexOutput),
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 337068e..0dfa300 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -90,6 +90,7 @@ LOCAL_SHARED_LIBRARIES := \
libicuuc \
liblog \
libmedia \
+ libmediautils \
libnetd_client \
libopus \
libsonivox \
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 6f22e26..f918d2d 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -21,7 +21,6 @@
#include "include/avc_utils.h"
#include "include/SoftwareRenderer.h"
-#include <binder/IBatteryStats.h>
#include <binder/IMemory.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
@@ -48,6 +47,7 @@
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
+#include <mediautils/BatteryNotifier.h>
#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <utils/Singleton.h>
@@ -108,134 +108,6 @@ private:
DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
};
-struct MediaCodec::BatteryNotifier : public Singleton<BatteryNotifier> {
- BatteryNotifier();
- virtual ~BatteryNotifier();
-
- void noteStartVideo();
- void noteStopVideo();
- void noteStartAudio();
- void noteStopAudio();
- void onBatteryStatServiceDied();
-
-private:
- struct DeathNotifier : public IBinder::DeathRecipient {
- DeathNotifier() {}
- virtual void binderDied(const wp<IBinder>& /*who*/) {
- BatteryNotifier::getInstance().onBatteryStatServiceDied();
- }
- };
-
- Mutex mLock;
- int32_t mVideoRefCount;
- int32_t mAudioRefCount;
- sp<IBatteryStats> mBatteryStatService;
- sp<DeathNotifier> mDeathNotifier;
-
- sp<IBatteryStats> getBatteryService_l();
-
- DISALLOW_EVIL_CONSTRUCTORS(BatteryNotifier);
-};
-
-ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier)
-
-MediaCodec::BatteryNotifier::BatteryNotifier() :
- mVideoRefCount(0),
- mAudioRefCount(0) {
-}
-
-sp<IBatteryStats> MediaCodec::BatteryNotifier::getBatteryService_l() {
- if (mBatteryStatService != NULL) {
- return mBatteryStatService;
- }
- // get battery service from service manager
- const sp<IServiceManager> sm(defaultServiceManager());
- if (sm != NULL) {
- const String16 name("batterystats");
- mBatteryStatService =
- interface_cast<IBatteryStats>(sm->getService(name));
- if (mBatteryStatService == NULL) {
- ALOGE("batterystats service unavailable!");
- return NULL;
- }
- mDeathNotifier = new DeathNotifier();
- IInterface::asBinder(mBatteryStatService)->linkToDeath(mDeathNotifier);
- // notify start now if media already started
- if (mVideoRefCount > 0) {
- mBatteryStatService->noteStartVideo(AID_MEDIA);
- }
- if (mAudioRefCount > 0) {
- mBatteryStatService->noteStartAudio(AID_MEDIA);
- }
- }
- return mBatteryStatService;
-}
-
-MediaCodec::BatteryNotifier::~BatteryNotifier() {
- if (mDeathNotifier != NULL) {
- IInterface::asBinder(mBatteryStatService)->
- unlinkToDeath(mDeathNotifier);
- }
-}
-
-void MediaCodec::BatteryNotifier::noteStartVideo() {
- Mutex::Autolock _l(mLock);
- sp<IBatteryStats> batteryService = getBatteryService_l();
- if (mVideoRefCount == 0 && batteryService != NULL) {
- batteryService->noteStartVideo(AID_MEDIA);
- }
- mVideoRefCount++;
-}
-
-void MediaCodec::BatteryNotifier::noteStopVideo() {
- Mutex::Autolock _l(mLock);
- if (mVideoRefCount == 0) {
- ALOGW("BatteryNotifier::noteStop(): video refcount is broken!");
- return;
- }
-
- sp<IBatteryStats> batteryService = getBatteryService_l();
-
- mVideoRefCount--;
- if (mVideoRefCount == 0 && batteryService != NULL) {
- batteryService->noteStopVideo(AID_MEDIA);
- }
-}
-
-void MediaCodec::BatteryNotifier::noteStartAudio() {
- Mutex::Autolock _l(mLock);
- sp<IBatteryStats> batteryService = getBatteryService_l();
- if (mAudioRefCount == 0 && batteryService != NULL) {
- batteryService->noteStartAudio(AID_MEDIA);
- }
- mAudioRefCount++;
-}
-
-void MediaCodec::BatteryNotifier::noteStopAudio() {
- Mutex::Autolock _l(mLock);
- if (mAudioRefCount == 0) {
- ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!");
- return;
- }
-
- sp<IBatteryStats> batteryService = getBatteryService_l();
-
- mAudioRefCount--;
- if (mAudioRefCount == 0 && batteryService != NULL) {
- batteryService->noteStopAudio(AID_MEDIA);
- }
-}
-
-void MediaCodec::BatteryNotifier::onBatteryStatServiceDied() {
- Mutex::Autolock _l(mLock);
- mBatteryStatService.clear();
- mDeathNotifier.clear();
- // Do not reset mVideoRefCount and mAudioRefCount here. The ref
- // counting is independent of the battery service availability.
- // We need this if battery service becomes available after media
- // started.
-}
-
MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy() {
}
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 6708828..f366b1f 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -73,10 +73,24 @@ sp<IMediaCodecList> MediaCodecList::getLocalInstance() {
if (gCodecList->initCheck() == OK) {
sCodecList = gCodecList;
- struct stat s;
- if (stat(kProfilingResults, &s) == -1) {
+ FILE *resultsFile = fopen(kProfilingResults, "r");
+ if (resultsFile) {
+ AString currentVersion = getProfilingVersionString();
+ size_t currentVersionSize = currentVersion.size();
+ char *versionString = new char[currentVersionSize];
+ fgets(versionString, currentVersionSize, resultsFile);
+ if (strncmp(versionString, currentVersion.c_str(), currentVersionSize) != 0) {
+ // profiling result out of date
+ profilingNeeded = true;
+ }
+ fclose(resultsFile);
+ delete[] versionString;
+ } else {
// profiling results doesn't existed
profilingNeeded = true;
+ }
+
+ if (profilingNeeded) {
for (size_t i = 0; i < gCodecList->countCodecs(); ++i) {
infos.push_back(gCodecList->getCodecInfo(i));
}
diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp
index 006454d..a928163 100644
--- a/media/libstagefright/MediaCodecListOverrides.cpp
+++ b/media/libstagefright/MediaCodecListOverrides.cpp
@@ -20,6 +20,7 @@
#include "MediaCodecListOverrides.h"
+#include <cutils/properties.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
#include <media/IMediaCodecList.h>
@@ -34,6 +35,15 @@ namespace android {
const char *kProfilingResults = "/data/misc/media/media_codecs_profiling_results.xml";
+AString getProfilingVersionString() {
+ char val[PROPERTY_VALUE_MAX];
+ if (property_get("ro.build.display.id", val, NULL) && (strlen(val) > 0)) {
+ return AStringPrintf("<!-- Profiled-with: %s -->", val);
+ }
+
+ return "<!-- Profiled-with: UNKNOWN_BUILD_ID -->";
+}
+
// a limit to avoid allocating unreasonable number of codec instances in the measurement.
// this should be in sync with the MAX_SUPPORTED_INSTANCES defined in MediaCodecInfo.java.
static const int kMaxInstances = 32;
@@ -375,6 +385,8 @@ void exportResultsToXML(
}
AString overrides;
+ overrides.append(getProfilingVersionString());
+ overrides.append("\n");
overrides.append("<MediaCodecs>\n");
if (global_results.size() > 0) {
overrides.append(" <Settings>\n");
diff --git a/media/libstagefright/MediaCodecListOverrides.h b/media/libstagefright/MediaCodecListOverrides.h
index e350d2a..d4bb225 100644
--- a/media/libstagefright/MediaCodecListOverrides.h
+++ b/media/libstagefright/MediaCodecListOverrides.h
@@ -26,10 +26,13 @@
namespace android {
+extern const char *kProfilingVersionString;
extern const char *kProfilingResults;
struct MediaCodecInfo;
+AString getProfilingVersionString();
+
bool splitString(const AString &s, const AString &delimiter, AString *s1, AString *s2);
// profile codecs and save the result to xml file named kProfilingResults.
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index f1ebea2..5d04628 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -72,7 +72,7 @@ struct MuxOMX : public IOMX {
node_id node, OMX_STATETYPE* state);
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable);
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
virtual status_t prepareForAdaptivePlayback(
node_id node, OMX_U32 port_index, OMX_BOOL enable,
@@ -90,7 +90,7 @@ struct MuxOMX : public IOMX {
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer);
+ buffer_id *buffer, OMX_U32 allottedSize);
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -102,7 +102,7 @@ struct MuxOMX : public IOMX {
virtual status_t createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer);
+ sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type);
virtual status_t createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
@@ -110,7 +110,7 @@ struct MuxOMX : public IOMX {
virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer);
+ const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type);
virtual status_t signalEndOfInputStream(node_id node);
@@ -120,7 +120,7 @@ struct MuxOMX : public IOMX {
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer);
+ buffer_id *buffer, OMX_U32 allottedSize);
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer);
@@ -292,8 +292,8 @@ status_t MuxOMX::getState(
}
status_t MuxOMX::storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable) {
- return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
+ return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type);
}
status_t MuxOMX::prepareForAdaptivePlayback(
@@ -322,8 +322,8 @@ status_t MuxOMX::getGraphicBufferUsage(
status_t MuxOMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
- return getOMX(node)->useBuffer(node, port_index, params, buffer);
+ buffer_id *buffer, OMX_U32 allottedSize) {
+ return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize);
}
status_t MuxOMX::useGraphicBuffer(
@@ -342,9 +342,9 @@ status_t MuxOMX::updateGraphicBufferInMeta(
status_t MuxOMX::createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer) {
+ sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
status_t err = getOMX(node)->createInputSurface(
- node, port_index, bufferProducer);
+ node, port_index, bufferProducer, type);
return err;
}
@@ -358,8 +358,8 @@ status_t MuxOMX::createPersistentInputSurface(
status_t MuxOMX::setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer) {
- return getOMX(node)->setInputSurface(node, port_index, bufferConsumer);
+ const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
+ return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, type);
}
status_t MuxOMX::signalEndOfInputStream(node_id node) {
@@ -375,9 +375,9 @@ status_t MuxOMX::allocateBuffer(
status_t MuxOMX::allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
return getOMX(node)->allocateBufferWithBackup(
- node, port_index, params, buffer);
+ node, port_index, params, buffer, allottedSize);
}
status_t MuxOMX::freeBuffer(
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index aa6a7c0..927cc6c 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1678,7 +1678,7 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
&info.mData);
} else {
err = mOMX->allocateBufferWithBackup(
- mNode, portIndex, mem, &buffer);
+ mNode, portIndex, mem, &buffer, mem->size());
}
} else if (portIndex == kPortIndexOutput
&& (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
@@ -1690,10 +1690,10 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
&info.mData);
} else {
err = mOMX->allocateBufferWithBackup(
- mNode, portIndex, mem, &buffer);
+ mNode, portIndex, mem, &buffer, mem->size());
}
} else {
- err = mOMX->useBuffer(mNode, portIndex, mem, &buffer);
+ err = mOMX->useBuffer(mNode, portIndex, mem, &buffer, mem->size());
}
if (err != OK) {
diff --git a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
index d1b0f76..a9723ea 100644
--- a/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp
@@ -428,7 +428,15 @@ void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
}
}
-void SoftAMR::onPortFlushCompleted(OMX_U32 /* portIndex */) {
+void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) {
+ ALOGV("onPortFlushCompleted portindex %d, resetting frame ", portIndex);
+ if (portIndex == 0) {
+ if (mMode == MODE_NARROW) {
+ Speech_Decode_Frame_reset(mState);
+ } else {
+ pvDecoder_AmrWb_Reset(mState, 0 /* reset_all */);
+ }
+ }
}
void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index c183208..c34954b 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -69,7 +69,7 @@ public:
node_id node, OMX_U32 port_index, OMX_U32* usage);
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable);
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type);
virtual status_t prepareForAdaptivePlayback(
node_id node, OMX_U32 portIndex, OMX_BOOL enable,
@@ -81,7 +81,7 @@ public:
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer);
+ buffer_id *buffer, OMX_U32 allottedSize);
virtual status_t useGraphicBuffer(
node_id node, OMX_U32 port_index,
@@ -93,7 +93,8 @@ public:
virtual status_t createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer);
+ sp<IGraphicBufferProducer> *bufferProducer,
+ MetadataBufferType *type);
virtual status_t createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
@@ -101,7 +102,8 @@ public:
virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer);
+ const sp<IGraphicBufferConsumer> &bufferConsumer,
+ MetadataBufferType *type);
virtual status_t signalEndOfInputStream(node_id node);
@@ -111,7 +113,7 @@ public:
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer);
+ buffer_id *buffer, OMX_U32 allottedSize);
virtual status_t freeBuffer(
node_id node, OMX_U32 port_index, buffer_id buffer);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 3c032f9..fe6dccd 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -58,7 +58,8 @@ struct OMXNodeInstance {
status_t getGraphicBufferUsage(OMX_U32 portIndex, OMX_U32* usage);
- status_t storeMetaDataInBuffers(OMX_U32 portIndex, OMX_BOOL enable);
+ status_t storeMetaDataInBuffers(
+ OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type);
status_t prepareForAdaptivePlayback(
OMX_U32 portIndex, OMX_BOOL enable,
@@ -70,7 +71,7 @@ struct OMXNodeInstance {
status_t useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer);
+ OMX::buffer_id *buffer, OMX_U32 allottedSize);
status_t useGraphicBuffer(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
@@ -81,14 +82,16 @@ struct OMXNodeInstance {
OMX::buffer_id buffer);
status_t createInputSurface(
- OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer);
+ OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer,
+ MetadataBufferType *type);
static status_t createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer);
status_t setInputSurface(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer);
+ OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer,
+ MetadataBufferType *type);
status_t signalEndOfInputStream();
@@ -98,7 +101,7 @@ struct OMXNodeInstance {
status_t allocateBufferWithBackup(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer);
+ OMX::buffer_id *buffer, OMX_U32 allottedSize);
status_t freeBuffer(OMX_U32 portIndex, OMX::buffer_id buffer);
@@ -109,9 +112,8 @@ struct OMXNodeInstance {
OMX_U32 rangeOffset, OMX_U32 rangeLength,
OMX_U32 flags, OMX_TICKS timestamp);
- status_t emptyDirectBuffer(
- OMX_BUFFERHEADERTYPE *header,
- OMX_U32 rangeOffset, OMX_U32 rangeLength,
+ status_t emptyGraphicBuffer(
+ OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &buffer,
OMX_U32 flags, OMX_TICKS timestamp);
status_t getExtensionIndex(
@@ -156,6 +158,7 @@ private:
uint32_t mBufferIDCount;
KeyedVector<OMX::buffer_id, OMX_BUFFERHEADERTYPE *> mBufferIDToBufferHeader;
KeyedVector<OMX_BUFFERHEADERTYPE *, OMX::buffer_id> mBufferHeaderToBufferID;
+ MetadataBufferType mMetadataType[2];
// For debug support
char *mName;
@@ -203,15 +206,19 @@ private:
OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
status_t storeMetaDataInBuffers_l(
- OMX_U32 portIndex, OMX_BOOL enable,
- OMX_BOOL useGraphicBuffer, OMX_BOOL *usingGraphicBufferInMeta);
+ OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type);
status_t emptyBuffer_l(
OMX_BUFFERHEADERTYPE *header,
OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr);
+ status_t updateGraphicBufferInMeta_l(
+ OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
+
status_t createGraphicBufferSource(
- OMX_U32 portIndex, sp<IGraphicBufferConsumer> consumer = NULL);
+ OMX_U32 portIndex, sp<IGraphicBufferConsumer> consumer /* nullable */,
+ MetadataBufferType *type);
sp<GraphicBufferSource> getGraphicBufferSource();
void setGraphicBufferSource(const sp<GraphicBufferSource>& bufferSource);
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index e0ee87b..aae3e9f 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -194,18 +194,19 @@ void MPEG2TSExtractor::init() {
ATSParser::VIDEO).get()
: (AnotherPacketSource *)mParser->getSource(
ATSParser::AUDIO).get();
- int64_t prevBufferedDurationUs = 0;
+ size_t prevSyncSize = 1;
int64_t durationUs = -1;
List<int64_t> durations;
// Estimate duration --- stabilize until you get <500ms deviation.
- while (feedMore() == OK && ALooper::GetNowUs() - startTime <= 2000000ll) {
- status_t err;
- int64_t bufferedDurationUs = impl->getBufferedDurationUs(&err);
- if (err != OK) {
- break;
- }
- if (bufferedDurationUs != prevBufferedDurationUs) {
- durationUs = size * bufferedDurationUs / mOffset;
+ while (feedMore() == OK
+ && ALooper::GetNowUs() - startTime <= 2000000ll) {
+ if (mSeekSyncPoints->size() > prevSyncSize) {
+ prevSyncSize = mSeekSyncPoints->size();
+ int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
+ - mSeekSyncPoints->keyAt(0);
+ off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1)
+ - mSeekSyncPoints->valueAt(0);
+ durationUs = size * diffUs / diffOffset;
durations.push_back(durationUs);
if (durations.size() > 5) {
durations.erase(durations.begin());
@@ -225,9 +226,14 @@ void MPEG2TSExtractor::init() {
break;
}
}
- prevBufferedDurationUs = bufferedDurationUs;
}
}
+ status_t err;
+ int64_t bufferedDurationUs;
+ bufferedDurationUs = impl->getBufferedDurationUs(&err);
+ if (err == ERROR_END_OF_STREAM) {
+ durationUs = bufferedDurationUs;
+ }
if (durationUs > 0) {
const sp<MetaData> meta = impl->getFormat();
meta->setInt64(kKeyDuration, durationUs);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 01cd8f0..f797e63 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -29,6 +29,7 @@
#include <media/hardware/MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
+#include <HardwareAPI.h>
#include <inttypes.h>
#include "FrameDropper.h"
@@ -43,7 +44,6 @@ GraphicBufferSource::GraphicBufferSource(
uint32_t bufferWidth,
uint32_t bufferHeight,
uint32_t bufferCount,
- bool useGraphicBufferInMeta,
const sp<IGraphicBufferConsumer> &consumer) :
mInitCheck(UNKNOWN_ERROR),
mNodeInstance(nodeInstance),
@@ -68,8 +68,7 @@ GraphicBufferSource::GraphicBufferSource(
mTimePerCaptureUs(-1ll),
mTimePerFrameUs(-1ll),
mPrevCaptureUs(-1ll),
- mPrevFrameUs(-1ll),
- mUseGraphicBufferInMeta(useGraphicBufferInMeta) {
+ mPrevFrameUs(-1ll) {
ALOGV("GraphicBufferSource w=%u h=%u c=%u",
bufferWidth, bufferHeight, bufferCount);
@@ -262,27 +261,27 @@ void GraphicBufferSource::codecBufferEmptied(OMX_BUFFERHEADERTYPE* header) {
return;
}
- if (EXTRA_CHECK) {
+ if (EXTRA_CHECK && header->nAllocLen >= sizeof(MetadataBufferType)) {
// Pull the graphic buffer handle back out of the buffer, and confirm
// that it matches expectations.
OMX_U8* data = header->pBuffer;
MetadataBufferType type = *(MetadataBufferType *)data;
- if (type == kMetadataBufferTypeGrallocSource) {
- buffer_handle_t bufferHandle;
- memcpy(&bufferHandle, data + 4, sizeof(buffer_handle_t));
- if (bufferHandle != codecBuffer.mGraphicBuffer->handle) {
+ if (type == kMetadataBufferTypeGrallocSource
+ && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
+ VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)data;
+ if (grallocMeta.hHandle != codecBuffer.mGraphicBuffer->handle) {
// should never happen
ALOGE("codecBufferEmptied: buffer's handle is %p, expected %p",
- bufferHandle, codecBuffer.mGraphicBuffer->handle);
+ grallocMeta.hHandle, codecBuffer.mGraphicBuffer->handle);
CHECK(!"codecBufferEmptied: mismatched buffer");
}
- } else if (type == kMetadataBufferTypeGraphicBuffer) {
- GraphicBuffer *buffer;
- memcpy(&buffer, data + 4, sizeof(buffer));
- if (buffer != codecBuffer.mGraphicBuffer.get()) {
+ } else if (type == kMetadataBufferTypeANWBuffer
+ && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
+ VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)data;
+ if (nativeMeta.pBuffer != codecBuffer.mGraphicBuffer->getNativeBuffer()) {
// should never happen
ALOGE("codecBufferEmptied: buffer is %p, expected %p",
- buffer, codecBuffer.mGraphicBuffer.get());
+ nativeMeta.pBuffer, codecBuffer.mGraphicBuffer->getNativeBuffer());
CHECK(!"codecBufferEmptied: mismatched buffer");
}
}
@@ -703,36 +702,17 @@ status_t GraphicBufferSource::submitBuffer_l(
codecBuffer.mFrameNumber = item.mFrameNumber;
OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
- CHECK(header->nAllocLen >= 4 + sizeof(buffer_handle_t));
- OMX_U8* data = header->pBuffer;
- buffer_handle_t handle;
- if (!mUseGraphicBufferInMeta) {
- const OMX_U32 type = kMetadataBufferTypeGrallocSource;
- handle = codecBuffer.mGraphicBuffer->handle;
- memcpy(data, &type, 4);
- memcpy(data + 4, &handle, sizeof(buffer_handle_t));
- } else {
- // codecBuffer holds a reference to the GraphicBuffer, so
- // it is valid while it is with the OMX component
- const OMX_U32 type = kMetadataBufferTypeGraphicBuffer;
- memcpy(data, &type, 4);
- // passing a non-reference-counted graphicBuffer
- GraphicBuffer *buffer = codecBuffer.mGraphicBuffer.get();
- handle = buffer->handle;
- memcpy(data + 4, &buffer, sizeof(buffer));
- }
-
- status_t err = mNodeInstance->emptyDirectBuffer(header, 0,
- 4 + sizeof(buffer_handle_t), OMX_BUFFERFLAG_ENDOFFRAME,
- timeUs);
+ sp<GraphicBuffer> buffer = codecBuffer.mGraphicBuffer;
+ status_t err = mNodeInstance->emptyGraphicBuffer(
+ header, buffer, OMX_BUFFERFLAG_ENDOFFRAME, timeUs);
if (err != OK) {
- ALOGW("WARNING: emptyDirectBuffer failed: 0x%x", err);
+ ALOGW("WARNING: emptyNativeWindowBuffer failed: 0x%x", err);
codecBuffer.mGraphicBuffer = NULL;
return err;
}
- ALOGV("emptyDirectBuffer succeeded, h=%p p=%p bufhandle=%p",
- header, header->pBuffer, handle);
+ ALOGV("emptyNativeWindowBuffer succeeded, h=%p p=%p buf=%p bufhandle=%p",
+ header, header->pBuffer, buffer->getNativeBuffer(), buffer->handle);
return OK;
}
@@ -755,19 +735,9 @@ void GraphicBufferSource::submitEndOfInputStream_l() {
CodecBuffer& codecBuffer(mCodecBuffers.editItemAt(cbi));
OMX_BUFFERHEADERTYPE* header = codecBuffer.mHeader;
- if (EXTRA_CHECK) {
- // Guard against implementations that don't check nFilledLen.
- size_t fillLen = 4 + sizeof(buffer_handle_t);
- CHECK(header->nAllocLen >= fillLen);
- OMX_U8* data = header->pBuffer;
- memset(data, 0xcd, fillLen);
- }
-
- uint64_t timestamp = 0; // does this matter?
-
- status_t err = mNodeInstance->emptyDirectBuffer(header, /*offset*/ 0,
- /*length*/ 0, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
- timestamp);
+ status_t err = mNodeInstance->emptyGraphicBuffer(
+ header, NULL /* buffer */, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS,
+ 0 /* timestamp */);
if (err != OK) {
ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
} else {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 1047fb3..21ee96a 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -55,7 +55,6 @@ public:
uint32_t bufferWidth,
uint32_t bufferHeight,
uint32_t bufferCount,
- bool useGraphicBufferInMeta = false,
const sp<IGraphicBufferConsumer> &consumer = NULL
);
@@ -286,7 +285,7 @@ private:
int64_t mPrevCaptureUs;
int64_t mPrevFrameUs;
- bool mUseGraphicBufferInMeta;
+ MetadataBufferType mMetadataBufferType;
void onMessageReceived(const sp<AMessage> &msg);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index a1ceb2e..4ca827c 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -332,8 +332,8 @@ status_t OMX::getGraphicBufferUsage(
}
status_t OMX::storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable) {
- return findInstance(node)->storeMetaDataInBuffers(port_index, enable);
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
+ return findInstance(node)->storeMetaDataInBuffers(port_index, enable, type);
}
status_t OMX::prepareForAdaptivePlayback(
@@ -352,9 +352,9 @@ status_t OMX::configureVideoTunnelMode(
status_t OMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
return findInstance(node)->useBuffer(
- port_index, params, buffer);
+ port_index, params, buffer, allottedSize);
}
status_t OMX::useGraphicBuffer(
@@ -373,9 +373,9 @@ status_t OMX::updateGraphicBufferInMeta(
status_t OMX::createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer) {
+ sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
return findInstance(node)->createInputSurface(
- port_index, bufferProducer);
+ port_index, bufferProducer, type);
}
status_t OMX::createPersistentInputSurface(
@@ -387,8 +387,8 @@ status_t OMX::createPersistentInputSurface(
status_t OMX::setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer) {
- return findInstance(node)->setInputSurface(port_index, bufferConsumer);
+ const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
+ return findInstance(node)->setInputSurface(port_index, bufferConsumer, type);
}
@@ -405,9 +405,9 @@ status_t OMX::allocateBuffer(
status_t OMX::allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
return findInstance(node)->allocateBufferWithBackup(
- port_index, params, buffer);
+ port_index, params, buffer, allottedSize);
}
status_t OMX::freeBuffer(node_id node, OMX_U32 port_index, buffer_id buffer) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 3dc1f7f..e4b2de4 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -32,6 +32,7 @@
#include <gui/BufferQueue.h>
#include <HardwareAPI.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/misc.h>
@@ -135,6 +136,18 @@ struct BufferMeta {
header->nFilledLen);
}
+ // return either the codec or the backup buffer
+ sp<ABuffer> getBuffer(const OMX_BUFFERHEADERTYPE *header, bool backup) {
+ sp<ABuffer> buf;
+ if (backup && mMem != NULL) {
+ buf = new ABuffer(mMem->pointer(), mMem->size());
+ } else {
+ buf = new ABuffer(header->pBuffer, header->nAllocLen);
+ }
+ buf->setRange(header->nOffset, header->nFilledLen);
+ return buf;
+ }
+
void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
mGraphicBuffer = graphicBuffer;
}
@@ -180,6 +193,8 @@ OMXNodeInstance::OMXNodeInstance(
mNumPortBuffers[1] = 0;
mDebugLevelBumpPendingBuffers[0] = 0;
mDebugLevelBumpPendingBuffers[1] = 0;
+ mMetadataType[0] = kMetadataBufferTypeInvalid;
+ mMetadataType[1] = kMetadataBufferTypeInvalid;
}
OMXNodeInstance::~OMXNodeInstance() {
@@ -486,63 +501,73 @@ status_t OMXNodeInstance::getGraphicBufferUsage(
}
status_t OMXNodeInstance::storeMetaDataInBuffers(
- OMX_U32 portIndex,
- OMX_BOOL enable) {
+ OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
Mutex::Autolock autolock(mLock);
CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable);
- return storeMetaDataInBuffers_l(
- portIndex, enable,
- OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
+ return storeMetaDataInBuffers_l(portIndex, enable, type);
}
status_t OMXNodeInstance::storeMetaDataInBuffers_l(
- OMX_U32 portIndex,
- OMX_BOOL enable,
- OMX_BOOL useGraphicBuffer,
- OMX_BOOL *usingGraphicBufferInMetadata) {
+ OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {
+ if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+ return BAD_VALUE;
+ }
+
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.storeMetaDataInBuffers");
- OMX_STRING graphicBufferName = const_cast<OMX_STRING>(
- "OMX.google.android.index.storeGraphicBufferInMetaData");
- if (usingGraphicBufferInMetadata == NULL) {
- usingGraphicBufferInMetadata = &useGraphicBuffer;
- }
+ OMX_STRING nativeBufferName = const_cast<OMX_STRING>(
+ "OMX.google.android.index.storeANWBufferInMetadata");
+ MetadataBufferType negotiatedType;
- OMX_ERRORTYPE err =
- (useGraphicBuffer && portIndex == kPortIndexInput)
- ? OMX_GetExtensionIndex(mHandle, graphicBufferName, &index)
- : OMX_ErrorBadParameter;
- if (err == OMX_ErrorNone) {
- *usingGraphicBufferInMetadata = OMX_TRUE;
- name = graphicBufferName;
- } else {
- err = OMX_GetExtensionIndex(mHandle, name, &index);
- }
+ StoreMetaDataInBuffersParams params;
+ InitOMXParams(&params);
+ params.nPortIndex = portIndex;
+ params.bStoreMetaData = enable;
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, nativeBufferName, &index);
OMX_ERRORTYPE xerr = err;
if (err == OMX_ErrorNone) {
- StoreMetaDataInBuffersParams params;
- InitOMXParams(&params);
- params.nPortIndex = portIndex;
- params.bStoreMetaData = enable;
-
err = OMX_SetParameter(mHandle, index, &params);
+ if (err == OMX_ErrorNone) {
+ name = nativeBufferName; // set name for debugging
+ negotiatedType = kMetadataBufferTypeANWBuffer;
+ }
+ }
+ if (err != OMX_ErrorNone) {
+ err = OMX_GetExtensionIndex(mHandle, name, &index);
+ xerr = err;
+ if (err == OMX_ErrorNone) {
+ negotiatedType = kMetadataBufferTypeGrallocSource;
+ err = OMX_SetParameter(mHandle, index, &params);
+ }
}
// don't log loud error if component does not support metadata mode on the output
if (err != OMX_ErrorNone) {
- *usingGraphicBufferInMetadata = OMX_FALSE;
if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
CLOGW("component does not support metadata mode; using fallback");
} else if (xerr != OMX_ErrorNone) {
CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
} else {
- CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d GB=%d", name, index,
- portString(portIndex), portIndex, enable, useGraphicBuffer);
+ CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d type=%d", name, index,
+ portString(portIndex), portIndex, enable, negotiatedType);
+ }
+ negotiatedType = mMetadataType[portIndex];
+ } else {
+ if (!enable) {
+ negotiatedType = kMetadataBufferTypeInvalid;
}
+ mMetadataType[portIndex] = negotiatedType;
}
+ CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u negotiated %s:%d",
+ portString(portIndex), portIndex, asString(negotiatedType), negotiatedType);
+
+ if (type != NULL) {
+ *type = negotiatedType;
+ }
+
return StatusFromOMXError(err);
}
@@ -620,8 +645,11 @@ status_t OMXNodeInstance::configureVideoTunnelMode(
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer) {
+ OMX::buffer_id *buffer, OMX_U32 allottedSize) {
Mutex::Autolock autoLock(mLock);
+ if (allottedSize > params->size()) {
+ return BAD_VALUE;
+ }
BufferMeta *buffer_meta = new BufferMeta(params);
@@ -629,10 +657,11 @@ status_t OMXNodeInstance::useBuffer(
OMX_ERRORTYPE err = OMX_UseBuffer(
mHandle, &header, portIndex, buffer_meta,
- params->size(), static_cast<OMX_U8 *>(params->pointer()));
+ allottedSize, static_cast<OMX_U8 *>(params->pointer()));
if (err != OMX_ErrorNone) {
- CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
+ CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(
+ portIndex, (size_t)allottedSize, params->pointer()));
delete buffer_meta;
buffer_meta = NULL;
@@ -654,7 +683,7 @@ status_t OMXNodeInstance::useBuffer(
}
CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
- *buffer, portIndex, "%zu@%p", params->size(), params->pointer()));
+ *buffer, portIndex, "%u@%p", allottedSize, params->pointer()));
return OK;
}
@@ -770,37 +799,59 @@ status_t OMXNodeInstance::useGraphicBuffer(
return OK;
}
-status_t OMXNodeInstance::updateGraphicBufferInMeta(
+status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
- OMX::buffer_id buffer) {
- Mutex::Autolock autoLock(mLock);
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
+ if (portIndex != kPortIndexInput && portIndex != kPortIndexOutput) {
+ return BAD_VALUE;
+ }
- OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
- VideoDecoderOutputMetaData *metadata =
- (VideoDecoderOutputMetaData *)(header->pBuffer);
BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
bufferMeta->setGraphicBuffer(graphicBuffer);
- metadata->eType = kMetadataBufferTypeGrallocSource;
- metadata->pHandle = graphicBuffer->handle;
+ if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource
+ && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
+ VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(header->pBuffer);
+ metadata.eType = kMetadataBufferTypeGrallocSource;
+ metadata.hHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
+ } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
+ && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
+ VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(header->pBuffer);
+ metadata.eType = kMetadataBufferTypeANWBuffer;
+ metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
+ metadata.nFenceFd = -1;
+ } else {
+ CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x bad type (%d) or size (%u)",
+ portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
+ return BAD_VALUE;
+ }
+
CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
portString(portIndex), portIndex, buffer, graphicBuffer->handle);
return OK;
}
+status_t OMXNodeInstance::updateGraphicBufferInMeta(
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
+ OMX::buffer_id buffer) {
+ Mutex::Autolock autoLock(mLock);
+ OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
+ return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header);
+}
+
status_t OMXNodeInstance::createGraphicBufferSource(
- OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer) {
+ OMX_U32 portIndex, sp<IGraphicBufferConsumer> bufferConsumer, MetadataBufferType *type) {
status_t err;
const sp<GraphicBufferSource>& surfaceCheck = getGraphicBufferSource();
if (surfaceCheck != NULL) {
+ if (portIndex < NELEM(mMetadataType) && type != NULL) {
+ *type = mMetadataType[portIndex];
+ }
return ALREADY_EXISTS;
}
- // Input buffers will hold meta-data (gralloc references).
- OMX_BOOL usingGraphicBuffer = OMX_FALSE;
- err = storeMetaDataInBuffers_l(
- portIndex, OMX_TRUE,
- OMX_TRUE /* useGraphicBuffer */, &usingGraphicBuffer);
+ // Input buffers will hold meta-data (ANativeWindowBuffer references).
+ err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, type);
if (err != OK) {
return err;
}
@@ -830,7 +881,6 @@ status_t OMXNodeInstance::createGraphicBufferSource(
def.format.video.nFrameWidth,
def.format.video.nFrameHeight,
def.nBufferCountActual,
- usingGraphicBuffer,
bufferConsumer);
if ((err = bufferSource->initCheck()) != OK) {
@@ -842,9 +892,9 @@ status_t OMXNodeInstance::createGraphicBufferSource(
}
status_t OMXNodeInstance::createInputSurface(
- OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer) {
+ OMX_U32 portIndex, sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
Mutex::Autolock autolock(mLock);
- status_t err = createGraphicBufferSource(portIndex);
+ status_t err = createGraphicBufferSource(portIndex, NULL /* bufferConsumer */, type);
if (err != OK) {
return err;
@@ -882,9 +932,10 @@ status_t OMXNodeInstance::createPersistentInputSurface(
}
status_t OMXNodeInstance::setInputSurface(
- OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer) {
+ OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer,
+ MetadataBufferType *type) {
Mutex::Autolock autolock(mLock);
- return createGraphicBufferSource(portIndex, bufferConsumer);
+ return createGraphicBufferSource(portIndex, bufferConsumer, type);
}
status_t OMXNodeInstance::signalEndOfInputStream() {
@@ -939,19 +990,21 @@ status_t OMXNodeInstance::allocateBuffer(
status_t OMXNodeInstance::allocateBufferWithBackup(
OMX_U32 portIndex, const sp<IMemory> &params,
- OMX::buffer_id *buffer) {
+ OMX::buffer_id *buffer, OMX_U32 allottedSize) {
Mutex::Autolock autoLock(mLock);
+ if (allottedSize > params->size()) {
+ return BAD_VALUE;
+ }
BufferMeta *buffer_meta = new BufferMeta(params, true);
OMX_BUFFERHEADERTYPE *header;
OMX_ERRORTYPE err = OMX_AllocateBuffer(
- mHandle, &header, portIndex, buffer_meta, params->size());
-
+ mHandle, &header, portIndex, buffer_meta, allottedSize);
if (err != OMX_ErrorNone) {
CLOG_ERROR(allocateBufferWithBackup, err,
- SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
+ SIMPLE_BUFFER(portIndex, (size_t)allottedSize, params->pointer()));
delete buffer_meta;
buffer_meta = NULL;
@@ -971,8 +1024,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
bufferSource->addCodecBuffer(header);
}
- CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %p",
- params->size(), params->pointer(), header->pBuffer));
+ CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%u@%p :> %p",
+ allottedSize, params->pointer(), header->pBuffer));
return OK;
}
@@ -1038,7 +1091,24 @@ status_t OMXNodeInstance::emptyBuffer(
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(header->pAppPrivate);
- buffer_meta->CopyToOMX(header);
+ sp<ABuffer> backup = buffer_meta->getBuffer(header, true /* backup */);
+ sp<ABuffer> codec = buffer_meta->getBuffer(header, false /* backup */);
+
+ // convert incoming ANW meta buffers if component is configured for gralloc metadata mode
+ if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource
+ && backup->capacity() >= sizeof(VideoNativeMetadata)
+ && codec->capacity() >= sizeof(VideoGrallocMetadata)
+ && ((VideoNativeMetadata *)backup->base())->eType
+ == kMetadataBufferTypeANWBuffer) {
+ VideoNativeMetadata &backupMeta = *(VideoNativeMetadata *)backup->base();
+ VideoGrallocMetadata &codecMeta = *(VideoGrallocMetadata *)codec->base();
+ ALOGV("converting ANWB %p to handle %p", backupMeta.pBuffer, backupMeta.pBuffer->handle);
+ codecMeta.hHandle = backupMeta.pBuffer->handle;
+ codecMeta.eType = kMetadataBufferTypeGrallocSource;
+ header->nFilledLen = sizeof(codecMeta);
+ } else {
+ buffer_meta->CopyToOMX(header);
+ }
return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer);
}
@@ -1100,15 +1170,19 @@ status_t OMXNodeInstance::emptyBuffer_l(
}
// like emptyBuffer, but the data is already in header->pBuffer
-status_t OMXNodeInstance::emptyDirectBuffer(
- OMX_BUFFERHEADERTYPE *header,
- OMX_U32 rangeOffset, OMX_U32 rangeLength,
+status_t OMXNodeInstance::emptyGraphicBuffer(
+ OMX_BUFFERHEADERTYPE *header, const sp<GraphicBuffer> &graphicBuffer,
OMX_U32 flags, OMX_TICKS timestamp) {
Mutex::Autolock autoLock(mLock);
+ OMX::buffer_id buffer = findBufferID(header);
+ status_t err = updateGraphicBufferInMeta_l(kPortIndexInput, graphicBuffer, buffer, header);
+ if (err != OK) {
+ CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER((intptr_t)header->pBuffer, header));
+ return err;
+ }
- header->nFilledLen = rangeLength;
- header->nOffset = rangeOffset;
-
+ header->nOffset = 0;
+ header->nFilledLen = graphicBuffer == NULL ? 0 : header->nAllocLen;
return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer);
}
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index d4d6217..5f80cbc 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -155,7 +155,7 @@ void SoftVideoEncoderOMXComponent::updatePortParams() {
uint32_t rawBufferSize =
inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2;
if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
- inDef->nBufferSize = 4 + max(sizeof(buffer_handle_t), sizeof(GraphicBuffer *));
+ inDef->nBufferSize = max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata));
} else {
inDef->nBufferSize = rawBufferSize;
}
@@ -482,8 +482,8 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
size_t dstVStride = height;
MetadataBufferType bufferType = *(MetadataBufferType *)src;
- bool usingGraphicBuffer = bufferType == kMetadataBufferTypeGraphicBuffer;
- if (!usingGraphicBuffer && bufferType != kMetadataBufferTypeGrallocSource) {
+ bool usingANWBuffer = bufferType == kMetadataBufferTypeANWBuffer;
+ if (!usingANWBuffer && bufferType != kMetadataBufferTypeGrallocSource) {
ALOGE("Unsupported metadata type (%d)", bufferType);
return NULL;
}
@@ -499,13 +499,14 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
int format;
size_t srcStride;
size_t srcVStride;
- if (usingGraphicBuffer) {
- if (srcSize < sizeof(OMX_U32) + sizeof(GraphicBuffer *)) {
- ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(OMX_U32) + sizeof(GraphicBuffer *));
+ if (usingANWBuffer) {
+ if (srcSize < sizeof(VideoNativeMetadata)) {
+ ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoNativeMetadata));
return NULL;
}
- GraphicBuffer *buffer = *(GraphicBuffer **)(src + sizeof(OMX_U32));
+ VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)src;
+ ANativeWindowBuffer *buffer = nativeMeta.pBuffer;
handle = buffer->handle;
format = buffer->format;
srcStride = buffer->stride;
@@ -519,12 +520,13 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
} else {
// TODO: remove this part. Check if anyone uses this.
- if (srcSize < sizeof(OMX_U32) + sizeof(buffer_handle_t)) {
- ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(OMX_U32) + sizeof(buffer_handle_t));
+ if (srcSize < sizeof(VideoGrallocMetadata)) {
+ ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoGrallocMetadata));
return NULL;
}
- handle = *(buffer_handle_t *)(src + sizeof(OMX_U32));
+ VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)(src);
+ handle = grallocMeta.hHandle;
// assume HAL_PIXEL_FORMAT_RGBA_8888
// there is no way to get the src stride without the graphic buffer
format = HAL_PIXEL_FORMAT_RGBA_8888;
@@ -606,7 +608,7 @@ const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer(
OMX_ERRORTYPE SoftVideoEncoderOMXComponent::getExtensionIndex(
const char *name, OMX_INDEXTYPE *index) {
if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers") ||
- !strcmp(name, "OMX.google.android.index.storeGraphicBufferInMetaData")) {
+ !strcmp(name, "OMX.google.android.index.storeANWBufferInMetadata")) {
*(int32_t*)index = kStoreMetaDataExtensionIndex;
return OMX_ErrorNone;
}
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index 67ff145..294b2ed 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -193,7 +193,7 @@ status_t Harness::allocatePortBuffers(
CHECK(buffer.mMemory != NULL);
err = mOMX->allocateBufferWithBackup(
- node, portIndex, buffer.mMemory, &buffer.mID);
+ node, portIndex, buffer.mMemory, &buffer.mID, buffer.mMemory->size());
EXPECT_SUCCESS(err, "allocateBuffer");
buffers->push(buffer);
diff --git a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
index cee62a3..ab547be 100644
--- a/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
+++ b/media/libstagefright/tests/MediaCodecListOverrides_test.cpp
@@ -150,7 +150,11 @@ TEST_F(MediaCodecListOverridesTest, exportTestResultsToXML) {
fclose(f);
free(buf);
- EXPECT_TRUE(overrides == kTestOverridesStr);
+ AString expected;
+ expected.append(getProfilingVersionString());
+ expected.append("\n");
+ expected.append(kTestOverridesStr);
+ EXPECT_TRUE(overrides == expected);
remove(fileName);
}
diff --git a/media/utils/Android.mk b/media/utils/Android.mk
new file mode 100644
index 0000000..dfadbc8
--- /dev/null
+++ b/media/utils/Android.mk
@@ -0,0 +1,39 @@
+# Copyright 2015 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ BatteryNotifier.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libcutils \
+ liblog \
+ libutils \
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS += \
+ -Wall \
+ -Wextra \
+ -Werror \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+
+LOCAL_MODULE := libmediautils
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/utils/BatteryNotifier.cpp b/media/utils/BatteryNotifier.cpp
new file mode 100644
index 0000000..7f9cd7a
--- /dev/null
+++ b/media/utils/BatteryNotifier.cpp
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2015, 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 "include/mediautils/BatteryNotifier.h"
+
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+void BatteryNotifier::DeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
+ BatteryNotifier::getInstance().onBatteryStatServiceDied();
+}
+
+BatteryNotifier::BatteryNotifier() : mVideoRefCount(0), mAudioRefCount(0) {}
+
+BatteryNotifier::~BatteryNotifier() {
+ Mutex::Autolock _l(mLock);
+ if (mDeathNotifier != nullptr) {
+ IInterface::asBinder(mBatteryStatService)->unlinkToDeath(mDeathNotifier);
+ }
+}
+
+void BatteryNotifier::noteStartVideo() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ if (mVideoRefCount == 0 && batteryService != nullptr) {
+ batteryService->noteStartVideo(AID_MEDIA);
+ }
+ mVideoRefCount++;
+}
+
+void BatteryNotifier::noteStopVideo() {
+ Mutex::Autolock _l(mLock);
+ if (mVideoRefCount == 0) {
+ ALOGW("%s: video refcount is broken.", __FUNCTION__);
+ return;
+ }
+
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+
+ mVideoRefCount--;
+ if (mVideoRefCount == 0 && batteryService != nullptr) {
+ batteryService->noteStopVideo(AID_MEDIA);
+ }
+}
+
+void BatteryNotifier::noteResetVideo() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ mVideoRefCount = 0;
+ if (batteryService != nullptr) {
+ batteryService->noteResetAudio();
+ }
+}
+
+void BatteryNotifier::noteStartAudio() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ if (mAudioRefCount == 0 && batteryService != nullptr) {
+ batteryService->noteStartAudio(AID_MEDIA);
+ }
+ mAudioRefCount++;
+}
+
+void BatteryNotifier::noteStopAudio() {
+ Mutex::Autolock _l(mLock);
+ if (mAudioRefCount == 0) {
+ ALOGW("%s: audio refcount is broken.", __FUNCTION__);
+ return;
+ }
+
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+
+ mAudioRefCount--;
+ if (mAudioRefCount == 0 && batteryService != nullptr) {
+ batteryService->noteStopAudio(AID_MEDIA);
+ }
+}
+
+void BatteryNotifier::noteResetAudio() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ mAudioRefCount = 0;
+ if (batteryService != nullptr) {
+ batteryService->noteResetAudio();
+ }
+}
+
+void BatteryNotifier::noteFlashlightOn(const String8& id, int uid) {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+
+ std::pair<String8, int> k = std::make_pair(id, uid);
+ if (!mFlashlightState[k]) {
+ mFlashlightState[k] = true;
+ if (batteryService != nullptr) {
+ batteryService->noteFlashlightOn(uid);
+ }
+ }
+}
+
+void BatteryNotifier::noteFlashlightOff(const String8& id, int uid) {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+
+ std::pair<String8, int> k = std::make_pair(id, uid);
+ if (mFlashlightState[k]) {
+ mFlashlightState[k] = false;
+ if (batteryService != nullptr) {
+ batteryService->noteFlashlightOff(uid);
+ }
+ }
+}
+
+void BatteryNotifier::noteResetFlashlight() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ mFlashlightState.clear();
+ if (batteryService != nullptr) {
+ batteryService->noteResetFlashlight();
+ }
+}
+
+void BatteryNotifier::noteStartCamera(const String8& id, int uid) {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ std::pair<String8, int> k = std::make_pair(id, uid);
+ if (!mCameraState[k]) {
+ mCameraState[k] = true;
+ if (batteryService != nullptr) {
+ batteryService->noteStartCamera(uid);
+ }
+ }
+}
+
+void BatteryNotifier::noteStopCamera(const String8& id, int uid) {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ std::pair<String8, int> k = std::make_pair(id, uid);
+ if (mCameraState[k]) {
+ mCameraState[k] = false;
+ if (batteryService != nullptr) {
+ batteryService->noteStopCamera(uid);
+ }
+ }
+}
+
+void BatteryNotifier::noteResetCamera() {
+ Mutex::Autolock _l(mLock);
+ sp<IBatteryStats> batteryService = getBatteryService_l();
+ mCameraState.clear();
+ if (batteryService != nullptr) {
+ batteryService->noteResetCamera();
+ }
+}
+
+void BatteryNotifier::onBatteryStatServiceDied() {
+ Mutex::Autolock _l(mLock);
+ mBatteryStatService.clear();
+ mDeathNotifier.clear();
+ // Do not reset mVideoRefCount and mAudioRefCount here. The ref
+ // counting is independent of the battery service availability.
+ // We need this if battery service becomes available after media
+ // started.
+
+}
+
+sp<IBatteryStats> BatteryNotifier::getBatteryService_l() {
+ if (mBatteryStatService != nullptr) {
+ return mBatteryStatService;
+ }
+ // Get battery service from service manager
+ const sp<IServiceManager> sm(defaultServiceManager());
+ if (sm != nullptr) {
+ const String16 name("batterystats");
+ mBatteryStatService = interface_cast<IBatteryStats>(sm->checkService(name));
+ if (mBatteryStatService == nullptr) {
+ ALOGE("batterystats service unavailable!");
+ return nullptr;
+ }
+
+ mDeathNotifier = new DeathNotifier();
+ IInterface::asBinder(mBatteryStatService)->linkToDeath(mDeathNotifier);
+
+ // Notify start now if media already started
+ if (mVideoRefCount > 0) {
+ mBatteryStatService->noteStartVideo(AID_MEDIA);
+ }
+ if (mAudioRefCount > 0) {
+ mBatteryStatService->noteStartAudio(AID_MEDIA);
+ }
+ }
+ return mBatteryStatService;
+}
+
+ANDROID_SINGLETON_STATIC_INSTANCE(BatteryNotifier);
+
+} // namespace android
diff --git a/media/utils/README b/media/utils/README
new file mode 100644
index 0000000..65ab0b8
--- /dev/null
+++ b/media/utils/README
@@ -0,0 +1,4 @@
+This is a common shared library for media utility classes.
+
+Consider adding your utility class/function here if it will
+be used across several of the media libraries.
diff --git a/media/utils/include/mediautils/BatteryNotifier.h b/media/utils/include/mediautils/BatteryNotifier.h
new file mode 100644
index 0000000..4904804
--- /dev/null
+++ b/media/utils/include/mediautils/BatteryNotifier.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015, 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 MEDIA_BATTERY_NOTIFIER_H
+#define MEDIA_BATTERY_NOTIFIER_H
+
+#include <binder/IBatteryStats.h>
+#include <utils/Singleton.h>
+#include <utils/String8.h>
+
+#include <map>
+#include <utility>
+
+namespace android {
+
+/**
+ * Class used for logging battery life events in mediaserver.
+ */
+class BatteryNotifier : public Singleton<BatteryNotifier> {
+
+ friend class Singleton<BatteryNotifier>;
+ BatteryNotifier();
+
+public:
+ ~BatteryNotifier();
+
+ void noteStartVideo();
+ void noteStopVideo();
+ void noteResetVideo();
+ void noteStartAudio();
+ void noteStopAudio();
+ void noteResetAudio();
+ void noteFlashlightOn(const String8& id, int uid);
+ void noteFlashlightOff(const String8& id, int uid);
+ void noteResetFlashlight();
+ void noteStartCamera(const String8& id, int uid);
+ void noteStopCamera(const String8& id, int uid);
+ void noteResetCamera();
+
+private:
+ void onBatteryStatServiceDied();
+
+ class DeathNotifier : public IBinder::DeathRecipient {
+ virtual void binderDied(const wp<IBinder>& /*who*/);
+ };
+
+ Mutex mLock;
+ int mVideoRefCount;
+ int mAudioRefCount;
+ std::map<std::pair<String8, int>, bool> mFlashlightState;
+ std::map<std::pair<String8, int>, bool> mCameraState;
+ sp<IBatteryStats> mBatteryStatService;
+ sp<DeathNotifier> mDeathNotifier;
+
+ sp<IBatteryStats> getBatteryService_l();
+};
+
+} // namespace android
+
+#endif // MEDIA_BATTERY_NOTIFIER_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 8bccb47..949c91d 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -335,13 +335,21 @@ status_t AudioFlinger::EffectModule::configure()
// TODO: handle configuration of effects replacing track process
channelMask = thread->channelMask();
+ mConfig.outputCfg.channels = channelMask;
if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
} else {
mConfig.inputCfg.channels = channelMask;
+ // TODO: Update this logic when multichannel effects are implemented.
+ // For offloaded tracks consider mono output as stereo for proper effect initialization
+ if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
+ mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+ ALOGV("Overriding effect input and output as STEREO");
+ }
}
- mConfig.outputCfg.channels = channelMask;
+
mConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
mConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
mConfig.inputCfg.samplingRate = thread->sampleRate();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 0593e1b..7809eff 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -356,13 +356,47 @@ String8 devicesToString(audio_devices_t devices)
AUDIO_DEVICE_OUT_SPEAKER, "SPEAKER",
AUDIO_DEVICE_OUT_WIRED_HEADSET, "WIRED_HEADSET",
AUDIO_DEVICE_OUT_WIRED_HEADPHONE, "WIRED_HEADPHONE",
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "BLUETOOTH_SCO",
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET, "BLUETOOTH_SCO_HEADSET",
+ AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, "BLUETOOTH_SCO_CARKIT",
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "BLUETOOTH_A2DP",
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, "BLUETOOTH_A2DP_HEADPHONES",
+ AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, "BLUETOOTH_A2DP_SPEAKER",
+ AUDIO_DEVICE_OUT_AUX_DIGITAL, "AUX_DIGITAL",
+ AUDIO_DEVICE_OUT_HDMI, "HDMI",
+ AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET, "ANLG_DOCK_HEADSET",
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, "DGTL_DOCK_HEADSET",
+ AUDIO_DEVICE_OUT_USB_ACCESSORY, "USB_ACCESSORY",
+ AUDIO_DEVICE_OUT_USB_DEVICE, "USB_DEVICE",
AUDIO_DEVICE_OUT_TELEPHONY_TX, "TELEPHONY_TX",
+ AUDIO_DEVICE_OUT_LINE, "LINE",
+ AUDIO_DEVICE_OUT_HDMI_ARC, "HDMI_ARC",
+ AUDIO_DEVICE_OUT_SPDIF, "SPDIF",
+ AUDIO_DEVICE_OUT_FM, "FM",
+ AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE",
+ AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE",
AUDIO_DEVICE_NONE, "NONE", // must be last
}, mappingsIn[] = {
+ AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION",
+ AUDIO_DEVICE_IN_AMBIENT, "AMBIENT",
AUDIO_DEVICE_IN_BUILTIN_MIC, "BUILTIN_MIC",
+ AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "BLUETOOTH_SCO_HEADSET",
AUDIO_DEVICE_IN_WIRED_HEADSET, "WIRED_HEADSET",
+ AUDIO_DEVICE_IN_AUX_DIGITAL, "AUX_DIGITAL",
AUDIO_DEVICE_IN_VOICE_CALL, "VOICE_CALL",
+ AUDIO_DEVICE_IN_TELEPHONY_RX, "TELEPHONY_RX",
+ AUDIO_DEVICE_IN_BACK_MIC, "BACK_MIC",
AUDIO_DEVICE_IN_REMOTE_SUBMIX, "REMOTE_SUBMIX",
+ AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, "ANLG_DOCK_HEADSET",
+ AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, "DGTL_DOCK_HEADSET",
+ AUDIO_DEVICE_IN_USB_ACCESSORY, "USB_ACCESSORY",
+ AUDIO_DEVICE_IN_USB_DEVICE, "USB_DEVICE",
+ AUDIO_DEVICE_IN_FM_TUNER, "FM_TUNER",
+ AUDIO_DEVICE_IN_TV_TUNER, "TV_TUNER",
+ AUDIO_DEVICE_IN_LINE, "LINE",
+ AUDIO_DEVICE_IN_SPDIF, "SPDIF",
+ AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP",
+ AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK",
AUDIO_DEVICE_NONE, "NONE", // must be last
};
String8 result;
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 9c60911..cbead32 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -62,6 +62,7 @@ LOCAL_SHARED_LIBRARIES:= \
libbinder \
libcutils \
libmedia \
+ libmediautils \
libcamera_client \
libgui \
libhardware \
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 79e73f9..6f073ed 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -41,6 +41,7 @@
#include <media/AudioSystem.h>
#include <media/IMediaHTTPService.h>
#include <media/mediaplayer.h>
+#include <mediautils/BatteryNotifier.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/String16.h>
@@ -140,6 +141,11 @@ void CameraService::onFirstRef()
BnCameraService::onFirstRef();
+ // Update battery life tracking if service is restarting
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteResetCamera();
+ notifier.noteResetFlashlight();
+
camera_module_t *rawModule;
int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
(const hw_module_t **)&rawModule);
@@ -336,12 +342,39 @@ void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
res = setTorchStatusLocked(cameraId, newStatus);
if (res) {
- ALOGE("%s: Failed to set the torch status", __FUNCTION__,
- (uint32_t)newStatus);
+ ALOGE("%s: Failed to set the torch status", __FUNCTION__, (uint32_t)newStatus);
return;
}
{
+ // Update battery life logging for flashlight
+ Mutex::Autolock al(mTorchClientMapMutex);
+ auto iter = mTorchUidMap.find(cameraId);
+ if (iter != mTorchUidMap.end()) {
+ int oldUid = iter->second.second;
+ int newUid = iter->second.first;
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ if (oldUid != newUid) {
+ // If the UID has changed, log the status and update current UID in mTorchUidMap
+ if (status == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOff(cameraId, oldUid);
+ }
+ if (newStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOn(cameraId, newUid);
+ }
+ iter->second.second = newUid;
+ } else {
+ // If the UID has not changed, log the status
+ if (newStatus == ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON) {
+ notifier.noteFlashlightOn(cameraId, oldUid);
+ } else {
+ notifier.noteFlashlightOff(cameraId, oldUid);
+ }
+ }
+ }
+ }
+
+ {
Mutex::Autolock lock(mStatusListenerLock);
for (auto& i : mListenerList) {
i->onTorchStatusChanged(newStatus, String16{cameraId});
@@ -1154,12 +1187,13 @@ status_t CameraService::connectDevice(
status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder) {
- if (enabled && clientBinder == NULL) {
+ if (enabled && clientBinder == nullptr) {
ALOGE("%s: torch client binder is NULL", __FUNCTION__);
return -EINVAL;
}
String8 id = String8(cameraId.string());
+ int uid = getCallingUid();
// verify id is valid.
auto state = getCameraState(id);
@@ -1198,7 +1232,21 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
}
}
+ {
+ // Update UID map - this is used in the torch status changed callbacks, so must be done
+ // before setTorchMode
+ Mutex::Autolock al(mTorchClientMapMutex);
+ if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
+ mTorchUidMap[id].first = uid;
+ mTorchUidMap[id].second = uid;
+ } else {
+ // Set the pending UID
+ mTorchUidMap[id].first = uid;
+ }
+ }
+
status_t res = mFlashlight->setTorchMode(id, enabled);
+
if (res) {
ALOGE("%s: setting torch mode of camera %s to %d failed. %s (%d)",
__FUNCTION__, id.string(), enabled, strerror(-res), res);
@@ -1209,19 +1257,17 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,
// update the link to client's death
Mutex::Autolock al(mTorchClientMapMutex);
ssize_t index = mTorchClientMap.indexOfKey(id);
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
if (enabled) {
if (index == NAME_NOT_FOUND) {
mTorchClientMap.add(id, clientBinder);
} else {
- const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
- oldBinder->unlinkToDeath(this);
-
+ mTorchClientMap.valueAt(index)->unlinkToDeath(this);
mTorchClientMap.replaceValueAt(index, clientBinder);
}
clientBinder->linkToDeath(this);
} else if (index != NAME_NOT_FOUND) {
- sp<IBinder> oldBinder = mTorchClientMap.valueAt(index);
- oldBinder->unlinkToDeath(this);
+ mTorchClientMap.valueAt(index)->unlinkToDeath(this);
}
}
@@ -1243,8 +1289,7 @@ void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size
}
}
-status_t CameraService::addListener(
- const sp<ICameraServiceListener>& listener) {
+status_t CameraService::addListener(const sp<ICameraServiceListener>& listener) {
ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
if (listener == 0) {
@@ -1965,9 +2010,40 @@ String8 CameraService::CameraState::getId() const {
}
// ----------------------------------------------------------------------------
+// ClientEventListener
+// ----------------------------------------------------------------------------
+
+void CameraService::ClientEventListener::onClientAdded(
+ const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor) {
+ auto basicClient = descriptor.getValue();
+ if (basicClient.get() != nullptr) {
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteStartCamera(descriptor.getKey(),
+ static_cast<int>(basicClient->getClientUid()));
+ }
+}
+
+void CameraService::ClientEventListener::onClientRemoved(
+ const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor) {
+ auto basicClient = descriptor.getValue();
+ if (basicClient.get() != nullptr) {
+ BatteryNotifier& notifier(BatteryNotifier::getInstance());
+ notifier.noteStopCamera(descriptor.getKey(),
+ static_cast<int>(basicClient->getClientUid()));
+ }
+}
+
+
+// ----------------------------------------------------------------------------
// CameraClientManager
// ----------------------------------------------------------------------------
+CameraService::CameraClientManager::CameraClientManager() {
+ setListener(std::make_shared<ClientEventListener>());
+}
+
CameraService::CameraClientManager::~CameraClientManager() {}
sp<CameraService::BasicClient> CameraService::CameraClientManager::getCameraClient(
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index ce3cb44..3298772 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -46,6 +46,7 @@
#include <string>
#include <map>
#include <memory>
+#include <utility>
namespace android {
@@ -327,6 +328,20 @@ public:
}; // class Client
+ /**
+ * A listener class that implements the LISTENER interface for use with a ClientManager, and
+ * implements the following methods:
+ * void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+ * void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ */
+ class ClientEventListener {
+ public:
+ void onClientAdded(const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor);
+ void onClientRemoved(const resource_policy::ClientDescriptor<String8,
+ sp<CameraService::BasicClient>>& descriptor);
+ }; // class ClientEventListener
+
typedef std::shared_ptr<resource_policy::ClientDescriptor<String8,
sp<CameraService::BasicClient>>> DescriptorPtr;
@@ -338,9 +353,10 @@ public:
* This class manages the eviction behavior for the camera clients. See the parent class
* implementation in utils/ClientManager for the specifics of this behavior.
*/
- class CameraClientManager :
- public resource_policy::ClientManager<String8, sp<CameraService::BasicClient>> {
+ class CameraClientManager : public resource_policy::ClientManager<String8,
+ sp<CameraService::BasicClient>, ClientEventListener> {
public:
+ CameraClientManager();
virtual ~CameraClientManager();
/**
@@ -624,13 +640,15 @@ private:
sp<CameraFlashlight> mFlashlight;
// guard mTorchStatusMap
Mutex mTorchStatusMutex;
- // guard mTorchClientMap
+ // guard mTorchClientMap, mTorchUidMap
Mutex mTorchClientMapMutex;
// camera id -> torch status
KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap;
// camera id -> torch client binder
// only store the last client that turns on each camera's torch mode
- KeyedVector<String8, sp<IBinder> > mTorchClientMap;
+ KeyedVector<String8, sp<IBinder>> mTorchClientMap;
+ // camera id -> [incoming uid, current uid] pair
+ std::map<String8, std::pair<int, int>> mTorchUidMap;
// check and handle if torch client's process has died
void handleTorchClientBinderDied(const wp<IBinder> &who);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 0bc8ed1..45d9421 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2613,6 +2613,21 @@ status_t Camera3Device::RequestThread::clear(
if (listener != NULL) {
for (RequestList::iterator it = mRequestQueue.begin();
it != mRequestQueue.end(); ++it) {
+ // Abort the input buffers for reprocess requests.
+ if ((*it)->mInputStream != NULL) {
+ camera3_stream_buffer_t inputBuffer;
+ status_t res = (*it)->mInputStream->getInputBuffer(&inputBuffer);
+ if (res != OK) {
+ ALOGW("%s: %d: couldn't get input buffer while clearing the request "
+ "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
+ } else {
+ res = (*it)->mInputStream->returnInputBuffer(inputBuffer);
+ if (res != OK) {
+ ALOGE("%s: %d: couldn't return input buffer while clearing the request "
+ "list: %s (%d)", __FUNCTION__, __LINE__, strerror(-res), res);
+ }
+ }
+ }
// Set the frame number this request would have had, if it
// had been submitted; this frame number will not be reused.
// The requestId and burstId fields were set when the request was
@@ -2752,31 +2767,11 @@ bool Camera3Device::RequestThread::threadLoop() {
__FUNCTION__);
}
- camera3_stream_buffer_t inputBuffer;
uint32_t totalNumBuffers = 0;
// Fill in buffers
-
if (nextRequest->mInputStream != NULL) {
- res = nextRequest->mInputStream->getInputBuffer(&inputBuffer);
- if (res != OK) {
- // Can't get input buffer from gralloc queue - this could be due to
- // disconnected queue or other producer misbehavior, so not a fatal
- // error
- ALOGE("RequestThread: Can't get input buffer, skipping request:"
- " %s (%d)", strerror(-res), res);
- {
- Mutex::Autolock l(mRequestLock);
- if (mListener != NULL) {
- mListener->notifyError(
- ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
- nextRequest->mResultExtras);
- }
- }
- cleanUpFailedRequest(request, nextRequest, outputBuffers);
- return true;
- }
- request.input_buffer = &inputBuffer;
+ request.input_buffer = &nextRequest->mInputBuffer;
totalNumBuffers += 1;
} else {
request.input_buffer = NULL;
@@ -2932,9 +2927,9 @@ void Camera3Device::RequestThread::cleanUpFailedRequest(
if (request.settings != NULL) {
nextRequest->mSettings.unlock(request.settings);
}
- if (request.input_buffer != NULL) {
- request.input_buffer->status = CAMERA3_BUFFER_STATUS_ERROR;
- nextRequest->mInputStream->returnInputBuffer(*(request.input_buffer));
+ if (nextRequest->mInputStream != NULL) {
+ nextRequest->mInputBuffer.status = CAMERA3_BUFFER_STATUS_ERROR;
+ nextRequest->mInputStream->returnInputBuffer(nextRequest->mInputBuffer);
}
for (size_t i = 0; i < request.num_output_buffers; i++) {
outputBuffers.editItemAt(i).status = CAMERA3_BUFFER_STATUS_ERROR;
@@ -3026,6 +3021,25 @@ sp<Camera3Device::CaptureRequest>
nextRequest->mResultExtras.frameNumber = mFrameNumber++;
nextRequest->mResultExtras.afTriggerId = mCurrentAfTriggerId;
nextRequest->mResultExtras.precaptureTriggerId = mCurrentPreCaptureTriggerId;
+
+ // Since RequestThread::clear() removes buffers from the input stream,
+ // get the right buffer here before unlocking mRequestLock
+ if (nextRequest->mInputStream != NULL) {
+ res = nextRequest->mInputStream->getInputBuffer(&nextRequest->mInputBuffer);
+ if (res != OK) {
+ // Can't get input buffer from gralloc queue - this could be due to
+ // disconnected queue or other producer misbehavior, so not a fatal
+ // error
+ ALOGE("%s: Can't get input buffer, skipping request:"
+ " %s (%d)", __FUNCTION__, strerror(-res), res);
+ if (mListener != NULL) {
+ mListener->notifyError(
+ ICameraDeviceCallbacks::ERROR_CAMERA_REQUEST,
+ nextRequest->mResultExtras);
+ }
+ return NULL;
+ }
+ }
}
mNextRequest = nextRequest;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index fcb5180..b9313fc 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -234,6 +234,7 @@ class Camera3Device :
public:
CameraMetadata mSettings;
sp<camera3::Camera3Stream> mInputStream;
+ camera3_stream_buffer_t mInputBuffer;
Vector<sp<camera3::Camera3OutputStreamInterface> >
mOutputStreams;
CaptureResultExtras mResultExtras;
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index 5afb7a3..7ae58d5 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -172,6 +172,26 @@ void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
// --------------------------------------------------------------------------------
/**
+ * A default class implementing the LISTENER interface used by ClientManager.
+ */
+template<class KEY, class VALUE>
+class DefaultEventListener {
+public:
+ void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+};
+
+template<class KEY, class VALUE>
+void DefaultEventListener<KEY, VALUE>::onClientAdded(
+ const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
+
+template<class KEY, class VALUE>
+void DefaultEventListener<KEY, VALUE>::onClientRemoved(
+ const ClientDescriptor<KEY, VALUE>& /*descriptor*/) {}
+
+// --------------------------------------------------------------------------------
+
+/**
* The ClientManager class wraps an LRU-ordered list of active clients and implements eviction
* behavior for handling shared resource access.
*
@@ -189,7 +209,7 @@ void ClientDescriptor<KEY, VALUE>::setPriority(int32_t priority) {
* incoming descriptor has the highest priority. Otherwise, the incoming descriptor is
* removed instead.
*/
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER=DefaultEventListener<KEY, VALUE>>
class ClientManager {
public:
// The default maximum "cost" allowed before evicting
@@ -275,6 +295,24 @@ public:
status_t waitUntilRemoved(const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
nsecs_t timeout) const;
+ /**
+ * Set the current listener for client add/remove events.
+ *
+ * The listener instance must inherit from the LISTENER class and implement the following
+ * methods:
+ * void onClientRemoved(const ClientDescriptor<KEY, VALUE>& descriptor);
+ * void onClientAdded(const ClientDescriptor<KEY, VALUE>& descriptor);
+ *
+ * These callback methods will be called with the ClientManager's lock held, and should
+ * not call any further ClientManager methods.
+ *
+ * The onClientRemoved method will be called when the client has been removed or evicted
+ * from the ClientManager that this event listener has been added to. The onClientAdded
+ * method will be called when the client has been added to the ClientManager that this
+ * event listener has been added to.
+ */
+ void setListener(const std::shared_ptr<LISTENER>& listener);
+
protected:
~ClientManager();
@@ -300,36 +338,38 @@ private:
int32_t mMaxCost;
// LRU ordered, most recent at end
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> mClients;
+ std::shared_ptr<LISTENER> mListener;
}; // class ClientManager
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::ClientManager() :
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::ClientManager() :
ClientManager(DEFAULT_MAX_COST) {}
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::ClientManager(int32_t totalCost) : mMaxCost(totalCost) {}
-template<class KEY, class VALUE>
-ClientManager<KEY, VALUE>::~ClientManager() {}
+template<class KEY, class VALUE, class LISTENER>
+ClientManager<KEY, VALUE, LISTENER>::~ClientManager() {}
-template<class KEY, class VALUE>
-std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::wouldEvict(
+template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE, LISTENER>::wouldEvict(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
Mutex::Autolock lock(mLock);
return wouldEvictLocked(client);
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::getIncompatibleClients(
+ClientManager<KEY, VALUE, LISTENER>::getIncompatibleClients(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) const {
Mutex::Autolock lock(mLock);
return wouldEvictLocked(client, /*returnIncompatibleClients*/true);
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::wouldEvictLocked(
+ClientManager<KEY, VALUE, LISTENER>::wouldEvictLocked(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client,
bool returnIncompatibleClients) const {
@@ -420,8 +460,9 @@ ClientManager<KEY, VALUE>::wouldEvictLocked(
}
-template<class KEY, class VALUE>
-std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VALUE>::addAndEvict(
+template<class KEY, class VALUE, class LISTENER>
+std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
+ClientManager<KEY, VALUE, LISTENER>::addAndEvict(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& client) {
Mutex::Autolock lock(mLock);
auto evicted = wouldEvictLocked(client);
@@ -433,6 +474,9 @@ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VA
auto iter = evicted.cbegin();
if (iter != evicted.cend()) {
+
+ if (mListener != nullptr) mListener->onClientRemoved(**iter);
+
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
[&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
@@ -444,21 +488,22 @@ std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>> ClientManager<KEY, VA
}), mClients.end());
}
+ if (mListener != nullptr) mListener->onClientAdded(*client);
mClients.push_back(client);
mRemovedCondition.broadcast();
return evicted;
}
-template<class KEY, class VALUE>
+template<class KEY, class VALUE, class LISTENER>
std::vector<std::shared_ptr<ClientDescriptor<KEY, VALUE>>>
-ClientManager<KEY, VALUE>::getAll() const {
+ClientManager<KEY, VALUE, LISTENER>::getAll() const {
Mutex::Autolock lock(mLock);
return mClients;
}
-template<class KEY, class VALUE>
-std::vector<KEY> ClientManager<KEY, VALUE>::getAllKeys() const {
+template<class KEY, class VALUE, class LISTENER>
+std::vector<KEY> ClientManager<KEY, VALUE, LISTENER>::getAllKeys() const {
Mutex::Autolock lock(mLock);
std::vector<KEY> keys(mClients.size());
for (const auto& i : mClients) {
@@ -467,8 +512,8 @@ std::vector<KEY> ClientManager<KEY, VALUE>::getAllKeys() const {
return keys;
}
-template<class KEY, class VALUE>
-std::vector<int32_t> ClientManager<KEY, VALUE>::getAllOwners() const {
+template<class KEY, class VALUE, class LISTENER>
+std::vector<int32_t> ClientManager<KEY, VALUE, LISTENER>::getAllOwners() const {
Mutex::Autolock lock(mLock);
std::set<int32_t> owners;
for (const auto& i : mClients) {
@@ -477,8 +522,8 @@ std::vector<int32_t> ClientManager<KEY, VALUE>::getAllOwners() const {
return std::vector<int32_t>(owners.begin(), owners.end());
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::updatePriorities(
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::updatePriorities(
const std::map<int32_t,int32_t>& ownerPriorityList) {
Mutex::Autolock lock(mLock);
for (auto& i : mClients) {
@@ -489,8 +534,8 @@ void ClientManager<KEY, VALUE>::updatePriorities(
}
}
-template<class KEY, class VALUE>
-std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::get(
+template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::get(
const KEY& key) const {
Mutex::Autolock lock(mLock);
for (const auto& i : mClients) {
@@ -499,23 +544,30 @@ std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::get(
return std::shared_ptr<ClientDescriptor<KEY, VALUE>>(nullptr);
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::removeAll() {
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::removeAll() {
Mutex::Autolock lock(mLock);
+ if (mListener != nullptr) {
+ for (const auto& i : mClients) {
+ mListener->onClientRemoved(*i);
+ }
+ }
mClients.clear();
mRemovedCondition.broadcast();
}
-template<class KEY, class VALUE>
-std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::remove(const KEY& key) {
+template<class KEY, class VALUE, class LISTENER>
+std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE, LISTENER>::remove(
+ const KEY& key) {
Mutex::Autolock lock(mLock);
std::shared_ptr<ClientDescriptor<KEY, VALUE>> ret;
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
- [&key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+ [this, &key, &ret] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
if (curClientPtr->getKey() == key) {
+ if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
ret = curClientPtr;
return true;
}
@@ -526,8 +578,8 @@ std::shared_ptr<ClientDescriptor<KEY, VALUE>> ClientManager<KEY, VALUE>::remove(
return ret;
}
-template<class KEY, class VALUE>
-status_t ClientManager<KEY, VALUE>::waitUntilRemoved(
+template<class KEY, class VALUE, class LISTENER>
+status_t ClientManager<KEY, VALUE, LISTENER>::waitUntilRemoved(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>> client,
nsecs_t timeout) const {
status_t ret = NO_ERROR;
@@ -558,14 +610,21 @@ status_t ClientManager<KEY, VALUE>::waitUntilRemoved(
return ret;
}
-template<class KEY, class VALUE>
-void ClientManager<KEY, VALUE>::remove(
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::setListener(const std::shared_ptr<LISTENER>& listener) {
+ Mutex::Autolock lock(mLock);
+ mListener = listener;
+}
+
+template<class KEY, class VALUE, class LISTENER>
+void ClientManager<KEY, VALUE, LISTENER>::remove(
const std::shared_ptr<ClientDescriptor<KEY, VALUE>>& value) {
Mutex::Autolock lock(mLock);
// Remove evicted clients from list
mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
- [&value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+ [this, &value] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
if (curClientPtr == value) {
+ if (mListener != nullptr) mListener->onClientRemoved(*curClientPtr);
return true;
}
return false;
@@ -573,8 +632,8 @@ void ClientManager<KEY, VALUE>::remove(
mRemovedCondition.broadcast();
}
-template<class KEY, class VALUE>
-int64_t ClientManager<KEY, VALUE>::getCurrentCostLocked() const {
+template<class KEY, class VALUE, class LISTENER>
+int64_t ClientManager<KEY, VALUE, LISTENER>::getCurrentCostLocked() const {
int64_t totalCost = 0;
for (const auto& x : mClients) {
totalCost += x->getCost();