Merge "Part of fix for bug 5065047 build libchromium as a shared lib"
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 9392cf2..d8fef09 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -84,6 +84,8 @@
const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW[] = "max-num-detected-faces-hw";
+const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
const char CameraParameters::TRUE[] = "true";
const char CameraParameters::FALSE[] = "false";
diff --git a/drm/common/IDrmManagerService.cpp b/drm/common/IDrmManagerService.cpp
index 2d8e877..986f32c 100644
--- a/drm/common/IDrmManagerService.cpp
+++ b/drm/common/IDrmManagerService.cpp
@@ -110,11 +110,11 @@
handle->extendedData.clear();
}
-int BpDrmManagerService::addUniqueId(int uniqueId) {
+int BpDrmManagerService::addUniqueId(bool isNative) {
LOGV("add uniqueid");
Parcel data, reply;
data.writeInterfaceToken(IDrmManagerService::getInterfaceDescriptor());
- data.writeInt32(uniqueId);
+ data.writeInt32(isNative);
remote()->transact(ADD_UNIQUEID, data, &reply);
return reply.readInt32();
}
diff --git a/drm/drmserver/DrmManager.cpp b/drm/drmserver/DrmManager.cpp
index 1809619..3e4fe8c 100644
--- a/drm/drmserver/DrmManager.cpp
+++ b/drm/drmserver/DrmManager.cpp
@@ -49,32 +49,42 @@
}
-int DrmManager::addUniqueId(int uniqueId) {
+int DrmManager::addUniqueId(bool isNative) {
Mutex::Autolock _l(mLock);
- if (0 == uniqueId) {
- int temp = 0;
- bool foundUniqueId = false;
- srand(time(NULL));
- while (!foundUniqueId) {
- const int size = mUniqueIdVector.size();
- temp = rand() % 100;
+ int temp = 0;
+ bool foundUniqueId = false;
+ const int size = mUniqueIdVector.size();
+ const int uniqueIdRange = 0xfff;
+ int maxLoopTimes = (uniqueIdRange - 1) / 2;
+ srand(time(NULL));
- int index = 0;
- for (; index < size; ++index) {
- if (mUniqueIdVector.itemAt(index) == temp) {
- foundUniqueId = false;
- break;
- }
- }
- if (index == size) {
- foundUniqueId = true;
+ while (!foundUniqueId) {
+ temp = rand() & uniqueIdRange;
+
+ if (isNative) {
+ // set a flag to differentiate DrmManagerClient
+ // created from native side and java side
+ temp |= 0x1000;
+ }
+
+ int index = 0;
+ for (; index < size; ++index) {
+ if (mUniqueIdVector.itemAt(index) == temp) {
+ foundUniqueId = false;
+ break;
}
}
- uniqueId = temp;
+ if (index == size) {
+ foundUniqueId = true;
+ }
+
+ maxLoopTimes --;
+ LOG_FATAL_IF(maxLoopTimes <= 0, "cannot find an unique ID for this session");
}
- mUniqueIdVector.push(uniqueId);
- return uniqueId;
+
+ mUniqueIdVector.push(temp);
+ return temp;
}
void DrmManager::removeUniqueId(int uniqueId) {
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 583669e..7ebcac3 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -78,8 +78,8 @@
delete mDrmManager; mDrmManager = NULL;
}
-int DrmManagerService::addUniqueId(int uniqueId) {
- return mDrmManager->addUniqueId(uniqueId);
+int DrmManagerService::addUniqueId(bool isNative) {
+ return mDrmManager->addUniqueId(isNative);
}
void DrmManagerService::removeUniqueId(int uniqueId) {
diff --git a/drm/libdrmframework/DrmManagerClient.cpp b/drm/libdrmframework/DrmManagerClient.cpp
index b50199f..c9c0d57 100644
--- a/drm/libdrmframework/DrmManagerClient.cpp
+++ b/drm/libdrmframework/DrmManagerClient.cpp
@@ -24,7 +24,7 @@
DrmManagerClient::DrmManagerClient():
mUniqueId(0), mDrmManagerClientImpl(NULL) {
- mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId);
+ mDrmManagerClientImpl = DrmManagerClientImpl::create(&mUniqueId, true);
mDrmManagerClientImpl->addClient(mUniqueId);
}
diff --git a/drm/libdrmframework/DrmManagerClientImpl.cpp b/drm/libdrmframework/DrmManagerClientImpl.cpp
index a36bd4a..67f58ca 100644
--- a/drm/libdrmframework/DrmManagerClientImpl.cpp
+++ b/drm/libdrmframework/DrmManagerClientImpl.cpp
@@ -33,13 +33,10 @@
sp<DrmManagerClientImpl::DeathNotifier> DrmManagerClientImpl::sDeathNotifier;
const String8 DrmManagerClientImpl::EMPTY_STRING("");
-DrmManagerClientImpl* DrmManagerClientImpl::create(int* pUniqueId) {
- if (0 == *pUniqueId) {
- int uniqueId = getDrmManagerService()->addUniqueId(*pUniqueId);
- *pUniqueId = uniqueId;
- } else {
- getDrmManagerService()->addUniqueId(*pUniqueId);
- }
+DrmManagerClientImpl* DrmManagerClientImpl::create(
+ int* pUniqueId, bool isNative) {
+ *pUniqueId = getDrmManagerService()->addUniqueId(isNative);
+
return new DrmManagerClientImpl();
}
diff --git a/drm/libdrmframework/include/DrmManager.h b/drm/libdrmframework/include/DrmManager.h
index af2c2a8..ac2b946 100644
--- a/drm/libdrmframework/include/DrmManager.h
+++ b/drm/libdrmframework/include/DrmManager.h
@@ -53,7 +53,7 @@
virtual ~DrmManager();
public:
- int addUniqueId(int uniqueId);
+ int addUniqueId(bool isNative);
void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/include/DrmManagerClientImpl.h b/drm/libdrmframework/include/DrmManagerClientImpl.h
index 564896b..e3338d9 100644
--- a/drm/libdrmframework/include/DrmManagerClientImpl.h
+++ b/drm/libdrmframework/include/DrmManagerClientImpl.h
@@ -38,7 +38,7 @@
DrmManagerClientImpl() { }
public:
- static DrmManagerClientImpl* create(int* pUniqueId);
+ static DrmManagerClientImpl* create(int* pUniqueId, bool isNative);
static void remove(int uniqueId);
diff --git a/drm/libdrmframework/include/DrmManagerService.h b/drm/libdrmframework/include/DrmManagerService.h
index 227496a..9cb5804 100644
--- a/drm/libdrmframework/include/DrmManagerService.h
+++ b/drm/libdrmframework/include/DrmManagerService.h
@@ -46,7 +46,7 @@
virtual ~DrmManagerService();
public:
- int addUniqueId(int uniqueId);
+ int addUniqueId(bool isNative);
void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/include/IDrmManagerService.h b/drm/libdrmframework/include/IDrmManagerService.h
index 7727e55..b9618bb 100644
--- a/drm/libdrmframework/include/IDrmManagerService.h
+++ b/drm/libdrmframework/include/IDrmManagerService.h
@@ -81,7 +81,7 @@
DECLARE_META_INTERFACE(DrmManagerService);
public:
- virtual int addUniqueId(int uniqueId) = 0;
+ virtual int addUniqueId(bool isNative) = 0;
virtual void removeUniqueId(int uniqueId) = 0;
@@ -167,7 +167,7 @@
BpDrmManagerService(const sp<IBinder>& impl)
: BpInterface<IDrmManagerService>(impl) {}
- virtual int addUniqueId(int uniqueId);
+ virtual int addUniqueId(bool isNative);
virtual void removeUniqueId(int uniqueId);
diff --git a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
index b61e3d3..4a5afcf 100644
--- a/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
+++ b/drm/libdrmframework/plugins/common/include/DrmEngineBase.h
@@ -143,7 +143,13 @@
* Register a callback to be invoked when the caller required to
* receive necessary information
*
- * @param[in] uniqueId Unique identifier for a session
+ * @param[in] uniqueId Unique identifier for a session. uniqueId is a random
+ * number generated in the DRM service. If the DrmManagerClient
+ * is created in native code, uniqueId will be a number ranged
+ * from 0x1000 to 0x1fff. If it comes from Java code, the uniqueId
+ * will be a number ranged from 0x00 to 0xfff. So bit 0x1000 in
+ * uniqueId could be used in DRM plugins to differentiate native
+ * OnInfoListener and Java OnInfoListener.
* @param[in] infoListener Listener
* @return status_t
* Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 83d4f6d..d2f398a 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -455,6 +455,16 @@
// Example: "176x144,1280x720". Read only.
static const char KEY_SUPPORTED_VIDEO_SIZES[];
+ // The maximum number of detected faces supported by hardware face
+ // detection. If the value is 0, hardware face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_HW[];
+
+ // The maximum number of detected faces supported by software face
+ // detection. If the value is 0, software face detection is not supported.
+ // Example: "5". Read only
+ static const char KEY_MAX_NUM_DETECTED_FACES_SW[];
+
// Preferred preview frame size in pixels for video recording.
// The width and height must be one of the supported sizes retrieved
// via KEY_SUPPORTED_PREVIEW_SIZES. This key can be used only when
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 496b23e..1417416 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
#include <media/IEffect.h>
#include <media/IEffectClient.h>
#include <hardware/audio_effect.h>
@@ -111,6 +112,36 @@
/*
+ * Returns a list of descriptors corresponding to the pre processings enabled by default
+ * on an AudioRecord with the supplied audio session ID.
+ *
+ * Parameters:
+ * audioSession: audio session ID.
+ * descriptors: address where the effect descriptors should be returned.
+ * count: as input, the maximum number of descriptor than should be returned
+ * as output, the number of descriptor returned if status is NO_ERROR or the actual
+ * number of enabled pre processings if status is NO_MEMORY
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * NO_MEMORY the number of descriptor to return is more than the maximum number
+ * indicated by count.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid audio session or descriptor pointers
+ *
+ * Returned value
+ * *descriptor updated with descriptors of pre processings enabled by default
+ * *count number of descriptors returned if returned status is N_ERROR.
+ * total number of pre processing enabled by default if returned status is
+ * NO_MEMORY. This happens if the count passed as input is less than the number
+ * of descriptors to return
+ */
+ static status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
+
+ /*
* Events used by callback function (effect_callback_t).
*/
enum event_type {
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 86b9f85..ed265e1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -85,6 +85,9 @@
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count) = 0;
};
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 007aea6..ec84e25 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -43,7 +43,6 @@
virtual status_t setAudioEncoder(int ae) = 0;
virtual status_t setOutputFile(const char* path) = 0;
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
- virtual status_t setOutputFileAuxiliary(int fd) = 0;
virtual status_t setVideoSize(int width, int height) = 0;
virtual status_t setVideoFrameRate(int frames_per_second) = 0;
virtual status_t setParameters(const String8& params) = 0;
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 1136f6c..1a67671 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -130,13 +130,22 @@
MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7
};
-enum media_set_parameter_keys {
- KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
- KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,
+// Keep KEY_PARAMETER_* in sync with MediaPlayer.java.
+// The same enum space is used for both set and get, in case there are future keys that
+// can be both set and get. But as of now, all parameters are either set only or get only.
+enum media_parameter_keys {
+ KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000, // set only
+ KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001, // set only
// Streaming/buffering parameters
- KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
+ KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100, // set only
+
+ // Return a Parcel containing a single int, which is the channel count of the
+ // audio track, or zero for error (e.g. no audio track) or unknown.
+ KEY_PARAMETER_AUDIO_CHANNEL_COUNT = 1200, // get only
+
};
+
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
class MediaPlayerListener: virtual public RefBase
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 72d3736..30db642 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -215,7 +215,6 @@
status_t setAudioEncoder(int ae);
status_t setOutputFile(const char* path);
status_t setOutputFile(int fd, int64_t offset, int64_t length);
- status_t setOutputFileAuxiliary(int fd);
status_t setVideoSize(int width, int height);
status_t setVideoFrameRate(int frames_per_second);
status_t setParameters(const String8& params);
@@ -249,7 +248,6 @@
bool mIsAudioEncoderSet;
bool mIsVideoEncoderSet;
bool mIsOutputFileSet;
- bool mIsAuxiliaryOutputFileSet;
Mutex mLock;
Mutex mNotifyLock;
};
diff --git a/include/media/stagefright/CameraSourceTimeLapse.h b/include/media/stagefright/CameraSourceTimeLapse.h
index f07ebba..0e264c7 100644
--- a/include/media/stagefright/CameraSourceTimeLapse.h
+++ b/include/media/stagefright/CameraSourceTimeLapse.h
@@ -53,27 +53,10 @@
void startQuickReadReturns();
private:
- // If true, will use still camera takePicture() for time lapse frames
- // If false, will use the videocamera frames instead.
- bool mUseStillCameraForTimeLapse;
-
- // Size of picture taken from still camera. This may be larger than the size
- // of the video, as still camera may not support the exact video resolution
- // demanded. See setPictureSizeToClosestSupported().
- int32_t mPictureWidth;
- int32_t mPictureHeight;
-
// size of the encoded video.
int32_t mVideoWidth;
int32_t mVideoHeight;
- // True if we need to crop the still camera image to get the video frame.
- bool mNeedCropping;
-
- // Start location of the cropping rectangle.
- int32_t mCropRectStartX;
- int32_t mCropRectStartY;
-
// Time between capture of two frames during time lapse recording
// Negative value indicates that timelapse is disabled.
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -84,9 +67,6 @@
// Real timestamp of the last encoded time lapse frame
int64_t mLastTimeLapseFrameRealTimestampUs;
- // Thread id of thread which takes still picture and sleeps in a loop.
- pthread_t mThreadTimeLapse;
-
// Variable set in dataCallbackTimestamp() to help skipCurrentFrame()
// to know if current frame needs to be skipped.
bool mSkipCurrentFrame;
@@ -111,9 +91,6 @@
// Lock for accessing quick stop variables.
Mutex mQuickStopLock;
- // Condition variable to wake up still picture thread.
- Condition mTakePictureCondition;
-
// mQuickStop is set to true if we use quick read() returns, otherwise it is set
// to false. Once in this mode read() return a copy of the last read frame
// with the same time stamp. See startQuickReadReturns().
@@ -148,32 +125,13 @@
// Wrapper over CameraSource::read() to implement quick stop.
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
- // For still camera case starts a thread which calls camera's takePicture()
- // in a loop. For video camera case, just starts the camera's video recording.
- virtual void startCameraRecording();
-
- // For still camera case joins the thread created in startCameraRecording().
// For video camera case, just stops the camera's video recording.
virtual void stopCameraRecording();
- // For still camera case don't need to do anything as memory is locally
- // allocated with refcounting.
- // For video camera case just tell the camera to release the frame.
- virtual void releaseRecordingFrame(const sp<IMemory>& frame);
-
// mSkipCurrentFrame is set to true in dataCallbackTimestamp() if the current
// frame needs to be skipped and this function just returns the value of mSkipCurrentFrame.
virtual bool skipCurrentFrame(int64_t timestampUs);
- // Handles the callback to handle raw frame data from the still camera.
- // Creates a copy of the frame data as the camera can reuse the frame memory
- // once this callback returns. The function also sets a new timstamp corresponding
- // to one frame time ahead of the last encoded frame's time stamp. It then
- // calls dataCallbackTimestamp() of the base class with the copied data and the
- // modified timestamp, which will think that it recieved the frame from a video
- // camera and proceed as usual.
- virtual void dataCallback(int32_t msgType, const sp<IMemory> &data);
-
// In the video camera case calls skipFrameAndModifyTimeStamp() to modify
// timestamp and set mSkipCurrentFrame.
// Then it calls the base CameraSource::dataCallbackTimestamp()
@@ -189,24 +147,6 @@
// Otherwise returns false.
bool trySettingVideoSize(int32_t width, int32_t height);
- // The still camera may not support the demanded video width and height.
- // We look for the supported picture sizes from the still camera and
- // choose the smallest one with either dimensions higher than the corresponding
- // video dimensions. The still picture will be cropped to get the video frame.
- // The function returns true if the camera supports picture sizes greater than
- // or equal to the passed in width and height, and false otherwise.
- bool setPictureSizeToClosestSupported(int32_t width, int32_t height);
-
- // Computes the offset of the rectangle from where to start cropping the
- // still image into the video frame. We choose the center of the image to be
- // cropped. The offset is stored in (mCropRectStartX, mCropRectStartY).
- bool computeCropRectangleOffset();
-
- // Crops the source data into a smaller image starting at
- // (mCropRectStartX, mCropRectStartY) and of the size of the video frame.
- // The data is returned into a newly allocated IMemory.
- sp<IMemory> cropYUVImage(const sp<IMemory> &source_data);
-
// When video camera is used for time lapse capture, returns true
// until enough time has passed for the next time lapse frame. When
// the frame needs to be encoded, it returns false and also modifies
@@ -217,22 +157,6 @@
// Wrapper to enter threadTimeLapseEntry()
static void *ThreadTimeLapseWrapper(void *me);
- // Runs a loop which sleeps until a still picture is required
- // and then calls mCamera->takePicture() to take the still picture.
- // Used only in the case mUseStillCameraForTimeLapse = true.
- void threadTimeLapseEntry();
-
- // Wrapper to enter threadStartPreview()
- static void *ThreadStartPreviewWrapper(void *me);
-
- // Starts the camera's preview.
- void threadStartPreview();
-
- // Starts thread ThreadStartPreviewWrapper() for restarting preview.
- // Needs to be done in a thread so that dataCallback() which calls this function
- // can return, and the camera can know that takePicture() is done.
- void restartPreview();
-
// Creates a copy of source_data into a new memory of final type MemoryBase.
sp<IMemory> createIMemoryCopy(const sp<IMemory> &source_data);
diff --git a/include/media/stagefright/MetadataBufferType.h b/include/media/stagefright/MetadataBufferType.h
index 52a3257..4eaf8ac 100644
--- a/include/media/stagefright/MetadataBufferType.h
+++ b/include/media/stagefright/MetadataBufferType.h
@@ -69,6 +69,16 @@
* kMetadataBufferTypeGrallocSource is used to indicate that
* the payload of the metadata buffers can be interpreted as
* a buffer_handle_t.
+ * So in this case,the metadata that the encoder receives
+ * will have a byte stream that consists of two parts:
+ * 1. First, there is an integer indicating that it is a GRAlloc
+ * source (kMetadataBufferTypeGrallocSource)
+ * 2. This is followed by the buffer_handle_t that is a handle to the
+ * GRalloc buffer. The encoder needs to interpret this GRalloc handle
+ * and encode the frames.
+ * --------------------------------------------------------------
+ * | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+ * --------------------------------------------------------------
*/
kMetadataBufferTypeGrallocSource = 1,
diff --git a/include/media/stagefright/SurfaceMediaSource.h b/include/media/stagefright/SurfaceMediaSource.h
index 56bd9c3..fab258c 100644
--- a/include/media/stagefright/SurfaceMediaSource.h
+++ b/include/media/stagefright/SurfaceMediaSource.h
@@ -63,6 +63,10 @@
MediaBuffer **buffer, const ReadOptions *options = NULL);
virtual sp<MetaData> getFormat();
+ // Pass the metadata over to the buffer, call when you have the lock
+ void passMetadataBufferLocked(MediaBuffer **buffer);
+ bool checkBufferMatchesSlot(int slot, MediaBuffer *buffer);
+
// Get / Set the frame rate used for encoding. Default fps = 30
status_t setFrameRate(int32_t fps) ;
int32_t getFrameRate( ) const;
@@ -152,7 +156,7 @@
status_t setBufferCountServer(int bufferCount);
// getTimestamp retrieves the timestamp associated with the image
- // set by the most recent call to updateFrameInfoLocked().
+ // set by the most recent call to read()
//
// The timestamp is in nanoseconds, and is monotonically increasing. Its
// other semantics (zero point, etc) are source-dependent and should be
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 3919551..0633744 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -419,6 +419,15 @@
return af->getEffectDescriptor(uuid, descriptor);
}
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
// -------------------------------------------------------------------------
status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 1ec596e..16554c2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -590,7 +590,7 @@
audio_io_handle_t AudioRecord::getInput()
{
AutoMutex lock(mLock);
- return getInput_l();
+ return mInput;
}
// must be called with mLock held
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 49d410f..15f4be0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -53,6 +53,7 @@
UNREGISTER_EFFECT,
IS_STREAM_ACTIVE,
GET_DEVICES_FOR_STREAM,
+ QUERY_DEFAULT_PRE_PROCESSING
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -321,6 +322,31 @@
remote()->transact(IS_STREAM_ACTIVE, data, &reply);
return reply.readInt32();
}
+
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+ {
+ if (descriptors == NULL || count == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ data.writeInt32(*count);
+ status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ uint32_t retCount = reply.readInt32();
+ if (retCount != 0) {
+ uint32_t numDesc = (retCount < *count) ? retCount : *count;
+ reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+ }
+ *count = retCount;
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -559,6 +585,29 @@
return NO_ERROR;
} break;
+ case QUERY_DEFAULT_PRE_PROCESSING: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int audioSession = data.readInt32();
+ uint32_t count = data.readInt32();
+ uint32_t retCount = count;
+ effect_descriptor_t *descriptors =
+ (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+ status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+ reply->writeInt32(status);
+ if (status != NO_ERROR && status != NO_MEMORY) {
+ retCount = 0;
+ }
+ reply->writeInt32(retCount);
+ if (retCount) {
+ if (retCount < count) {
+ count = retCount;
+ }
+ reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+ }
+ delete[] descriptors;
+ return status;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 7e44c29..38e111e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -46,7 +46,6 @@
SET_AUDIO_ENCODER,
SET_OUTPUT_FILE_PATH,
SET_OUTPUT_FILE_FD,
- SET_OUTPUT_FILE_AUXILIARY_FD,
SET_VIDEO_SIZE,
SET_VIDEO_FRAMERATE,
SET_PARAMETERS,
@@ -177,15 +176,6 @@
return reply.readInt32();
}
- status_t setOutputFileAuxiliary(int fd) {
- LOGV("setOutputFileAuxiliary(%d)", fd);
- Parcel data, reply;
- data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
- data.writeFileDescriptor(fd);
- remote()->transact(SET_OUTPUT_FILE_AUXILIARY_FD, data, &reply);
- return reply.readInt32();
- }
-
status_t setVideoSize(int width, int height)
{
LOGV("setVideoSize(%dx%d)", width, height);
@@ -404,13 +394,6 @@
::close(fd);
return NO_ERROR;
} break;
- case SET_OUTPUT_FILE_AUXILIARY_FD: {
- LOGV("SET_OUTPUT_FILE_AUXILIARY_FD");
- CHECK_INTERFACE(IMediaRecorder, data, reply);
- int fd = dup(data.readFileDescriptor());
- reply->writeInt32(setOutputFileAuxiliary(fd));
- return NO_ERROR;
- } break;
case SET_VIDEO_SIZE: {
LOGV("SET_VIDEO_SIZE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index fab674c..11d281f 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -322,32 +322,6 @@
return ret;
}
-status_t MediaRecorder::setOutputFileAuxiliary(int fd)
-{
- LOGV("setOutputFileAuxiliary(%d)", fd);
- if(mMediaRecorder == NULL) {
- LOGE("media recorder is not initialized yet");
- return INVALID_OPERATION;
- }
- if (mIsAuxiliaryOutputFileSet) {
- LOGE("output file has already been set");
- return INVALID_OPERATION;
- }
- if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
- LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
- return INVALID_OPERATION;
- }
-
- status_t ret = mMediaRecorder->setOutputFileAuxiliary(fd);
- if (OK != ret) {
- LOGV("setOutputFileAuxiliary failed: %d", ret);
- mCurrentState = MEDIA_RECORDER_ERROR;
- return ret;
- }
- mIsAuxiliaryOutputFileSet = true;
- return ret;
-}
-
status_t MediaRecorder::setVideoSize(int width, int height)
{
LOGV("setVideoSize(%d, %d)", width, height);
@@ -629,7 +603,6 @@
mIsAudioEncoderSet = false;
mIsVideoEncoderSet = false;
mIsOutputFileSet = false;
- mIsAuxiliaryOutputFileSet = false;
}
// Release should be OK in any state
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 905b885..6f80b35 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -178,17 +178,6 @@
return mRecorder->setOutputFile(fd, offset, length);
}
-status_t MediaRecorderClient::setOutputFileAuxiliary(int fd)
-{
- LOGV("setOutputFileAuxiliary(%d)", fd);
- Mutex::Autolock lock(mLock);
- if (mRecorder == NULL) {
- LOGE("recorder is not initialized");
- return NO_INIT;
- }
- return mRecorder->setOutputFileAuxiliary(fd);
-}
-
status_t MediaRecorderClient::setVideoSize(int width, int height)
{
LOGV("setVideoSize(%dx%d)", width, height);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index c87a3c0..c9ccf22 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -41,7 +41,6 @@
virtual status_t setOutputFile(const char* path);
virtual status_t setOutputFile(int fd, int64_t offset,
int64_t length);
- virtual status_t setOutputFileAuxiliary(int fd);
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6427bb7..6fdb726 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -28,9 +28,7 @@
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/AACWriter.h>
#include <media/stagefright/CameraSource.h>
-#include <media/stagefright/VideoSourceDownSampler.h>
#include <media/stagefright/CameraSourceTimeLapse.h>
-#include <media/stagefright/MediaSourceSplitter.h>
#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaDebug.h>
@@ -67,8 +65,8 @@
StagefrightRecorder::StagefrightRecorder()
- : mWriter(NULL), mWriterAux(NULL),
- mOutputFd(-1), mOutputFdAux(-1),
+ : mWriter(NULL),
+ mOutputFd(-1),
mAudioSource(AUDIO_SOURCE_CNT),
mVideoSource(VIDEO_SOURCE_LIST_END),
mStarted(false), mSurfaceMediaSource(NULL) {
@@ -259,24 +257,6 @@
return OK;
}
-status_t StagefrightRecorder::setOutputFileAuxiliary(int fd) {
- LOGV("setOutputFileAuxiliary: %d", fd);
-
- if (fd < 0) {
- LOGE("Invalid file descriptor: %d", fd);
- return -EBADF;
- }
-
- mCaptureAuxVideo = true;
-
- if (mOutputFdAux >= 0) {
- ::close(mOutputFdAux);
- }
- mOutputFdAux = dup(fd);
-
- return OK;
-}
-
// Attempt to parse an int64 literal optionally surrounded by whitespace,
// returns true on success, false otherwise.
static bool safe_strtoi64(const char *s, int64_t *val) {
@@ -573,42 +553,6 @@
return OK;
}
-status_t StagefrightRecorder::setParamAuxVideoWidth(int32_t width) {
- LOGV("setParamAuxVideoWidth : %d", width);
-
- if (width <= 0) {
- LOGE("Width (%d) is not positive", width);
- return BAD_VALUE;
- }
-
- mAuxVideoWidth = width;
- return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoHeight(int32_t height) {
- LOGV("setParamAuxVideoHeight : %d", height);
-
- if (height <= 0) {
- LOGE("Height (%d) is not positive", height);
- return BAD_VALUE;
- }
-
- mAuxVideoHeight = height;
- return OK;
-}
-
-status_t StagefrightRecorder::setParamAuxVideoEncodingBitRate(int32_t bitRate) {
- LOGV("StagefrightRecorder::setParamAuxVideoEncodingBitRate: %d", bitRate);
-
- if (bitRate <= 0) {
- LOGE("Invalid video encoding bit rate: %d", bitRate);
- return BAD_VALUE;
- }
-
- mAuxVideoBitRate = bitRate;
- return OK;
-}
-
status_t StagefrightRecorder::setParamGeoDataLongitude(
int32_t longitudex10000) {
@@ -738,21 +682,6 @@
return setParamTimeBetweenTimeLapseFrameCapture(
1000LL * timeBetweenTimeLapseFrameCaptureMs);
}
- } else if (key == "video-aux-param-width") {
- int32_t auxWidth;
- if (safe_strtoi32(value.string(), &auxWidth)) {
- return setParamAuxVideoWidth(auxWidth);
- }
- } else if (key == "video-aux-param-height") {
- int32_t auxHeight;
- if (safe_strtoi32(value.string(), &auxHeight)) {
- return setParamAuxVideoHeight(auxHeight);
- }
- } else if (key == "video-aux-param-encoding-bitrate") {
- int32_t auxVideoBitRate;
- if (safe_strtoi32(value.string(), &auxVideoBitRate)) {
- return setParamAuxVideoEncodingBitRate(auxVideoBitRate);
- }
} else {
LOGE("setParameter: failed to find key %s", key.string());
}
@@ -1517,7 +1446,6 @@
}
status_t StagefrightRecorder::setupMPEG4Recording(
- bool useSplitCameraSource,
int outputFd,
int32_t videoWidth, int32_t videoHeight,
int32_t videoBitRate,
@@ -1531,28 +1459,7 @@
if (mVideoSource < VIDEO_SOURCE_LIST_END) {
sp<MediaSource> mediaSource;
- if (useSplitCameraSource) {
- // TODO: Check if there is a better way to handle this
- if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
- LOGE("Cannot use split camera when encoding frames");
- return INVALID_OPERATION;
- }
- LOGV("Using Split camera source");
- mediaSource = mCameraSourceSplitter->createClient();
- } else {
- err = setupMediaSource(&mediaSource);
- }
-
- if ((videoWidth != mVideoWidth) || (videoHeight != mVideoHeight)) {
- // TODO: Might be able to handle downsampling even if using GRAlloc
- if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) {
- LOGE("Cannot change size or Downsample when encoding frames");
- return INVALID_OPERATION;
- }
- // Use downsampling from the original source.
- mediaSource =
- new VideoSourceDownSampler(mediaSource, videoWidth, videoHeight);
- }
+ err = setupMediaSource(&mediaSource);
if (err != OK) {
return err;
}
@@ -1620,24 +1527,8 @@
}
status_t StagefrightRecorder::startMPEG4Recording() {
- if (mCaptureAuxVideo) {
- if (!mCaptureTimeLapse) {
- LOGE("Auxiliary video can be captured only in time lapse mode");
- return UNKNOWN_ERROR;
- }
- LOGV("Creating MediaSourceSplitter");
- sp<CameraSource> cameraSource;
- status_t err = setupCameraSource(&cameraSource);
- if (err != OK) {
- return err;
- }
- mCameraSourceSplitter = new MediaSourceSplitter(cameraSource);
- } else {
- mCameraSourceSplitter = NULL;
- }
-
int32_t totalBitRate;
- status_t err = setupMPEG4Recording(mCaptureAuxVideo,
+ status_t err = setupMPEG4Recording(
mOutputFd, mVideoWidth, mVideoHeight,
mVideoBitRate, &totalBitRate, &mWriter);
if (err != OK) {
@@ -1653,33 +1544,6 @@
return err;
}
- if (mCaptureAuxVideo) {
- CHECK(mOutputFdAux >= 0);
- if (mWriterAux != NULL) {
- LOGE("Auxiliary File writer is not avaialble");
- return UNKNOWN_ERROR;
- }
- if ((mAuxVideoWidth > mVideoWidth) || (mAuxVideoHeight > mVideoHeight) ||
- ((mAuxVideoWidth == mVideoWidth) && mAuxVideoHeight == mVideoHeight)) {
- LOGE("Auxiliary video size (%d x %d) same or larger than the main video size (%d x %d)",
- mAuxVideoWidth, mAuxVideoHeight, mVideoWidth, mVideoHeight);
- return UNKNOWN_ERROR;
- }
-
- int32_t totalBitrateAux;
- err = setupMPEG4Recording(mCaptureAuxVideo,
- mOutputFdAux, mAuxVideoWidth, mAuxVideoHeight,
- mAuxVideoBitRate, &totalBitrateAux, &mWriterAux);
- if (err != OK) {
- return err;
- }
-
- sp<MetaData> metaAux = new MetaData;
- setupMPEG4MetaData(startTimeUs, totalBitrateAux, &metaAux);
-
- return mWriterAux->start(metaAux.get());
- }
-
return OK;
}
@@ -1690,13 +1554,6 @@
}
mWriter->pause();
- if (mCaptureAuxVideo) {
- if (mWriterAux == NULL) {
- return UNKNOWN_ERROR;
- }
- mWriterAux->pause();
- }
-
if (mStarted) {
mStarted = false;
@@ -1724,13 +1581,6 @@
mCameraSourceTimeLapse = NULL;
}
- if (mCaptureAuxVideo) {
- if (mWriterAux != NULL) {
- mWriterAux->stop();
- mWriterAux.clear();
- }
- }
-
if (mWriter != NULL) {
err = mWriter->stop();
mWriter.clear();
@@ -1741,13 +1591,6 @@
mOutputFd = -1;
}
- if (mCaptureAuxVideo) {
- if (mOutputFdAux >= 0) {
- ::close(mOutputFdAux);
- mOutputFdAux = -1;
- }
- }
-
if (mStarted) {
mStarted = false;
@@ -1787,11 +1630,8 @@
mVideoEncoder = VIDEO_ENCODER_H263;
mVideoWidth = 176;
mVideoHeight = 144;
- mAuxVideoWidth = 176;
- mAuxVideoHeight = 144;
mFrameRate = -1;
mVideoBitRate = 192000;
- mAuxVideoBitRate = 192000;
mSampleRate = 8000;
mAudioChannels = 1;
mAudioBitRate = 12200;
@@ -1811,8 +1651,6 @@
mTrackEveryTimeDurationUs = 0;
mCaptureTimeLapse = false;
mTimeBetweenTimeLapseFrameCaptureUs = -1;
- mCaptureAuxVideo = false;
- mCameraSourceSplitter = NULL;
mCameraSourceTimeLapse = NULL;
mIsMetaDataStoredInVideoBuffers = false;
mEncoderProfiles = MediaProfiles::getInstance();
@@ -1821,7 +1659,6 @@
mLongitudex10000 = -3600000;
mOutputFd = -1;
- mOutputFdAux = -1;
return OK;
}
@@ -1858,8 +1695,6 @@
snprintf(buffer, SIZE, " Recorder: %p\n", this);
snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd);
result.append(buffer);
- snprintf(buffer, SIZE, " Output file Auxiliary (fd %d):\n", mOutputFdAux);
- result.append(buffer);
snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat);
result.append(buffer);
snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes);
@@ -1904,14 +1739,10 @@
result.append(buffer);
snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
result.append(buffer);
- snprintf(buffer, SIZE, " Aux Frame size (pixels): %dx%d\n", mAuxVideoWidth, mAuxVideoHeight);
- result.append(buffer);
snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate);
result.append(buffer);
snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate);
result.append(buffer);
- snprintf(buffer, SIZE, " Aux Bit rate (bps): %d\n", mAuxVideoBitRate);
- result.append(buffer);
::write(fd, result.string(), result.size());
return OK;
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 1618b92..5c5f05c 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -30,7 +30,6 @@
class ICameraRecordingProxy;
class CameraSource;
class CameraSourceTimeLapse;
-class MediaSourceSplitter;
struct MediaSource;
struct MediaWriter;
class MetaData;
@@ -55,7 +54,6 @@
virtual status_t setPreviewSurface(const sp<Surface>& surface);
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
- virtual status_t setOutputFileAuxiliary(int fd);
virtual status_t setParameters(const String8& params);
virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
virtual status_t prepare();
@@ -74,8 +72,8 @@
sp<ICameraRecordingProxy> mCameraProxy;
sp<Surface> mPreviewSurface;
sp<IMediaRecorderClient> mListener;
- sp<MediaWriter> mWriter, mWriterAux;
- int mOutputFd, mOutputFdAux;
+ sp<MediaWriter> mWriter;
+ int mOutputFd;
sp<AudioSource> mAudioSourceNode;
audio_source_t mAudioSource;
@@ -85,9 +83,8 @@
video_encoder mVideoEncoder;
bool mUse64BitFileOffset;
int32_t mVideoWidth, mVideoHeight;
- int32_t mAuxVideoWidth, mAuxVideoHeight;
int32_t mFrameRate;
- int32_t mVideoBitRate, mAuxVideoBitRate;
+ int32_t mVideoBitRate;
int32_t mAudioBitRate;
int32_t mAudioChannels;
int32_t mSampleRate;
@@ -109,8 +106,6 @@
bool mCaptureTimeLapse;
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
- bool mCaptureAuxVideo;
- sp<MediaSourceSplitter> mCameraSourceSplitter;
sp<CameraSourceTimeLapse> mCameraSourceTimeLapse;
@@ -127,7 +122,6 @@
sp<SurfaceMediaSource> mSurfaceMediaSource;
status_t setupMPEG4Recording(
- bool useSplitCameraSource,
int outputFd,
int32_t videoWidth, int32_t videoHeight,
int32_t videoBitRate,
@@ -166,9 +160,6 @@
status_t setParamAudioTimeScale(int32_t timeScale);
status_t setParamTimeLapseEnable(int32_t timeLapseEnable);
status_t setParamTimeBetweenTimeLapseFrameCapture(int64_t timeUs);
- status_t setParamAuxVideoHeight(int32_t height);
- status_t setParamAuxVideoWidth(int32_t width);
- status_t setParamAuxVideoEncodingBitRate(int32_t bitRate);
status_t setParamVideoEncodingBitRate(int32_t bitRate);
status_t setParamVideoIFramesInterval(int32_t seconds);
status_t setParamVideoEncoderProfile(int32_t profile);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 0098537..67f6c79 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2238,7 +2238,22 @@
}
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
- return OK;
+ switch (key) {
+ case KEY_PARAMETER_AUDIO_CHANNEL_COUNT:
+ {
+ int32_t channelCount;
+ if (mAudioTrack == 0 ||
+ !mAudioTrack->getFormat()->findInt32(kKeyChannelCount, &channelCount)) {
+ channelCount = 0;
+ }
+ reply->writeInt32(channelCount);
+ }
+ return OK;
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
+ }
}
bool AwesomePlayer::isStreamingHTTP() const {
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index fe78c46..1ba79e5 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -24,15 +24,10 @@
#include <media/stagefright/CameraSourceTimeLapse.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MetaData.h>
-#include <media/stagefright/YUVImage.h>
-#include <media/stagefright/YUVCanvas.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
-#include <ui/Rect.h>
#include <utils/String8.h>
#include <utils/Vector.h>
-#include "OMX_Video.h"
-#include <limits.h>
namespace android {
@@ -74,20 +69,14 @@
mLastTimeLapseFrameRealTimestampUs(0),
mSkipCurrentFrame(false) {
- LOGD("starting time lapse mode: %lld us", mTimeBetweenTimeLapseFrameCaptureUs);
+ LOGD("starting time lapse mode: %lld us",
+ mTimeBetweenTimeLapseFrameCaptureUs);
+
mVideoWidth = videoSize.width;
mVideoHeight = videoSize.height;
- if (trySettingVideoSize(videoSize.width, videoSize.height)) {
- mUseStillCameraForTimeLapse = false;
- } else {
- // TODO: Add a check to see that mTimeBetweenTimeLapseFrameCaptureUs is greater
- // than the fastest rate at which the still camera can take pictures.
- mUseStillCameraForTimeLapse = true;
- CHECK(setPictureSizeToClosestSupported(videoSize.width, videoSize.height));
- mNeedCropping = computeCropRectangleOffset();
- mMeta->setInt32(kKeyWidth, videoSize.width);
- mMeta->setInt32(kKeyHeight, videoSize.height);
+ if (!trySettingVideoSize(videoSize.width, videoSize.height)) {
+ mInitCheck = NO_INIT;
}
// Initialize quick stop variables.
@@ -101,24 +90,22 @@
}
void CameraSourceTimeLapse::startQuickReadReturns() {
+ LOGV("startQuickReadReturns");
Mutex::Autolock autoLock(mQuickStopLock);
- LOGV("Enabling quick read returns");
// Enable quick stop mode.
mQuickStop = true;
- if (mUseStillCameraForTimeLapse) {
- // wake up the thread right away.
- mTakePictureCondition.signal();
- } else {
- // Force dataCallbackTimestamp() coming from the video camera to not skip the
- // next frame as we want read() to get a get a frame right away.
- mForceRead = true;
- }
+ // Force dataCallbackTimestamp() coming from the video camera to
+ // not skip the next frame as we want read() to get a get a frame
+ // right away.
+ mForceRead = true;
}
-bool CameraSourceTimeLapse::trySettingVideoSize(int32_t width, int32_t height) {
- LOGV("trySettingVideoSize: %dx%d", width, height);
+bool CameraSourceTimeLapse::trySettingVideoSize(
+ int32_t width, int32_t height) {
+
+ LOGV("trySettingVideoSize");
int64_t token = IPCThreadState::self()->clearCallingIdentity();
String8 s = mCamera->getParameters();
@@ -162,53 +149,8 @@
return isSuccessful;
}
-bool CameraSourceTimeLapse::setPictureSizeToClosestSupported(int32_t width, int32_t height) {
- LOGV("setPictureSizeToClosestSupported: %dx%d", width, height);
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- String8 s = mCamera->getParameters();
- IPCThreadState::self()->restoreCallingIdentity(token);
-
- CameraParameters params(s);
- Vector<Size> supportedSizes;
- params.getSupportedPictureSizes(supportedSizes);
-
- int32_t minPictureSize = INT_MAX;
- for (uint32_t i = 0; i < supportedSizes.size(); ++i) {
- int32_t pictureWidth = supportedSizes[i].width;
- int32_t pictureHeight = supportedSizes[i].height;
-
- if ((pictureWidth >= width) && (pictureHeight >= height)) {
- int32_t pictureSize = pictureWidth*pictureHeight;
- if (pictureSize < minPictureSize) {
- minPictureSize = pictureSize;
- mPictureWidth = pictureWidth;
- mPictureHeight = pictureHeight;
- }
- }
- }
- LOGV("Picture size = (%d, %d)", mPictureWidth, mPictureHeight);
- return (minPictureSize != INT_MAX);
-}
-
-bool CameraSourceTimeLapse::computeCropRectangleOffset() {
- if ((mPictureWidth == mVideoWidth) && (mPictureHeight == mVideoHeight)) {
- return false;
- }
-
- CHECK((mPictureWidth > mVideoWidth) && (mPictureHeight > mVideoHeight));
-
- int32_t widthDifference = mPictureWidth - mVideoWidth;
- int32_t heightDifference = mPictureHeight - mVideoHeight;
-
- mCropRectStartX = widthDifference/2;
- mCropRectStartY = heightDifference/2;
-
- LOGV("setting crop rectangle offset to (%d, %d)", mCropRectStartX, mCropRectStartY);
-
- return true;
-}
-
void CameraSourceTimeLapse::signalBufferReturned(MediaBuffer* buffer) {
+ LOGV("signalBufferReturned");
Mutex::Autolock autoLock(mQuickStopLock);
if (mQuickStop && (buffer == mLastReadBufferCopy)) {
buffer->setObserver(NULL);
@@ -218,7 +160,12 @@
}
}
-void createMediaBufferCopy(const MediaBuffer& sourceBuffer, int64_t frameTime, MediaBuffer **newBuffer) {
+void createMediaBufferCopy(
+ const MediaBuffer& sourceBuffer,
+ int64_t frameTime,
+ MediaBuffer **newBuffer) {
+
+ LOGV("createMediaBufferCopy");
size_t sourceSize = sourceBuffer.size();
void* sourcePointer = sourceBuffer.data();
@@ -229,6 +176,7 @@
}
void CameraSourceTimeLapse::fillLastReadBufferCopy(MediaBuffer& sourceBuffer) {
+ LOGV("fillLastReadBufferCopy");
int64_t frameTime;
CHECK(sourceBuffer.meta_data()->findInt64(kKeyTime, &frameTime));
createMediaBufferCopy(sourceBuffer, frameTime, &mLastReadBufferCopy);
@@ -238,11 +186,12 @@
status_t CameraSourceTimeLapse::read(
MediaBuffer **buffer, const ReadOptions *options) {
+ LOGV("read");
if (mLastReadBufferCopy == NULL) {
mLastReadStatus = CameraSource::read(buffer, options);
- // mQuickStop may have turned to true while read was blocked. Make a copy of
- // the buffer in that case.
+ // mQuickStop may have turned to true while read was blocked.
+ // Make a copy of the buffer in that case.
Mutex::Autolock autoLock(mQuickStopLock);
if (mQuickStop && *buffer) {
fillLastReadBufferCopy(**buffer);
@@ -255,105 +204,19 @@
}
}
-// static
-void *CameraSourceTimeLapse::ThreadTimeLapseWrapper(void *me) {
- CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
- source->threadTimeLapseEntry();
- return NULL;
-}
-
-void CameraSourceTimeLapse::threadTimeLapseEntry() {
- while (mStarted) {
- {
- Mutex::Autolock autoLock(mCameraIdleLock);
- if (!mCameraIdle) {
- mCameraIdleCondition.wait(mCameraIdleLock);
- }
- CHECK(mCameraIdle);
- mCameraIdle = false;
- }
-
- // Even if mQuickStop == true we need to take one more picture
- // as a read() may be blocked, waiting for a frame to get available.
- // After this takePicture, if mQuickStop == true, we can safely exit
- // this thread as read() will make a copy of this last frame and keep
- // returning it in the quick stop mode.
- Mutex::Autolock autoLock(mQuickStopLock);
- CHECK_EQ(OK, mCamera->takePicture(CAMERA_MSG_RAW_IMAGE));
- if (mQuickStop) {
- LOGV("threadTimeLapseEntry: Exiting due to mQuickStop = true");
- return;
- }
- mTakePictureCondition.waitRelative(mQuickStopLock,
- mTimeBetweenTimeLapseFrameCaptureUs * 1000);
- }
- LOGV("threadTimeLapseEntry: Exiting due to mStarted = false");
-}
-
-void CameraSourceTimeLapse::startCameraRecording() {
- if (mUseStillCameraForTimeLapse) {
- LOGV("start time lapse recording using still camera");
-
- int64_t token = IPCThreadState::self()->clearCallingIdentity();
- String8 s = mCamera->getParameters();
-
- CameraParameters params(s);
- params.setPictureSize(mPictureWidth, mPictureHeight);
- mCamera->setParameters(params.flatten());
- mCameraIdle = true;
- mStopWaitingForIdleCamera = false;
-
- // disable shutter sound and play the recording sound.
- mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
- mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
- IPCThreadState::self()->restoreCallingIdentity(token);
-
- // create a thread which takes pictures in a loop
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-
- pthread_create(&mThreadTimeLapse, &attr, ThreadTimeLapseWrapper, this);
- pthread_attr_destroy(&attr);
- } else {
- LOGV("start time lapse recording using video camera");
- CameraSource::startCameraRecording();
- }
-}
-
void CameraSourceTimeLapse::stopCameraRecording() {
- if (mUseStillCameraForTimeLapse) {
- void *dummy;
- pthread_join(mThreadTimeLapse, &dummy);
-
- // Last takePicture may still be underway. Wait for the camera to get
- // idle.
- Mutex::Autolock autoLock(mCameraIdleLock);
- mStopWaitingForIdleCamera = true;
- if (!mCameraIdle) {
- mCameraIdleCondition.wait(mCameraIdleLock);
- }
- CHECK(mCameraIdle);
- mCamera->setListener(NULL);
-
- // play the recording sound.
- mCamera->sendCommand(CAMERA_CMD_PLAY_RECORDING_SOUND, 0, 0);
- } else {
- CameraSource::stopCameraRecording();
- }
+ LOGV("stopCameraRecording");
+ CameraSource::stopCameraRecording();
if (mLastReadBufferCopy) {
mLastReadBufferCopy->release();
mLastReadBufferCopy = NULL;
}
}
-void CameraSourceTimeLapse::releaseRecordingFrame(const sp<IMemory>& frame) {
- if (!mUseStillCameraForTimeLapse) {
- CameraSource::releaseRecordingFrame(frame);
- }
-}
+sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(
+ const sp<IMemory> &source_data) {
-sp<IMemory> CameraSourceTimeLapse::createIMemoryCopy(const sp<IMemory> &source_data) {
+ LOGV("createIMemoryCopy");
size_t source_size = source_data->size();
void* source_pointer = source_data->pointer();
@@ -363,102 +226,8 @@
return newMemory;
}
-// Allocates IMemory of final type MemoryBase with the given size.
-sp<IMemory> allocateIMemory(size_t size) {
- sp<MemoryHeapBase> newMemoryHeap = new MemoryHeapBase(size);
- sp<MemoryBase> newMemory = new MemoryBase(newMemoryHeap, 0, size);
- return newMemory;
-}
-
-// static
-void *CameraSourceTimeLapse::ThreadStartPreviewWrapper(void *me) {
- CameraSourceTimeLapse *source = static_cast<CameraSourceTimeLapse *>(me);
- source->threadStartPreview();
- return NULL;
-}
-
-void CameraSourceTimeLapse::threadStartPreview() {
- CHECK_EQ(OK, mCamera->startPreview());
- Mutex::Autolock autoLock(mCameraIdleLock);
- mCameraIdle = true;
- mCameraIdleCondition.signal();
-}
-
-void CameraSourceTimeLapse::restartPreview() {
- // Start this in a different thread, so that the dataCallback can return
- LOGV("restartPreview");
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- pthread_t threadPreview;
- pthread_create(&threadPreview, &attr, ThreadStartPreviewWrapper, this);
- pthread_attr_destroy(&attr);
-}
-
-sp<IMemory> CameraSourceTimeLapse::cropYUVImage(const sp<IMemory> &source_data) {
- // find the YUV format
- int32_t srcFormat;
- CHECK(mMeta->findInt32(kKeyColorFormat, &srcFormat));
- YUVImage::YUVFormat yuvFormat;
- if (srcFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
- yuvFormat = YUVImage::YUV420SemiPlanar;
- } else {
- CHECK_EQ(srcFormat, OMX_COLOR_FormatYUV420Planar);
- yuvFormat = YUVImage::YUV420Planar;
- }
-
- // allocate memory for cropped image and setup a canvas using it.
- sp<IMemory> croppedImageMemory = allocateIMemory(
- YUVImage::bufferSize(yuvFormat, mVideoWidth, mVideoHeight));
- YUVImage yuvImageCropped(yuvFormat,
- mVideoWidth, mVideoHeight,
- (uint8_t *)croppedImageMemory->pointer());
- YUVCanvas yuvCanvasCrop(yuvImageCropped);
-
- YUVImage yuvImageSource(yuvFormat,
- mPictureWidth, mPictureHeight,
- (uint8_t *)source_data->pointer());
- yuvCanvasCrop.CopyImageRect(
- Rect(mCropRectStartX, mCropRectStartY,
- mCropRectStartX + mVideoWidth,
- mCropRectStartY + mVideoHeight),
- 0, 0,
- yuvImageSource);
-
- return croppedImageMemory;
-}
-
-void CameraSourceTimeLapse::dataCallback(int32_t msgType, const sp<IMemory> &data) {
- if (msgType == CAMERA_MSG_COMPRESSED_IMAGE) {
- // takePicture will complete after this callback, so restart preview.
- restartPreview();
- return;
- }
- if (msgType != CAMERA_MSG_RAW_IMAGE) {
- return;
- }
-
- LOGV("dataCallback for timelapse still frame");
- CHECK_EQ(true, mUseStillCameraForTimeLapse);
-
- int64_t timestampUs;
- if (mNumFramesReceived == 0) {
- timestampUs = mStartTimeUs;
- } else {
- timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- }
-
- if (mNeedCropping) {
- sp<IMemory> croppedImageData = cropYUVImage(data);
- dataCallbackTimestamp(timestampUs, msgType, croppedImageData);
- } else {
- sp<IMemory> dataCopy = createIMemoryCopy(data);
- dataCallbackTimestamp(timestampUs, msgType, dataCopy);
- }
-}
-
bool CameraSourceTimeLapse::skipCurrentFrame(int64_t timestampUs) {
+ LOGV("skipCurrentFrame");
if (mSkipCurrentFrame) {
mSkipCurrentFrame = false;
return true;
@@ -468,72 +237,58 @@
}
bool CameraSourceTimeLapse::skipFrameAndModifyTimeStamp(int64_t *timestampUs) {
- if (!mUseStillCameraForTimeLapse) {
- if (mLastTimeLapseFrameRealTimestampUs == 0) {
- // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
- // to current time (timestampUs) and save frame data.
- LOGV("dataCallbackTimestamp timelapse: initial frame");
+ LOGV("skipFrameAndModifyTimeStamp");
+ if (mLastTimeLapseFrameRealTimestampUs == 0) {
+ // First time lapse frame. Initialize mLastTimeLapseFrameRealTimestampUs
+ // to current time (timestampUs) and save frame data.
+ LOGV("dataCallbackTimestamp timelapse: initial frame");
- mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ return false;
+ }
+
+ {
+ Mutex::Autolock autoLock(mQuickStopLock);
+
+ // mForceRead may be set to true by startQuickReadReturns(). In that
+ // case don't skip this frame.
+ if (mForceRead) {
+ LOGV("dataCallbackTimestamp timelapse: forced read");
+ mForceRead = false;
+ *timestampUs =
+ mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
return false;
}
+ }
- {
- Mutex::Autolock autoLock(mQuickStopLock);
+ // Workaround to bypass the first 2 input frames for skipping.
+ // The first 2 output frames from the encoder are: decoder specific info and
+ // the compressed video frame data for the first input video frame.
+ if (mNumFramesEncoded >= 1 && *timestampUs <
+ (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
+ // Skip all frames from last encoded frame until
+ // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
+ // Tell the camera to release its recording frame and return.
+ LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
+ return true;
+ } else {
+ // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
+ // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
+ // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
+ // of the last encoded frame's time stamp.
+ LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
- // mForceRead may be set to true by startQuickReadReturns(). In that
- // case don't skip this frame.
- if (mForceRead) {
- LOGV("dataCallbackTimestamp timelapse: forced read");
- mForceRead = false;
- *timestampUs =
- mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- return false;
- }
- }
-
- // Workaround to bypass the first 2 input frames for skipping.
- // The first 2 output frames from the encoder are: decoder specific info and
- // the compressed video frame data for the first input video frame.
- if (mNumFramesEncoded >= 1 && *timestampUs <
- (mLastTimeLapseFrameRealTimestampUs + mTimeBetweenTimeLapseFrameCaptureUs)) {
- // Skip all frames from last encoded frame until
- // sufficient time (mTimeBetweenTimeLapseFrameCaptureUs) has passed.
- // Tell the camera to release its recording frame and return.
- LOGV("dataCallbackTimestamp timelapse: skipping intermediate frame");
- return true;
- } else {
- // Desired frame has arrived after mTimeBetweenTimeLapseFrameCaptureUs time:
- // - Reset mLastTimeLapseFrameRealTimestampUs to current time.
- // - Artificially modify timestampUs to be one frame time (1/framerate) ahead
- // of the last encoded frame's time stamp.
- LOGV("dataCallbackTimestamp timelapse: got timelapse frame");
-
- mLastTimeLapseFrameRealTimestampUs = *timestampUs;
- *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
- return false;
- }
+ mLastTimeLapseFrameRealTimestampUs = *timestampUs;
+ *timestampUs = mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
+ return false;
}
return false;
}
void CameraSourceTimeLapse::dataCallbackTimestamp(int64_t timestampUs, int32_t msgType,
const sp<IMemory> &data) {
- if (!mUseStillCameraForTimeLapse) {
- mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs);
- } else {
- Mutex::Autolock autoLock(mCameraIdleLock);
- // If we are using the still camera and stop() has been called, it may
- // be waiting for the camera to get idle. In that case return
- // immediately. Calling CameraSource::dataCallbackTimestamp() will lead
- // to a deadlock since it tries to access CameraSource::mLock which in
- // this case is held by CameraSource::stop() currently waiting for the
- // camera to get idle. And camera will not get idle until this call
- // returns.
- if (mStopWaitingForIdleCamera) {
- return;
- }
- }
+ LOGV("dataCallbackTimestamp");
+ mSkipCurrentFrame = skipFrameAndModifyTimeStamp(×tampUs);
CameraSource::dataCallbackTimestamp(timestampUs, msgType, data);
}
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index ff4b08f..3d8c56a 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/openmax/OMX_IVCommon.h>
+#include <media/stagefright/MetadataBufferType.h>
#include <surfaceflinger/ISurfaceComposer.h>
#include <surfaceflinger/SurfaceComposerClient.h>
@@ -710,9 +711,9 @@
mCurrentBuf = mSlots[mCurrentSlot].mGraphicBuffer;
mCurrentTimestamp = mSlots[mCurrentSlot].mTimestamp;
- // Pass the data to the MediaBuffer
- // TODO: Change later to pass in only the metadata
- *buffer = new MediaBuffer(mCurrentBuf);
+ // Pass the data to the MediaBuffer. Pass in only the metadata
+ passMetadataBufferLocked(buffer);
+
(*buffer)->setObserver(this);
(*buffer)->add_ref();
(*buffer)->meta_data()->setInt64(kKeyTime, mCurrentTimestamp);
@@ -720,6 +721,34 @@
return OK;
}
+// Pass the data to the MediaBuffer. Pass in only the metadata
+// The metadata passed consists of two parts:
+// 1. First, there is an integer indicating that it is a GRAlloc
+// source (kMetadataBufferTypeGrallocSource)
+// 2. This is followed by the buffer_handle_t that is a handle to the
+// GRalloc buffer. The encoder needs to interpret this GRalloc handle
+// and encode the frames.
+// --------------------------------------------------------------
+// | kMetadataBufferTypeGrallocSource | sizeof(buffer_handle_t) |
+// --------------------------------------------------------------
+// Note: Call only when you have the lock
+void SurfaceMediaSource::passMetadataBufferLocked(MediaBuffer **buffer) {
+ LOGV("passMetadataBuffer");
+ // MediaBuffer allocates and owns this data
+ MediaBuffer *tempBuffer =
+ new MediaBuffer(4 + sizeof(buffer_handle_t));
+ char *data = (char *)tempBuffer->data();
+ if (data == NULL) {
+ LOGE("Cannot allocate memory for passing buffer metadata!");
+ return;
+ }
+ OMX_U32 type = kMetadataBufferTypeGrallocSource;
+ memcpy(data, &type, 4);
+ memcpy(data + 4, &(mCurrentBuf->handle), sizeof(buffer_handle_t));
+ *buffer = tempBuffer;
+}
+
+
void SurfaceMediaSource::signalBufferReturned(MediaBuffer *buffer) {
LOGV("signalBufferReturned");
@@ -727,14 +756,13 @@
Mutex::Autolock autoLock(mMutex);
if (!mStarted) {
- LOGV("started = false. Nothing to do");
+ LOGW("signalBufferReturned: mStarted = false! Nothing to do!");
return;
}
for (Fifo::iterator it = mQueue.begin(); it != mQueue.end(); ++it) {
- if (mSlots[*it].mGraphicBuffer == buffer->graphicBuffer()) {
- LOGV("Buffer %d returned. Setting it 'FREE'. New Queue size = %d",
- *it, mQueue.size()-1);
+ CHECK(mSlots[*it].mGraphicBuffer != NULL);
+ if (checkBufferMatchesSlot(*it, buffer)) {
mSlots[*it].mBufferState = BufferSlot::FREE;
mQueue.erase(it);
buffer->setObserver(0);
@@ -751,6 +779,14 @@
}
}
+bool SurfaceMediaSource::checkBufferMatchesSlot(int slot, MediaBuffer *buffer) {
+ LOGV("Check if Buffer matches slot");
+ // need to convert to char* for pointer arithmetic and then
+ // copy the byte stream into our handle
+ buffer_handle_t bufferHandle ;
+ memcpy( &bufferHandle, (char *)(buffer->data()) + 4, sizeof(buffer_handle_t));
+ return mSlots[slot].mGraphicBuffer->handle == bufferHandle;
+}
} // end of namespace android
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index f4b3668..eb10ab7 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -25,6 +25,7 @@
#include "android/net/android_network_library_impl.h"
#include "base/threading/thread.h"
#include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
#include "net/base/host_resolver.h"
#include "net/base/ssl_config_service.h"
#include "net/http/http_auth_handler_factory.h"
@@ -140,6 +141,8 @@
network_delegate(),
net_log(),
NULL)); // backend_factory
+
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
}
const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 504d470..c8278ab 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -57,6 +57,9 @@
typedef OMXPluginBase *(*CreateOMXPluginFunc)();
CreateOMXPluginFunc createOMXPlugin =
(CreateOMXPluginFunc)dlsym(
+ mVendorLibHandle, "createOMXPlugin");
+ if (!createOMXPlugin)
+ createOMXPlugin = (CreateOMXPluginFunc)dlsym(
mVendorLibHandle, "_ZN7android15createOMXPluginEv");
if (createOMXPlugin) {
@@ -96,11 +99,19 @@
void OMXMaster::clearPlugins() {
Mutex::Autolock autoLock(mLock);
+ typedef void (*DestroyOMXPluginFunc)(OMXPluginBase*);
+ DestroyOMXPluginFunc destroyOMXPlugin =
+ (DestroyOMXPluginFunc)dlsym(
+ mVendorLibHandle, "destroyOMXPlugin");
+
mPluginByComponentName.clear();
for (List<OMXPluginBase *>::iterator it = mPlugins.begin();
- it != mPlugins.end(); ++it) {
- delete *it;
+ it != mPlugins.end(); ++it) {
+ if (destroyOMXPlugin)
+ destroyOMXPlugin(*it);
+ else
+ delete *it;
*it = NULL;
}
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index ce10812..dc6f2c9 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -71,8 +71,8 @@
mANW.clear();
}
- const int mYuvTexWidth;// = 64;
- const int mYuvTexHeight;// = 66;
+ const int mYuvTexWidth;
+ const int mYuvTexHeight;
sp<SurfaceMediaSource> mSMS;
sp<SurfaceTextureClient> mSTC;
@@ -124,7 +124,6 @@
// TODO: overwriting the colorformat since the format set by GRAlloc
// could be wrong or not be read by OMX
enc_meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
- // colorFormat);
sp<MediaSource> encoder =
@@ -225,7 +224,6 @@
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -239,7 +237,6 @@
// setting the client side buffer size different than the server size
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
10, 10, HAL_PIXEL_FORMAT_YV12));
- // OMX_COLOR_FormatYUV420Planar)); // ));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
@@ -258,6 +255,7 @@
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
@@ -276,10 +274,12 @@
// A dummy writer is used to simulate actual MPEG4Writer
TEST_F(SurfaceMediaSourceTest, EncodingFromCpuFilledYV12BufferNpotMultiBufferPassLag) {
LOGV("Testing MultiBufferPass, Dummy Recorder Lagging **************");
+
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
+
SimpleDummyRecorder writer(mSMS);
writer.start();
@@ -322,10 +322,9 @@
TEST_F(SurfaceMediaSourceTest, DISABLED_EncodingFromCpuFilledYV12BufferNpotWrite) {
LOGV("Testing the whole pipeline with actual Recorder");
ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
- 0, 0, HAL_PIXEL_FORMAT_YV12)); // OMX_COLOR_FormatYUV420Planar)); // ));
+ 0, 0, HAL_PIXEL_FORMAT_YV12));
ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
-
OMXClient client;
CHECK_EQ(OK, client.connect());
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index a0407b9..fa49592 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -21,7 +21,8 @@
libhardware \
libhardware_legacy \
libeffects \
- libdl
+ libdl \
+ libpowermanager
LOCAL_STATIC_LIBRARIES := \
libcpustats \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0323fe0..ec45530 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -53,6 +53,7 @@
#include <audio_effects/effect_visualizer.h>
#include <cpustats/ThreadCpuUsage.h>
+#include <powermanager/PowerManager.h>
// #define DEBUG_CPU_USAGE 10 // log statistics every n wall clock seconds
// ----------------------------------------------------------------------------
@@ -887,14 +888,18 @@
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id, uint32_t device)
: Thread(false),
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
- mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false), mDevice(device)
+ mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false),
+ mDevice(device)
{
+ mDeathRecipient = new PMDeathRecipient(this);
}
AudioFlinger::ThreadBase::~ThreadBase()
{
mParamCond.broadcast();
mNewParameters.clear();
+ // do not lock the mutex in destructor
+ releaseWakeLock_l();
}
void AudioFlinger::ThreadBase::exit()
@@ -1043,6 +1048,88 @@
return NO_ERROR;
}
+status_t AudioFlinger::ThreadBase::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+
+ snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+ write(fd, buffer, strlen(buffer));
+
+ for (size_t i = 0; i < mEffectChains.size(); ++i) {
+ sp<EffectChain> chain = mEffectChains[i];
+ if (chain != 0) {
+ chain->dump(fd, args);
+ }
+ }
+ return NO_ERROR;
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ acquireWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::acquireWakeLock_l()
+{
+ if (mPowerManager == 0) {
+ // use checkService() to avoid blocking if power service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("power"));
+ if (binder == 0) {
+ LOGW("Thread %s cannot connect to the power manager service", mName);
+ } else {
+ mPowerManager = interface_cast<IPowerManager>(binder);
+ binder->linkToDeath(mDeathRecipient);
+ }
+ }
+ if (mPowerManager != 0) {
+ sp<IBinder> binder = new BBinder();
+ status_t status = mPowerManager->acquireWakeLock(POWERMANAGER_PARTIAL_WAKE_LOCK,
+ binder,
+ String16(mName));
+ if (status == NO_ERROR) {
+ mWakeLockToken = binder;
+ }
+ LOGV("acquireWakeLock_l() %s status %d", mName, status);
+ }
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+}
+
+void AudioFlinger::ThreadBase::releaseWakeLock_l()
+{
+ if (mWakeLockToken != 0) {
+ LOGV("releaseWakeLock_l() %s", mName);
+ if (mPowerManager != 0) {
+ mPowerManager->releaseWakeLock(mWakeLockToken, 0);
+ }
+ mWakeLockToken.clear();
+ }
+}
+
+void AudioFlinger::ThreadBase::clearPowerManager()
+{
+ Mutex::Autolock _l(mLock);
+ releaseWakeLock_l();
+ mPowerManager.clear();
+}
+
+void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who)
+{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread != 0) {
+ thread->clearPowerManager();
+ }
+ LOGW("power manager service died !!!");
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
@@ -1053,6 +1140,8 @@
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
{
+ snprintf(mName, kNameLength, "AudioOut_%d", id);
+
readOutputParameters();
mMasterVolume = mAudioFlinger->masterVolume();
@@ -1111,24 +1200,6 @@
return NO_ERROR;
}
-status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
-{
- const size_t SIZE = 256;
- char buffer[SIZE];
- String8 result;
-
- snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
- write(fd, buffer, strlen(buffer));
-
- for (size_t i = 0; i < mEffectChains.size(); ++i) {
- sp<EffectChain> chain = mEffectChains[i];
- if (chain != 0) {
- chain->dump(fd, args);
- }
- }
- return NO_ERROR;
-}
-
status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -1169,12 +1240,7 @@
void AudioFlinger::PlaybackThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Playback Thread %p", this);
-
- run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+ run(mName, ANDROID_PRIORITY_URGENT_AUDIO);
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1521,6 +1587,8 @@
const CentralTendencyStatistics& stats = cpu.statistics();
#endif
+ acquireWakeLock();
+
while (!exitPending())
{
#ifdef DEBUG_CPU_USAGE
@@ -1584,10 +1652,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
// wait until we have something to do...
LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -1688,6 +1758,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("MixerThread %p exiting", this);
return false;
}
@@ -2175,6 +2247,8 @@
// hardware resources as soon as possible
nsecs_t standbyDelay = microseconds(activeSleepTime*2);
+ acquireWakeLock();
+
while (!exitPending())
{
bool rampVolume;
@@ -2214,9 +2288,11 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+ acquireWakeLock_l();
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
@@ -2435,6 +2511,8 @@
mOutput->stream->common.standby(&mOutput->stream->common);
}
+ releaseWakeLock();
+
LOGV("DirectOutputThread %p exiting", this);
return false;
}
@@ -2560,6 +2638,8 @@
uint32_t sleepTime = idleSleepTime;
Vector< sp<EffectChain> > effectChains;
+ acquireWakeLock();
+
while (!exitPending())
{
processConfigEvents();
@@ -2600,9 +2680,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
mWaitWorkCV.wait(mLock);
LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+ acquireWakeLock_l();
+
if (mMasterMute == false) {
char value[PROPERTY_VALUE_MAX];
property_get("ro.audio.silent", value, "0");
@@ -2689,6 +2772,8 @@
effectChains.clear();
}
+ releaseWakeLock();
+
return false;
}
@@ -3813,6 +3898,9 @@
mInput(input), mTrack(NULL), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{
mType = ThreadBase::RECORD;
+
+ snprintf(mName, kNameLength, "AudioIn_%d", id);
+
mReqChannelCount = popcount(channels);
mReqSampleRate = sampleRate;
readInputParameters();
@@ -3830,12 +3918,7 @@
void AudioFlinger::RecordThread::onFirstRef()
{
- const size_t SIZE = 256;
- char buffer[SIZE];
-
- snprintf(buffer, SIZE, "Record Thread %p", this);
-
- run(buffer, PRIORITY_URGENT_AUDIO);
+ run(mName, PRIORITY_URGENT_AUDIO);
}
bool AudioFlinger::RecordThread::threadLoop()
@@ -3846,6 +3929,8 @@
nsecs_t lastWarning = 0;
+ acquireWakeLock();
+
// start recording
while (!exitPending()) {
@@ -3862,10 +3947,12 @@
if (exitPending()) break;
+ releaseWakeLock_l();
LOGV("RecordThread: loop stopping");
// go to sleep
mWaitWorkCV.wait(mLock);
LOGV("RecordThread: loop starting");
+ acquireWakeLock_l();
continue;
}
if (mActiveTrack != 0) {
@@ -3906,8 +3993,6 @@
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
- // enable changes in effect chain
- unlockEffectChains(effectChains);
buffer.frameCount = mFrameCount;
if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
@@ -4007,9 +4092,9 @@
// clear the overflow.
usleep(kRecordThreadSleepUs);
}
- } else {
- unlockEffectChains(effectChains);
}
+ // enable changes in effect chain
+ unlockEffectChains(effectChains);
effectChains.clear();
}
@@ -4020,6 +4105,8 @@
mStartStopCond.broadcast();
+ releaseWakeLock();
+
LOGV("RecordThread %p exiting", this);
return false;
}
@@ -4178,6 +4265,7 @@
write(fd, result.string(), result.size());
dumpBase(fd, args);
+ dumpEffectChains(fd, args);
return NO_ERROR;
}
@@ -5579,13 +5667,11 @@
}
}
- // Release effect engine here so that it is done immediately. Otherwise it will be released
- // by the destructor when the last strong reference on the this object is released which can
- // happen after next process is called on this effect.
- if (size == 0 && mEffectInterface != NULL) {
- // release effect engine
- EffectRelease(mEffectInterface);
- mEffectInterface = NULL;
+ // Prevent calls to process() and other functions on effect interface from now on.
+ // The effect engine will be released by the destructor when the last strong reference on
+ // this object is released which can happen after next process is called.
+ if (size == 0) {
+ mState = DESTROYED;
}
return size;
@@ -5635,7 +5721,7 @@
mState = IDLE;
}
break;
- default: //IDLE , ACTIVE
+ default: //IDLE , ACTIVE, DESTROYED
break;
}
}
@@ -5644,7 +5730,7 @@
{
Mutex::Autolock _l(mLock);
- if (mEffectInterface == NULL ||
+ if (mState == DESTROYED || mEffectInterface == NULL ||
mConfig.inputCfg.buffer.raw == NULL ||
mConfig.outputCfg.buffer.raw == NULL) {
return;
@@ -5820,6 +5906,12 @@
return status;
}
+status_t AudioFlinger::EffectModule::stop()
+{
+ Mutex::Autolock _l(mLock);
+ return stop_l();
+}
+
status_t AudioFlinger::EffectModule::stop_l()
{
if (mEffectInterface == NULL) {
@@ -5856,7 +5948,7 @@
Mutex::Autolock _l(mLock);
// LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
- if (mEffectInterface == NULL) {
+ if (mState == DESTROYED || mEffectInterface == NULL) {
return NO_INIT;
}
status_t status = (*mEffectInterface)->command(mEffectInterface,
@@ -5905,6 +5997,8 @@
case ACTIVE:
mState = STOPPING;
break;
+ case DESTROYED:
+ return NO_ERROR; // simply ignore as we are being destroyed
}
for (size_t i = 1; i < mHandles.size(); i++) {
sp<EffectHandle> h = mHandles[i].promote();
@@ -5926,6 +6020,7 @@
case IDLE:
case STOPPING:
case STOPPED:
+ case DESTROYED:
default:
return false;
}
@@ -5941,6 +6036,7 @@
return true;
case IDLE:
case STARTING:
+ case DESTROYED:
default:
return false;
}
@@ -6542,6 +6638,10 @@
for (i = 0; i < size; i++) {
if (effect == mEffects[i]) {
+ // calling stop here will remove pre-processing effect from the audio HAL.
+ // This is safe as we hold the EffectChain mutex which guarantees that we are not in
+ // the middle of a read from audio HAL
+ mEffects[i]->stop();
if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
delete[] effect->inBuffer();
} else {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fff4f06..7b6215f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -43,6 +43,8 @@
#include "AudioBufferProvider.h"
+#include <powermanager/IPowerManager.h>
+
namespace android {
class audio_track_cblk_t;
@@ -285,6 +287,9 @@
};
status_t dumpBase(int fd, const Vector<String16>& args);
+ status_t dumpEffectChains(int fd, const Vector<String16>& args);
+
+ void clearPowerManager();
// base for record and playback
class TrackBase : public AudioBufferProvider, public RefBase {
@@ -385,6 +390,21 @@
int mParam;
};
+ class PMDeathRecipient : public IBinder::DeathRecipient {
+ public:
+ PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
+ virtual ~PMDeathRecipient() {}
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who);
+
+ private:
+ PMDeathRecipient(const PMDeathRecipient&);
+ PMDeathRecipient& operator = (const PMDeathRecipient&);
+
+ wp<ThreadBase> mThread;
+ };
+
virtual status_t initCheck() const = 0;
int type() const { return mType; }
uint32_t sampleRate() const;
@@ -461,6 +481,11 @@
protected:
+ void acquireWakeLock();
+ void acquireWakeLock_l();
+ void releaseWakeLock();
+ void releaseWakeLock_l();
+
friend class Track;
friend class TrackBase;
friend class PlaybackThread;
@@ -489,6 +514,11 @@
Vector< sp<EffectChain> > mEffectChains;
uint32_t mDevice; // output device for PlaybackThread
// input + output devices for RecordThread
+ static const int kNameLength = 32;
+ char mName[kNameLength];
+ sp<IPowerManager> mPowerManager;
+ sp<IBinder> mWakeLockToken;
+ sp<PMDeathRecipient> mDeathRecipient;
};
// --- PlaybackThread ---
@@ -724,7 +754,6 @@
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
status_t dumpTracks(int fd, const Vector<String16>& args);
- status_t dumpEffectChains(int fd, const Vector<String16>& args);
SortedVector< sp<Track> > mTracks;
// mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
@@ -995,7 +1024,8 @@
STARTING,
ACTIVE,
STOPPING,
- STOPPED
+ STOPPED,
+ DESTROYED
};
int id() { return mId; }
@@ -1040,6 +1070,7 @@
status_t setDevice(uint32_t device);
status_t setVolume(uint32_t *left, uint32_t *right, bool controller);
status_t setMode(uint32_t mode);
+ status_t stop();
status_t dump(int fd, const Vector<String16>& args);
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd1e153..6d06d83 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -497,6 +497,43 @@
return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
}
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+
+ if (mpAudioPolicy == NULL) {
+ *count = 0;
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+
+ size_t index;
+ for (index = 0; index < mInputs.size(); index++) {
+ if (mInputs.valueAt(index)->mSessionId == audioSession) {
+ break;
+ }
+ }
+ if (index == mInputs.size()) {
+ *count = 0;
+ return BAD_VALUE;
+ }
+ Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+ for (size_t i = 0; i < effects.size(); i++) {
+ effect_descriptor_t desc = effects[i]->descriptor();
+ if (i < *count) {
+ memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+ }
+ }
+ if (effects.size() > *count) {
+ status = NO_MEMORY;
+ }
+ *count = effects.size();
+ return status;
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
IPCThreadState::self()->getCallingPid());
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 62ad29e..834b794 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -104,6 +104,9 @@
virtual status_t unregisterEffect(int id);
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a583aad..31544b3 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -38,6 +38,7 @@
typedef void (*data_callback)(int32_t msgType,
const sp<IMemory> &dataPtr,
+ camera_frame_metadata_t *metadata,
void* user);
typedef void (*data_callback_timestamp)(nsecs_t timestamp,
@@ -386,7 +387,10 @@
if (mDevice->ops->get_parameters) {
char *temp = mDevice->ops->get_parameters(mDevice);
String8 str_parms(temp);
- free(temp);
+ if (mDevice->ops->put_parameters)
+ mDevice->ops->put_parameters(mDevice, temp);
+ else
+ free(temp);
parms.unflatten(str_parms);
}
return parms;
@@ -439,6 +443,7 @@
static void __data_cb(int32_t msg_type,
const camera_memory_t *data, unsigned int index,
+ camera_frame_metadata_t *metadata,
void *user)
{
LOGV("%s", __FUNCTION__);
@@ -450,7 +455,7 @@
index, mem->mNumBufs);
return;
}
- __this->mDataCb(msg_type, mem->mBuffers[index], __this->mCbUser);
+ __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
}
static void __data_cb_timestamp(nsecs_t timestamp, int32_t msg_type,
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
index 07b5a37..863f19e 100644
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -180,7 +180,7 @@
// Notify the client of a new frame.
if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
- mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
// Advance the buffer pointer.
mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
@@ -290,14 +290,14 @@
sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
FakeCamera cam(w, h);
cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
- mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
}
if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
- mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
}
return NO_ERROR;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 96b26e7..b03649e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -988,7 +988,7 @@
}
void CameraService::Client::dataCallback(int32_t msgType,
- const sp<IMemory>& dataPtr, void* user) {
+ const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
LOG2("dataCallback(%d)", msgType);
sp<Client> client = getClientFromCookie(user);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index c5fefb8..af7f06e 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -140,7 +140,8 @@
// these are static callback functions
static void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
- static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+ static void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+ camera_frame_metadata_t *metadata, void* user);
static void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
// convert client from cookie
static sp<Client> getClientFromCookie(void* user);