diff options
Diffstat (limited to 'include')
102 files changed, 3777 insertions, 1018 deletions
diff --git a/include/camera/CameraMetadata.h b/include/camera/CameraMetadata.h index 1254d3c..953d711 100644 --- a/include/camera/CameraMetadata.h +++ b/include/camera/CameraMetadata.h @@ -56,7 +56,7 @@ class CameraMetadata { * thread-safety, it simply prevents the camera_metadata_t pointer returned * here from being accidentally invalidated by CameraMetadata operations. */ - const camera_metadata_t* getAndLock(); + const camera_metadata_t* getAndLock() const; /** * Unlock the CameraMetadata for use again. After this unlock, the pointer @@ -208,7 +208,7 @@ class CameraMetadata { private: camera_metadata_t *mBuffer; - bool mLocked; + mutable bool mLocked; /** * Check if tag has a given type diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index c6074fc..ba33ffe 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -108,6 +108,9 @@ public: */ void getSupportedPreviewFormats(Vector<int>& formats) const; + // Returns true if no keys are present + bool isEmpty() const; + // Parameter keys to communicate between camera application and driver. // The access (read/write, read only, or write only) is viewed from the // perspective of applications, not driver. diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h index f7f06bb..1b68b5f 100644 --- a/include/camera/ICameraService.h +++ b/include/camera/ICameraService.h @@ -25,8 +25,6 @@ namespace android { class ICamera; class ICameraClient; -class IProCameraUser; -class IProCameraCallbacks; class ICameraServiceListener; class ICameraDeviceUser; class ICameraDeviceCallbacks; @@ -44,7 +42,6 @@ public: GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION, GET_CAMERA_INFO, CONNECT, - CONNECT_PRO, CONNECT_DEVICE, ADD_LISTENER, REMOVE_LISTENER, @@ -53,6 +50,8 @@ public: GET_LEGACY_PARAMETERS, SUPPORTS_CAMERA_API, CONNECT_LEGACY, + SET_TORCH_MODE, + NOTIFY_SYSTEM_EVENT, }; enum { @@ -65,13 +64,34 @@ public: }; enum { + CAMERA_TYPE_BACKWARD_COMPATIBLE = 0, + CAMERA_TYPE_ALL = 1, + }; + + enum { CAMERA_HAL_API_VERSION_UNSPECIFIED = -1 - }; + }; + + /** + * Keep up-to-date with declarations in + * frameworks/base/services/core/java/com/android/server/camera/CameraService.java + * + * These event codes are intended to be used with the notifySystemEvent call. + */ + enum { + NO_EVENT = 0, + USER_SWITCHED, + }; public: DECLARE_META_INTERFACE(CameraService); + // Get the number of cameras that support basic color camera operation + // (type CAMERA_TYPE_BACKWARD_COMPATIBLE) virtual int32_t getNumberOfCameras() = 0; + // Get the number of cameras of the specified type, one of CAMERA_TYPE_* + // enums + virtual int32_t getNumberOfCameras(int cameraType) = 0; virtual status_t getCameraInfo(int cameraId, /*out*/ struct CameraInfo* cameraInfo) = 0; @@ -104,13 +124,6 @@ public: /*out*/ sp<ICamera>& device) = 0; - virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb, - int cameraId, - const String16& clientPackageName, - int clientUid, - /*out*/ - sp<IProCameraUser>& device) = 0; - virtual status_t connectDevice( const sp<ICameraDeviceCallbacks>& cameraCb, int cameraId, @@ -142,6 +155,26 @@ public: int clientUid, /*out*/ sp<ICamera>& device) = 0; + + /** + * Turn on or off a camera's torch mode. Torch mode will be turned off by + * camera service if the lastest client binder that turns it on dies. + * + * return values: + * 0: on a successful operation. + * -ENOSYS: the camera device doesn't support this operation. It it returned + * if and only if android.flash.into.available is false. + * -EBUSY: the camera device is opened. + * -EINVAL: camera_id is invalid or clientBinder is NULL when enabling a + * torch mode. + */ + virtual status_t setTorchMode(const String16& cameraId, bool enabled, + const sp<IBinder>& clientBinder) = 0; + + /** + * Notify the camera service of a system event. Should only be called from system_server. + */ + virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/camera/ICameraServiceListener.h b/include/camera/ICameraServiceListener.h index 0a0e43a..709ff31 100644 --- a/include/camera/ICameraServiceListener.h +++ b/include/camera/ICameraServiceListener.h @@ -66,9 +66,35 @@ public: STATUS_UNKNOWN = 0xFFFFFFFF, }; + /** + * The torch mode status of a camera. + * + * Initial status will be transmitted with onTorchStatusChanged immediately + * after this listener is added to the service listener list. + * + * The enums should be set to values matching + * include/hardware/camera_common.h + */ + enum TorchStatus { + // The camera's torch mode has become not available to use via + // setTorchMode(). + TORCH_STATUS_NOT_AVAILABLE = TORCH_MODE_STATUS_NOT_AVAILABLE, + // The camera's torch mode is off and available to be turned on via + // setTorchMode(). + TORCH_STATUS_AVAILABLE_OFF = TORCH_MODE_STATUS_AVAILABLE_OFF, + // The camera's torch mode is on and available to be turned off via + // setTorchMode(). + TORCH_STATUS_AVAILABLE_ON = TORCH_MODE_STATUS_AVAILABLE_ON, + + // Use to initialize variables only + TORCH_STATUS_UNKNOWN = 0xFFFFFFFF, + }; + DECLARE_META_INTERFACE(CameraServiceListener); virtual void onStatusChanged(Status status, int32_t cameraId) = 0; + + virtual void onTorchStatusChanged(TorchStatus status, const String16& cameraId) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/camera/ICameraServiceProxy.h b/include/camera/ICameraServiceProxy.h new file mode 100644 index 0000000..12a555f --- /dev/null +++ b/include/camera/ICameraServiceProxy.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_ICAMERASERVICEPROXY_H +#define ANDROID_HARDWARE_ICAMERASERVICEPROXY_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> + +namespace android { + +class ICameraServiceProxy : public IInterface { +public: + enum { + PING_FOR_USER_UPDATE = IBinder::FIRST_CALL_TRANSACTION, + }; + + DECLARE_META_INTERFACE(CameraServiceProxy); + + virtual void pingForUserUpdate() = 0; +}; + +class BnCameraServiceProxy: public BnInterface<ICameraServiceProxy> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + + + +}; // namespace android + +#endif // ANDROID_HARDWARE_ICAMERASERVICEPROXY_H + + diff --git a/include/camera/IProCameraCallbacks.h b/include/camera/IProCameraCallbacks.h deleted file mode 100644 index e8abb89..0000000 --- a/include/camera/IProCameraCallbacks.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HARDWARE_IPROCAMERA_CALLBACKS_H -#define ANDROID_HARDWARE_IPROCAMERA_CALLBACKS_H - -#include <utils/RefBase.h> -#include <binder/IInterface.h> -#include <binder/Parcel.h> -#include <binder/IMemory.h> -#include <utils/Timers.h> -#include <system/camera.h> - -struct camera_metadata; - -namespace android { - -class IProCameraCallbacks : public IInterface -{ - /** - * Keep up-to-date with IProCameraCallbacks.aidl in frameworks/base - */ -public: - DECLARE_META_INTERFACE(ProCameraCallbacks); - - virtual void notifyCallback(int32_t msgType, - int32_t ext1, - int32_t ext2) = 0; - - enum LockStatus { - LOCK_ACQUIRED, - LOCK_RELEASED, - LOCK_STOLEN, - }; - - virtual void onLockStatusChanged(LockStatus newLockStatus) = 0; - - /** Missing by design: implementation is client-side in ProCamera.cpp **/ - // virtual void onBufferReceived(int streamId, - // const CpuConsumer::LockedBufer& buf); - virtual void onResultReceived(int32_t requestId, - camera_metadata* result) = 0; -}; - -// ---------------------------------------------------------------------------- - -class BnProCameraCallbacks : public BnInterface<IProCameraCallbacks> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif diff --git a/include/camera/IProCameraUser.h b/include/camera/IProCameraUser.h deleted file mode 100644 index 2ccc4d2..0000000 --- a/include/camera/IProCameraUser.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HARDWARE_IPROCAMERAUSER_H -#define ANDROID_HARDWARE_IPROCAMERAUSER_H - -#include <utils/RefBase.h> -#include <binder/IInterface.h> -#include <binder/Parcel.h> -#include <binder/IMemory.h> -#include <utils/String8.h> -#include <camera/IProCameraCallbacks.h> - -struct camera_metadata; - -namespace android { - -class IProCameraUserClient; -class IGraphicBufferProducer; -class Surface; - -class IProCameraUser: public IInterface -{ - /** - * Keep up-to-date with IProCameraUser.aidl in frameworks/base - */ -public: - DECLARE_META_INTERFACE(ProCameraUser); - - virtual void disconnect() = 0; - - // connect to the service, given a callbacks listener - virtual status_t connect(const sp<IProCameraCallbacks>& callbacks) - = 0; - - /** - * Locking - **/ - virtual status_t exclusiveTryLock() = 0; - virtual status_t exclusiveLock() = 0; - virtual status_t exclusiveUnlock() = 0; - - virtual bool hasExclusiveLock() = 0; - - /** - * Request Handling - **/ - - // Note that the callee gets a copy of the metadata. - virtual int submitRequest(struct camera_metadata* metadata, - bool streaming = false) = 0; - virtual status_t cancelRequest(int requestId) = 0; - - virtual status_t deleteStream(int streamId) = 0; - virtual status_t createStream( - int width, int height, int format, - const sp<IGraphicBufferProducer>& bufferProducer, - /*out*/ - int* streamId) = 0; - - // Create a request object from a template. - virtual status_t createDefaultRequest(int templateId, - /*out*/ - camera_metadata** request) - = 0; - - // Get static camera metadata - virtual status_t getCameraInfo(int cameraId, - /*out*/ - camera_metadata** info) = 0; - -}; - -// ---------------------------------------------------------------------------- - -class BnProCameraUser: public BnInterface<IProCameraUser> -{ -public: - virtual status_t onTransact( uint32_t code, - const Parcel& data, - Parcel* reply, - uint32_t flags = 0); -}; - -}; // namespace android - -#endif diff --git a/include/camera/ProCamera.h b/include/camera/ProCamera.h deleted file mode 100644 index e9b687a..0000000 --- a/include/camera/ProCamera.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HARDWARE_PRO_CAMERA_H -#define ANDROID_HARDWARE_PRO_CAMERA_H - -#include <utils/Timers.h> -#include <utils/KeyedVector.h> -#include <gui/IGraphicBufferProducer.h> -#include <system/camera.h> -#include <camera/IProCameraCallbacks.h> -#include <camera/IProCameraUser.h> -#include <camera/Camera.h> -#include <camera/CameraMetadata.h> -#include <camera/ICameraService.h> -#include <gui/CpuConsumer.h> - -#include <gui/Surface.h> - -#include <utils/Condition.h> -#include <utils/Mutex.h> - -#include <camera/CameraBase.h> - -struct camera_metadata; - -namespace android { - -// All callbacks on this class are concurrent -// (they come from separate threads) -class ProCameraListener : virtual public RefBase -{ -public: - virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; - - // Lock has been acquired. Write operations now available. - virtual void onLockAcquired() = 0; - // Lock has been released with exclusiveUnlock. - virtual void onLockReleased() = 0; - // Lock has been stolen by another client. - virtual void onLockStolen() = 0; - - // Lock free. - virtual void onTriggerNotify(int32_t msgType, int32_t ext1, int32_t ext2) - = 0; - // onFrameAvailable and OnResultReceived can come in with any order, - // use android.sensor.timestamp and LockedBuffer.timestamp to correlate them - - /** - * A new metadata buffer has been received. - * -- Ownership of request passes on to the callee, free with - * free_camera_metadata. - */ - virtual void onResultReceived(int32_t frameId, camera_metadata* result) = 0; - - // TODO: make onFrameAvailable pure virtual - - // A new frame buffer has been received for this stream. - // -- This callback only fires for createStreamCpu streams - // -- A buffer may be obtained by calling cpuConsumer->lockNextBuffer - // -- Use buf.timestamp to correlate with result's android.sensor.timestamp - // -- The buffer should be accessed with CpuConsumer::lockNextBuffer - // and CpuConsumer::unlockBuffer - virtual void onFrameAvailable(int /*streamId*/, - const sp<CpuConsumer>& /*cpuConsumer*/) { - } - -}; - -class ProCamera; - -template <> -struct CameraTraits<ProCamera> -{ - typedef ProCameraListener TCamListener; - typedef IProCameraUser TCamUser; - typedef IProCameraCallbacks TCamCallbacks; - typedef status_t (ICameraService::*TCamConnectService)(const sp<IProCameraCallbacks>&, - int, const String16&, int, - /*out*/ - sp<IProCameraUser>&); - static TCamConnectService fnConnectService; -}; - - -class ProCamera : - public CameraBase<ProCamera>, - public BnProCameraCallbacks -{ -public: - /** - * Connect a shared camera. By default access is restricted to read only - * (Lock free) operations. To be able to submit custom requests a lock needs - * to be acquired with exclusive[Try]Lock. - */ - static sp<ProCamera> connect(int cameraId); - virtual ~ProCamera(); - - /** - * Exclusive Locks: - * - We may request exclusive access to a camera if no other - * clients are using the camera. This works as a traditional - * client, writing/reading any camera state. - * - An application opening the camera (a regular 'Camera') will - * always steal away the exclusive lock from a ProCamera, - * this will call onLockReleased. - * - onLockAcquired will be called again once it is possible - * to again exclusively lock the camera. - * - */ - - /** - * All exclusiveLock/unlock functions are asynchronous. The remote endpoint - * shall not block while waiting to acquire the lock. Instead the lock - * notifications will come in asynchronously on the listener. - */ - - /** - * Attempt to acquire the lock instantly (non-blocking) - * - If this succeeds, you do not need to wait for onLockAcquired - * but the event will still be fired - * - * Returns -EBUSY if already locked. 0 on success. - */ - status_t exclusiveTryLock(); - // always returns 0. wait for onLockAcquired before lock is acquired. - status_t exclusiveLock(); - // release a lock if we have one, or cancel the lock request. - status_t exclusiveUnlock(); - - // exclusive lock = do whatever we want. no lock = read only. - bool hasExclusiveLock(); - - /** - * < 0 error, >= 0 the request ID. streaming to have the request repeat - * until cancelled. - * The request queue is flushed when a lock is released or stolen - * if not locked will return PERMISSION_DENIED - */ - int submitRequest(const struct camera_metadata* metadata, - bool streaming = false); - // if not locked will return PERMISSION_DENIED, BAD_VALUE if requestId bad - status_t cancelRequest(int requestId); - - /** - * Ask for a stream to be enabled. - * Lock free. Service maintains counter of streams. - */ - status_t requestStream(int streamId); -// TODO: remove requestStream, its useless. - - /** - * Delete a stream. - * Lock free. - * - * NOTE: As a side effect this cancels ALL streaming requests. - * - * Errors: BAD_VALUE if unknown stream ID. - * PERMISSION_DENIED if the stream wasn't yours - */ - status_t deleteStream(int streamId); - - /** - * Create a new HW stream, whose sink will be the window. - * Lock free. Service maintains counter of streams. - * Errors: -EBUSY if too many streams created - */ - status_t createStream(int width, int height, int format, - const sp<Surface>& surface, - /*out*/ - int* streamId); - - /** - * Create a new HW stream, whose sink will be the SurfaceTexture. - * Lock free. Service maintains counter of streams. - * Errors: -EBUSY if too many streams created - */ - status_t createStream(int width, int height, int format, - const sp<IGraphicBufferProducer>& bufferProducer, - /*out*/ - int* streamId); - status_t createStreamCpu(int width, int height, int format, - int heapCount, - /*out*/ - sp<CpuConsumer>* cpuConsumer, - int* streamId); - status_t createStreamCpu(int width, int height, int format, - int heapCount, - bool synchronousMode, - /*out*/ - sp<CpuConsumer>* cpuConsumer, - int* streamId); - - // Create a request object from a template. - status_t createDefaultRequest(int templateId, - /*out*/ - camera_metadata** request) const; - - // Get static camera metadata - camera_metadata* getCameraInfo(int cameraId); - - // Blocks until a frame is available (CPU streams only) - // - Obtain the frame data by calling CpuConsumer::lockNextBuffer - // - Release the frame data after use with CpuConsumer::unlockBuffer - // Return value: - // - >0 - number of frames available to be locked - // - <0 - error (refer to error codes) - // Error codes: - // -ETIMEDOUT if it took too long to get a frame - int waitForFrameBuffer(int streamId); - - // Blocks until a metadata result is available - // - Obtain the metadata by calling consumeFrameMetadata() - // Error codes: - // -ETIMEDOUT if it took too long to get a frame - status_t waitForFrameMetadata(); - - // Get the latest metadata. This is destructive. - // - Calling this repeatedly will produce empty metadata objects. - // - Use waitForFrameMetadata to sync until new data is available. - CameraMetadata consumeFrameMetadata(); - - // Convenience method to drop frame buffers (CPU streams only) - // Return values: - // >=0 - number of frames dropped (up to count) - // <0 - error code - // Error codes: - // BAD_VALUE - invalid streamId or count passed - int dropFrameBuffer(int streamId, int count); - -protected: - //////////////////////////////////////////////////////// - // IProCameraCallbacks implementation - //////////////////////////////////////////////////////// - virtual void notifyCallback(int32_t msgType, - int32_t ext, - int32_t ext2); - - virtual void onLockStatusChanged( - IProCameraCallbacks::LockStatus newLockStatus); - - virtual void onResultReceived(int32_t requestId, - camera_metadata* result); -private: - ProCamera(int cameraId); - - class ProFrameListener : public CpuConsumer::FrameAvailableListener { - public: - ProFrameListener(wp<ProCamera> camera, int streamID) { - mCamera = camera; - mStreamId = streamID; - } - - protected: - virtual void onFrameAvailable(const BufferItem& /* item */) { - sp<ProCamera> c = mCamera.promote(); - if (c.get() != NULL) { - c->onFrameAvailable(mStreamId); - } - } - - private: - wp<ProCamera> mCamera; - int mStreamId; - }; - friend class ProFrameListener; - - struct StreamInfo - { - StreamInfo(int streamId) { - this->streamID = streamId; - cpuStream = false; - frameReady = 0; - } - - StreamInfo() { - streamID = -1; - cpuStream = false; - } - - int streamID; - bool cpuStream; - sp<CpuConsumer> cpuConsumer; - bool synchronousMode; - sp<ProFrameListener> frameAvailableListener; - sp<Surface> stc; - int frameReady; - }; - - Condition mWaitCondition; - Mutex mWaitMutex; - static const nsecs_t mWaitTimeout = 1000000000; // 1sec - KeyedVector<int, StreamInfo> mStreams; - bool mMetadataReady; - CameraMetadata mLatestMetadata; - - void onFrameAvailable(int streamId); - - StreamInfo& getStreamInfo(int streamId); - - friend class CameraBase; -}; - -}; // namespace android - -#endif diff --git a/include/camera/camera2/CaptureRequest.h b/include/camera/camera2/CaptureRequest.h index e56d61f..eeab217 100644 --- a/include/camera/camera2/CaptureRequest.h +++ b/include/camera/camera2/CaptureRequest.h @@ -30,6 +30,7 @@ public: CameraMetadata mMetadata; Vector<sp<Surface> > mSurfaceList; + bool mIsReprocess; /** * Keep impl up-to-date with CaptureRequest.java in frameworks/base diff --git a/include/camera/camera2/ICameraDeviceCallbacks.h b/include/camera/camera2/ICameraDeviceCallbacks.h index 670480b..c57b39f 100644 --- a/include/camera/camera2/ICameraDeviceCallbacks.h +++ b/include/camera/camera2/ICameraDeviceCallbacks.h @@ -65,6 +65,9 @@ public: // One way virtual void onResultReceived(const CameraMetadata& metadata, const CaptureResultExtras& resultExtras) = 0; + + // One way + virtual void onPrepared(int streamId) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/camera/camera2/ICameraDeviceUser.h b/include/camera/camera2/ICameraDeviceUser.h index 35488bb..a7bf8ab 100644 --- a/include/camera/camera2/ICameraDeviceUser.h +++ b/include/camera/camera2/ICameraDeviceUser.h @@ -27,9 +27,9 @@ namespace android { class ICameraDeviceUserClient; class IGraphicBufferProducer; -class Surface; class CaptureRequest; class CameraMetadata; +class OutputConfiguration; enum { NO_IN_FLIGHT_REPEATING_FRAMES = -1, @@ -97,12 +97,24 @@ public: * must be called before any requests can be submitted. * <p> */ - virtual status_t endConfigure() = 0; + virtual status_t endConfigure(bool isConstrainedHighSpeed = false) = 0; virtual status_t deleteStream(int streamId) = 0; - virtual status_t createStream( - int width, int height, int format, - const sp<IGraphicBufferProducer>& bufferProducer) = 0; + + virtual status_t createStream(const OutputConfiguration& outputConfiguration) = 0; + + /** + * Create an input stream of width, height, and format (one of + * HAL_PIXEL_FORMAT_*) + * + * Return stream ID if it's a non-negative value. status_t if it's a + * negative value. + */ + virtual status_t createInputStream(int width, int height, int format) = 0; + + // get the buffer producer of the input stream + virtual status_t getInputBufferProducer( + sp<IGraphicBufferProducer> *producer) = 0; // Create a request object from a template. virtual status_t createDefaultRequest(int templateId, @@ -121,6 +133,17 @@ public: */ virtual status_t flush(/*out*/ int64_t* lastFrameNumber = NULL) = 0; + + /** + * Preallocate buffers for a given output stream asynchronously. + */ + virtual status_t prepare(int streamId) = 0; + + /** + * Free all unused buffers for a given output stream. + */ + virtual status_t tearDown(int streamId) = 0; + }; // ---------------------------------------------------------------------------- diff --git a/include/camera/camera2/OutputConfiguration.h b/include/camera/camera2/OutputConfiguration.h new file mode 100644 index 0000000..5bcbe15 --- /dev/null +++ b/include/camera/camera2/OutputConfiguration.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H +#define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H + +#include <utils/RefBase.h> +#include <gui/IGraphicBufferProducer.h> + +namespace android { + +class Surface; + +class OutputConfiguration : public virtual RefBase { +public: + + static const int INVALID_ROTATION; + sp<IGraphicBufferProducer> getGraphicBufferProducer() const; + int getRotation() const; + + /** + * Keep impl up-to-date with OutputConfiguration.java in frameworks/base + */ + status_t writeToParcel(Parcel& parcel) const; + // getGraphicBufferProducer will be NULL if error occurred + // getRotation will be INVALID_ROTATION if error occurred + OutputConfiguration(const Parcel& parcel); + + OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation); + +private: + sp<IGraphicBufferProducer> mGbp; + int mRotation; + + // helper function + static String16 readMaybeEmptyString16(const Parcel& parcel); +}; +}; // namespace android + +#endif diff --git a/include/media/AVSyncSettings.h b/include/media/AVSyncSettings.h new file mode 100644 index 0000000..10e3bcc --- /dev/null +++ b/include/media/AVSyncSettings.h @@ -0,0 +1,61 @@ +/* + * 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 ANDROID_AV_SYNC_SETTINGS_H +#define ANDROID_AV_SYNC_SETTINGS_H + +namespace android { + +enum AVSyncSource : unsigned { + // let the system decide the best sync source + AVSYNC_SOURCE_DEFAULT = 0, + // sync to the system clock + AVSYNC_SOURCE_SYSTEM_CLOCK = 1, + // sync to the audio track + AVSYNC_SOURCE_AUDIO = 2, + // sync to the display vsync + AVSYNC_SOURCE_VSYNC = 3, + AVSYNC_SOURCE_MAX, +}; + +enum AVSyncAudioAdjustMode : unsigned { + // let the system decide the best audio adjust mode + AVSYNC_AUDIO_ADJUST_MODE_DEFAULT = 0, + // adjust audio by time stretching + AVSYNC_AUDIO_ADJUST_MODE_STRETCH = 1, + // adjust audio by resampling + AVSYNC_AUDIO_ADJUST_MODE_RESAMPLE = 2, + AVSYNC_AUDIO_ADJUST_MODE_MAX, +}; + +// max tolerance when adjusting playback speed to desired playback speed +#define AVSYNC_TOLERANCE_MAX 1.0f + +struct AVSyncSettings { + AVSyncSource mSource; + AVSyncAudioAdjustMode mAudioAdjustMode; + float mTolerance; + AVSyncSettings() + : mSource(AVSYNC_SOURCE_DEFAULT), + mAudioAdjustMode(AVSYNC_AUDIO_ADJUST_MODE_DEFAULT), + mTolerance(.044f) { } +}; + +} // namespace android + +// --------------------------------------------------------------------------- + +#endif // ANDROID_AV_SYNC_SETTINGS_H diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h index 583695d..5af6c10 100644 --- a/include/media/AudioEffect.h +++ b/include/media/AudioEffect.h @@ -201,8 +201,12 @@ public: */ /* Simple Constructor. + * + * Parameters: + * + * opPackageName: The package name used for app op checks. */ - AudioEffect(); + AudioEffect(const String16& opPackageName); /* Constructor. @@ -211,6 +215,7 @@ public: * * type: type of effect created: can be null if uuid is specified. This corresponds to * the OpenSL ES interface implemented by this effect. + * opPackageName: The package name used for app op checks. * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to * a particular implementation of an effect type. * priority: requested priority for effect control: the priority level corresponds to the @@ -227,6 +232,7 @@ public: */ AudioEffect(const effect_uuid_t *type, + const String16& opPackageName, const effect_uuid_t *uuid = NULL, int32_t priority = 0, effect_callback_t cbf = NULL, @@ -239,6 +245,7 @@ public: * Same as above but with type and uuid specified by character strings */ AudioEffect(const char *typeStr, + const String16& opPackageName, const char *uuidStr = NULL, int32_t priority = 0, effect_callback_t cbf = NULL, @@ -406,7 +413,9 @@ protected: void* mUserData; // client context for callback function effect_descriptor_t mDescriptor; // effect descriptor int32_t mId; // system wide unique effect engine instance ID - Mutex mLock; // Mutex for mEnabled access + Mutex mLock; // Mutex for mEnabled access + + String16 mOpPackageName; // The package name used for app op checks. // IEffectClient virtual void controlStatusChanged(bool controlGranted); @@ -420,7 +429,8 @@ protected: private: // Implements the IEffectClient interface - class EffectClient : public android::BnEffectClient, public android::IBinder::DeathRecipient + class EffectClient : + public android::BnEffectClient, public android::IBinder::DeathRecipient { public: @@ -428,24 +438,39 @@ private: // IEffectClient virtual void controlStatusChanged(bool controlGranted) { - mEffect->controlStatusChanged(controlGranted); + sp<AudioEffect> effect = mEffect.promote(); + if (effect != 0) { + effect->controlStatusChanged(controlGranted); + } } virtual void enableStatusChanged(bool enabled) { - mEffect->enableStatusChanged(enabled); + sp<AudioEffect> effect = mEffect.promote(); + if (effect != 0) { + effect->enableStatusChanged(enabled); + } } virtual void commandExecuted(uint32_t cmdCode, uint32_t cmdSize, void *pCmdData, uint32_t replySize, void *pReplyData) { - mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData); + sp<AudioEffect> effect = mEffect.promote(); + if (effect != 0) { + effect->commandExecuted( + cmdCode, cmdSize, pCmdData, replySize, pReplyData); + } } // IBinder::DeathRecipient - virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();} + virtual void binderDied(const wp<IBinder>& who) { + sp<AudioEffect> effect = mEffect.promote(); + if (effect != 0) { + effect->binderDied(); + } + } private: - AudioEffect *mEffect; + wp<AudioEffect> mEffect; }; void binderDied(); diff --git a/include/media/AudioIoDescriptor.h b/include/media/AudioIoDescriptor.h new file mode 100644 index 0000000..c94b738 --- /dev/null +++ b/include/media/AudioIoDescriptor.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 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 ANDROID_AUDIO_IO_DESCRIPTOR_H +#define ANDROID_AUDIO_IO_DESCRIPTOR_H + +namespace android { + +enum audio_io_config_event { + AUDIO_OUTPUT_OPENED, + AUDIO_OUTPUT_CLOSED, + AUDIO_OUTPUT_CONFIG_CHANGED, + AUDIO_INPUT_OPENED, + AUDIO_INPUT_CLOSED, + AUDIO_INPUT_CONFIG_CHANGED, +}; + +// audio input/output descriptor used to cache output configurations in client process to avoid +// frequent calls through IAudioFlinger +class AudioIoDescriptor : public RefBase { +public: + AudioIoDescriptor() : + mIoHandle(AUDIO_IO_HANDLE_NONE), + mSamplingRate(0), mFormat(AUDIO_FORMAT_DEFAULT), mChannelMask(AUDIO_CHANNEL_NONE), + mFrameCount(0), mLatency(0) + { + memset(&mPatch, 0, sizeof(struct audio_patch)); + } + + virtual ~AudioIoDescriptor() {} + + audio_port_handle_t getDeviceId() { + if (mPatch.num_sources != 0 && mPatch.num_sinks != 0) { + if (mPatch.sources[0].type == AUDIO_PORT_TYPE_MIX) { + // this is an output mix + // FIXME: the API only returns the first device in case of multiple device selection + return mPatch.sinks[0].id; + } else { + // this is an input mix + return mPatch.sources[0].id; + } + } + return AUDIO_PORT_HANDLE_NONE; + } + + audio_io_handle_t mIoHandle; + struct audio_patch mPatch; + uint32_t mSamplingRate; + audio_format_t mFormat; + audio_channel_mask_t mChannelMask; + size_t mFrameCount; + uint32_t mLatency; +}; + + +}; // namespace android + +#endif /*ANDROID_AUDIO_IO_DESCRIPTOR_H*/ diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h index a755e1e..feed402 100644 --- a/include/media/AudioPolicy.h +++ b/include/media/AudioPolicy.h @@ -38,8 +38,17 @@ namespace android { #define MIX_TYPE_PLAYERS 0 #define MIX_TYPE_RECORDERS 1 -#define ROUTE_FLAG_RENDER 0x1 -#define ROUTE_FLAG_LOOP_BACK (0x1 << 1) +// definition of the different events that can be reported on a dynamic policy from +// AudioSystem's implementation of the AudioPolicyClient interface +// keep in sync with AudioSystem.java +#define DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE 0 + +#define MIX_STATE_DISABLED -1 +#define MIX_STATE_IDLE 0 +#define MIX_STATE_MIXING 1 + +#define MIX_ROUTE_FLAG_RENDER 0x1 +#define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1) #define MAX_MIXES_PER_POLICY 10 #define MAX_CRITERIA_PER_MIX 20 @@ -61,11 +70,15 @@ public: class AudioMix { public: + // flag on an AudioMix indicating the activity on this mix (IDLE, MIXING) + // must be reported through the AudioPolicyClient interface + static const uint32_t kCbFlagNotifyActivity = 0x1; + AudioMix() {} AudioMix(Vector<AttributeMatchCriterion> criteria, uint32_t mixType, audio_config_t format, - uint32_t routeFlags, String8 registrationId) : + uint32_t routeFlags, String8 registrationId, uint32_t flags) : mCriteria(criteria), mMixType(mixType), mFormat(format), - mRouteFlags(routeFlags), mRegistrationId(registrationId) {} + mRouteFlags(routeFlags), mRegistrationId(registrationId), mCbFlags(flags){} status_t readFromParcel(Parcel *parcel); status_t writeToParcel(Parcel *parcel) const; @@ -75,6 +88,7 @@ public: audio_config_t mFormat; uint32_t mRouteFlags; String8 mRegistrationId; + uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag* }; }; // namespace android diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index f70d981..c4c7b0e 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -42,8 +42,7 @@ public: EVENT_MORE_DATA = 0, // Request to read available data from buffer. // If this event is delivered but the callback handler // does not want to read the available data, the handler must - // explicitly - // ignore the event by setting frameCount to zero. + // explicitly ignore the event by setting frameCount to zero. EVENT_OVERRUN = 1, // Buffer overrun occurred. EVENT_MARKER = 2, // Record head is at the specified marker position // (See setMarkerPosition()). @@ -53,7 +52,7 @@ public: // voluntary invalidation by mediaserver, or mediaserver crash. }; - /* Client should declare Buffer on the stack and pass address to obtainBuffer() + /* Client should declare a Buffer and pass address to obtainBuffer() * and releaseBuffer(). See also callback_t for EVENT_MORE_DATA. */ @@ -62,20 +61,25 @@ public: public: // FIXME use m prefix size_t frameCount; // number of sample frames corresponding to size; - // on input it is the number of frames available, - // on output is the number of frames actually drained - // (currently ignored but will make the primary field in future) + // on input to obtainBuffer() it is the number of frames desired + // on output from obtainBuffer() it is the number of available + // frames to be read + // on input to releaseBuffer() it is currently ignored size_t size; // input/output in bytes == frameCount * frameSize - // on output is the number of bytes actually drained - // FIXME this is redundant with respect to frameCount, - // and TRANSFER_OBTAIN mode is broken for 8-bit data - // since we don't define the frame format + // on input to obtainBuffer() it is ignored + // on output from obtainBuffer() it is the number of available + // bytes to be read, which is frameCount * frameSize + // on input to releaseBuffer() it is the number of bytes to + // release + // FIXME This is redundant with respect to frameCount. Consider + // removing size and making frameCount the primary field. union { void* raw; short* i16; // signed 16-bit int8_t* i8; // unsigned 8-bit, offset by 0x80 + // input to obtainBuffer(): unused, output: pointer to buffer }; }; @@ -88,8 +92,8 @@ public: * user: Pointer to context for use by the callback receiver. * info: Pointer to optional parameter according to event type: * - EVENT_MORE_DATA: pointer to AudioRecord::Buffer struct. The callback must not read - * more bytes than indicated by 'size' field and update 'size' if fewer bytes are - * consumed. + * more bytes than indicated by 'size' field and update 'size' if + * fewer bytes are consumed. * - EVENT_OVERRUN: unused. * - EVENT_MARKER: pointer to const uint32_t containing the marker position in frames. * - EVENT_NEW_POS: pointer to const uint32_t containing the new position in frames. @@ -106,6 +110,7 @@ public: * - BAD_VALUE: unsupported configuration * frameCount is guaranteed to be non-zero if status is NO_ERROR, * and is undefined otherwise. + * FIXME This API assumes a route, and so should be deprecated. */ static status_t getMinFrameCount(size_t* frameCount, @@ -118,14 +123,18 @@ public: enum transfer_type { TRANSFER_DEFAULT, // not specified explicitly; determine from the other parameters TRANSFER_CALLBACK, // callback EVENT_MORE_DATA - TRANSFER_OBTAIN, // FIXME deprecated: call obtainBuffer() and releaseBuffer() + TRANSFER_OBTAIN, // call obtainBuffer() and releaseBuffer() TRANSFER_SYNC, // synchronous read() }; /* Constructs an uninitialized AudioRecord. No connection with * AudioFlinger takes place. Use set() after this. + * + * Parameters: + * + * opPackageName: The package name used for app ops. */ - AudioRecord(); + AudioRecord(const String16& opPackageName); /* Creates an AudioRecord object and registers it with AudioFlinger. * Once created, the track needs to be started before it can be used. @@ -138,27 +147,30 @@ public: * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed * 16 bits per sample). * channelMask: Channel mask, such that audio_is_input_channel(channelMask) is true. + * opPackageName: The package name used for app ops. * frameCount: Minimum size of track PCM buffer in frames. This defines the * application's contribution to the * latency of the track. The actual size selected by the AudioRecord could * be larger if the requested size is not compatible with current audio HAL * latency. Zero means to use a default value. * cbf: Callback function. If not null, this function is called periodically - * to consume new data and inform of marker, position updates, etc. + * to consume new data in TRANSFER_CALLBACK mode + * and inform of marker, position updates, etc. * user: Context for use by the callback receiver. * notificationFrames: The callback function is called each time notificationFrames PCM * frames are ready in record track output buffer. * sessionId: Not yet supported. * transferType: How data is transferred from AudioRecord. * flags: See comments on audio_input_flags_t in <system/audio.h> + * pAttributes: If not NULL, supersedes inputSource for use case selection. * threadCanCallJava: Not present in parameter list, and so is fixed at false. - * pAttributes: if not NULL, supersedes inputSource for use case selection */ AudioRecord(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t frameCount = 0, callback_t cbf = NULL, void* user = NULL, @@ -166,6 +178,8 @@ public: int sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, + int uid = -1, + pid_t pid = -1, const audio_attributes_t* pAttributes = NULL); /* Terminates the AudioRecord and unregisters it from AudioFlinger. @@ -177,6 +191,7 @@ public: /* Initialize an AudioRecord that was created using the AudioRecord() constructor. * Don't call set() more than once, or after an AudioRecord() constructor that takes parameters. + * set() is not multi-thread safe. * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful intialization * - INVALID_OPERATION: AudioRecord is already initialized or record device is already in use @@ -201,6 +216,8 @@ public: int sessionId = AUDIO_SESSION_ALLOCATE, transfer_type transferType = TRANSFER_DEFAULT, audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, + int uid = -1, + pid_t pid = -1, const audio_attributes_t* pAttributes = NULL); /* Result of constructing the AudioRecord. This must be checked for successful initialization @@ -211,7 +228,7 @@ public: status_t initCheck() const { return mStatus; } /* Returns this track's estimated latency in milliseconds. - * This includes the latency due to AudioRecord buffer size, + * This includes the latency due to AudioRecord buffer size, resampling if applicable, * and audio hardware driver. */ uint32_t latency() const { return mLatency; } @@ -243,11 +260,6 @@ public: */ uint32_t getSampleRate() const { return mSampleRate; } - /* Return the notification frame count. - * This is approximately how often the callback is invoked, for transfer type TRANSFER_CALLBACK. - */ - size_t notificationFrames() const { return mNotificationFramesAct; } - /* Sets marker position. When record reaches the number of frames specified, * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition * with marker == 0 cancels marker notification callback. @@ -309,7 +321,12 @@ public: * Returned value: * handle on audio hardware input */ - audio_io_handle_t getInput() const; +// FIXME The only known public caller is frameworks/opt/net/voip/src/jni/rtp/AudioGroup.cpp + audio_io_handle_t getInput() const __attribute__((__deprecated__)) + { return getInputPrivate(); } +private: + audio_io_handle_t getInputPrivate() const; +public: /* Returns the audio session ID associated with this AudioRecord. * @@ -323,10 +340,18 @@ public: */ int getSessionId() const { return mSessionId; } - /* Obtains a buffer of up to "audioBuffer->frameCount" full frames. + /* Public API for TRANSFER_OBTAIN mode. + * Obtains a buffer of up to "audioBuffer->frameCount" full frames. * After draining these frames of data, the caller should release them with releaseBuffer(). * If the track buffer is not empty, obtainBuffer() returns as many contiguous * full frames as are available immediately. + * + * If nonContig is non-NULL, it is an output parameter that will be set to the number of + * additional non-contiguous frames that are predicted to be available immediately, + * if the client were to release the first frames and then call obtainBuffer() again. + * This value is only a prediction, and needs to be confirmed. + * It will be set to zero for an error return. + * * If the track buffer is empty and track is stopped, obtainBuffer() returns WOULD_BLOCK * regardless of the value of waitCount. * If the track buffer is empty and track is not stopped, obtainBuffer() blocks with a @@ -336,9 +361,6 @@ public: * or return WOULD_BLOCK depending on the value of the "waitCount" * parameter. * - * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications, - * which should use read() or callback EVENT_MORE_DATA instead. - * * Interpretation of waitCount: * +n limits wait time to n * WAIT_PERIOD_MS, * -1 causes an (almost) infinite wait time, @@ -347,6 +369,8 @@ public: * Buffer fields * On entry: * frameCount number of frames requested + * size ignored + * raw ignored * After error return: * frameCount 0 * size 0 @@ -357,13 +381,58 @@ public: * raw pointer to the buffer */ - /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */ - status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount) - __attribute__((__deprecated__)); + status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount, + size_t *nonContig = NULL); + + // Explicit Routing + /** + * TODO Document this method. + */ + status_t setInputDevice(audio_port_handle_t deviceId); + + /** + * TODO Document this method. + */ + audio_port_handle_t getInputDevice(); + + /* Returns the ID of the audio device actually used by the input to which this AudioRecord + * is attached. + * A value of AUDIO_PORT_HANDLE_NONE indicates the AudioRecord is not attached to any input. + * + * Parameters: + * none. + */ + audio_port_handle_t getRoutedDeviceId(); + + /* Add an AudioDeviceCallback. The caller will be notified when the audio device + * to which this AudioRecord is routed is updated. + * Replaces any previously installed callback. + * Parameters: + * callback: The callback interface + * Returns NO_ERROR if successful. + * INVALID_OPERATION if the same callback is already installed. + * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable + * BAD_VALUE if the callback is NULL + */ + status_t addAudioDeviceCallback( + const sp<AudioSystem::AudioDeviceCallback>& callback); + + /* remove an AudioDeviceCallback. + * Parameters: + * callback: The callback interface + * Returns NO_ERROR if successful. + * INVALID_OPERATION if the callback is not installed + * BAD_VALUE if the callback is NULL + */ + status_t removeAudioDeviceCallback( + const sp<AudioSystem::AudioDeviceCallback>& callback); private: /* If nonContig is non-NULL, it is an output parameter that will be set to the number of - * additional non-contiguous frames that are available immediately. + * additional non-contiguous frames that are predicted to be available immediately, + * if the client were to release the first frames and then call obtainBuffer() again. + * This value is only a prediction, and needs to be confirmed. + * It will be set to zero for an error return. * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(), * in case the requested amount of frames is in two or more non-contiguous regions. * FIXME requested and elapsed are both relative times. Consider changing to absolute time. @@ -372,9 +441,15 @@ private: struct timespec *elapsed = NULL, size_t *nonContig = NULL); public: - /* Release an emptied buffer of "audioBuffer->frameCount" frames for AudioFlinger to re-fill. */ - // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed - void releaseBuffer(Buffer* audioBuffer); + /* Public API for TRANSFER_OBTAIN mode. + * Release an emptied buffer of "audioBuffer->frameCount" frames for AudioFlinger to re-fill. + * + * Buffer fields: + * frameCount currently ignored but recommend to set to actual number of frames consumed + * size actual number of bytes consumed, must be multiple of frameSize + * raw ignored + */ + void releaseBuffer(const Buffer* audioBuffer); /* As a convenience we provide a read() interface to the audio buffer. * Input parameter 'size' is in byte units. @@ -386,8 +461,11 @@ public: * WOULD_BLOCK when obtainBuffer() returns same, or * AudioRecord was stopped during the read * or any other error code returned by IAudioRecord::start() or restoreRecord_l(). + * Default behavior is to only return when all data has been transferred. Set 'blocking' to + * false for the method to return immediately without waiting to try multiple times to read + * the full content of the buffer. */ - ssize_t read(void* buffer, size_t size); + ssize_t read(void* buffer, size_t size, bool blocking = true); /* Return the number of input frames lost in the audio driver since the last call of this * function. Audio driver is expected to reset the value to 0 and restart counting upon @@ -416,6 +494,7 @@ private: void pause(); // suspend thread from execution at next loop boundary void resume(); // allow thread to execute, if not requested to exit + void wake(); // wake to handle changed notification conditions. private: void pauseInternal(nsecs_t ns = 0LL); @@ -430,7 +509,9 @@ private: bool mPaused; // whether thread is requested to pause at next loop entry bool mPausedInt; // whether thread internally requests pause nsecs_t mPausedNs; // if mPausedInt then associated timeout, otherwise ignored - bool mIgnoreNextPausedInt; // whether to ignore next mPausedInt request + bool mIgnoreNextPausedInt; // skip any internal pause and go immediately + // to processAudioBuffer() as state may have changed + // since pause time calculated. }; // body of AudioRecordThread::threadLoop() @@ -445,7 +526,7 @@ private: // caller must hold lock on mLock for all _l methods - status_t openRecord_l(size_t epoch); + status_t openRecord_l(size_t epoch, const String16& opPackageName); // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); @@ -458,7 +539,7 @@ private: bool mActive; // for client callback handler - callback_t mCbf; // callback handler for events, or NULL + callback_t mCbf; // callback handler for events, or NULL void* mUserData; // for notification APIs @@ -475,13 +556,15 @@ private: bool mRetryOnPartialBuffer; // sleep and retry after partial obtainBuffer() uint32_t mObservedSequence; // last observed value of mSequence - uint32_t mMarkerPosition; // in wrapping (overflow) frame units + uint32_t mMarkerPosition; // in wrapping (overflow) frame units bool mMarkerReached; - uint32_t mNewPosition; // in frames - uint32_t mUpdatePeriod; // in frames, zero means no EVENT_NEW_POS + uint32_t mNewPosition; // in frames + uint32_t mUpdatePeriod; // in frames, zero means no EVENT_NEW_POS status_t mStatus; + String16 mOpPackageName; // The package name used for app ops. + size_t mFrameCount; // corresponds to current IAudioRecord, value is // reported back by AudioFlinger to the client size_t mReqFrameCount; // frame count to request the first or next time @@ -531,7 +614,14 @@ private: sp<DeathNotifier> mDeathNotifier; uint32_t mSequence; // incremented for each new IAudioRecord attempt + int mClientUid; + pid_t mClientPid; audio_attributes_t mAttributes; + + // For Device Selection API + // a value of AUDIO_PORT_HANDLE_NONE indicated default (AudioPolicyManager) routing. + audio_port_handle_t mSelectedDeviceId; + sp<AudioSystem::AudioDeviceCallback> mDeviceCallback; }; }; // namespace android diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h index 97847a0..055f724 100644 --- a/include/media/AudioResamplerPublic.h +++ b/include/media/AudioResamplerPublic.h @@ -17,6 +17,11 @@ #ifndef ANDROID_AUDIO_RESAMPLER_PUBLIC_H #define ANDROID_AUDIO_RESAMPLER_PUBLIC_H +#include <stdint.h> +#include <math.h> + +namespace android { + // AUDIO_RESAMPLER_DOWN_RATIO_MAX is the maximum ratio between the original // audio sample rate and the target rate when downsampling, // as permitted in the audio framework, e.g. AudioTrack and AudioFlinger. @@ -26,4 +31,147 @@ // TODO: replace with an API #define AUDIO_RESAMPLER_DOWN_RATIO_MAX 256 +// AUDIO_RESAMPLER_UP_RATIO_MAX is the maximum suggested ratio between the original +// audio sample rate and the target rate when upsampling. It is loosely enforced by +// the system. One issue with large upsampling ratios is the approximation by +// an int32_t of the phase increments, making the resulting sample rate inexact. +#define AUDIO_RESAMPLER_UP_RATIO_MAX 65536 + +// AUDIO_TIMESTRETCH_SPEED_MIN and AUDIO_TIMESTRETCH_SPEED_MAX define the min and max time stretch +// speeds supported by the system. These are enforced by the system and values outside this range +// will result in a runtime error. +// Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than +// the ones specified here +// AUDIO_TIMESTRETCH_SPEED_MIN_DELTA is the minimum absolute speed difference that might trigger a +// parameter update +#define AUDIO_TIMESTRETCH_SPEED_MIN 0.01f +#define AUDIO_TIMESTRETCH_SPEED_MAX 20.0f +#define AUDIO_TIMESTRETCH_SPEED_NORMAL 1.0f +#define AUDIO_TIMESTRETCH_SPEED_MIN_DELTA 0.0001f + +// AUDIO_TIMESTRETCH_PITCH_MIN and AUDIO_TIMESTRETCH_PITCH_MAX define the min and max time stretch +// pitch shifting supported by the system. These are not enforced by the system and values +// outside this range might result in a pitch different than the one requested. +// Depending on the AudioPlaybackRate::mStretchMode, the effective limits might be narrower than +// the ones specified here. +// AUDIO_TIMESTRETCH_PITCH_MIN_DELTA is the minimum absolute pitch difference that might trigger a +// parameter update +#define AUDIO_TIMESTRETCH_PITCH_MIN 0.25f +#define AUDIO_TIMESTRETCH_PITCH_MAX 4.0f +#define AUDIO_TIMESTRETCH_PITCH_NORMAL 1.0f +#define AUDIO_TIMESTRETCH_PITCH_MIN_DELTA 0.0001f + + +//Determines the current algorithm used for stretching +enum AudioTimestretchStretchMode : int32_t { + AUDIO_TIMESTRETCH_STRETCH_DEFAULT = 0, + AUDIO_TIMESTRETCH_STRETCH_SPEECH = 1, + //TODO: add more stretch modes/algorithms +}; + +//Limits for AUDIO_TIMESTRETCH_STRETCH_SPEECH mode +#define TIMESTRETCH_SONIC_SPEED_MIN 0.1f +#define TIMESTRETCH_SONIC_SPEED_MAX 6.0f + +//Determines behavior of Timestretch if current algorithm can't perform +//with current parameters. +// FALLBACK_CUT_REPEAT: (internal only) for speed <1.0 will truncate frames +// for speed > 1.0 will repeat frames +// FALLBACK_MUTE: will set all processed frames to zero +// FALLBACK_FAIL: will stop program execution and log a fatal error +enum AudioTimestretchFallbackMode : int32_t { + AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT = -1, + AUDIO_TIMESTRETCH_FALLBACK_DEFAULT = 0, + AUDIO_TIMESTRETCH_FALLBACK_MUTE = 1, + AUDIO_TIMESTRETCH_FALLBACK_FAIL = 2, +}; + +struct AudioPlaybackRate { + float mSpeed; + float mPitch; + enum AudioTimestretchStretchMode mStretchMode; + enum AudioTimestretchFallbackMode mFallbackMode; +}; + +static const AudioPlaybackRate AUDIO_PLAYBACK_RATE_DEFAULT = { + AUDIO_TIMESTRETCH_SPEED_NORMAL, + AUDIO_TIMESTRETCH_PITCH_NORMAL, + AUDIO_TIMESTRETCH_STRETCH_DEFAULT, + AUDIO_TIMESTRETCH_FALLBACK_DEFAULT +}; + +static inline bool isAudioPlaybackRateEqual(const AudioPlaybackRate &pr1, + const AudioPlaybackRate &pr2) { + return fabs(pr1.mSpeed - pr2.mSpeed) < AUDIO_TIMESTRETCH_SPEED_MIN_DELTA && + fabs(pr1.mPitch - pr2.mPitch) < AUDIO_TIMESTRETCH_PITCH_MIN_DELTA && + pr2.mStretchMode == pr2.mStretchMode && + pr2.mFallbackMode == pr2.mFallbackMode; +} + +static inline bool isAudioPlaybackRateValid(const AudioPlaybackRate &playbackRate) { + if (playbackRate.mFallbackMode == AUDIO_TIMESTRETCH_FALLBACK_FAIL && + (playbackRate.mStretchMode == AUDIO_TIMESTRETCH_STRETCH_SPEECH || + playbackRate.mStretchMode == AUDIO_TIMESTRETCH_STRETCH_DEFAULT)) { + //test sonic specific constraints + return playbackRate.mSpeed >= TIMESTRETCH_SONIC_SPEED_MIN && + playbackRate.mSpeed <= TIMESTRETCH_SONIC_SPEED_MAX && + playbackRate.mPitch >= AUDIO_TIMESTRETCH_PITCH_MIN && + playbackRate.mPitch <= AUDIO_TIMESTRETCH_PITCH_MAX; + } else { + return playbackRate.mSpeed >= AUDIO_TIMESTRETCH_SPEED_MIN && + playbackRate.mSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX && + playbackRate.mPitch >= AUDIO_TIMESTRETCH_PITCH_MIN && + playbackRate.mPitch <= AUDIO_TIMESTRETCH_PITCH_MAX; + } +} + +// TODO: Consider putting these inlines into a class scope + +// Returns the source frames needed to resample to destination frames. This is not a precise +// value and depends on the resampler (and possibly how it handles rounding internally). +// Nevertheless, this should be an upper bound on the requirements of the resampler. +// If srcSampleRate and dstSampleRate are equal, then it returns destination frames, which +// may not be true if the resampler is asynchronous. +static inline size_t sourceFramesNeeded( + uint32_t srcSampleRate, size_t dstFramesRequired, uint32_t dstSampleRate) { + // +1 for rounding - always do this even if matched ratio (resampler may use phases not ratio) + // +1 for additional sample needed for interpolation + return srcSampleRate == dstSampleRate ? dstFramesRequired : + size_t((uint64_t)dstFramesRequired * srcSampleRate / dstSampleRate + 1 + 1); +} + +// An upper bound for the number of destination frames possible from srcFrames +// after sample rate conversion. This may be used for buffer sizing. +static inline size_t destinationFramesPossible(size_t srcFrames, uint32_t srcSampleRate, + uint32_t dstSampleRate) { + if (srcSampleRate == dstSampleRate) { + return srcFrames; + } + uint64_t dstFrames = (uint64_t)srcFrames * dstSampleRate / srcSampleRate; + return dstFrames > 2 ? dstFrames - 2 : 0; +} + +static inline size_t sourceFramesNeededWithTimestretch( + uint32_t srcSampleRate, size_t dstFramesRequired, uint32_t dstSampleRate, + float speed) { + // required is the number of input frames the resampler needs + size_t required = sourceFramesNeeded(srcSampleRate, dstFramesRequired, dstSampleRate); + // to deliver this, the time stretcher requires: + return required * (double)speed + 1 + 1; // accounting for rounding dependencies +} + +// Identifies sample rates that we associate with music +// and thus eligible for better resampling and fast capture. +// This is somewhat less than 44100 to allow for pitch correction +// involving resampling as well as asynchronous resampling. +#define AUDIO_PROCESSING_MUSIC_RATE 40000 + +static inline bool isMusicRate(uint32_t sampleRate) { + return sampleRate >= AUDIO_PROCESSING_MUSIC_RATE; +} + +} // namespace android + +// --------------------------------------------------------------------------- + #endif // ANDROID_AUDIO_RESAMPLER_PUBLIC_H diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index 843a354..06116a5 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -19,6 +19,7 @@ #include <hardware/audio_effect.h> #include <media/AudioPolicy.h> +#include <media/AudioIoDescriptor.h> #include <media/IAudioFlingerClient.h> #include <media/IAudioPolicyServiceClient.h> #include <system/audio.h> @@ -29,6 +30,7 @@ namespace android { typedef void (*audio_error_callback)(status_t err); +typedef void (*dynamic_policy_callback)(int event, String8 regId, int val); class IAudioFlinger; class IAudioPolicyService; @@ -89,6 +91,7 @@ public: static String8 getParameters(const String8& keys); static void setErrorCallback(audio_error_callback cb); + static void setDynPolicyCallback(dynamic_policy_callback cb); // helper function to obtain AudioFlinger service handle static const sp<IAudioFlinger> get_audio_flinger(); @@ -98,10 +101,13 @@ public: // Returned samplingRate and frameCount output values are guaranteed // to be non-zero if status == NO_ERROR + // FIXME This API assumes a route, and so should be deprecated. static status_t getOutputSamplingRate(uint32_t* samplingRate, audio_stream_type_t stream); + // FIXME This API assumes a route, and so should be deprecated. static status_t getOutputFrameCount(size_t* frameCount, audio_stream_type_t stream); + // FIXME This API assumes a route, and so should be deprecated. static status_t getOutputLatency(uint32_t* latency, audio_stream_type_t stream); static status_t getSamplingRate(audio_io_handle_t output, @@ -110,19 +116,20 @@ public: // audio_stream->get_buffer_size()/audio_stream_out_frame_size() static status_t getFrameCount(audio_io_handle_t output, size_t* frameCount); - // returns the audio output stream latency in ms. Corresponds to + // returns the audio output latency in ms. Corresponds to // audio_stream_out->get_latency() static status_t getLatency(audio_io_handle_t output, uint32_t* latency); // return status NO_ERROR implies *buffSize > 0 + // FIXME This API assumes a route, and so should deprecated. static status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, size_t* buffSize); static status_t setVoiceVolume(float volume); // return the number of audio frames written by AudioFlinger to audio HAL and - // audio dsp to DAC since the specified output I/O handle has exited standby. + // audio dsp to DAC since the specified output has exited standby. // returned status (from utils/Errors.h) can be: // - NO_ERROR: successful operation, halFrames and dspFrames point to valid data // - INVALID_OPERATION: Not supported on current hardware platform @@ -151,32 +158,8 @@ public: // or no HW sync source is used. static audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId); - // types of io configuration change events received with ioConfigChanged() - enum io_config_event { - OUTPUT_OPENED, - OUTPUT_CLOSED, - OUTPUT_CONFIG_CHANGED, - INPUT_OPENED, - INPUT_CLOSED, - INPUT_CONFIG_CHANGED, - STREAM_CONFIG_CHANGED, - NUM_CONFIG_EVENTS - }; - - // audio output descriptor used to cache output configurations in client process to avoid - // frequent calls through IAudioFlinger - class OutputDescriptor { - public: - OutputDescriptor() - : samplingRate(0), format(AUDIO_FORMAT_DEFAULT), channelMask(0), frameCount(0), latency(0) - {} - - uint32_t samplingRate; - audio_format_t format; - audio_channel_mask_t channelMask; - size_t frameCount; - uint32_t latency; - }; + // Indicate JAVA services are ready (scheduling, power management ...) + static status_t systemReady(); // Events used to synchronize actions between audio sessions. // For instance SYNC_EVENT_PRESENTATION_COMPLETE can be used to delay recording start until @@ -201,7 +184,7 @@ public: // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions) // static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, - const char *device_address); + const char *device_address, const char *device_name); static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address); static status_t setPhoneState(audio_mode_t state); @@ -217,14 +200,16 @@ public: audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, const audio_offload_info_t *offloadInfo = NULL); static status_t getOutputForAttr(const audio_attributes_t *attr, - audio_io_handle_t *output, - audio_session_t session, - audio_stream_type_t *stream, - uint32_t samplingRate = 0, - audio_format_t format = AUDIO_FORMAT_DEFAULT, - audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO, - audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - const audio_offload_info_t *offloadInfo = NULL); + audio_io_handle_t *output, + audio_session_t session, + audio_stream_type_t *stream, + uid_t uid, + uint32_t samplingRate = 0, + audio_format_t format = AUDIO_FORMAT_DEFAULT, + audio_channel_mask_t channelMask = AUDIO_CHANNEL_OUT_STEREO, + audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE, + const audio_offload_info_t *offloadInfo = NULL); static status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, audio_session_t session); @@ -240,10 +225,12 @@ public: static status_t getInputForAttr(const audio_attributes_t *attr, audio_io_handle_t *input, audio_session_t session, + uid_t uid, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, - audio_input_flags_t flags); + audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE); static status_t startInput(audio_io_handle_t input, audio_session_t session); @@ -327,6 +314,12 @@ public: static status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration); + static status_t startAudioSource(const struct audio_port_config *source, + const audio_attributes_t *attributes, + audio_io_handle_t *handle); + static status_t stopAudioSource(audio_io_handle_t handle); + + // ---------------------------------------------------------------------------- class AudioPortCallback : public RefBase @@ -342,16 +335,42 @@ public: }; - static void setAudioPortCallback(sp<AudioPortCallback> callBack); + static status_t addAudioPortCallback(const sp<AudioPortCallback>& callback); + static status_t removeAudioPortCallback(const sp<AudioPortCallback>& callback); + + class AudioDeviceCallback : public RefBase + { + public: + + AudioDeviceCallback() {} + virtual ~AudioDeviceCallback() {} + + virtual void onAudioDeviceUpdate(audio_io_handle_t audioIo, + audio_port_handle_t deviceId) = 0; + }; + + static status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback, + audio_io_handle_t audioIo); + static status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback, + audio_io_handle_t audioIo); + + static audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo); private: class AudioFlingerClient: public IBinder::DeathRecipient, public BnAudioFlingerClient { public: - AudioFlingerClient() { + AudioFlingerClient() : + mInBuffSize(0), mInSamplingRate(0), + mInFormat(AUDIO_FORMAT_DEFAULT), mInChannelMask(AUDIO_CHANNEL_NONE) { } + void clearIoCache(); + status_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, + audio_channel_mask_t channelMask, size_t* buffSize); + sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle); + // DeathRecipient virtual void binderDied(const wp<IBinder>& who); @@ -359,7 +378,27 @@ private: // indicate a change in the configuration of an output or input: keeps the cached // values for output/input parameters up-to-date in client process - virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2); + virtual void ioConfigChanged(audio_io_config_event event, + const sp<AudioIoDescriptor>& ioDesc); + + + status_t addAudioDeviceCallback(const sp<AudioDeviceCallback>& callback, + audio_io_handle_t audioIo); + status_t removeAudioDeviceCallback(const sp<AudioDeviceCallback>& callback, + audio_io_handle_t audioIo); + + audio_port_handle_t getDeviceIdForIo(audio_io_handle_t audioIo); + + private: + Mutex mLock; + DefaultKeyedVector<audio_io_handle_t, sp<AudioIoDescriptor> > mIoDescriptors; + DefaultKeyedVector<audio_io_handle_t, Vector < sp<AudioDeviceCallback> > > + mAudioDeviceCallbacks; + // cached values for recording getInputBufferSize() queries + size_t mInBuffSize; // zero indicates cache is invalid + uint32_t mInSamplingRate; + audio_format_t mInFormat; + audio_channel_mask_t mInChannelMask; }; class AudioPolicyServiceClient: public IBinder::DeathRecipient, @@ -369,26 +408,35 @@ private: AudioPolicyServiceClient() { } + int addAudioPortCallback(const sp<AudioPortCallback>& callback); + int removeAudioPortCallback(const sp<AudioPortCallback>& callback); + // DeathRecipient virtual void binderDied(const wp<IBinder>& who); // IAudioPolicyServiceClient virtual void onAudioPortListUpdate(); virtual void onAudioPatchListUpdate(); + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state); + + private: + Mutex mLock; + Vector <sp <AudioPortCallback> > mAudioPortCallbacks; }; + static const sp<AudioFlingerClient> getAudioFlingerClient(); + static sp<AudioIoDescriptor> getIoDescriptor(audio_io_handle_t ioHandle); + static sp<AudioFlingerClient> gAudioFlingerClient; static sp<AudioPolicyServiceClient> gAudioPolicyServiceClient; friend class AudioFlingerClient; friend class AudioPolicyServiceClient; static Mutex gLock; // protects gAudioFlinger and gAudioErrorCallback, - static Mutex gLockCache; // protects gOutputs, gPrevInSamplingRate, gPrevInFormat, - // gPrevInChannelMask and gInBuffSize static Mutex gLockAPS; // protects gAudioPolicyService and gAudioPolicyServiceClient - static Mutex gLockAPC; // protects gAudioPortCallback static sp<IAudioFlinger> gAudioFlinger; static audio_error_callback gAudioErrorCallback; + static dynamic_policy_callback gDynPolicyCallback; static size_t gInBuffSize; // previous parameters for recording buffer size queries @@ -397,12 +445,6 @@ private: static audio_channel_mask_t gPrevInChannelMask; static sp<IAudioPolicyService> gAudioPolicyService; - - // list of output descriptors containing cached parameters - // (sampling rate, framecount, channel count...) - static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs; - - static sp<AudioPortCallback> gAudioPortCallback; }; }; // namespace android diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index fd51b8f..e02f1b7 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -21,6 +21,7 @@ #include <media/AudioSystem.h> #include <media/AudioTimestamp.h> #include <media/IAudioTrack.h> +#include <media/AudioResamplerPublic.h> #include <utils/threads.h> namespace android { @@ -42,28 +43,38 @@ public: */ enum event_type { EVENT_MORE_DATA = 0, // Request to write more data to buffer. + // This event only occurs for TRANSFER_CALLBACK. // If this event is delivered but the callback handler - // does not want to write more data, the handler must explicitly + // does not want to write more data, the handler must // ignore the event by setting frameCount to zero. - EVENT_UNDERRUN = 1, // Buffer underrun occurred. + // This might occur, for example, if the application is + // waiting for source data or is at the end of stream. + // + // For data filling, it is preferred that the callback + // does not block and instead returns a short count on + // the amount of data actually delivered + // (or 0, if no data is currently available). + EVENT_UNDERRUN = 1, // Buffer underrun occurred. This will not occur for + // static tracks. EVENT_LOOP_END = 2, // Sample loop end was reached; playback restarted from - // loop start if loop count was not 0. + // loop start if loop count was not 0 for a static track. EVENT_MARKER = 3, // Playback head is at the specified marker position // (See setMarkerPosition()). EVENT_NEW_POS = 4, // Playback head is at a new position // (See setPositionUpdatePeriod()). - EVENT_BUFFER_END = 5, // Playback head is at the end of the buffer. - // Not currently used by android.media.AudioTrack. + EVENT_BUFFER_END = 5, // Playback has completed for a static track. EVENT_NEW_IAUDIOTRACK = 6, // IAudioTrack was re-created, either due to re-routing and // 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) + // back (after stop is called) for an offloaded track. +#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 Buffer on the stack and pass address to obtainBuffer() + /* Client should declare a Buffer and pass the address to obtainBuffer() * and releaseBuffer(). See also callback_t for EVENT_MORE_DATA. */ @@ -72,22 +83,26 @@ public: public: // FIXME use m prefix size_t frameCount; // number of sample frames corresponding to size; - // on input it is the number of frames desired, - // on output is the number of frames actually filled - // (currently ignored, but will make the primary field in future) + // on input to obtainBuffer() it is the number of frames desired, + // on output from obtainBuffer() it is the number of available + // [empty slots for] frames to be filled + // on input to releaseBuffer() it is currently ignored size_t size; // input/output in bytes == frameCount * frameSize - // on input it is unused - // on output is the number of bytes actually filled - // FIXME this is redundant with respect to frameCount, - // and TRANSFER_OBTAIN mode is broken for 8-bit data - // since we don't define the frame format + // on input to obtainBuffer() it is ignored + // on output from obtainBuffer() it is the number of available + // [empty slots for] bytes to be filled, + // which is frameCount * frameSize + // on input to releaseBuffer() it is the number of bytes to + // release + // FIXME This is redundant with respect to frameCount. Consider + // removing size and making frameCount the primary field. union { void* raw; short* i16; // signed 16-bit int8_t* i8; // unsigned 8-bit, offset by 0x80 - }; // input: unused, output: pointer to buffer + }; // input to obtainBuffer(): unused, output: pointer to buffer }; /* As a convenience, if a callback is supplied, a handler thread @@ -121,6 +136,7 @@ public: * - BAD_VALUE: unsupported configuration * frameCount is guaranteed to be non-zero if status is NO_ERROR, * and is undefined otherwise. + * FIXME This API assumes a route, and so should be deprecated. */ static status_t getMinFrameCount(size_t* frameCount, @@ -132,7 +148,7 @@ public: enum transfer_type { TRANSFER_DEFAULT, // not specified explicitly; determine from the other parameters TRANSFER_CALLBACK, // callback EVENT_MORE_DATA - TRANSFER_OBTAIN, // FIXME deprecated: call obtainBuffer() and releaseBuffer() + TRANSFER_OBTAIN, // call obtainBuffer() and releaseBuffer() TRANSFER_SYNC, // synchronous write() TRANSFER_SHARED, // shared memory }; @@ -145,18 +161,15 @@ public: /* Creates an AudioTrack object and registers it with AudioFlinger. * Once created, the track needs to be started before it can be used. * Unspecified values are set to appropriate default values. - * With this constructor, the track is configured for streaming mode. - * Data to be rendered is supplied by write() or by the callback EVENT_MORE_DATA. - * Intermixing a combination of write() and non-ignored EVENT_MORE_DATA is not allowed. * * Parameters: * * streamType: Select the type of audio stream this track is attached to * (e.g. AUDIO_STREAM_MUSIC). * sampleRate: Data source sampling rate in Hz. - * format: Audio format. For mixed tracks, any PCM format supported by server is OK - * or AUDIO_FORMAT_PCM_8_BIT which is handled on client side. For direct - * and offloaded tracks, the possible format(s) depends on the output sink. + * format: Audio format. For mixed tracks, any PCM format supported by server is OK. + * For direct and offloaded tracks, the possible format(s) depends on the + * output sink. * channelMask: Channel mask, such that audio_is_output_channel(channelMask) is true. * frameCount: Minimum size of track PCM buffer in frames. This defines the * application's contribution to the @@ -165,20 +178,32 @@ public: * configuration. Zero means to use a default value. * flags: See comments on audio_output_flags_t in <system/audio.h>. * cbf: Callback function. If not null, this function is called periodically - * to provide new data and inform of marker, position updates, etc. + * to provide new data in TRANSFER_CALLBACK mode + * and inform of marker, position updates, etc. * user: Context for use by the callback receiver. * notificationFrames: The callback function is called each time notificationFrames PCM * frames have been consumed from track input buffer. * This is expressed in units of frames at the initial source sample rate. * sessionId: Specific session ID, or zero to use default. * transferType: How data is transferred to AudioTrack. + * offloadInfo: If not NULL, provides offload parameters for + * AudioSystem::getOutputForAttr(). + * uid: User ID of the app which initially requested this AudioTrack + * for power management tracking, or -1 for current user ID. + * pid: Process ID of the app which initially requested this AudioTrack + * for power management tracking, or -1 for current process ID. + * pAttributes: If not NULL, supersedes streamType for use case selection. + * doNotReconnect: If set to true, AudioTrack won't automatically recreate the IAudioTrack + binder to AudioFlinger. + It will return an error instead. The application will recreate + the track based on offloading or different channel configuration, etc. * threadCanCallJava: Not present in parameter list, and so is fixed at false. */ AudioTrack( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, - audio_channel_mask_t, + audio_channel_mask_t channelMask, size_t frameCount = 0, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, callback_t cbf = NULL, @@ -189,13 +214,15 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Creates an audio track and registers it with AudioFlinger. * With this constructor, the track is configured for static buffer mode. - * The format must not be 8-bit linear PCM. * Data to be rendered is passed in a shared memory buffer - * identified by the argument sharedBuffer, which must be non-0. + * identified by the argument sharedBuffer, which should be non-0. + * If sharedBuffer is zero, this constructor is equivalent to the previous constructor + * but without the ability to specify a non-zero value for the frameCount parameter. * The memory should be initialized to the desired data before calling start(). * The write() method is not supported in this case. * It is recommended to pass a callback function to be notified of playback end by an @@ -216,7 +243,8 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Terminates the AudioTrack and unregisters it from AudioFlinger. * Also destroys all resources associated with the AudioTrack. @@ -227,6 +255,7 @@ public: /* Initialize an AudioTrack that was created using the AudioTrack() constructor. * Don't call set() more than once, or after the AudioTrack() constructors that take parameters. + * set() is not multi-thread safe. * Returned status (from utils/Errors.h) can be: * - NO_ERROR: successful initialization * - INVALID_OPERATION: AudioTrack is already initialized @@ -259,7 +288,8 @@ public: const audio_offload_info_t *offloadInfo = NULL, int uid = -1, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + bool doNotReconnect = false); /* Result of constructing the AudioTrack. This must be checked for successful initialization * before using any AudioTrack API (except for set()), because using @@ -347,6 +377,26 @@ public: /* Return current source sample rate in Hz */ uint32_t getSampleRate() const; + /* Return the original source sample rate in Hz. This corresponds to the sample rate + * if playback rate had normal speed and pitch. + */ + uint32_t getOriginalSampleRate() const; + + /* Set source playback rate for timestretch + * 1.0 is normal speed: < 1.0 is slower, > 1.0 is faster + * 1.0 is normal pitch: < 1.0 is lower pitch, > 1.0 is higher pitch + * + * AUDIO_TIMESTRETCH_SPEED_MIN <= speed <= AUDIO_TIMESTRETCH_SPEED_MAX + * AUDIO_TIMESTRETCH_PITCH_MIN <= pitch <= AUDIO_TIMESTRETCH_PITCH_MAX + * + * Speed increases the playback rate of media, but does not alter pitch. + * Pitch increases the "tonal frequency" of media, but does not affect the playback rate. + */ + status_t setPlaybackRate(const AudioPlaybackRate &playbackRate); + + /* Return current playback rate */ + const AudioPlaybackRate& getPlaybackRate() const; + /* Enables looping and sets the start and end points of looping. * Only supported for static buffer mode. * @@ -461,7 +511,38 @@ public: * handle on audio hardware output, or AUDIO_IO_HANDLE_NONE if the * track needed to be re-created but that failed */ +private: audio_io_handle_t getOutput() const; +public: + + /* Selects the audio device to use for output of this AudioTrack. A value of + * AUDIO_PORT_HANDLE_NONE indicates default (AudioPolicyManager) routing. + * + * Parameters: + * The device ID of the selected device (as returned by the AudioDevicesManager API). + * + * Returned value: + * - NO_ERROR: successful operation + * TODO: what else can happen here? + */ + status_t setOutputDevice(audio_port_handle_t deviceId); + + /* Returns the ID of the audio device selected for this AudioTrack. + * A value of AUDIO_PORT_HANDLE_NONE indicates default (AudioPolicyManager) routing. + * + * Parameters: + * none. + */ + audio_port_handle_t getOutputDevice(); + + /* Returns the ID of the audio device actually used by the output to which this AudioTrack is + * attached. + * A value of AUDIO_PORT_HANDLE_NONE indicates the audio track is not attached to any output. + * + * Parameters: + * none. + */ + audio_port_handle_t getRoutedDeviceId(); /* Returns the unique session ID associated with this track. * @@ -487,10 +568,18 @@ public: */ status_t attachAuxEffect(int effectId); - /* Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames. + /* Public API for TRANSFER_OBTAIN mode. + * Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames. * After filling these slots with data, the caller should release them with releaseBuffer(). * If the track buffer is not full, obtainBuffer() returns as many contiguous * [empty slots for] frames as are available immediately. + * + * If nonContig is non-NULL, it is an output parameter that will be set to the number of + * additional non-contiguous frames that are predicted to be available immediately, + * if the client were to release the first frames and then call obtainBuffer() again. + * This value is only a prediction, and needs to be confirmed. + * It will be set to zero for an error return. + * * If the track buffer is full and track is stopped, obtainBuffer() returns WOULD_BLOCK * regardless of the value of waitCount. * If the track buffer is full and track is not stopped, obtainBuffer() blocks with a @@ -499,10 +588,6 @@ public: * is exhausted, at which point obtainBuffer() will either block * or return WOULD_BLOCK depending on the value of the "waitCount" * parameter. - * Each sample is 16-bit signed PCM. - * - * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications, - * which should use write() or callback EVENT_MORE_DATA instead. * * Interpretation of waitCount: * +n limits wait time to n * WAIT_PERIOD_MS, @@ -511,24 +596,27 @@ public: * * Buffer fields * On entry: - * frameCount number of frames requested + * frameCount number of [empty slots for] frames requested + * size ignored + * raw ignored * After error return: * frameCount 0 * size 0 * raw undefined * After successful return: - * frameCount actual number of frames available, <= number requested + * frameCount actual number of [empty slots for] frames available, <= number requested * size actual number of bytes available * raw pointer to the buffer */ - - /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */ - status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount) - __attribute__((__deprecated__)); + status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount, + size_t *nonContig = NULL); private: /* If nonContig is non-NULL, it is an output parameter that will be set to the number of - * additional non-contiguous frames that are available immediately. + * additional non-contiguous frames that are predicted to be available immediately, + * if the client were to release the first frames and then call obtainBuffer() again. + * This value is only a prediction, and needs to be confirmed. + * It will be set to zero for an error return. * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(), * in case the requested amount of frames is in two or more non-contiguous regions. * FIXME requested and elapsed are both relative times. Consider changing to absolute time. @@ -537,9 +625,15 @@ private: struct timespec *elapsed = NULL, size_t *nonContig = NULL); public: - /* Release a filled buffer of "audioBuffer->frameCount" frames for AudioFlinger to process. */ - // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed - void releaseBuffer(Buffer* audioBuffer); + /* Public API for TRANSFER_OBTAIN mode. + * Release a filled buffer of frames for AudioFlinger to process. + * + * Buffer fields: + * frameCount currently ignored but recommend to set to actual number of frames filled + * size actual number of bytes filled, must be multiple of frameSize + * raw ignored + */ + void releaseBuffer(const Buffer* audioBuffer); /* As a convenience we provide a write() interface to the audio buffer. * Input parameter 'size' is in byte units. @@ -550,8 +644,14 @@ public: * BAD_VALUE size is invalid * WOULD_BLOCK when obtainBuffer() returns same, or * AudioTrack was stopped during the write + * DEAD_OBJECT when AudioFlinger dies or the output device changes and + * the track cannot be automatically restored. + * The application needs to recreate the AudioTrack + * because the audio device changed or AudioFlinger died. + * This typically occurs for direct or offload tracks + * or if mDoNotReconnect is true. * or any other error code returned by IAudioTrack::start() or restoreTrack_l(). - * Default behavior is to only return until all data has been transferred. Set 'blocking' to + * Default behavior is to only return when all data has been transferred. Set 'blocking' to * false for the method to return immediately without waiting to try multiple times to write * the full content of the buffer. */ @@ -559,6 +659,7 @@ public: /* * Dumps the state of an audio track. + * Not a general-purpose API; intended only for use by media player service to dump its tracks. */ status_t dump(int fd, const Vector<String16>& args) const; @@ -589,19 +690,45 @@ public: * overall hardware latency to physical output. In WOULD_BLOCK cases, * one might poll again, or use getPosition(), or use 0 position and * current time for the timestamp. + * DEAD_OBJECT if AudioFlinger dies or the output device changes and + * the track cannot be automatically restored. + * The application needs to recreate the AudioTrack + * because the audio device changed or AudioFlinger died. + * This typically occurs for direct or offload tracks + * or if mDoNotReconnect is true. * INVALID_OPERATION if called on a FastTrack, wrong state, or some other error. * * The timestamp parameter is undefined on return, if status is not NO_ERROR. */ status_t getTimestamp(AudioTimestamp& timestamp); + /* Add an AudioDeviceCallback. The caller will be notified when the audio device to which this + * AudioTrack is routed is updated. + * Replaces any previously installed callback. + * Parameters: + * callback: The callback interface + * Returns NO_ERROR if successful. + * INVALID_OPERATION if the same callback is already installed. + * NO_INIT or PREMISSION_DENIED if AudioFlinger service is not reachable + * BAD_VALUE if the callback is NULL + */ + status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback); + + /* remove an AudioDeviceCallback. + * Parameters: + * callback: The callback interface + * Returns NO_ERROR if successful. + * INVALID_OPERATION if the callback is not installed + * BAD_VALUE if the callback is NULL + */ + status_t removeAudioDeviceCallback( + const sp<AudioSystem::AudioDeviceCallback>& callback); + protected: /* copying audio tracks is not allowed */ AudioTrack(const AudioTrack& other); AudioTrack& operator = (const AudioTrack& other); - void setAttributesFromStreamType(audio_stream_type_t streamType); - /* a small internal class to handle the callback */ class AudioTrackThread : public Thread { @@ -614,6 +741,7 @@ protected: void pause(); // suspend thread from execution at next loop boundary void resume(); // allow thread to execute, if not requested to exit + void wake(); // wake to handle changed notification conditions. private: void pauseInternal(nsecs_t ns = 0LL); @@ -628,7 +756,9 @@ protected: bool mPaused; // whether thread is requested to pause at next loop entry bool mPausedInt; // whether thread internally requests pause nsecs_t mPausedNs; // if mPausedInt then associated timeout, otherwise ignored - bool mIgnoreNextPausedInt; // whether to ignore next mPausedInt request + bool mIgnoreNextPausedInt; // skip any internal pause and go immediately + // to processAudioBuffer() as state may have changed + // since pause time calculated. }; // body of AudioTrackThread::threadLoop() @@ -641,10 +771,6 @@ protected: static const nsecs_t NS_WHENEVER = -1, NS_INACTIVE = -2, NS_NEVER = -3; nsecs_t processAudioBuffer(); - bool isOffloaded() const; - bool isDirect() const; - bool isOffloadedOrDirect() const; - // caller must hold lock on mLock for all _l methods status_t createTrack_l(); @@ -657,6 +783,10 @@ protected: // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreTrack_l(const char *from); + bool isOffloaded() const; + bool isDirect() const; + bool isOffloadedOrDirect() const; + bool isOffloaded_l() const { return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; } @@ -670,6 +800,9 @@ protected: // increment mPosition by the delta of mServer, and return new value of mPosition uint32_t updateAndGetPosition_l(); + // check sample rate and speed is compatible with AudioTrack + bool isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const; + // Next 4 fields may be changed if IAudioTrack is re-created, but always != 0 sp<IAudioTrack> mAudioTrack; sp<IMemory> mCblkMemory; @@ -680,12 +813,21 @@ protected: float mVolume[2]; float mSendLevel; - mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it. + mutable uint32_t mSampleRate; // mutable because getSampleRate() can update it + uint32_t mOriginalSampleRate; + AudioPlaybackRate mPlaybackRate; size_t mFrameCount; // corresponds to current IAudioTrack, value is // reported back by AudioFlinger to the client size_t mReqFrameCount; // frame count to request the first or next time // a new IAudioTrack is needed, non-decreasing + // The following AudioFlinger server-side values are cached in createAudioTrack_l(). + // These values can be used for informational purposes until the track is invalidated, + // whereupon restoreTrack_l() calls createTrack_l() to update the values. + uint32_t mAfLatency; // AudioFlinger latency in ms + size_t mAfFrameCount; // AudioFlinger frame count + uint32_t mAfSampleRate; // AudioFlinger sample rate + // constant after constructor or set() audio_format_t mFormat; // as requested by client, not forced to 16-bit audio_stream_type_t mStreamType; // mStreamType == AUDIO_STREAM_DEFAULT implies @@ -698,10 +840,7 @@ protected: const audio_offload_info_t* mOffloadInfo; audio_attributes_t mAttributes; - // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data. For 8-bit PCM data, it's - // twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer. - size_t mFrameSize; // app-level frame size - size_t mFrameSizeAF; // AudioFlinger frame size + size_t mFrameSize; // frame size in bytes status_t mStatus; @@ -732,17 +871,25 @@ protected: bool mRefreshRemaining; // processAudioBuffer() should refresh // mRemainingFrames and mRetryOnPartialBuffer + // used for static track cbf and restoration + int32_t mLoopCount; // last setLoop loopCount; zero means disabled + uint32_t mLoopStart; // last setLoop loopStart + uint32_t mLoopEnd; // last setLoop loopEnd + int32_t mLoopCountNotified; // the last loopCount notified by callback. + // mLoopCountNotified counts down, matching + // the remaining loop count for static track + // playback. + // These are private to processAudioBuffer(), and are not protected by a lock uint32_t mRemainingFrames; // number of frames to request in obtainBuffer() bool mRetryOnPartialBuffer; // sleep and retry after partial obtainBuffer() uint32_t mObservedSequence; // last observed value of mSequence - uint32_t mLoopPeriod; // in frames, zero means looping is disabled - uint32_t mMarkerPosition; // in wrapping (overflow) frame units bool mMarkerReached; uint32_t mNewPosition; // in frames uint32_t mUpdatePeriod; // in frames, zero means no EVENT_NEW_POS + uint32_t mServer; // in frames, last known mProxy->getPosition() // which is count of frames consumed by server, // reset by new IAudioTrack, @@ -758,10 +905,17 @@ protected: int64_t mStartUs; // the start time after flush or stop. // only used for offloaded and direct tracks. + bool mPreviousTimestampValid;// true if mPreviousTimestamp is valid + bool mTimestampStartupGlitchReported; // reduce log spam + bool mRetrogradeMotionReported; // reduce log spam + AudioTimestamp mPreviousTimestamp; // used to detect retrograde motion + audio_output_flags_t mFlags; // const after set(), except for bits AUDIO_OUTPUT_FLAG_FAST and AUDIO_OUTPUT_FLAG_OFFLOAD. // mLock must be held to read or write those bits reliably. + bool mDoNotReconnect; + int mSessionId; int mAuxEffectId; @@ -783,6 +937,10 @@ protected: bool mInUnderrun; // whether track is currently in underrun state uint32_t mPausedPosition; + // For Device Selection API + // a value of AUDIO_PORT_HANDLE_NONE indicated default (AudioPolicyManager) routing. + audio_port_handle_t mSelectedDeviceId; + private: class DeathNotifier : public IBinder::DeathRecipient { public: @@ -797,6 +955,8 @@ private: uint32_t mSequence; // incremented for each new IAudioTrack attempt int mClientUid; pid_t mClientPid; + + sp<AudioSystem::AudioDeviceCallback> mDeviceCallback; }; class TimedAudioTrack : public AudioTrack diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h index b1ed7b0..64a3212 100644 --- a/include/media/EffectsFactoryApi.h +++ b/include/media/EffectsFactoryApi.h @@ -171,6 +171,8 @@ int EffectGetDescriptor(const effect_uuid_t *pEffectUuid, effect_descriptor_t *p //////////////////////////////////////////////////////////////////////////////// int EffectIsNullUuid(const effect_uuid_t *pEffectUuid); +int EffectDumpEffects(int fd); + #if __cplusplus } // extern "C" #endif diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 31a14f0..5051aff 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -85,15 +85,19 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& callingPackage, size_t *pFrameCount, track_flags_t *flags, pid_t tid, // -1 means unused, otherwise must be valid non-0 + int clientUid, int *sessionId, size_t *notificationFrames, sp<IMemory>& cblk, sp<IMemory>& buffers, // return value 0 means it follows cblk status_t *status) = 0; + // FIXME Surprisingly, sampleRate/format/frameCount/latency don't work for input handles + /* query the audio hardware state. This state never changes, * and therefore can be cached. */ @@ -142,6 +146,7 @@ public: virtual void registerClient(const sp<IAudioFlingerClient>& client) = 0; // retrieve the audio recording buffer size + // FIXME This API assumes a route, and so should be deprecated. virtual size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask) const = 0; @@ -195,6 +200,7 @@ public: // AudioFlinger doesn't take over handle reference from client audio_io_handle_t output, int sessionId, + const String16& callingPackage, status_t *status, int *id, int *enabled) = 0; @@ -237,6 +243,9 @@ public: /* Get the HW synchronization source used for an audio session */ virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) = 0; + + /* Indicate JAVA services are ready (scheduling, power management ...) */ + virtual status_t systemReady() = 0; }; diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h index 75a9971..0080bc9 100644 --- a/include/media/IAudioFlingerClient.h +++ b/include/media/IAudioFlingerClient.h @@ -22,6 +22,7 @@ #include <binder/IInterface.h> #include <utils/KeyedVector.h> #include <system/audio.h> +#include <media/AudioIoDescriptor.h> namespace android { @@ -33,7 +34,8 @@ public: DECLARE_META_INTERFACE(AudioFlingerClient); // Notifies a change of audio input/output configuration. - virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) = 0; + virtual void ioConfigChanged(audio_io_config_event event, + const sp<AudioIoDescriptor>& ioDesc) = 0; }; diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h index c98c475..6b93f6f 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -44,7 +44,8 @@ public: // virtual status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, - const char *device_address) = 0; + const char *device_address, + const char *device_name) = 0; virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address) = 0; virtual status_t setPhoneState(audio_mode_t state) = 0; @@ -61,10 +62,12 @@ public: audio_io_handle_t *output, audio_session_t session, audio_stream_type_t *stream, + uid_t uid, uint32_t samplingRate = 0, audio_format_t format = AUDIO_FORMAT_DEFAULT, audio_channel_mask_t channelMask = 0, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE, const audio_offload_info_t *offloadInfo = NULL) = 0; virtual status_t startOutput(audio_io_handle_t output, audio_stream_type_t stream, @@ -76,12 +79,14 @@ public: audio_stream_type_t stream, audio_session_t session) = 0; virtual status_t getInputForAttr(const audio_attributes_t *attr, - audio_io_handle_t *input, - audio_session_t session, - uint32_t samplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - audio_input_flags_t flags) = 0; + audio_io_handle_t *input, + audio_session_t session, + uid_t uid, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_input_flags_t flags, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE) = 0; virtual status_t startInput(audio_io_handle_t input, audio_session_t session) = 0; virtual status_t stopInput(audio_io_handle_t input, @@ -144,6 +149,8 @@ public: virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) = 0; + virtual void setAudioPortCallbacksEnabled(bool enabled) = 0; + virtual status_t acquireSoundTriggerSession(audio_session_t *session, audio_io_handle_t *ioHandle, audio_devices_t *device) = 0; @@ -153,6 +160,11 @@ public: virtual audio_mode_t getPhoneState() = 0; virtual status_t registerPolicyMixes(Vector<AudioMix> mixes, bool registration) = 0; + + virtual status_t startAudioSource(const struct audio_port_config *source, + const audio_attributes_t *attributes, + audio_io_handle_t *handle) = 0; + virtual status_t stopAudioSource(audio_io_handle_t handle) = 0; }; diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h index 59df046..a7f2cc3 100644 --- a/include/media/IAudioPolicyServiceClient.h +++ b/include/media/IAudioPolicyServiceClient.h @@ -35,6 +35,8 @@ public: virtual void onAudioPortListUpdate() = 0; // Notifies a change of audio patch configuration. virtual void onAudioPatchListUpdate() = 0; + // Notifies a change in the mixing state of a specific mix in a dynamic audio policy + virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0; }; diff --git a/include/media/ICrypto.h b/include/media/ICrypto.h index 07742ca..ea316de 100644 --- a/include/media/ICrypto.h +++ b/include/media/ICrypto.h @@ -25,6 +25,7 @@ namespace android { struct AString; +class IMemory; struct ICrypto : public IInterface { DECLARE_META_INTERFACE(Crypto); @@ -43,12 +44,14 @@ struct ICrypto : public IInterface { virtual void notifyResolution(uint32_t width, uint32_t height) = 0; + virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0; + virtual ssize_t decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, - const void *srcPtr, + const sp<IMemory> &sharedBuffer, size_t offset, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, void *dstPtr, AString *errorDetailMsg) = 0; @@ -61,6 +64,9 @@ struct BnCrypto : public BnInterface<ICrypto> { virtual status_t onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags = 0); +private: + void readVector(const Parcel &data, Vector<uint8_t> &vector) const; + void writeVector(Parcel *reply, Vector<uint8_t> const &vector) const; }; } // namespace android diff --git a/include/media/IDataSource.h b/include/media/IDataSource.h new file mode 100644 index 0000000..07e46f7 --- /dev/null +++ b/include/media/IDataSource.h @@ -0,0 +1,61 @@ +/* + * 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 ANDROID_IDATASOURCE_H +#define ANDROID_IDATASOURCE_H + +#include <binder/IInterface.h> +#include <media/stagefright/foundation/ABase.h> +#include <utils/Errors.h> + +namespace android { + +class IMemory; + +// A binder interface for implementing a stagefright DataSource remotely. +class IDataSource : public IInterface { +public: + DECLARE_META_INTERFACE(DataSource); + + // Get the memory that readAt writes into. + virtual sp<IMemory> getIMemory() = 0; + // Read up to |size| bytes into the memory returned by getIMemory(). Returns + // the number of bytes read, or -1 on error. |size| must not be larger than + // the buffer. + virtual ssize_t readAt(off64_t offset, size_t size) = 0; + // Get the size, or -1 if the size is unknown. + virtual status_t getSize(off64_t* size) = 0; + // This should be called before deleting |this|. The other methods may + // return errors if they're called after calling close(). + virtual void close() = 0; + +private: + DISALLOW_EVIL_CONSTRUCTORS(IDataSource); +}; + +// ---------------------------------------------------------------------------- + +class BnDataSource : public BnInterface<IDataSource> { +public: + virtual status_t onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IDATASOURCE_H diff --git a/include/media/IDrm.h b/include/media/IDrm.h index affcbd7..9449beb 100644 --- a/include/media/IDrm.h +++ b/include/media/IDrm.h @@ -47,7 +47,8 @@ struct IDrm : public IInterface { Vector<uint8_t> const &initData, String8 const &mimeType, DrmPlugin::KeyType keyType, KeyedVector<String8, String8> const &optionalParameters, - Vector<uint8_t> &request, String8 &defaultUrl) = 0; + Vector<uint8_t> &request, String8 &defaultUrl, + DrmPlugin::KeyRequestType *keyRequestType) = 0; virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId, Vector<uint8_t> const &response, diff --git a/include/media/IMediaCodecList.h b/include/media/IMediaCodecList.h index e93ea8b..12b52d7 100644 --- a/include/media/IMediaCodecList.h +++ b/include/media/IMediaCodecList.h @@ -21,6 +21,8 @@ #include <binder/IInterface.h> #include <binder/Parcel.h> +#include <media/stagefright/foundation/AMessage.h> + namespace android { struct MediaCodecInfo; @@ -33,6 +35,8 @@ public: virtual size_t countCodecs() const = 0; virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const = 0; + virtual const sp<AMessage> getGlobalSettings() const = 0; + virtual ssize_t findCodecByType( const char *type, bool encoder, size_t startIndex = 0) const = 0; diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h index 2529800..c90f254 100644 --- a/include/media/IMediaMetadataRetriever.h +++ b/include/media/IMediaMetadataRetriever.h @@ -26,6 +26,7 @@ namespace android { +class IDataSource; struct IMediaHTTPService; class IMediaMetadataRetriever: public IInterface @@ -40,6 +41,7 @@ public: const KeyedVector<String8, String8> *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setDataSource(const sp<IDataSource>& dataSource) = 0; virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0; virtual sp<IMemory> extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index db62cd5..0fd8933 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -31,9 +31,12 @@ namespace android { class Parcel; class Surface; -class IStreamSource; +class IDataSource; +struct IStreamSource; class IGraphicBufferProducer; struct IMediaHTTPService; +struct AudioPlaybackRate; +struct AVSyncSettings; class IMediaPlayer: public IInterface { @@ -49,6 +52,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; virtual status_t setDataSource(const sp<IStreamSource>& source) = 0; + virtual status_t setDataSource(const sp<IDataSource>& source) = 0; virtual status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) = 0; virtual status_t prepareAsync() = 0; @@ -56,6 +60,11 @@ public: virtual status_t stop() = 0; virtual status_t pause() = 0; virtual status_t isPlaying(bool* state) = 0; + virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate) = 0; + virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) = 0; + virtual status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint) = 0; + virtual status_t getSyncSettings(AVSyncSettings* sync /* nonnull */, + float* videoFps /* nonnull */) = 0; virtual status_t seekTo(int msec) = 0; virtual status_t getCurrentPosition(int* msec) = 0; virtual status_t getDuration(int* msec) = 0; diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index 67b599a..a316ce2 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -47,9 +47,10 @@ class IMediaPlayerService: public IInterface public: DECLARE_META_INTERFACE(MediaPlayerService); - virtual sp<IMediaRecorder> createMediaRecorder() = 0; + virtual sp<IMediaRecorder> createMediaRecorder(const String16 &opPackageName) = 0; virtual sp<IMediaMetadataRetriever> createMetadataRetriever() = 0; - virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0; + virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId = 0) + = 0; virtual sp<IOMX> getOMX() = 0; virtual sp<ICrypto> makeCrypto() = 0; @@ -64,8 +65,8 @@ public: // display client when display connection, disconnection or errors occur. // The assumption is that at most one remote display will be connected to the // provided interface at a time. - virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client, - const String8& iface) = 0; + virtual sp<IRemoteDisplay> listenForRemoteDisplay(const String16 &opPackageName, + const sp<IRemoteDisplayClient>& client, const String8& iface) = 0; // codecs and audio devices usage tracking for the battery app enum BatteryDataBits { diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h index 3e67550..77ed5d3 100644 --- a/include/media/IMediaRecorder.h +++ b/include/media/IMediaRecorder.h @@ -26,6 +26,7 @@ class Surface; class ICamera; class ICameraRecordingProxy; class IMediaRecorderClient; +class IGraphicBufferConsumer; class IGraphicBufferProducer; class IMediaRecorder: public IInterface @@ -41,7 +42,6 @@ public: virtual status_t setOutputFormat(int of) = 0; virtual status_t setVideoEncoder(int ve) = 0; 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 setVideoSize(int width, int height) = 0; virtual status_t setVideoFrameRate(int frames_per_second) = 0; @@ -56,6 +56,7 @@ public: virtual status_t init() = 0; virtual status_t close() = 0; virtual status_t release() = 0; + virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0; virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0; }; diff --git a/include/media/IOMX.h b/include/media/IOMX.h index 595e51f..27ad694 100644 --- a/include/media/IOMX.h +++ b/include/media/IOMX.h @@ -20,10 +20,15 @@ #include <binder/IInterface.h> #include <gui/IGraphicBufferProducer.h> +#include <gui/IGraphicBufferConsumer.h> #include <ui/GraphicBuffer.h> #include <utils/List.h> #include <utils/String8.h> +#include <list> + +#include <media/hardware/MetadataBufferType.h> + #include <OMX_Core.h> #include <OMX_Video.h> @@ -80,14 +85,16 @@ 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, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0; - virtual status_t configureVideoTunnelMode( + virtual status_t configureVideoTunnelMode( node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0; @@ -97,9 +104,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> ¶ms, - buffer_id *buffer) = 0; + buffer_id *buffer, OMX_U32 allottedSize) = 0; virtual status_t useGraphicBuffer( node_id node, OMX_U32 port_index, @@ -109,9 +117,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, + MetadataBufferType *type) = 0; virtual status_t signalEndOfInputStream(node_id node) = 0; @@ -123,20 +145,32 @@ 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> ¶ms, - 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; - virtual status_t fillBuffer(node_id node, buffer_id buffer) = 0; - + enum { + kFenceTimeoutMs = 1000 + }; + // Calls OMX_FillBuffer on buffer, and passes |fenceFd| to component if it supports + // fences. Otherwise, it waits on |fenceFd| before calling OMX_FillBuffer. + // Takes ownership of |fenceFd| even if this call fails. + virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd = -1) = 0; + + // Calls OMX_EmptyBuffer on buffer (after updating buffer header with |range_offset|, + // |range_length|, |flags| and |timestamp|). Passes |fenceFd| to component if it + // supports fences. Otherwise, it waits on |fenceFd| before calling OMX_EmptyBuffer. + // Takes ownership of |fenceFd| even if this call fails. virtual status_t emptyBuffer( node_id node, buffer_id buffer, OMX_U32 range_offset, OMX_U32 range_length, - OMX_U32 flags, OMX_TICKS timestamp) = 0; + OMX_U32 flags, OMX_TICKS timestamp, int fenceFd = -1) = 0; virtual status_t getExtensionIndex( node_id node, @@ -147,6 +181,7 @@ public: INTERNAL_OPTION_SUSPEND, // data is a bool INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, // data is an int64_t INTERNAL_OPTION_MAX_TIMESTAMP_GAP, // data is int64_t + INTERNAL_OPTION_MAX_FPS, // data is float INTERNAL_OPTION_START_TIME, // data is an int64_t INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2] }; @@ -163,10 +198,11 @@ struct omx_message { EVENT, EMPTY_BUFFER_DONE, FILL_BUFFER_DONE, - + FRAME_RENDERED, } type; IOMX::node_id node; + int fenceFd; // used for EMPTY_BUFFER_DONE and FILL_BUFFER_DONE; client must close this union { // if type == EVENT @@ -190,6 +226,11 @@ struct omx_message { OMX_TICKS timestamp; } extended_buffer_data; + // if type == FRAME_RENDERED + struct { + OMX_TICKS timestamp; + OMX_S64 nanoTime; + } render_data; } u; }; @@ -197,7 +238,8 @@ class IOMXObserver : public IInterface { public: DECLARE_META_INTERFACE(OMXObserver); - virtual void onMessage(const omx_message &msg) = 0; + // Handle (list of) messages. + virtual void onMessages(const std::list<omx_message> &messages) = 0; }; //////////////////////////////////////////////////////////////////////////////// @@ -229,4 +271,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/IResourceManagerClient.h b/include/media/IResourceManagerClient.h new file mode 100644 index 0000000..aa0cd88 --- /dev/null +++ b/include/media/IResourceManagerClient.h @@ -0,0 +1,49 @@ +/* + * 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 ANDROID_IRESOURCEMANAGERCLIENT_H +#define ANDROID_IRESOURCEMANAGERCLIENT_H + +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> + +namespace android { + +class IResourceManagerClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(ResourceManagerClient); + + virtual bool reclaimResource() = 0; + virtual String8 getName() = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnResourceManagerClient: public BnInterface<IResourceManagerClient> +{ +public: + virtual status_t onTransact(uint32_t code, + const Parcel &data, + Parcel *reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IRESOURCEMANAGERCLIENT_H diff --git a/include/media/IResourceManagerService.h b/include/media/IResourceManagerService.h new file mode 100644 index 0000000..1e4f6de --- /dev/null +++ b/include/media/IResourceManagerService.h @@ -0,0 +1,66 @@ +/* + * 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 ANDROID_IRESOURCEMANAGERSERVICE_H +#define ANDROID_IRESOURCEMANAGERSERVICE_H + +#include <utils/Errors.h> // for status_t +#include <utils/KeyedVector.h> +#include <utils/RefBase.h> +#include <utils/String8.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> + +#include <media/IResourceManagerClient.h> +#include <media/MediaResource.h> +#include <media/MediaResourcePolicy.h> + +namespace android { + +class IResourceManagerService: public IInterface +{ +public: + DECLARE_META_INTERFACE(ResourceManagerService); + + virtual void config(const Vector<MediaResourcePolicy> &policies) = 0; + + virtual void addResource( + int pid, + int64_t clientId, + const sp<IResourceManagerClient> client, + const Vector<MediaResource> &resources) = 0; + + virtual void removeResource(int pid, int64_t clientId) = 0; + + virtual bool reclaimResource( + int callingPid, + const Vector<MediaResource> &resources) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnResourceManagerService: public BnInterface<IResourceManagerService> +{ +public: + virtual status_t onTransact(uint32_t code, + const Parcel &data, + Parcel *reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IRESOURCEMANAGERSERVICE_H diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h index 677119b..4a6aafd 100644 --- a/include/media/IStreamSource.h +++ b/include/media/IStreamSource.h @@ -23,7 +23,7 @@ namespace android { struct AMessage; -struct IMemory; +class IMemory; struct IStreamListener; struct IStreamSource : public IInterface { @@ -81,6 +81,13 @@ struct IStreamListener : public IInterface { // with the next PTS occuring in the stream. The value is of type int64_t. static const char *const kKeyMediaTimeUs; + // Optionally signalled as part of a discontinuity that includes + // DISCONTINUITY_TIME. It indicates the media time (in us) of a recent + // sample from the same content, and is used as a hint for the parser to + // handle PTS wraparound. This is required when a new parser is created + // to continue parsing content from the same timeline. + static const char *const kKeyRecentMediaTimeUs; + virtual void issueCommand( Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0; }; diff --git a/include/media/MediaCodecInfo.h b/include/media/MediaCodecInfo.h index cd56adb..4067b47 100644 --- a/include/media/MediaCodecInfo.h +++ b/include/media/MediaCodecInfo.h @@ -32,9 +32,11 @@ namespace android { struct AMessage; -struct Parcel; +class Parcel; struct CodecCapabilities; +typedef KeyedVector<AString, AString> CodecSettings; + struct MediaCodecInfo : public RefBase { struct ProfileLevel { uint32_t mProfile; @@ -104,6 +106,7 @@ private: MediaCodecInfo(AString name, bool encoder, const char *mime); void addQuirk(const char *name); status_t addMime(const char *mime); + status_t updateMime(const char *mime); status_t initializeCapabilities(const CodecCapabilities &caps); void addDetail(const AString &key, const AString &value); void addFeature(const AString &key, int32_t value); @@ -114,6 +117,7 @@ private: DISALLOW_EVIL_CONSTRUCTORS(MediaCodecInfo); friend class MediaCodecList; + friend class MediaCodecListOverridesTest; }; } // namespace android diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h index 38dbb20..bce6ee3 100644 --- a/include/media/MediaMetadataRetrieverInterface.h +++ b/include/media/MediaMetadataRetrieverInterface.h @@ -25,6 +25,7 @@ namespace android { +class DataSource; struct IMediaHTTPService; // Abstract base class @@ -40,6 +41,7 @@ public: const KeyedVector<String8, String8> *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setDataSource(const sp<DataSource>& source) = 0; virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0; virtual MediaAlbumArt* extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 4a6bf28..de82554 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -26,8 +26,10 @@ #include <utils/RefBase.h> #include <media/mediaplayer.h> +#include <media/AudioResamplerPublic.h> #include <media/AudioSystem.h> #include <media/AudioTimestamp.h> +#include <media/AVSyncSettings.h> #include <media/Metadata.h> // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is @@ -36,6 +38,7 @@ struct sockaddr_in; namespace android { +class DataSource; class Parcel; class Surface; class IGraphicBufferProducer; @@ -110,20 +113,35 @@ public: AudioCallback cb = NULL, void *cookie = NULL, audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE, - const audio_offload_info_t *offloadInfo = NULL) = 0; + const audio_offload_info_t *offloadInfo = NULL, + bool doNotReconnect = false, + uint32_t suggestedFrameCount = 0) = 0; virtual status_t start() = 0; - virtual ssize_t write(const void* buffer, size_t size) = 0; + + /* Input parameter |size| is in byte units stored in |buffer|. + * Data is copied over and actual number of bytes written (>= 0) + * is returned, or no data is copied and a negative status code + * is returned (even when |blocking| is true). + * When |blocking| is false, AudioSink will immediately return after + * part of or full |buffer| is copied over. + * When |blocking| is true, AudioSink will wait to copy the entire + * buffer, unless an error occurs or the copy operation is + * prematurely stopped. + */ + virtual ssize_t write(const void* buffer, size_t size, bool blocking = true) = 0; + virtual void stop() = 0; virtual void flush() = 0; virtual void pause() = 0; virtual void close() = 0; - virtual status_t setPlaybackRatePermille(int32_t rate) { return INVALID_OPERATION; } + virtual status_t setPlaybackRate(const AudioPlaybackRate& rate) = 0; + virtual status_t getPlaybackRate(AudioPlaybackRate* rate /* nonnull */) = 0; virtual bool needsTrailingPadding() { return true; } - virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR; }; - virtual String8 getParameters(const String8& keys) { return String8::empty(); }; + virtual status_t setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; } + virtual String8 getParameters(const String8& /* keys */) { return String8::empty(); } }; MediaPlayerBase() : mCookie(0), mNotify(0) {} @@ -131,7 +149,7 @@ public: virtual status_t initCheck() = 0; virtual bool hardwareOutput() = 0; - virtual status_t setUID(uid_t uid) { + virtual status_t setUID(uid_t /* uid */) { return INVALID_OPERATION; } @@ -142,7 +160,11 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; - virtual status_t setDataSource(const sp<IStreamSource> &source) { + virtual status_t setDataSource(const sp<IStreamSource>& /* source */) { + return INVALID_OPERATION; + } + + virtual status_t setDataSource(const sp<DataSource>& /* source */) { return INVALID_OPERATION; } @@ -156,6 +178,31 @@ public: virtual status_t stop() = 0; virtual status_t pause() = 0; virtual bool isPlaying() = 0; + virtual status_t setPlaybackSettings(const AudioPlaybackRate& rate) { + // by default, players only support setting rate to the default + if (!isAudioPlaybackRateEqual(rate, AUDIO_PLAYBACK_RATE_DEFAULT)) { + return BAD_VALUE; + } + return OK; + } + virtual status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */) { + *rate = AUDIO_PLAYBACK_RATE_DEFAULT; + return OK; + } + virtual status_t setSyncSettings(const AVSyncSettings& sync, float /* videoFps */) { + // By default, players only support setting sync source to default; all other sync + // settings are ignored. There is no requirement for getters to return set values. + if (sync.mSource != AVSYNC_SOURCE_DEFAULT) { + return BAD_VALUE; + } + return OK; + } + virtual status_t getSyncSettings( + AVSyncSettings* sync /* nonnull */, float* videoFps /* nonnull */) { + *sync = AVSyncSettings(); + *videoFps = -1.f; + return OK; + } virtual status_t seekTo(int msec) = 0; virtual status_t getCurrentPosition(int *msec) = 0; virtual status_t getDuration(int *msec) = 0; @@ -166,13 +213,13 @@ public: virtual status_t getParameter(int key, Parcel *reply) = 0; // default no-op implementation of optional extensions - virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) { + virtual status_t setRetransmitEndpoint(const struct sockaddr_in* /* endpoint */) { return INVALID_OPERATION; } - virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) { + virtual status_t getRetransmitEndpoint(struct sockaddr_in* /* endpoint */) { return INVALID_OPERATION; } - virtual status_t setNextPlayer(const sp<MediaPlayerBase>& next) { + virtual status_t setNextPlayer(const sp<MediaPlayerBase>& /* next */) { return OK; } @@ -192,8 +239,8 @@ public: // the known metadata should be returned. // @param[inout] records Parcel where the player appends its metadata. // @return OK if the call was successful. - virtual status_t getMetadata(const media::Metadata::Filter& ids, - Parcel *records) { + virtual status_t getMetadata(const media::Metadata::Filter& /* ids */, + Parcel* /* records */) { return INVALID_OPERATION; }; @@ -216,7 +263,7 @@ public: if (notifyCB) notifyCB(cookie, msg, ext1, ext2, obj); } - virtual status_t dump(int fd, const Vector<String16> &args) const { + virtual status_t dump(int /* fd */, const Vector<String16>& /* args */) const { return INVALID_OPERATION; } 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/MediaRecorderBase.h b/include/media/MediaRecorderBase.h index d7ac302..d6cc4bb 100644 --- a/include/media/MediaRecorderBase.h +++ b/include/media/MediaRecorderBase.h @@ -26,10 +26,12 @@ namespace android { class ICameraRecordingProxy; class Surface; +class IGraphicBufferConsumer; class IGraphicBufferProducer; struct MediaRecorderBase { - MediaRecorderBase() {} + MediaRecorderBase(const String16 &opPackageName) + : mOpPackageName(opPackageName) {} virtual ~MediaRecorderBase() {} virtual status_t init() = 0; @@ -43,7 +45,6 @@ struct MediaRecorderBase { virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy) = 0; virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface) = 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) {return INVALID_OPERATION;} virtual status_t setParameters(const String8& params) = 0; @@ -56,8 +57,13 @@ struct MediaRecorderBase { virtual status_t reset() = 0; virtual status_t getMaxAmplitude(int *max) = 0; virtual status_t dump(int fd, const Vector<String16>& args) const = 0; + virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0; virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0; + +protected: + String16 mOpPackageName; + private: MediaRecorderBase(const MediaRecorderBase &); MediaRecorderBase &operator=(const MediaRecorderBase &); diff --git a/include/media/MediaResource.h b/include/media/MediaResource.h new file mode 100644 index 0000000..20f2cad --- /dev/null +++ b/include/media/MediaResource.h @@ -0,0 +1,53 @@ +/* + * 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 ANDROID_MEDIA_RESOURCE_H +#define ANDROID_MEDIA_RESOURCE_H + +#include <binder/Parcel.h> +#include <utils/String8.h> + +namespace android { + +extern const char kResourceSecureCodec[]; +extern const char kResourceNonSecureCodec[]; +extern const char kResourceAudioCodec[]; +extern const char kResourceVideoCodec[]; +extern const char kResourceGraphicMemory[]; + +class MediaResource { +public: + MediaResource(); + MediaResource(String8 type, uint64_t value); + MediaResource(String8 type, String8 subType, uint64_t value); + + void readFromParcel(const Parcel &parcel); + void writeToParcel(Parcel *parcel) const; + + String8 toString() const; + + bool operator==(const MediaResource &other) const; + bool operator!=(const MediaResource &other) const; + + String8 mType; + String8 mSubType; + uint64_t mValue; +}; + +}; // namespace android + +#endif // ANDROID_MEDIA_RESOURCE_H diff --git a/include/media/MediaResourcePolicy.h b/include/media/MediaResourcePolicy.h new file mode 100644 index 0000000..9bc2eec --- /dev/null +++ b/include/media/MediaResourcePolicy.h @@ -0,0 +1,45 @@ +/* + * 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 ANDROID_MEDIA_RESOURCE_POLICY_H +#define ANDROID_MEDIA_RESOURCE_POLICY_H + +#include <binder/Parcel.h> +#include <utils/String8.h> + +namespace android { + +extern const char kPolicySupportsMultipleSecureCodecs[]; +extern const char kPolicySupportsSecureWithNonSecureCodec[]; + +class MediaResourcePolicy { +public: + MediaResourcePolicy(); + MediaResourcePolicy(String8 type, String8 value); + + void readFromParcel(const Parcel &parcel); + void writeToParcel(Parcel *parcel) const; + + String8 toString() const; + + String8 mType; + String8 mValue; +}; + +}; // namespace android + +#endif // ANDROID_MEDIA_RESOURCE_POLICY_H diff --git a/include/media/RingBuffer.h b/include/media/RingBuffer.h new file mode 100644 index 0000000..df7c00e --- /dev/null +++ b/include/media/RingBuffer.h @@ -0,0 +1,361 @@ +/* + * Copyright (C) 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 ANDROID_SERVICE_UTILS_RING_BUFFER_H +#define ANDROID_SERVICE_UTILS_RING_BUFFER_H + +#include <utils/Log.h> +#include <cutils/compiler.h> + +#include <iterator> +#include <utility> +#include <vector> + +namespace android { + +/** + * A RingBuffer class that maintains an array of objects that can grow up to a certain size. + * Elements added to the RingBuffer are inserted in the logical front of the buffer, and + * invalidate all current iterators for that RingBuffer object. + */ +template <class T> +class RingBuffer final { +public: + + /** + * Construct a RingBuffer that can grow up to the given length. + */ + RingBuffer(size_t length); + + /** + * Forward iterator to this class. Implements an std:forward_iterator. + */ + class iterator : public std::iterator<std::forward_iterator_tag, T> { + public: + iterator(T* ptr, size_t size, size_t pos, size_t ctr); + + iterator& operator++(); + + iterator operator++(int); + + bool operator==(const iterator& rhs); + + bool operator!=(const iterator& rhs); + + T& operator*(); + + T* operator->(); + + private: + T* mPtr; + size_t mSize; + size_t mPos; + size_t mCtr; + }; + + /** + * Constant forward iterator to this class. Implements an std:forward_iterator. + */ + class const_iterator : public std::iterator<std::forward_iterator_tag, T> { + public: + const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr); + + const_iterator& operator++(); + + const_iterator operator++(int); + + bool operator==(const const_iterator& rhs); + + bool operator!=(const const_iterator& rhs); + + const T& operator*(); + + const T* operator->(); + + private: + const T* mPtr; + size_t mSize; + size_t mPos; + size_t mCtr; + }; + + /** + * Adds item to the front of this RingBuffer. If the RingBuffer is at its maximum length, + * this will result in the last element being replaced (this is done using the element's + * assignment operator). + * + * All current iterators are invalidated. + */ + void add(const T& item); + + /** + * Moves item to the front of this RingBuffer. Following a call to this, item should no + * longer be used. If the RingBuffer is at its maximum length, this will result in the + * last element being replaced (this is done using the element's assignment operator). + * + * All current iterators are invalidated. + */ + void add(T&& item); + + /** + * Construct item in-place in the front of this RingBuffer using the given arguments. If + * the RingBuffer is at its maximum length, this will result in the last element being + * replaced (this is done using the element's assignment operator). + * + * All current iterators are invalidated. + */ + template <class... Args> + void emplace(Args&&... args); + + /** + * Get an iterator to the front of this RingBuffer. + */ + iterator begin(); + + /** + * Get an iterator to the end of this RingBuffer. + */ + iterator end(); + + /** + * Get a const_iterator to the front of this RingBuffer. + */ + const_iterator begin() const; + + /** + * Get a const_iterator to the end of this RingBuffer. + */ + const_iterator end() const; + + /** + * Return a reference to the element at a given index. If the index is out of range for + * this ringbuffer, [0, size), the behavior for this is undefined. + */ + T& operator[](size_t index); + + /** + * Return a const reference to the element at a given index. If the index is out of range + * for this ringbuffer, [0, size), the behavior for this is undefined. + */ + const T& operator[](size_t index) const; + + /** + * Return the current size of this RingBuffer. + */ + size_t size() const; + + /** + * Remove all elements from this RingBuffer and set the size to 0. + */ + void clear(); + +private: + size_t mFrontIdx; + size_t mMaxBufferSize; + std::vector<T> mBuffer; +}; // class RingBuffer + + +template <class T> +RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {} + +template <class T> +RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) : + mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {} + +template <class T> +typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() { + ++mCtr; + + if (CC_UNLIKELY(mCtr == mSize)) { + mPos = mSize; + return *this; + } + + mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1); + return *this; +} + +template <class T> +typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) { + iterator tmp{mPtr, mSize, mPos, mCtr}; + ++(*this); + return tmp; +} + +template <class T> +bool RingBuffer<T>::iterator::operator==(const iterator& rhs) { + return (mPtr + mPos) == (rhs.mPtr + rhs.mPos); +} + +template <class T> +bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) { + return (mPtr + mPos) != (rhs.mPtr + rhs.mPos); +} + +template <class T> +T& RingBuffer<T>::iterator::operator*() { + return *(mPtr + mPos); +} + +template <class T> +T* RingBuffer<T>::iterator::operator->() { + return mPtr + mPos; +} + +template <class T> +RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) : + mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {} + +template <class T> +typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() { + ++mCtr; + + if (CC_UNLIKELY(mCtr == mSize)) { + mPos = mSize; + return *this; + } + + mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1); + return *this; +} + +template <class T> +typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) { + const_iterator tmp{mPtr, mSize, mPos, mCtr}; + ++(*this); + return tmp; +} + +template <class T> +bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) { + return (mPtr + mPos) == (rhs.mPtr + rhs.mPos); +} + +template <class T> +bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) { + return (mPtr + mPos) != (rhs.mPtr + rhs.mPos); +} + +template <class T> +const T& RingBuffer<T>::const_iterator::operator*() { + return *(mPtr + mPos); +} + +template <class T> +const T* RingBuffer<T>::const_iterator::operator->() { + return mPtr + mPos; +} + +template <class T> +void RingBuffer<T>::add(const T& item) { + if (mBuffer.size() < mMaxBufferSize) { + mBuffer.push_back(item); + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); + return; + } + + mBuffer[mFrontIdx] = item; + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); +} + +template <class T> +void RingBuffer<T>::add(T&& item) { + if (mBuffer.size() != mMaxBufferSize) { + mBuffer.push_back(std::forward<T>(item)); + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); + return; + } + + // Only works for types with move assignment operator + mBuffer[mFrontIdx] = std::forward<T>(item); + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); +} + +template <class T> +template <class... Args> +void RingBuffer<T>::emplace(Args&&... args) { + if (mBuffer.size() != mMaxBufferSize) { + mBuffer.emplace_back(std::forward<Args>(args)...); + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); + return; + } + + // Only works for types with move assignment operator + mBuffer[mFrontIdx] = T(std::forward<Args>(args)...); + mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize); +} + +template <class T> +typename RingBuffer<T>::iterator RingBuffer<T>::begin() { + size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1; + return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0); +} + +template <class T> +typename RingBuffer<T>::iterator RingBuffer<T>::end() { + size_t s = mBuffer.size(); + return iterator(mBuffer.data(), s, s, s); +} + +template <class T> +typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const { + size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1; + return const_iterator(mBuffer.data(), mBuffer.size(), + (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0); +} + +template <class T> +typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const { + size_t s = mBuffer.size(); + return const_iterator(mBuffer.data(), s, s, s); +} + +template <class T> +T& RingBuffer<T>::operator[](size_t index) { + LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.", + index, mBuffer.size()); + size_t pos = (index >= mFrontIdx) ? + mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index; + return mBuffer[pos]; +} + +template <class T> +const T& RingBuffer<T>::operator[](size_t index) const { + LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.", + index, mBuffer.size()); + size_t pos = (index >= mFrontIdx) ? + mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index; + return mBuffer[pos]; +} + +template <class T> +size_t RingBuffer<T>::size() const { + return mBuffer.size(); +} + +template <class T> +void RingBuffer<T>::clear() { + mBuffer.clear(); + mFrontIdx = 0; +} + +}; // namespace android + +#endif // ANDROID_SERVICE_UTILS_RING_BUFFER_H + + diff --git a/include/media/SingleStateQueue.h b/include/media/SingleStateQueue.h index 04c5fd0..d423962 100644 --- a/include/media/SingleStateQueue.h +++ b/include/media/SingleStateQueue.h @@ -21,6 +21,7 @@ // Non-blocking single-reader / single-writer multi-word atomic load / store #include <stdint.h> +#include <cutils/atomic.h> namespace android { @@ -31,6 +32,12 @@ public: class Mutator; class Observer; + enum SSQ_STATUS { + SSQ_PENDING, /* = 0 */ + SSQ_READ, + SSQ_DONE, + }; + struct Shared { // needs to be part of a union so don't define constructor or destructor @@ -41,28 +48,56 @@ private: void init() { mAck = 0; mSequence = 0; } volatile int32_t mAck; -#if 0 - int mPad[7]; - // cache line boundary -#endif volatile int32_t mSequence; T mValue; }; class Mutator { public: - Mutator(Shared *shared); - /*virtual*/ ~Mutator() { } + Mutator(Shared *shared) + : mSequence(0), mShared(shared) + { + // exactly one of Mutator and Observer must initialize, currently it is Observer + // shared->init(); + } // push new value onto state queue, overwriting previous value; // returns a sequence number which can be used with ack() - int32_t push(const T& value); - - // return true if most recent push has been observed - bool ack(); + int32_t push(const T& value) + { + Shared *shared = mShared; + int32_t sequence = mSequence; + sequence++; + android_atomic_acquire_store(sequence, &shared->mSequence); + shared->mValue = value; + sequence++; + android_atomic_release_store(sequence, &shared->mSequence); + mSequence = sequence; + // consider signalling a futex here, if we know that observer is waiting + return sequence; + } + + // returns the status of the last state push. This may be a stale value. + // + // SSQ_PENDING, or 0, means it has not been observed + // SSQ_READ means it has been read + // SSQ_DONE means it has been acted upon, after Observer::done() is called + enum SSQ_STATUS ack() const + { + // in the case of SSQ_DONE, prevent any subtle data-races of subsequent reads + // being performed (out-of-order) before the ack read, should the caller be + // depending on sequentiality of reads. + const int32_t ack = android_atomic_acquire_load(&mShared->mAck); + return ack - mSequence & ~1 ? SSQ_PENDING /* seq differ */ : + ack & 1 ? SSQ_DONE : SSQ_READ; + } // return true if a push with specified sequence number or later has been observed - bool ack(int32_t sequence); + bool ack(int32_t sequence) const + { + // this relies on 2's complement rollover to detect an ancient sequence number + return mShared->mAck - sequence >= 0; + } private: int32_t mSequence; @@ -71,11 +106,54 @@ private: class Observer { public: - Observer(Shared *shared); - /*virtual*/ ~Observer() { } + Observer(Shared *shared) + : mSequence(0), mSeed(1), mShared(shared) + { + // exactly one of Mutator and Observer must initialize, currently it is Observer + shared->init(); + } // return true if value has changed - bool poll(T& value); + bool poll(T& value) + { + Shared *shared = mShared; + int32_t before = shared->mSequence; + if (before == mSequence) { + return false; + } + for (int tries = 0; ; ) { + const int MAX_TRIES = 5; + if (before & 1) { + if (++tries >= MAX_TRIES) { + return false; + } + before = shared->mSequence; + } else { + android_memory_barrier(); + T temp = shared->mValue; + int32_t after = android_atomic_release_load(&shared->mSequence); + if (after == before) { + value = temp; + shared->mAck = before; + mSequence = before; // mSequence is even after poll success + return true; + } + if (++tries >= MAX_TRIES) { + return false; + } + before = after; + } + } + } + + // (optional) used to indicate to the Mutator that the state that has been polled + // has also been acted upon. + void done() + { + const int32_t ack = mShared->mAck + 1; + // ensure all previous writes have been performed. + android_atomic_release_store(ack, &mShared->mAck); // mSequence is odd after "done" + } private: int32_t mSequence; diff --git a/include/media/StringArray.h b/include/media/StringArray.h index ae47085..48d98bf 100644 --- a/include/media/StringArray.h +++ b/include/media/StringArray.h @@ -16,7 +16,7 @@ // // Sortable array of strings. STL-ish, but STL-free. -// +// #ifndef _LIBS_MEDIA_STRING_ARRAY_H #define _LIBS_MEDIA_STRING_ARRAY_H diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h index 6167dd6..186e018 100644 --- a/include/media/Visualizer.h +++ b/include/media/Visualizer.h @@ -65,7 +65,8 @@ public: /* Constructor. * See AudioEffect constructor for details on parameters. */ - Visualizer(int32_t priority = 0, + Visualizer(const String16& opPackageName, + int32_t priority = 0, effect_callback_t cbf = NULL, void* user = NULL, int sessionId = 0); @@ -94,7 +95,8 @@ public: // install a callback to receive periodic captures. The capture rate is specified in milliHertz // and the capture format is according to flags (see callback_flags). - status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate); + status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate, + bool force = false); // set the capture size capture size must be a power of two in the range // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN] diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index b35cf32..f655f35 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -25,6 +25,7 @@ namespace android { +class IDataSource; struct IMediaHTTPService; class IMediaPlayerService; class IMediaMetadataRetriever; @@ -57,6 +58,7 @@ enum { METADATA_KEY_IS_DRM = 22, METADATA_KEY_LOCATION = 23, METADATA_KEY_VIDEO_ROTATION = 24, + METADATA_KEY_CAPTURE_FRAMERATE = 25, // Add more here... }; @@ -74,6 +76,7 @@ public: const KeyedVector<String8, String8> *headers = NULL); status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp<IDataSource>& dataSource); sp<IMemory> getFrameAtTime(int64_t timeUs, int option); sp<IMemory> extractAlbumArt(); const char* extractMetadata(int keyCode); diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 5830933..3fe749c 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -20,6 +20,8 @@ #include <arpa/inet.h> #include <binder/IMemory.h> + +#include <media/AudioResamplerPublic.h> #include <media/IMediaPlayerClient.h> #include <media/IMediaPlayer.h> #include <media/IMediaDeathNotifier.h> @@ -32,8 +34,9 @@ class ANativeWindow; namespace android { -class Surface; +struct AVSyncSettings; class IGraphicBufferProducer; +class Surface; enum media_event_type { MEDIA_NOP = 0, // interface test message @@ -50,6 +53,7 @@ enum media_event_type { MEDIA_ERROR = 100, MEDIA_INFO = 200, MEDIA_SUBTITLE_DATA = 201, + MEDIA_META_DATA = 202, }; // Generic error codes for the media player framework. Errors are fatal, the @@ -183,6 +187,7 @@ enum media_track_type { MEDIA_TRACK_TYPE_AUDIO = 2, MEDIA_TRACK_TYPE_TIMEDTEXT = 3, MEDIA_TRACK_TYPE_SUBTITLE = 4, + MEDIA_TRACK_TYPE_METADATA = 5, }; // ---------------------------------------------------------------------------- @@ -211,6 +216,7 @@ public: status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setDataSource(const sp<IStreamSource> &source); + status_t setDataSource(const sp<IDataSource> &source); status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer); status_t setListener(const sp<MediaPlayerListener>& listener); @@ -220,6 +226,12 @@ public: status_t stop(); status_t pause(); bool isPlaying(); + status_t setPlaybackSettings(const AudioPlaybackRate& rate); + status_t getPlaybackSettings(AudioPlaybackRate* rate /* nonnull */); + status_t setSyncSettings(const AVSyncSettings& sync, float videoFpsHint); + status_t getSyncSettings( + AVSyncSettings* sync /* nonnull */, + float* videoFps /* nonnull */); status_t getVideoWidth(int *w); status_t getVideoHeight(int *h); status_t seekTo(int msec); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index b0a62a7..15ff82d 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -32,6 +32,7 @@ class IMediaRecorder; class ICamera; class ICameraRecordingProxy; class IGraphicBufferProducer; +struct PersistentSurface; class Surface; typedef void (*media_completion_f)(status_t status, void *cookie); @@ -209,7 +210,7 @@ class MediaRecorder : public BnMediaRecorderClient, public virtual IMediaDeathNotifier { public: - MediaRecorder(); + MediaRecorder(const String16& opPackageName); ~MediaRecorder(); void died(); @@ -221,7 +222,6 @@ public: status_t setOutputFormat(int of); status_t setVideoEncoder(int ve); status_t setAudioEncoder(int ae); - status_t setOutputFile(const char* path); status_t setOutputFile(int fd, int64_t offset, int64_t length); status_t setVideoSize(int width, int height); status_t setVideoFrameRate(int frames_per_second); @@ -237,6 +237,7 @@ public: status_t close(); status_t release(); void notify(int msg, int ext1, int ext2); + status_t setInputSurface(const sp<PersistentSurface>& surface); sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer(); private: diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h index d422576..d9bbc8d 100644 --- a/include/media/nbaio/NBAIO.h +++ b/include/media/nbaio/NBAIO.h @@ -231,7 +231,8 @@ public: virtual status_t getTimestamp(AudioTimestamp& timestamp) { return INVALID_OPERATION; } protected: - NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0) { } + NBAIO_Sink(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesWritten(0) + { } virtual ~NBAIO_Sink() { } // Implementations are free to ignore these if they don't need them @@ -322,7 +323,8 @@ public: virtual void onTimestamp(const AudioTimestamp& timestamp) { } protected: - NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0) { } + NBAIO_Source(const NBAIO_Format& format = Format_Invalid) : NBAIO_Port(format), mFramesRead(0) + { } virtual ~NBAIO_Source() { } // Implementations are free to ignore these if they don't need them diff --git a/include/media/nbaio/NBLog.h b/include/media/nbaio/NBLog.h index bcbbc04..1297b51 100644 --- a/include/media/nbaio/NBLog.h +++ b/include/media/nbaio/NBLog.h @@ -21,7 +21,7 @@ #include <binder/IMemory.h> #include <utils/Mutex.h> -#include <media/nbaio/roundup.h> +#include <audio_utils/roundup.h> namespace android { diff --git a/include/media/stagefright/AACWriter.h b/include/media/stagefright/AACWriter.h index d22707a..aa60a19 100644 --- a/include/media/stagefright/AACWriter.h +++ b/include/media/stagefright/AACWriter.h @@ -24,10 +24,9 @@ namespace android { struct MediaSource; -struct MetaData; +class MetaData; struct AACWriter : public MediaWriter { - AACWriter(const char *filename); AACWriter(int fd); status_t initCheck() const; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 7825508..8b5b862 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -20,9 +20,11 @@ #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> +#include <media/stagefright/FrameRenderTracker.h> #include <media/stagefright/SkipCutBuffer.h> #include <OMX_Audio.h> @@ -44,9 +46,12 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { virtual void initiateAllocateComponent(const sp<AMessage> &msg); virtual void initiateConfigureComponent(const sp<AMessage> &msg); virtual void initiateCreateInputSurface(); + virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface); virtual void initiateStart(); virtual void initiateShutdown(bool keepComponentAllocated = false); + virtual status_t setSurface(const sp<Surface> &surface); + virtual void signalFlush(); virtual void signalResume(); @@ -105,6 +110,10 @@ private: enum { kWhatSetup = 'setu', kWhatOMXMessage = 'omx ', + // same as kWhatOMXMessage - but only used with + // handleMessage during OMX message-list handling + kWhatOMXMessageItem = 'omxI', + kWhatOMXMessageList = 'omxL', kWhatInputBufferFilled = 'inpF', kWhatOutputBufferDrained = 'outD', kWhatShutdown = 'shut', @@ -113,12 +122,14 @@ private: kWhatDrainDeferredMessages = 'drai', kWhatAllocateComponent = 'allo', kWhatConfigureComponent = 'conf', + kWhatSetSurface = 'setS', kWhatCreateInputSurface = 'cisf', + kWhatSetInputSurface = 'sisf', kWhatSignalEndOfInputStream = 'eois', kWhatStart = 'star', kWhatRequestIDRFrame = 'ridr', kWhatSetParameters = 'setP', - kWhatSubmitOutputMetaDataBufferIfEOS = 'subm', + kWhatSubmitOutputMetadataBufferIfEOS = 'subm', kWhatOMXDied = 'OMXd', kWhatReleaseCodecInstance = 'relC', }; @@ -134,6 +145,12 @@ private: kFlagIsGrallocUsageProtected = 4, }; + enum { + kVideoGrallocUsage = (GRALLOC_USAGE_HW_TEXTURE + | GRALLOC_USAGE_HW_COMPOSER + | GRALLOC_USAGE_EXTERNAL_DISP), + }; + struct BufferInfo { enum Status { OWNED_BY_US, @@ -141,16 +158,39 @@ private: OWNED_BY_UPSTREAM, OWNED_BY_DOWNSTREAM, OWNED_BY_NATIVE_WINDOW, + UNRECOGNIZED, // not a tracked buffer }; + static inline Status getSafeStatus(BufferInfo *info) { + return info == NULL ? UNRECOGNIZED : info->mStatus; + } + IOMX::buffer_id mBufferID; Status mStatus; unsigned mDequeuedAt; sp<ABuffer> mData; sp<GraphicBuffer> mGraphicBuffer; + int mFenceFd; + FrameRenderTracker::Info *mRenderInfo; + + // The following field and 4 methods are used for debugging only + bool mIsReadFence; + // Store |fenceFd| and set read/write flag. Log error, if there is already a fence stored. + void setReadFence(int fenceFd, const char *dbg); + void setWriteFence(int fenceFd, const char *dbg); + // Log error, if the current fence is not a read/write fence. + void checkReadFence(const char *dbg); + void checkWriteFence(const char *dbg); }; + static const char *_asString(BufferInfo::Status s); + void dumpBuffers(OMX_U32 portIndex); + + // If |fd| is non-negative, waits for fence with |fd| and logs an error if it fails. Returns + // the error code or OK on success. If |fd| is negative, it returns OK + status_t waitForFence(int fd, const char *dbg); + #if TRACK_BUFFER_TIMING struct BufferStats { int64_t mEmptyBufferTimeUs; @@ -181,10 +221,12 @@ private: sp<MemoryDealer> mDealer[2]; sp<ANativeWindow> mNativeWindow; + int mNativeWindowUsageBits; sp<AMessage> mInputFormat; sp<AMessage> mOutputFormat; sp<AMessage> mBaseOutputFormat; + FrameRenderTracker mRenderTracker; // render information for buffers rendered by ACodec Vector<BufferInfo> mBuffers[2]; bool mPortEOS[2]; status_t mInputEOSResult; @@ -192,8 +234,8 @@ private: List<sp<AMessage> > mDeferredQueue; bool mSentFormat; + bool mIsVideo; bool mIsEncoder; - bool mUseMetadataOnEncoderOutput; bool mFatalError; bool mShutdownInProgress; bool mExplicitShutdown; @@ -209,12 +251,15 @@ private: bool mChannelMaskPresent; int32_t mChannelMask; unsigned mDequeueCounter; - bool mStoreMetaDataInOutputBuffers; - int32_t mMetaDataBuffersToSubmit; + MetadataBufferType mInputMetadataType; + MetadataBufferType mOutputMetadataType; + bool mLegacyAdaptiveExperiment; + int32_t mMetadataBuffersToSubmit; size_t mNumUndequeuedBuffers; int64_t mRepeatFrameDelayUs; int64_t mMaxPtsGapUs; + float mMaxFps; int64_t mTimePerFrameUs; int64_t mTimePerCaptureUs; @@ -228,17 +273,29 @@ private: status_t freeBuffersOnPort(OMX_U32 portIndex); status_t freeBuffer(OMX_U32 portIndex, size_t i); + status_t handleSetSurface(const sp<Surface> &surface); + status_t setupNativeWindowSizeFormatAndUsage( + ANativeWindow *nativeWindow /* nonnull */, int *finalUsage /* nonnull */); + 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); @@ -299,6 +356,9 @@ private: status_t setupRawAudioFormat( OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels); + status_t setPriority(int32_t priority); + status_t setOperatingRate(float rateFloat, bool isVideo); + status_t setMinBufferSize(OMX_U32 portIndex, size_t size); status_t setupMPEG4EncoderParameters(const sp<AMessage> &msg); @@ -316,8 +376,6 @@ private: status_t initNativeWindow(); - status_t pushBlankBuffersToNativeWindow(); - // Returns true iff all buffers on the given port have status // OWNED_BY_US or OWNED_BY_NATIVE_WINDOW. bool allYourBuffersAreBelongToUs(OMX_U32 portIndex); @@ -332,6 +390,23 @@ private: void deferMessage(const sp<AMessage> &msg); void processDeferredMessages(); + void onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); + // called when we have dequeued a buffer |buf| from the native window to track render info. + // |fenceFd| is the dequeue fence, and |info| points to the buffer info where this buffer is + // stored. + void updateRenderInfoForDequeuedBuffer( + ANativeWindowBuffer *buf, int fenceFd, BufferInfo *info); + + // Checks to see if any frames have rendered up until |until|, and to notify client + // (MediaCodec) of rendered frames up-until the frame pointed to by |until| or the first + // unrendered frame. These frames are removed from the render queue. + // If |dropIncomplete| is true, unrendered frames up-until |until| will be dropped from the + // queue, allowing all rendered framed up till then to be notified of. + // (This will effectively clear the render queue up-until (and including) |until|.) + // If |until| is NULL, or is not in the rendered queue, this method will check all frames. + void notifyOfRenderedFrames( + bool dropIncomplete = false, FrameRenderTracker::Info *until = NULL); + void sendFormatChange(const sp<AMessage> &reply); status_t getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify); diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h index 392f968..b38be55 100644 --- a/include/media/stagefright/AMRWriter.h +++ b/include/media/stagefright/AMRWriter.h @@ -26,10 +26,9 @@ namespace android { struct MediaSource; -struct MetaData; +class MetaData; struct AMRWriter : public MediaWriter { - AMRWriter(const char *filename); AMRWriter(int fd); status_t initCheck() const; diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h index 14afb85..e0cd965 100644 --- a/include/media/stagefright/AudioPlayer.h +++ b/include/media/stagefright/AudioPlayer.h @@ -25,9 +25,10 @@ namespace android { -class MediaSource; +struct AudioPlaybackRate; class AudioTrack; -class AwesomePlayer; +struct AwesomePlayer; +class MediaSource; class AudioPlayer : public TimeSource { public: @@ -73,7 +74,8 @@ public: bool isSeeking(); bool reachedEOS(status_t *finalStatus); - status_t setPlaybackRatePermille(int32_t ratePermille); + status_t setPlaybackRate(const AudioPlaybackRate &rate); + status_t getPlaybackRate(AudioPlaybackRate *rate /* nonnull */); void notifyAudioEOS(); diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index 4c9aaad..3074910 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -35,8 +35,10 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { // _not_ a bitmask of audio_channels_t constants. AudioSource( audio_source_t inputSource, + const String16 &opPackageName, uint32_t sampleRate, - uint32_t channels = 1); + uint32_t channels, + uint32_t outSampleRate = 0); status_t initCheck() const; @@ -77,11 +79,13 @@ private: status_t mInitCheck; bool mStarted; int32_t mSampleRate; + int32_t mOutSampleRate; bool mTrackMaxAmplitude; int64_t mStartTimeUs; int16_t mMaxAmplitude; int64_t mPrevSampleTimeUs; + int64_t mFirstSampleTimeUs; int64_t mInitialReadTimeUs; int64_t mNumFramesReceived; int64_t mNumClientOwnedBuffers; diff --git a/include/media/stagefright/BufferProducerWrapper.h b/include/media/stagefright/BufferProducerWrapper.h index d8acf30..4caa2c6 100644 --- a/include/media/stagefright/BufferProducerWrapper.h +++ b/include/media/stagefright/BufferProducerWrapper.h @@ -19,6 +19,7 @@ #define BUFFER_PRODUCER_WRAPPER_H_ #include <gui/IGraphicBufferProducer.h> +#include <media/stagefright/foundation/ABase.h> namespace android { diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h index dd0a106..069e897 100644 --- a/include/media/stagefright/CameraSource.h +++ b/include/media/stagefright/CameraSource.h @@ -83,7 +83,7 @@ public: Size videoSize, int32_t frameRate, const sp<IGraphicBufferProducer>& surface, - bool storeMetaDataInVideoBuffers = false); + bool storeMetaDataInVideoBuffers = true); virtual ~CameraSource(); @@ -149,6 +149,8 @@ protected: int32_t mNumInputBuffers; int32_t mVideoFrameRate; int32_t mColorFormat; + int32_t mEncoderFormat; + int32_t mEncoderDataSpace; status_t mInitCheck; sp<Camera> mCamera; @@ -188,7 +190,7 @@ protected: void releaseCamera(); private: - friend class CameraSourceListener; + friend struct CameraSourceListener; Mutex mLock; Condition mFrameAvailableCondition; diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h index 1bf27a6..bb36052 100644 --- a/include/media/stagefright/CodecBase.h +++ b/include/media/stagefright/CodecBase.h @@ -26,6 +26,7 @@ namespace android { struct ABuffer; +struct PersistentSurface; struct CodecBase : public AHandler { enum { @@ -39,8 +40,10 @@ struct CodecBase : public AHandler { kWhatComponentAllocated = 'cAll', kWhatComponentConfigured = 'cCon', kWhatInputSurfaceCreated = 'isfc', + kWhatInputSurfaceAccepted = 'isfa', kWhatSignaledInputEOS = 'seos', kWhatBuffersAllocated = 'allc', + kWhatOutputFramesRendered = 'outR', }; virtual void setNotificationMessage(const sp<AMessage> &msg) = 0; @@ -48,12 +51,16 @@ struct CodecBase : public AHandler { virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0; virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0; virtual void initiateCreateInputSurface() = 0; + virtual void initiateSetInputSurface( + const sp<PersistentSurface> &surface) = 0; virtual void initiateStart() = 0; virtual void initiateShutdown(bool keepComponentAllocated = false) = 0; // require an explicit message handler virtual void onMessageReceived(const sp<AMessage> &msg) = 0; + virtual status_t setSurface(const sp<Surface> &surface) { return INVALID_OPERATION; } + virtual void signalFlush() = 0; virtual void signalResume() = 0; diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index 3630263..dcde36f 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -32,6 +32,7 @@ namespace android { struct AMessage; struct AString; +class IDataSource; struct IMediaHTTPService; class String8; struct HTTPBase; @@ -53,11 +54,15 @@ public: HTTPBase *httpSource = NULL); static sp<DataSource> CreateMediaHTTP(const sp<IMediaHTTPService> &httpService); + static sp<DataSource> CreateFromIDataSource(const sp<IDataSource> &source); DataSource() {} virtual status_t initCheck() const = 0; + // Returns the number of bytes read, or -1 on failure. It's not an error if + // this returns zero; it just means the given offset is equal to, or + // beyond, the end of the source. virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0; // Convenience methods: diff --git a/include/media/stagefright/FrameRenderTracker.h b/include/media/stagefright/FrameRenderTracker.h new file mode 100644 index 0000000..9333e8f --- /dev/null +++ b/include/media/stagefright/FrameRenderTracker.h @@ -0,0 +1,143 @@ +/* + * 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 FRAME_RENDER_TRACKER_H_ + +#define FRAME_RENDER_TRACKER_H_ + +#include <utils/RefBase.h> +#include <utils/Timers.h> +#include <system/window.h> + +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AString.h> + +#include <list> + +namespace android { + +class Fence; +class GraphicBuffer; + +struct FrameRenderTracker : public RefBase { + // Tracks the render information about a frame. Frames go through several states while + // the render information is tracked: + // + // 1. queued frame: mMediaTime and mGraphicBuffer are set for the frame. mFence is the + // queue fence (read fence). mIndex is negative, and mRenderTimeNs is invalid. + // Key characteristics: mFence is not NULL and mIndex is negative. + // + // 2. dequeued frame: mFence is updated with the dequeue fence (write fence). mIndex is set. + // Key characteristics: mFence is not NULL and mIndex is non-negative. mRenderTime is still + // invalid. + // + // 3. rendered frame or frame: mFence is cleared, mRenderTimeNs is set. + // Key characteristics: mFence is NULL. + // + struct Info { + // set by client during onFrameQueued or onFrameRendered + int64_t getMediaTimeUs() const { return mMediaTimeUs; } + + // -1 if frame is not yet rendered + nsecs_t getRenderTimeNs() const { return mRenderTimeNs; } + + // set by client during updateRenderInfoForDequeuedBuffer; -1 otherwise + ssize_t getIndex() const { return mIndex; } + + // creates information for a queued frame + Info(int64_t mediaTimeUs, const sp<GraphicBuffer> &graphicBuffer, const sp<Fence> &fence) + : mMediaTimeUs(mediaTimeUs), + mRenderTimeNs(-1), + mIndex(-1), + mGraphicBuffer(graphicBuffer), + mFence(fence) { + } + + // creates information for a frame rendered on a tunneled surface + Info(int64_t mediaTimeUs, nsecs_t renderTimeNs) + : mMediaTimeUs(mediaTimeUs), + mRenderTimeNs(renderTimeNs), + mIndex(-1), + mGraphicBuffer(NULL), + mFence(NULL) { + } + + private: + int64_t mMediaTimeUs; + nsecs_t mRenderTimeNs; + ssize_t mIndex; // to be used by client + sp<GraphicBuffer> mGraphicBuffer; + sp<Fence> mFence; + + friend class FrameRenderTracker; + }; + + FrameRenderTracker(); + + void setComponentName(const AString &componentName); + + // clears all tracked frames, and resets last render time + void clear(nsecs_t lastRenderTimeNs); + + // called when |graphicBuffer| corresponding to |mediaTimeUs| is + // queued to the output surface using |fence|. + void onFrameQueued( + int64_t mediaTimeUs, const sp<GraphicBuffer> &graphicBuffer, const sp<Fence> &fence); + + // Called when we have dequeued a buffer |buf| from the native window to track render info. + // |fenceFd| is the dequeue fence, and |index| is a positive buffer ID to be usable by the + // client to track this render info among the dequeued buffers. + // Returns pointer to the tracked info, or NULL if buffer is not tracked or if |index| + // is negative. + Info *updateInfoForDequeuedBuffer(ANativeWindowBuffer *buf, int fenceFd, int index); + + // called when tunneled codec signals frame rendered event + // returns BAD_VALUE if systemNano is not monotonic. Otherwise, returns OK. + status_t onFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano); + + // Checks to see if any frames have rendered up until |until|. If |until| is NULL or not a + // tracked info, this method searches the entire render queue. + // Returns list of rendered frames up-until the frame pointed to by |until| or the first + // unrendered frame, as well as any dropped frames (those with invalid fence) up-until |until|. + // These frames are removed from the render queue. + // If |dropIncomplete| is true, unrendered frames up-until |until| will also be dropped from the + // queue, allowing all rendered framed up till then to be notified of. + // (This will effectively clear the render queue up-until (and including) |until|.) + std::list<Info> checkFencesAndGetRenderedFrames(const Info *until, bool dropIncomplete); + + // Stop tracking a queued frame (e.g. if the frame has been discarded). If |info| is NULL or is + // not tracked, this method is a no-op. If |index| is specified, all indices larger that |index| + // are decremented. This is useful if the untracked frame is deleted from the frame vector. + void untrackFrame(const Info *info, ssize_t index = SSIZE_MAX); + + void dumpRenderQueue() const; + + virtual ~FrameRenderTracker(); + +private: + + // Render information for buffers. Regular surface buffers are queued in the order of + // rendering. Tunneled buffers are queued in the order of receipt. + std::list<Info> mRenderQueue; + nsecs_t mLastRenderTimeNs; + AString mComponentName; + + DISALLOW_EVIL_CONSTRUCTORS(FrameRenderTracker); +}; + +} // namespace android + +#endif // FRAME_RENDER_TRACKER_H_ diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h index 2e2922e..3d7960b 100644 --- a/include/media/stagefright/MPEG2TSWriter.h +++ b/include/media/stagefright/MPEG2TSWriter.h @@ -29,7 +29,6 @@ struct ABuffer; struct MPEG2TSWriter : public MediaWriter { MPEG2TSWriter(int fd); - MPEG2TSWriter(const char *filename); MPEG2TSWriter( void *cookie, diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 26ce5f9..a195fe8 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -26,13 +26,13 @@ namespace android { +class AMessage; class MediaBuffer; class MediaSource; class MetaData; class MPEG4Writer : public MediaWriter { public: - MPEG4Writer(const char *filename); MPEG4Writer(int fd); // Limitations @@ -49,6 +49,7 @@ public: virtual status_t dump(int fd, const Vector<String16>& args); void beginBox(const char *fourcc); + void beginBox(uint32_t id); void writeInt8(int8_t x); void writeInt16(int16_t x); void writeInt32(int32_t x); @@ -63,6 +64,7 @@ public: int32_t getTimeScale() const { return mTimeScale; } status_t setGeoData(int latitudex10000, int longitudex10000); + status_t setCaptureRate(float captureFps); virtual void setStartTimeOffsetMs(int ms) { mStartTimeOffsetMs = ms; } virtual int32_t getStartTimeOffsetMs() const { return mStartTimeOffsetMs; } @@ -89,6 +91,7 @@ private: off64_t mFreeBoxOffset; bool mStreamableFile; off64_t mEstimatedMoovBoxSize; + off64_t mMoovExtraSize; uint32_t mInterleaveDurationUs; int32_t mTimeScale; int64_t mStartTimestampUs; @@ -103,6 +106,8 @@ private: List<off64_t> mBoxes; + sp<AMessage> mMetaKeys; + void setStartTimestampUs(int64_t timeUs); int64_t getStartTimestampUs(); // Not const status_t startTracks(MetaData *params); @@ -196,6 +201,12 @@ private: void writeGeoDataBox(); void writeLatitude(int degreex10000); void writeLongitude(int degreex10000); + + void addDeviceMeta(); + void writeHdlr(); + void writeKeys(); + void writeIlst(); + void writeMetaBox(); void sendSessionSummary(); void release(); status_t reset(); diff --git a/include/media/stagefright/MediaClock.h b/include/media/stagefright/MediaClock.h new file mode 100644 index 0000000..dd1a809 --- /dev/null +++ b/include/media/stagefright/MediaClock.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 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_CLOCK_H_ + +#define MEDIA_CLOCK_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <utils/Mutex.h> +#include <utils/RefBase.h> + +namespace android { + +struct AMessage; + +struct MediaClock : public RefBase { + MediaClock(); + + void setStartingTimeMedia(int64_t startingTimeMediaUs); + + void clearAnchor(); + // It's required to use timestamp of just rendered frame as + // anchor time in paused state. + void updateAnchor( + int64_t anchorTimeMediaUs, + int64_t anchorTimeRealUs, + int64_t maxTimeMediaUs = INT64_MAX); + + void updateMaxTimeMedia(int64_t maxTimeMediaUs); + + void setPlaybackRate(float rate); + float getPlaybackRate() const; + + // query media time corresponding to real time |realUs|, and save the + // result in |outMediaUs|. + status_t getMediaTime( + int64_t realUs, + int64_t *outMediaUs, + bool allowPastMaxTime = false) const; + // query real time corresponding to media time |targetMediaUs|. + // The result is saved in |outRealUs|. + status_t getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs) const; + +protected: + virtual ~MediaClock(); + +private: + status_t getMediaTime_l( + int64_t realUs, + int64_t *outMediaUs, + bool allowPastMaxTime) const; + + mutable Mutex mLock; + + int64_t mAnchorTimeMediaUs; + int64_t mAnchorTimeRealUs; + int64_t mMaxTimeMediaUs; + int64_t mStartingTimeMediaUs; + + float mPlaybackRate; + + DISALLOW_EVIL_CONSTRUCTORS(MediaClock); +}; + +} // namespace android + +#endif // MEDIA_CLOCK_H_ diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h index d448097..c10963d 100644 --- a/include/media/stagefright/MediaCodec.h +++ b/include/media/stagefright/MediaCodec.h @@ -20,17 +20,25 @@ #include <gui/IGraphicBufferProducer.h> #include <media/hardware/CryptoAPI.h> +#include <media/MediaResource.h> #include <media/stagefright/foundation/AHandler.h> +#include <media/stagefright/FrameRenderTracker.h> #include <utils/Vector.h> namespace android { struct ABuffer; struct AMessage; +struct AReplyToken; struct AString; struct CodecBase; -struct ICrypto; struct IBatteryStats; +struct ICrypto; +class IMemory; +struct MemoryDealer; +class IResourceManagerClient; +class IResourceManagerService; +struct PersistentSurface; struct SoftwareRenderer; struct Surface; @@ -50,15 +58,20 @@ struct MediaCodec : public AHandler { CB_OUTPUT_AVAILABLE = 2, CB_ERROR = 3, CB_OUTPUT_FORMAT_CHANGED = 4, + CB_RESOURCE_RECLAIMED = 5, }; - struct BatteryNotifier; + static const pid_t kNoPid = -1; static sp<MediaCodec> CreateByType( - const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err = NULL); + const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err = NULL, + pid_t pid = kNoPid); static sp<MediaCodec> CreateByComponentName( - const sp<ALooper> &looper, const char *name, status_t *err = NULL); + const sp<ALooper> &looper, const char *name, status_t *err = NULL, + pid_t pid = kNoPid); + + static sp<PersistentSurface> CreatePersistentInputSurface(); status_t configure( const sp<AMessage> &format, @@ -68,8 +81,12 @@ struct MediaCodec : public AHandler { status_t setCallback(const sp<AMessage> &callback); + status_t setOnFrameRenderedNotification(const sp<AMessage> ¬ify); + status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer); + status_t setInputSurface(const sp<PersistentSurface> &surface); + status_t start(); // Returns to a state in which the component remains allocated but @@ -125,6 +142,8 @@ struct MediaCodec : public AHandler { status_t getOutputFormat(sp<AMessage> *format) const; status_t getInputFormat(sp<AMessage> *format) const; + status_t getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const; + status_t getInputBuffers(Vector<sp<ABuffer> > *buffers) const; status_t getOutputBuffers(Vector<sp<ABuffer> > *buffers) const; @@ -132,6 +151,8 @@ struct MediaCodec : public AHandler { status_t getOutputFormat(size_t index, sp<AMessage> *format); status_t getInputBuffer(size_t index, sp<ABuffer> *buffer); + status_t setSurface(const sp<Surface> &nativeWindow); + status_t requestIDRFrame(); // Notification will be posted once there "is something to do", i.e. @@ -143,11 +164,22 @@ struct MediaCodec : public AHandler { status_t setParameters(const sp<AMessage> ¶ms); + // Create a MediaCodec notification message from a list of rendered or dropped render infos + // by adding rendered frame information to a base notification message. Returns the number + // of frames that were rendered. + static size_t CreateFramesRenderedMessage( + std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg); + protected: virtual ~MediaCodec(); virtual void onMessageReceived(const sp<AMessage> &msg); private: + // used by ResourceManagerClient + status_t reclaim(); + friend struct ResourceManagerClient; + +private: enum State { UNINITIALIZED, INITIALIZING, @@ -170,7 +202,9 @@ private: enum { kWhatInit = 'init', kWhatConfigure = 'conf', + kWhatSetSurface = 'sSur', kWhatCreateInputSurface = 'cisf', + kWhatSetInputSurface = 'sisf', kWhatStart = 'strt', kWhatStop = 'stop', kWhatRelease = 'rele', @@ -191,6 +225,7 @@ private: kWhatGetName = 'getN', kWhatSetParameters = 'setP', kWhatSetCallback = 'setC', + kWhatSetNotification = 'setN', }; enum { @@ -206,39 +241,78 @@ private: kFlagGatherCodecSpecificData = 512, kFlagIsAsync = 1024, kFlagIsComponentAllocated = 2048, + kFlagPushBlankBuffersOnShutdown = 4096, }; struct BufferInfo { uint32_t mBufferID; sp<ABuffer> mData; sp<ABuffer> mEncryptedData; + sp<IMemory> mSharedEncryptedBuffer; sp<AMessage> mNotify; sp<AMessage> mFormat; bool mOwnedByClient; }; + struct ResourceManagerServiceProxy : public IBinder::DeathRecipient { + ResourceManagerServiceProxy(pid_t pid); + ~ResourceManagerServiceProxy(); + + void init(); + + // implements DeathRecipient + virtual void binderDied(const wp<IBinder>& /*who*/); + + void addResource( + int64_t clientId, + const sp<IResourceManagerClient> client, + const Vector<MediaResource> &resources); + + void removeResource(int64_t clientId); + + bool reclaimResource(const Vector<MediaResource> &resources); + + private: + Mutex mLock; + sp<IResourceManagerService> mService; + pid_t mPid; + }; + State mState; + bool mReleasedByResourceManager; sp<ALooper> mLooper; sp<ALooper> mCodecLooper; sp<CodecBase> mCodec; AString mComponentName; - uint32_t mReplyID; + sp<AReplyToken> mReplyID; uint32_t mFlags; status_t mStickyError; - sp<Surface> mNativeWindow; + sp<Surface> mSurface; SoftwareRenderer *mSoftRenderer; + sp<AMessage> mOutputFormat; sp<AMessage> mInputFormat; sp<AMessage> mCallback; + sp<AMessage> mOnFrameRenderedNotification; + sp<MemoryDealer> mDealer; + + sp<IResourceManagerClient> mResourceManagerClient; + sp<ResourceManagerServiceProxy> mResourceManagerService; bool mBatteryStatNotified; bool mIsVideo; + int32_t mVideoWidth; + int32_t mVideoHeight; + int32_t mRotationDegrees; // initial create parameters AString mInitName; bool mInitNameIsType; bool mInitIsEncoder; + // configure parameter + sp<AMessage> mConfigureMsg; + // Used only to synchronize asynchronous getBufferAndFormat // across all the other (synchronous) buffer state change // operations, such as de/queueIn/OutputBuffer, start and @@ -249,10 +323,10 @@ private: Vector<BufferInfo> mPortBuffers[2]; int32_t mDequeueInputTimeoutGeneration; - uint32_t mDequeueInputReplyID; + sp<AReplyToken> mDequeueInputReplyID; int32_t mDequeueOutputTimeoutGeneration; - uint32_t mDequeueOutputReplyID; + sp<AReplyToken> mDequeueOutputReplyID; sp<ICrypto> mCrypto; @@ -261,13 +335,14 @@ private: sp<AMessage> mActivityNotify; bool mHaveInputSurface; + bool mHavePendingInputBuffers; - MediaCodec(const sp<ALooper> &looper); + MediaCodec(const sp<ALooper> &looper, pid_t pid); static status_t PostAndAwaitResponse( const sp<AMessage> &msg, sp<AMessage> *response); - static void PostReplyWithError(int32_t replyID, int32_t err); + void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err); status_t init(const AString &name, bool nameIsType, bool encoder); @@ -283,15 +358,16 @@ private: size_t portIndex, size_t index, sp<ABuffer> *buffer, sp<AMessage> *format); - bool handleDequeueInputBuffer(uint32_t replyID, bool newRequest = false); - bool handleDequeueOutputBuffer(uint32_t replyID, bool newRequest = false); + bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false); + bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false); void cancelPendingDequeueOperations(); void extractCSD(const sp<AMessage> &format); status_t queueCSDInputBuffer(size_t bufferIndex); - status_t setNativeWindow( - const sp<Surface> &surface); + status_t handleSetSurface(const sp<Surface> &surface); + status_t connectToSurface(const sp<Surface> &surface); + status_t disconnectFromSurface(); void postActivityNotificationIfPossible(); @@ -306,6 +382,9 @@ private: void updateBatteryStat(); bool isExecuting() const; + uint64_t getGraphicBufferSize(); + void addResource(const String8 &type, const String8 &subtype, uint64_t value); + /* called to get the last codec error when the sticky flag is set. * if no such codec error is found, returns UNKNOWN_ERROR. */ diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h index ac7b053..bf4db87 100644 --- a/include/media/stagefright/MediaCodecList.h +++ b/include/media/stagefright/MediaCodecList.h @@ -32,6 +32,8 @@ namespace android { +extern const char *kMaxEncoderInputBuffers; + struct AMessage; struct MediaCodecList : public BnMediaCodecList { @@ -52,9 +54,17 @@ struct MediaCodecList : public BnMediaCodecList { return mCodecInfos.itemAt(index); } + virtual const sp<AMessage> getGlobalSettings() const; + // to be used by MediaPlayerService alone static sp<IMediaCodecList> getLocalInstance(); + // only to be used by getLocalInstance + static void *profilerThreadWrapper(void * /*arg*/); + + // only to be used by MediaPlayerService + void parseTopLevelXMLFile(const char *path, bool ignore_errors = false); + private: class BinderDeathObserver : public IBinder::DeathRecipient { void binderDied(const wp<IBinder> &the_late_who __unused); @@ -64,6 +74,7 @@ private: enum Section { SECTION_TOPLEVEL, + SECTION_SETTINGS, SECTION_DECODERS, SECTION_DECODER, SECTION_DECODER_TYPE, @@ -78,10 +89,14 @@ private: status_t mInitCheck; Section mCurrentSection; + bool mUpdate; Vector<Section> mPastSections; int32_t mDepth; AString mHrefBase; + sp<AMessage> mGlobalSettings; + KeyedVector<AString, CodecSettings> mOverrides; + Vector<sp<MediaCodecInfo> > mCodecInfos; sp<MediaCodecInfo> mCurrentInfo; sp<IOMX> mOMX; @@ -91,7 +106,6 @@ private: status_t initCheck() const; void parseXMLFile(const char *path); - void parseTopLevelXMLFile(const char *path); static void StartElementHandlerWrapper( void *me, const char *name, const char **attrs); @@ -102,9 +116,12 @@ private: void endElementHandler(const char *name); status_t includeXMLFile(const char **attrs); + status_t addSettingFromAttributes(const char **attrs); status_t addMediaCodecFromAttributes(bool encoder, const char **attrs); void addMediaCodec(bool encoder, const char *name, const char *type = NULL); + void setCurrentCodecInfo(bool encoder, const char *name, const char *type); + status_t addQuirk(const char **attrs); status_t addTypeFromAttributes(const char **attrs); status_t addLimit(const char **attrs); diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h index 0970b2b..71f58a9 100644 --- a/include/media/stagefright/MediaCodecSource.h +++ b/include/media/stagefright/MediaCodecSource.h @@ -23,9 +23,11 @@ namespace android { -class ALooper; +struct ALooper; class AMessage; +struct AReplyToken; class IGraphicBufferProducer; +class IGraphicBufferConsumer; class MediaCodec; class MetaData; @@ -40,6 +42,7 @@ struct MediaCodecSource : public MediaSource, const sp<ALooper> &looper, const sp<AMessage> &format, const sp<MediaSource> &source, + const sp<IGraphicBufferConsumer> &consumer = NULL, uint32_t flags = 0); bool isVideo() const { return mIsVideo; } @@ -78,6 +81,7 @@ private: const sp<ALooper> &looper, const sp<AMessage> &outputFormat, const sp<MediaSource> &source, + const sp<IGraphicBufferConsumer> &consumer, uint32_t flags = 0); status_t onStart(MetaData *params); @@ -99,13 +103,17 @@ private: sp<Puller> mPuller; sp<MediaCodec> mEncoder; uint32_t mFlags; - List<uint32_t> mStopReplyIDQueue; + List<sp<AReplyToken>> mStopReplyIDQueue; bool mIsVideo; bool mStarted; bool mStopping; bool mDoMoreWorkPending; + bool mSetEncoderFormat; + int mEncoderFormat; + int mEncoderDataSpace; sp<AMessage> mEncoderActivityNotify; sp<IGraphicBufferProducer> mGraphicBufferProducer; + sp<IGraphicBufferConsumer> mGraphicBufferConsumer; List<MediaBuffer *> mInputBufferQueue; List<size_t> mAvailEncoderInputIndices; List<int64_t> mDecodingTimeQueue; // decoding time (us) for video diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h index a0036e0..21eb04a 100644 --- a/include/media/stagefright/MediaDefs.h +++ b/include/media/stagefright/MediaDefs.h @@ -64,6 +64,7 @@ extern const char *MEDIA_MIMETYPE_TEXT_3GPP; extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP; extern const char *MEDIA_MIMETYPE_TEXT_VTT; extern const char *MEDIA_MIMETYPE_TEXT_CEA_608; +extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3; } // namespace android diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h new file mode 100644 index 0000000..d0a572c --- /dev/null +++ b/include/media/stagefright/MediaFilter.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2014 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_FILTER_H_ +#define MEDIA_FILTER_H_ + +#include <media/stagefright/CodecBase.h> + +namespace android { + +struct ABuffer; +struct GraphicBufferListener; +struct MemoryDealer; +struct SimpleFilter; + +struct MediaFilter : public CodecBase { + MediaFilter(); + + virtual void setNotificationMessage(const sp<AMessage> &msg); + + virtual void initiateAllocateComponent(const sp<AMessage> &msg); + virtual void initiateConfigureComponent(const sp<AMessage> &msg); + virtual void initiateCreateInputSurface(); + virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface); + + virtual void initiateStart(); + virtual void initiateShutdown(bool keepComponentAllocated = false); + + virtual void signalFlush(); + virtual void signalResume(); + + virtual void signalRequestIDRFrame(); + virtual void signalSetParameters(const sp<AMessage> &msg); + virtual void signalEndOfInputStream(); + + virtual void onMessageReceived(const sp<AMessage> &msg); + + struct PortDescription : public CodecBase::PortDescription { + virtual size_t countBuffers(); + virtual IOMX::buffer_id bufferIDAt(size_t index) const; + virtual sp<ABuffer> bufferAt(size_t index) const; + + protected: + PortDescription(); + + private: + friend struct MediaFilter; + + Vector<IOMX::buffer_id> mBufferIDs; + Vector<sp<ABuffer> > mBuffers; + + void addBuffer(IOMX::buffer_id id, const sp<ABuffer> &buffer); + + DISALLOW_EVIL_CONSTRUCTORS(PortDescription); + }; + +protected: + virtual ~MediaFilter(); + +private: + struct BufferInfo { + enum Status { + OWNED_BY_US, + OWNED_BY_UPSTREAM, + }; + + IOMX::buffer_id mBufferID; + int32_t mGeneration; + int32_t mOutputFlags; + Status mStatus; + + sp<ABuffer> mData; + }; + + enum State { + UNINITIALIZED, + INITIALIZED, + CONFIGURED, + STARTED, + }; + + enum { + kWhatInputBufferFilled = 'inpF', + kWhatOutputBufferDrained = 'outD', + kWhatShutdown = 'shut', + kWhatFlush = 'flus', + kWhatResume = 'resm', + kWhatAllocateComponent = 'allo', + kWhatConfigureComponent = 'conf', + kWhatCreateInputSurface = 'cisf', + kWhatSignalEndOfInputStream = 'eois', + kWhatStart = 'star', + kWhatSetParameters = 'setP', + kWhatProcessBuffers = 'proc', + }; + + enum { + kPortIndexInput = 0, + kPortIndexOutput = 1 + }; + + // member variables + AString mComponentName; + State mState; + status_t mInputEOSResult; + int32_t mWidth, mHeight; + int32_t mStride, mSliceHeight; + int32_t mColorFormatIn, mColorFormatOut; + size_t mMaxInputSize, mMaxOutputSize; + int32_t mGeneration; + sp<AMessage> mNotify; + sp<AMessage> mInputFormat; + sp<AMessage> mOutputFormat; + + sp<MemoryDealer> mDealer[2]; + Vector<BufferInfo> mBuffers[2]; + Vector<BufferInfo*> mAvailableInputBuffers; + Vector<BufferInfo*> mAvailableOutputBuffers; + bool mPortEOS[2]; + + sp<SimpleFilter> mFilter; + sp<GraphicBufferListener> mGraphicBufferListener; + + // helper functions + void signalProcessBuffers(); + void signalError(status_t error); + + status_t allocateBuffersOnPort(OMX_U32 portIndex); + BufferInfo *findBufferByID( + uint32_t portIndex, IOMX::buffer_id bufferID, + ssize_t *index = NULL); + void postFillThisBuffer(BufferInfo *info); + void postDrainThisBuffer(BufferInfo *info); + void postEOS(); + void sendFormatChange(); + void requestFillEmptyInput(); + void processBuffers(); + + void onAllocateComponent(const sp<AMessage> &msg); + void onConfigureComponent(const sp<AMessage> &msg); + void onStart(); + void onInputBufferFilled(const sp<AMessage> &msg); + void onOutputBufferDrained(const sp<AMessage> &msg); + void onShutdown(const sp<AMessage> &msg); + void onFlush(); + void onSetParameters(const sp<AMessage> &msg); + void onCreateInputSurface(); + void onInputFrameAvailable(); + void onSignalEndOfInputStream(); + + DISALLOW_EVIL_CONSTRUCTORS(MediaFilter); +}; + +} // namespace android + +#endif // MEDIA_FILTER_H_ diff --git a/include/media/stagefright/MediaMuxer.h b/include/media/stagefright/MediaMuxer.h index 9da98d9..fa855a8 100644 --- a/include/media/stagefright/MediaMuxer.h +++ b/include/media/stagefright/MediaMuxer.h @@ -29,9 +29,9 @@ namespace android { struct ABuffer; struct AMessage; struct MediaAdapter; -struct MediaBuffer; +class MediaBuffer; struct MediaSource; -struct MetaData; +class MetaData; struct MediaWriter; // MediaMuxer is used to mux multiple tracks into a video. Currently, we only @@ -50,9 +50,6 @@ public: OUTPUT_FORMAT_LIST_END // must be last - used to validate format type }; - // Construct the muxer with the output file path. - MediaMuxer(const char *path, OutputFormat format); - // Construct the muxer with the file descriptor. Note that the MediaMuxer // will close this file at stop(). MediaMuxer(int fd, OutputFormat format); diff --git a/include/media/stagefright/MediaSync.h b/include/media/stagefright/MediaSync.h new file mode 100644 index 0000000..ef8cb23 --- /dev/null +++ b/include/media/stagefright/MediaSync.h @@ -0,0 +1,291 @@ +/* + * 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_SYNC_H +#define MEDIA_SYNC_H + +#include <gui/IConsumerListener.h> +#include <gui/IProducerListener.h> + +#include <media/AudioResamplerPublic.h> +#include <media/AVSyncSettings.h> +#include <media/stagefright/foundation/AHandler.h> + +#include <utils/Condition.h> +#include <utils/KeyedVector.h> +#include <utils/Mutex.h> + +namespace android { + +class AudioTrack; +class BufferItem; +class Fence; +class GraphicBuffer; +class IGraphicBufferConsumer; +class IGraphicBufferProducer; +struct MediaClock; +struct VideoFrameScheduler; + +// MediaSync manages media playback and its synchronization to a media clock +// source. It can be also used for video-only playback. +// +// For video playback, it requires an output surface and provides an input +// surface. It then controls the rendering of input buffers (buffer queued to +// the input surface) on the output surface to happen at the appropriate time. +// +// For audio playback, it requires an audio track and takes updates of +// information of rendered audio data to maintain media clock when audio track +// serves as media clock source. (TODO: move audio rendering from JAVA to +// native code). +// +// It can use the audio or video track as media clock source, as well as an +// external clock. (TODO: actually support external clock as media clock +// sources; use video track as media clock source for audio-and-video stream). +// +// In video-only mode, MediaSync will playback every video frame even though +// a video frame arrives late based on its timestamp and last frame's. +// +// The client needs to configure surface (for output video rendering) and audio +// track (for querying information of audio rendering) for MediaSync. +// +// Then the client needs to obtain a surface from MediaSync and render video +// frames onto that surface. Internally, the MediaSync will receive those video +// frames and render them onto the output surface at the appropriate time. +// +// The client needs to call updateQueuedAudioData() immediately after it writes +// audio data to the audio track. Such information will be used to update media +// clock. +// +class MediaSync : public AHandler { +public: + // Create an instance of MediaSync. + static sp<MediaSync> create(); + + // Called when MediaSync is used to render video. It should be called + // before createInputSurface(). + status_t setSurface(const sp<IGraphicBufferProducer> &output); + + // Called when audio track is used as media clock source. It should be + // called before updateQueuedAudioData(). + status_t setAudioTrack(const sp<AudioTrack> &audioTrack); + + // Create a surface for client to render video frames. This is the surface + // on which the client should render video frames. Those video frames will + // be internally directed to output surface for rendering at appropriate + // time. + status_t createInputSurface(sp<IGraphicBufferProducer> *outBufferProducer); + + // Update just-rendered audio data size and the presentation timestamp of + // the first frame of that audio data. It should be called immediately + // after the client write audio data into AudioTrack. + // This function assumes continous audio stream. + // TODO: support gap or backwards updates. + status_t updateQueuedAudioData( + size_t sizeInBytes, int64_t presentationTimeUs); + + // Set the consumer name of the input queue. + void setName(const AString &name); + + // Get the media clock used by the MediaSync so that the client can obtain + // corresponding media time or real time via + // MediaClock::getMediaTime() and MediaClock::getRealTimeFor(). + sp<const MediaClock> getMediaClock(); + + // Flush mediasync + void flush(); + + // Set the video frame rate hint - this is used by the video FrameScheduler + status_t setVideoFrameRateHint(float rate); + + // Get the video frame rate measurement from the FrameScheduler + // returns -1 if there is no measurement + float getVideoFrameRate(); + + // Set the sync settings parameters. + status_t setSyncSettings(const AVSyncSettings &syncSettings); + + // Gets the sync settings parameters. + void getSyncSettings(AVSyncSettings *syncSettings /* nonnull */); + + // Sets the playback rate using playback settings. + // This method can be called any time. + status_t setPlaybackSettings(const AudioPlaybackRate &rate); + + // Gets the playback rate (playback settings parameters). + void getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */); + + // Get the play time for pending audio frames in audio sink. + status_t getPlayTimeForPendingAudioFrames(int64_t *outTimeUs); + +protected: + virtual void onMessageReceived(const sp<AMessage> &msg); + +private: + enum { + kWhatDrainVideo = 'dVid', + }; + + // This is a thin wrapper class that lets us listen to + // IConsumerListener::onFrameAvailable from mInput. + class InputListener : public BnConsumerListener, + public IBinder::DeathRecipient { + public: + InputListener(const sp<MediaSync> &sync); + virtual ~InputListener(); + + // From IConsumerListener + virtual void onFrameAvailable(const BufferItem &item); + + // From IConsumerListener + // We don't care about released buffers because we detach each buffer as + // soon as we acquire it. See the comment for onBufferReleased below for + // some clarifying notes about the name. + virtual void onBuffersReleased() {} + + // From IConsumerListener + // We don't care about sideband streams, since we won't relay them. + virtual void onSidebandStreamChanged(); + + // From IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder> &who); + + private: + sp<MediaSync> mSync; + }; + + // This is a thin wrapper class that lets us listen to + // IProducerListener::onBufferReleased from mOutput. + class OutputListener : public BnProducerListener, + public IBinder::DeathRecipient { + public: + OutputListener(const sp<MediaSync> &sync, const sp<IGraphicBufferProducer> &output); + virtual ~OutputListener(); + + // From IProducerListener + virtual void onBufferReleased(); + + // From IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder> &who); + + private: + sp<MediaSync> mSync; + sp<IGraphicBufferProducer> mOutput; + }; + + // mIsAbandoned is set to true when the input or output dies. + // Once the MediaSync has been abandoned by one side, it will disconnect + // from the other side and not attempt to communicate with it further. + bool mIsAbandoned; + + mutable Mutex mMutex; + Condition mReleaseCondition; + size_t mNumOutstandingBuffers; + sp<IGraphicBufferConsumer> mInput; + sp<IGraphicBufferProducer> mOutput; + int mUsageFlagsFromOutput; + uint32_t mMaxAcquiredBufferCount; // max acquired buffer count + bool mReturnPendingInputFrame; // set while we are pending before acquiring an input frame + + sp<AudioTrack> mAudioTrack; + uint32_t mNativeSampleRateInHz; + int64_t mNumFramesWritten; + bool mHasAudio; + + int64_t mNextBufferItemMediaUs; + List<BufferItem> mBufferItems; + sp<VideoFrameScheduler> mFrameScheduler; + + // Keep track of buffers received from |mInput|. This is needed because + // it's possible the consumer of |mOutput| could return a different + // GraphicBuffer::handle (e.g., due to passing buffers through IPC), + // and that could cause problem if the producer of |mInput| only + // supports pre-registered buffers. + KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersFromInput; + + // Keep track of buffers sent to |mOutput|. When a new output surface comes + // in, those buffers will be returned to input and old output surface will + // be disconnected immediately. + KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersSentToOutput; + + sp<ALooper> mLooper; + float mPlaybackRate; + + AudioPlaybackRate mPlaybackSettings; + AVSyncSettings mSyncSettings; + + sp<MediaClock> mMediaClock; + + MediaSync(); + + // Must be accessed through RefBase + virtual ~MediaSync(); + + int64_t getRealTime(int64_t mediaTimeUs, int64_t nowUs); + int64_t getDurationIfPlayedAtNativeSampleRate_l(int64_t numFrames); + int64_t getPlayedOutAudioDurationMedia_l(int64_t nowUs); + + void onDrainVideo_l(); + + // This implements the onFrameAvailable callback from IConsumerListener. + // It gets called from an InputListener. + // During this callback, we detach the buffer from the input, and queue + // it for rendering on the output. This call can block if there are too + // many outstanding buffers. If it blocks, it will resume when + // onBufferReleasedByOutput releases a buffer back to the input. + void onFrameAvailableFromInput(); + + // Send |bufferItem| to the output for rendering. + void renderOneBufferItem_l(const BufferItem &bufferItem); + + // This implements the onBufferReleased callback from IProducerListener. + // It gets called from an OutputListener. + // During this callback, we detach the buffer from the output, and release + // it to the input. A blocked onFrameAvailable call will be allowed to proceed. + void onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output); + + // Return |buffer| back to the input. + void returnBufferToInput_l(const sp<GraphicBuffer> &buffer, const sp<Fence> &fence); + + // When this is called, the MediaSync disconnects from (i.e., abandons) its + // input or output, and signals any waiting onFrameAvailable calls to wake + // up. This must be called with mMutex locked. + void onAbandoned_l(bool isInput); + + // Set the playback in a desired speed. + // This method can be called any time. + // |rate| is the ratio between desired speed and the normal one, and should + // be non-negative. The meaning of rate values: + // 1.0 -- normal playback + // 0.0 -- stop or pause + // larger than 1.0 -- faster than normal speed + // between 0.0 and 1.0 -- slower than normal speed + void updatePlaybackRate_l(float rate); + + // apply new sync settings + void resync_l(); + + // apply playback settings only - without resyncing or updating playback rate + status_t setPlaybackSettings_l(const AudioPlaybackRate &rate); + + // helper. + bool isPlaying() { return mPlaybackRate != 0.0; } + + DISALLOW_EVIL_CONSTRUCTORS(MediaSync); +}; + +} // namespace android + +#endif diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h index e27ea1d..8e02506 100644 --- a/include/media/stagefright/MediaWriter.h +++ b/include/media/stagefright/MediaWriter.h @@ -24,7 +24,7 @@ namespace android { struct MediaSource; -struct MetaData; +class MetaData; struct MediaWriter : public RefBase { MediaWriter() diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h index 3f42790..8d4e15a 100644 --- a/include/media/stagefright/MetaData.h +++ b/include/media/stagefright/MetaData.h @@ -70,11 +70,15 @@ enum { kKeyDriftTime = 'dftT', // int64_t (usecs) kKeyAnchorTime = 'ancT', // int64_t (usecs) kKeyDuration = 'dura', // int64_t (usecs) - kKeyColorFormat = 'colf', + kKeyPixelFormat = 'pixf', // int32_t + kKeyColorFormat = 'colf', // int32_t + kKeyColorSpace = 'cols', // int32_t kKeyPlatformPrivate = 'priv', // pointer kKeyDecoderComponent = 'decC', // cstring kKeyBufferID = 'bfID', kKeyMaxInputSize = 'inpS', + kKeyMaxWidth = 'maxW', + kKeyMaxHeight = 'maxH', kKeyThumbnailTime = 'thbT', // int64_t (usecs) kKeyTrackID = 'trID', kKeyIsDRM = 'idrm', // int32_t (bool) @@ -98,6 +102,7 @@ enum { kKeyCompilation = 'cpil', // cstring kKeyLocation = 'loc ', // cstring kKeyTimeScale = 'tmsl', // int32_t + kKeyCaptureFramerate = 'capF', // float (capture fps) // video profile and level kKeyVideoProfile = 'vprf', // int32_t @@ -173,6 +178,9 @@ enum { kKeyTrackIsDefault = 'dflt', // bool (int32_t) // Similar to MediaFormat.KEY_IS_FORCED_SUBTITLE but pertains to av tracks as well. kKeyTrackIsForced = 'frcd', // bool (int32_t) + + // H264 supplemental enhancement information offsets/sizes + kKeySEI = 'sei ', // raw data }; enum { diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h deleted file mode 100644 index cfeec22..0000000 --- a/include/media/stagefright/NativeWindowWrapper.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2011 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 NATIVE_WINDOW_WRAPPER_H_ - -#define NATIVE_WINDOW_WRAPPER_H_ - -#include <gui/Surface.h> - -namespace android { - -// Surface derives from ANativeWindow which derives from multiple -// base classes, in order to carry it in AMessages, we'll temporarily wrap it -// into a NativeWindowWrapper. - -struct NativeWindowWrapper : RefBase { - NativeWindowWrapper( - const sp<Surface> &surfaceTextureClient) : - mSurfaceTextureClient(surfaceTextureClient) { } - - sp<ANativeWindow> getNativeWindow() const { - return mSurfaceTextureClient; - } - - sp<Surface> getSurfaceTextureClient() const { - return mSurfaceTextureClient; - } - -private: - const sp<Surface> mSurfaceTextureClient; - - DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper); -}; - -} // namespace android - -#endif // NATIVE_WINDOW_WRAPPER_H_ diff --git a/include/media/stagefright/NuMediaExtractor.h b/include/media/stagefright/NuMediaExtractor.h index 402e7f8..fd74452 100644 --- a/include/media/stagefright/NuMediaExtractor.h +++ b/include/media/stagefright/NuMediaExtractor.h @@ -30,12 +30,12 @@ namespace android { struct ABuffer; struct AMessage; -struct DataSource; +class DataSource; struct IMediaHTTPService; -struct MediaBuffer; +class MediaBuffer; struct MediaExtractor; struct MediaSource; -struct MetaData; +class MetaData; struct NuMediaExtractor : public RefBase { enum SampleFlags { diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h index 84b1b1a..7fabcb3 100644 --- a/include/media/stagefright/OMXCodec.h +++ b/include/media/stagefright/OMXCodec.h @@ -298,7 +298,6 @@ private: status_t queueBufferToNativeWindow(BufferInfo *info); status_t cancelBufferToNativeWindow(BufferInfo *info); BufferInfo* dequeueBufferFromNativeWindow(); - status_t pushBlankBuffersToNativeWindow(); status_t freeBuffersOnPort( OMX_U32 portIndex, bool onlyThoseWeOwn = false); @@ -347,7 +346,6 @@ private: status_t configureCodec(const sp<MetaData> &meta); - status_t applyRotation(); status_t waitForBufferFilled_l(); int64_t getDecodingTimeUs(); diff --git a/include/media/stagefright/PersistentSurface.h b/include/media/stagefright/PersistentSurface.h new file mode 100644 index 0000000..a35b9f1 --- /dev/null +++ b/include/media/stagefright/PersistentSurface.h @@ -0,0 +1,51 @@ +/* + * 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 PERSISTENT_SURFACE_H_ + +#define PERSISTENT_SURFACE_H_ + +#include <gui/IGraphicBufferProducer.h> +#include <gui/IGraphicBufferConsumer.h> +#include <media/stagefright/foundation/ABase.h> + +namespace android { + +struct PersistentSurface : public RefBase { + PersistentSurface( + const sp<IGraphicBufferProducer>& bufferProducer, + const sp<IGraphicBufferConsumer>& bufferConsumer) : + mBufferProducer(bufferProducer), + mBufferConsumer(bufferConsumer) { } + + sp<IGraphicBufferProducer> getBufferProducer() const { + return mBufferProducer; + } + + sp<IGraphicBufferConsumer> getBufferConsumer() const { + return mBufferConsumer; + } + +private: + const sp<IGraphicBufferProducer> mBufferProducer; + const sp<IGraphicBufferConsumer> mBufferConsumer; + + DISALLOW_EVIL_CONSTRUCTORS(PersistentSurface); +}; + +} // namespace android + +#endif // PERSISTENT_SURFACE_H_ diff --git a/include/media/stagefright/ProcessInfo.h b/include/media/stagefright/ProcessInfo.h new file mode 100644 index 0000000..ec0cdff --- /dev/null +++ b/include/media/stagefright/ProcessInfo.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 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 PROCESS_INFO_H_ + +#define PROCESS_INFO_H_ + +#include <media/stagefright/foundation/ABase.h> +#include <media/stagefright/ProcessInfoInterface.h> + +namespace android { + +struct ProcessInfo : public ProcessInfoInterface { + ProcessInfo(); + + virtual bool getPriority(int pid, int* priority); + +protected: + virtual ~ProcessInfo(); + +private: + DISALLOW_EVIL_CONSTRUCTORS(ProcessInfo); +}; + +} // namespace android + +#endif // PROCESS_INFO_H_ diff --git a/include/media/nbaio/roundup.h b/include/media/stagefright/ProcessInfoInterface.h index 4c3cc25..222f92d 100644 --- a/include/media/nbaio/roundup.h +++ b/include/media/stagefright/ProcessInfoInterface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 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. @@ -14,18 +14,20 @@ * limitations under the License. */ -#ifndef ROUNDUP_H -#define ROUNDUP_H +#ifndef PROCESS_INFO_INTERFACE_H_ +#define PROCESS_INFO_INTERFACE_H_ -#ifdef __cplusplus -extern "C" { -#endif +#include <utils/RefBase.h> -// Round up to the next highest power of 2 -unsigned roundup(unsigned v); +namespace android { -#ifdef __cplusplus -} -#endif +struct ProcessInfoInterface : public RefBase { + virtual bool getPriority(int pid, int* priority) = 0; -#endif // ROUNDUP_H +protected: + virtual ~ProcessInfoInterface() {} +}; + +} // namespace android + +#endif // PROCESS_INFO_INTERFACE_H_ diff --git a/include/media/stagefright/RenderScriptWrapper.h b/include/media/stagefright/RenderScriptWrapper.h new file mode 100644 index 0000000..b42649e --- /dev/null +++ b/include/media/stagefright/RenderScriptWrapper.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 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 RENDERSCRIPT_WRAPPER_H_ +#define RENDERSCRIPT_WRAPPER_H_ + +#include <RenderScript.h> + +namespace android { + +struct RenderScriptWrapper : public RefBase { +public: + struct RSFilterCallback : public RefBase { + public: + // called by RSFilter to process each input buffer + virtual status_t processBuffers( + RSC::Allocation* inBuffer, + RSC::Allocation* outBuffer) = 0; + + virtual status_t handleSetParameters(const sp<AMessage> &msg) = 0; + }; + + sp<RSFilterCallback> mCallback; + RSC::sp<RSC::RS> mContext; +}; + +} // namespace android + +#endif // RENDERSCRIPT_WRAPPER_H_ diff --git a/include/media/stagefright/SurfaceUtils.h b/include/media/stagefright/SurfaceUtils.h new file mode 100644 index 0000000..c1a9c0a --- /dev/null +++ b/include/media/stagefright/SurfaceUtils.h @@ -0,0 +1,34 @@ +/* + * 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 SURFACE_UTILS_H_ + +#define SURFACE_UTILS_H_ + +#include <utils/Errors.h> + +struct ANativeWindow; + +namespace android { + +status_t setNativeWindowSizeFormatAndUsage( + ANativeWindow *nativeWindow /* nonnull */, + int width, int height, int format, int rotation, int usage); +status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */); + +} // namespace android + +#endif // SURFACE_UTILS_H_ diff --git a/include/media/stagefright/Utils.h b/include/media/stagefright/Utils.h index a795c80..5e9d7d4 100644 --- a/include/media/stagefright/Utils.h +++ b/include/media/stagefright/Utils.h @@ -41,7 +41,7 @@ uint64_t U64LE_AT(const uint8_t *ptr); uint64_t ntoh64(uint64_t x); uint64_t hton64(uint64_t x); -struct MetaData; +class MetaData; struct AMessage; status_t convertMetaDataToMessage( const sp<MetaData> &meta, sp<AMessage> *format); @@ -65,6 +65,26 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, AString uriDebugString(const AString &uri, bool incognito = false); +struct HLSTime { + int32_t mSeq; + int64_t mTimeUs; + sp<AMessage> mMeta; + + HLSTime(const sp<AMessage> &meta = NULL); + int64_t getSegmentTimeUs() const; +}; + +bool operator <(const HLSTime &t0, const HLSTime &t1); + +// read and write various object to/from AMessage + +void writeToAMessage(sp<AMessage> msg, const AudioPlaybackRate &rate); +void readFromAMessage(const sp<AMessage> &msg, AudioPlaybackRate *rate /* nonnull */); + +void writeToAMessage(sp<AMessage> msg, const AVSyncSettings &sync, float videoFpsHint); +void readFromAMessage( + const sp<AMessage> &msg, AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */); + } // namespace android #endif // UTILS_H_ diff --git a/include/media/stagefright/VideoFrameScheduler.h b/include/media/stagefright/VideoFrameScheduler.h new file mode 100644 index 0000000..9d97dfd --- /dev/null +++ b/include/media/stagefright/VideoFrameScheduler.h @@ -0,0 +1,103 @@ +/* + * Copyright 2014, 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 VIDEO_FRAME_SCHEDULER_H_ +#define VIDEO_FRAME_SCHEDULER_H_ + +#include <utils/RefBase.h> +#include <utils/Timers.h> + +#include <media/stagefright/foundation/ABase.h> + +namespace android { + +class ISurfaceComposer; + +struct VideoFrameScheduler : public RefBase { + VideoFrameScheduler(); + + // (re)initialize scheduler + void init(float videoFps = -1); + // use in case of video render-time discontinuity, e.g. seek + void restart(); + // get adjusted nanotime for a video frame render at renderTime + nsecs_t schedule(nsecs_t renderTime); + + // returns the vsync period for the main display + nsecs_t getVsyncPeriod(); + + // returns the current frames-per-second, or 0.f if not primed + float getFrameRate(); + + void release(); + + static const size_t kHistorySize = 8; + +protected: + virtual ~VideoFrameScheduler(); + +private: + struct PLL { + PLL(); + + // reset PLL to new PLL + void reset(float fps = -1); + // keep current estimate, but restart phase + void restart(); + // returns period or 0 if not yet primed + nsecs_t addSample(nsecs_t time); + nsecs_t getPeriod() const; + + private: + nsecs_t mPeriod; + nsecs_t mPhase; + + bool mPrimed; // have an estimate for the period + size_t mSamplesUsedForPriming; + + nsecs_t mLastTime; // last input time + nsecs_t mRefitAt; // next input time to fit at + + size_t mNumSamples; // can go past kHistorySize + nsecs_t mTimes[kHistorySize]; + + void test(); + // returns whether fit was successful + bool fit(nsecs_t phase, nsecs_t period, size_t numSamples, + int64_t *a, int64_t *b, int64_t *err); + void prime(size_t numSamples); + }; + + void updateVsync(); + + nsecs_t mVsyncTime; // vsync timing from display + nsecs_t mVsyncPeriod; + nsecs_t mVsyncRefreshAt; // next time to refresh timing info + + nsecs_t mLastVsyncTime; // estimated vsync time for last frame + nsecs_t mTimeCorrection; // running adjustment + + PLL mPll; // PLL for video frame rate based on render time + + sp<ISurfaceComposer> mComposer; + + DISALLOW_EVIL_CONSTRUCTORS(VideoFrameScheduler); +}; + +} // namespace android + +#endif // VIDEO_FRAME_SCHEDULER_H_ + diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h index 72e3d87..ef1e010 100644 --- a/include/media/stagefright/foundation/ABase.h +++ b/include/media/stagefright/foundation/ABase.h @@ -18,7 +18,9 @@ #define A_BASE_H_ +#ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) +#endif #define DISALLOW_EVIL_CONSTRUCTORS(name) \ name(const name &); \ diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h index 1d0e2cb..65f415a 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 @@ -92,7 +117,7 @@ struct ADebug { }; - // parse the property or string to get the debug level for a component name + // parse the property or string to get a long-type level for a component name // string format is: // <level>[:<glob>][,<level>[:<glob>]...] // - <level> is 0-5 corresponding to ADebug::Level @@ -100,14 +125,38 @@ struct ADebug { // matches all components // - string is read left-to-right, and the last matching level is returned, or // the def if no terms matched + static long GetLevelFromSettingsString( + const char *name, const char *value, long def); + static long GetLevelFromProperty( + const char *name, const char *value, long def); + + // same for ADebug::Level - performs clamping to valid debug ranges static Level GetDebugLevelFromProperty( const char *name, const char *propertyName, Level def = kDebugNone); - static Level GetDebugLevelFromString( - const char *name, const char *value, Level def = kDebugNone); // remove redundant segments of a codec name, and return a newly allocated // string suitable for debugging static char *GetDebugName(const char *name); + + inline static bool isExperimentEnabled( + const char *name __unused /* nonnull */, bool allow __unused = true) { +#ifdef ENABLE_STAGEFRIGHT_EXPERIMENTS + if (!strcmp(name, "legacy-adaptive")) { + return getExperimentFlag(allow, name, 2, 1); // every other day + } else if (!strcmp(name, "legacy-setsurface")) { + return getExperimentFlag(allow, name, 3, 1); // every third day + } else { + ALOGE("unknown experiment '%s' (disabled)", name); + } +#endif + return false; + } + +private: + // pass in allow, so we can print in the log if the experiment is disabled + static bool getExperimentFlag( + bool allow, const char *name, uint64_t modulo, uint64_t limit, + uint64_t plus = 0, uint64_t timeDivisor = 24 * 60 * 60 /* 1 day */); }; } // namespace android diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h index 41ade77..fe02a86 100644 --- a/include/media/stagefright/foundation/AHandler.h +++ b/include/media/stagefright/foundation/AHandler.h @@ -29,6 +29,7 @@ struct AMessage; struct AHandler : public RefBase { AHandler() : mID(0), + mVerboseStats(false), mMessageCounter(0) { } @@ -36,23 +37,40 @@ struct AHandler : public RefBase { return mID; } - sp<ALooper> looper(); + sp<ALooper> looper() const { + return mLooper.promote(); + } + + wp<ALooper> getLooper() const { + return mLooper; + } + + wp<AHandler> getHandler() const { + // allow getting a weak reference to a const handler + return const_cast<AHandler *>(this); + } protected: virtual void onMessageReceived(const sp<AMessage> &msg) = 0; private: - friend struct ALooperRoster; + friend struct AMessage; // deliverMessage() + friend struct ALooperRoster; // setID() ALooper::handler_id mID; + wp<ALooper> mLooper; - void setID(ALooper::handler_id id) { + inline void setID(ALooper::handler_id id, wp<ALooper> looper) { mID = id; + mLooper = looper; } + bool mVerboseStats; uint32_t mMessageCounter; KeyedVector<uint32_t, uint32_t> mMessages; + void deliverMessage(const sp<AMessage> &msg); + DISALLOW_EVIL_CONSTRUCTORS(AHandler); }; diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h index 70e0c5e..09c469b 100644 --- a/include/media/stagefright/foundation/ALooper.h +++ b/include/media/stagefright/foundation/ALooper.h @@ -30,6 +30,7 @@ namespace android { struct AHandler; struct AMessage; +struct AReplyToken; struct ALooper : public RefBase { typedef int32_t event_id; @@ -53,11 +54,15 @@ struct ALooper : public RefBase { static int64_t GetNowUs(); + const char *getName() const { + return mName.c_str(); + } + protected: virtual ~ALooper(); private: - friend struct ALooperRoster; + friend struct AMessage; // post() struct Event { int64_t mWhenUs; @@ -75,12 +80,32 @@ private: sp<LooperThread> mThread; bool mRunningLocally; + // use a separate lock for reply handling, as it is always on another thread + // use a central lock, however, to avoid creating a mutex for each reply + Mutex mRepliesLock; + Condition mRepliesCondition; + + // START --- methods used only by AMessage + + // posts a message on this looper with the given timeout void post(const sp<AMessage> &msg, int64_t delayUs); + + // creates a reply token to be used with this looper + sp<AReplyToken> createReplyToken(); + // waits for a response for the reply token. If status is OK, the response + // is stored into the supplied variable. Otherwise, it is unchanged. + status_t awaitResponse(const sp<AReplyToken> &replyToken, sp<AMessage> *response); + // posts a reply for a reply token. If the reply could be successfully posted, + // it returns OK. Otherwise, it returns an error value. + status_t postReply(const sp<AReplyToken> &replyToken, const sp<AMessage> &msg); + + // END --- methods used only by AMessage + bool loop(); DISALLOW_EVIL_CONSTRUCTORS(ALooper); }; -} // namespace android +} // namespace android #endif // A_LOOPER_H_ diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h index a0be8eb..9912455 100644 --- a/include/media/stagefright/foundation/ALooperRoster.h +++ b/include/media/stagefright/foundation/ALooperRoster.h @@ -33,16 +33,6 @@ struct ALooperRoster { void unregisterHandler(ALooper::handler_id handlerID); void unregisterStaleHandlers(); - status_t postMessage(const sp<AMessage> &msg, int64_t delayUs = 0); - void deliverMessage(const sp<AMessage> &msg); - - status_t postAndAwaitResponse( - const sp<AMessage> &msg, sp<AMessage> *response); - - void postReply(uint32_t replyID, const sp<AMessage> &reply); - - sp<ALooper> findLooper(ALooper::handler_id handlerID); - void dump(int fd, const Vector<String16>& args); private: @@ -54,10 +44,6 @@ private: Mutex mLock; KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers; ALooper::handler_id mNextHandlerID; - uint32_t mNextReplyID; - Condition mRepliesCondition; - - KeyedVector<uint32_t, sp<AMessage> > mReplies; DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster); }; diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h index a9e235b..83b9444 100644 --- a/include/media/stagefright/foundation/AMessage.h +++ b/include/media/stagefright/foundation/AMessage.h @@ -26,11 +26,41 @@ namespace android { struct ABuffer; +struct AHandler; struct AString; -struct Parcel; +class Parcel; + +struct AReplyToken : public RefBase { + AReplyToken(const sp<ALooper> &looper) + : mLooper(looper), + mReplied(false) { + } + +private: + friend struct AMessage; + friend struct ALooper; + wp<ALooper> mLooper; + sp<AMessage> mReply; + bool mReplied; + + sp<ALooper> getLooper() const { + return mLooper.promote(); + } + // if reply is not set, returns false; otherwise, it retrieves the reply and returns true + bool retrieveReply(sp<AMessage> *reply) { + if (mReplied) { + *reply = mReply; + mReply.clear(); + } + return mReplied; + } + // sets the reply for this token. returns OK or error + status_t setReply(const sp<AMessage> &reply); +}; struct AMessage : public RefBase { - AMessage(uint32_t what = 0, ALooper::handler_id target = 0); + AMessage(); + AMessage(uint32_t what, const sp<const AHandler> &handler); static sp<AMessage> FromParcel(const Parcel &parcel); void writeToParcel(Parcel *parcel) const; @@ -38,8 +68,7 @@ struct AMessage : public RefBase { void setWhat(uint32_t what); uint32_t what() const; - void setTarget(ALooper::handler_id target); - ALooper::handler_id target() const; + void setTarget(const sp<const AHandler> &handler); void clear(); @@ -76,18 +105,22 @@ struct AMessage : public RefBase { const char *name, int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) const; - void post(int64_t delayUs = 0); + status_t post(int64_t delayUs = 0); // Posts the message to its target and waits for a response (or error) // before returning. status_t postAndAwaitResponse(sp<AMessage> *response); // If this returns true, the sender of this message is synchronously - // awaiting a response, the "replyID" can be used to send the response - // via "postReply" below. - bool senderAwaitsResponse(uint32_t *replyID) const; + // awaiting a response and the reply token is consumed from the message + // and stored into replyID. The reply token must be used to send the response + // using "postReply" below. + bool senderAwaitsResponse(sp<AReplyToken> *replyID); - void postReply(uint32_t replyID); + // Posts the message as a response to a reply token. A reply token can + // only be used once. Returns OK if the response could be posted; otherwise, + // an error. + status_t postReply(const sp<AReplyToken> &replyID); // Performs a deep-copy of "this", contained messages are in turn "dup'ed". // Warning: RefBase items, i.e. "objects" are _not_ copied but only have @@ -117,9 +150,16 @@ protected: virtual ~AMessage(); private: + friend struct ALooper; // deliver() + uint32_t mWhat; + + // used only for debugging ALooper::handler_id mTarget; + wp<AHandler> mHandler; + wp<ALooper> mLooper; + struct Rect { int32_t mLeft, mTop, mRight, mBottom; }; @@ -157,6 +197,8 @@ private: size_t findItemIndex(const char *name, size_t len) const; + void deliver(); + DISALLOW_EVIL_CONSTRUCTORS(AMessage); }; diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h index 822dbb3..2f6d532 100644 --- a/include/media/stagefright/foundation/AString.h +++ b/include/media/stagefright/foundation/AString.h @@ -24,7 +24,7 @@ namespace android { class String8; -struct Parcel; +class Parcel; struct AString { AString(); diff --git a/include/media/stagefright/timedtext/TimedTextDriver.h b/include/media/stagefright/timedtext/TimedTextDriver.h index 37ef674..6f7c693 100644 --- a/include/media/stagefright/timedtext/TimedTextDriver.h +++ b/include/media/stagefright/timedtext/TimedTextDriver.h @@ -24,7 +24,7 @@ namespace android { -class ALooper; +struct ALooper; struct IMediaHTTPService; class MediaPlayerBase; class MediaSource; diff --git a/include/ndk/NdkMediaCodec.h b/include/ndk/NdkMediaCodec.h index c07f4c9..4f6a1ef 100644 --- a/include/ndk/NdkMediaCodec.h +++ b/include/ndk/NdkMediaCodec.h @@ -142,7 +142,8 @@ media_status_t AMediaCodec_queueSecureInputBuffer(AMediaCodec*, /** * Get the index of the next available buffer of processed data. */ -ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info, int64_t timeoutUs); +ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec*, AMediaCodecBufferInfo *info, + int64_t timeoutUs); AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec*); /** diff --git a/include/ndk/NdkMediaExtractor.h b/include/ndk/NdkMediaExtractor.h index 7a4e702..7324d31 100644 --- a/include/ndk/NdkMediaExtractor.h +++ b/include/ndk/NdkMediaExtractor.h @@ -55,12 +55,14 @@ media_status_t AMediaExtractor_delete(AMediaExtractor*); /** * Set the file descriptor from which the extractor will read. */ -media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor*, int fd, off64_t offset, off64_t length); +media_status_t AMediaExtractor_setDataSourceFd(AMediaExtractor*, int fd, off64_t offset, + off64_t length); /** * Set the URI from which the extractor will read. */ -media_status_t AMediaExtractor_setDataSource(AMediaExtractor*, const char *location); // TODO support headers +media_status_t AMediaExtractor_setDataSource(AMediaExtractor*, const char *location); + // TODO support headers /** * Return the number of tracks in the previously specified media file diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 31dff36..1e5064f 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -24,9 +24,9 @@ #include <utils/threads.h> #include <utils/Log.h> #include <utils/RefBase.h> -#include <media/nbaio/roundup.h> +#include <audio_utils/roundup.h> +#include <media/AudioResamplerPublic.h> #include <media/SingleStateQueue.h> -#include <private/media/StaticAudioTrackState.h> namespace android { @@ -54,24 +54,68 @@ namespace android { struct AudioTrackSharedStreaming { // similar to NBAIO MonoPipe // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2 - volatile int32_t mFront; // read by server - volatile int32_t mRear; // write by client + volatile int32_t mFront; // read by consumer (output: server, input: client) + volatile int32_t mRear; // written by producer (output: client, input: server) volatile int32_t mFlush; // incremented by client to indicate a request to flush; // server notices and discards all data between mFront and mRear volatile uint32_t mUnderrunFrames; // server increments for each unavailable but desired frame }; +// Represents a single state of an AudioTrack that was created in static mode (shared memory buffer +// supplied by the client). This state needs to be communicated from the client to server. As this +// state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the +// state is wrapped by a SingleStateQueue. +struct StaticAudioTrackState { + // Do not define constructors, destructors, or virtual methods as this is part of a + // union in shared memory and they will not get called properly. + + // These fields should both be size_t, but since they are located in shared memory we + // force to 32-bit. The client and server may have different typedefs for size_t. + + // The state has a sequence counter to indicate whether changes are made to loop or position. + // The sequence counter also currently indicates whether loop or position is first depending + // on which is greater; it jumps by max(mLoopSequence, mPositionSequence) + 1. + + uint32_t mLoopStart; + uint32_t mLoopEnd; + int32_t mLoopCount; + uint32_t mLoopSequence; // a sequence counter to indicate changes to loop + uint32_t mPosition; + uint32_t mPositionSequence; // a sequence counter to indicate changes to position +}; + typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue; +struct StaticAudioTrackPosLoop { + // Do not define constructors, destructors, or virtual methods as this is part of a + // union in shared memory and will not get called properly. + + // These fields should both be size_t, but since they are located in shared memory we + // force to 32-bit. The client and server may have different typedefs for size_t. + + // This struct information is stored in a single state queue to communicate the + // static AudioTrack server state to the client while data is consumed. + // It is smaller than StaticAudioTrackState to prevent unnecessary information from + // being sent. + + uint32_t mBufferPosition; + int32_t mLoopCount; +}; + +typedef SingleStateQueue<StaticAudioTrackPosLoop> StaticAudioTrackPosLoopQueue; + struct AudioTrackSharedStatic { + // client requests to the server for loop or position changes. StaticAudioTrackSingleStateQueue::Shared mSingleStateQueue; - // This field should be a size_t, but since it is located in shared memory we - // force to 32-bit. The client and server may have different typedefs for size_t. - uint32_t mBufferPosition; // updated asynchronously by server, - // "for entertainment purposes only" + // position info updated asynchronously by server and read by client, + // "for entertainment purposes only" + StaticAudioTrackPosLoopQueue::Shared + mPosLoopQueue; }; +typedef SingleStateQueue<AudioPlaybackRate> PlaybackRateQueue; + // ---------------------------------------------------------------------------- // Important: do not add any virtual methods, including ~ @@ -96,7 +140,8 @@ struct audio_track_cblk_t uint32_t mServer; // Number of filled frames consumed by server (mIsOut), // or filled frames provided by server (!mIsOut). // It is updated asynchronously by server without a barrier. - // The value should be used "for entertainment purposes only", + // The value should be used + // "for entertainment purposes only", // which means don't make important decisions based on it. uint32_t mPad1; // unused @@ -117,6 +162,8 @@ private: uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz // or 0 == default. Write-only client, read-only server. + PlaybackRateQueue::Shared mPlaybackRateQueue; + // client write-only, server read-only uint16_t mSendLevel; // Fixed point U4.12 so 0x1000 means 1.0 @@ -271,7 +318,8 @@ public: AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false) : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, - clientInServer) { } + clientInServer), + mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { } virtual ~AudioTrackClientProxy() { } // No barriers on the following operations, so the ordering of loads/stores @@ -291,6 +339,10 @@ public: mCblk->mSampleRate = sampleRate; } + void setPlaybackRate(const AudioPlaybackRate& playbackRate) { + mPlaybackRateMutator.push(playbackRate); + } + virtual void flush(); virtual uint32_t getUnderrunFrames() const { @@ -302,6 +354,9 @@ public: bool getStreamEndDone() const; status_t waitStreamEndDone(const struct timespec *requested); + +private: + PlaybackRateQueue::Mutator mPlaybackRateMutator; }; class StaticAudioTrackClientProxy : public AudioTrackClientProxy { @@ -313,8 +368,28 @@ public: virtual void flush(); #define MIN_LOOP 16 // minimum length of each loop iteration in frames + + // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the + // static buffer position and looping parameters. These commands are not + // synchronous (they do not wait or block); instead they take effect at the + // next buffer data read from the server side. However, the client side + // getters will read a cached version of the position and loop variables + // until the setting takes effect. + // + // setBufferPositionAndLoop() is equivalent to calling, in order, setLoop() and + // setBufferPosition(). + // + // The functions should not be relied upon to do parameter or state checking. + // That is done at the AudioTrack level. + void setLoop(size_t loopStart, size_t loopEnd, int loopCount); + void setBufferPosition(size_t position); + void setBufferPositionAndLoop(size_t position, size_t loopStart, size_t loopEnd, + int loopCount); size_t getBufferPosition(); + // getBufferPositionAndLoopCount() provides the proper snapshot of + // position and loopCount together. + void getBufferPositionAndLoopCount(size_t *position, int *loopCount); virtual size_t getMisalignment() { return 0; @@ -326,7 +401,9 @@ public: private: StaticAudioTrackSingleStateQueue::Mutator mMutator; - size_t mBufferPosition; // so that getBufferPosition() appears to be synchronous + StaticAudioTrackPosLoopQueue::Observer mPosLoopObserver; + StaticAudioTrackState mState; // last communicated state to server + StaticAudioTrackPosLoop mPosLoop; // snapshot of position and loop. }; // ---------------------------------------------------------------------------- @@ -394,8 +471,10 @@ class AudioTrackServerProxy : public ServerProxy { public: AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool clientInServer = false, uint32_t sampleRate = 0) - : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { + : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer), + mPlaybackRateObserver(&cblk->mPlaybackRateQueue) { mCblk->mSampleRate = sampleRate; + mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT; } protected: virtual ~AudioTrackServerProxy() { } @@ -429,6 +508,13 @@ public: // Return the total number of frames that AudioFlinger has obtained and released virtual size_t framesReleased() const { return mCblk->mServer; } + + // Return the playback speed and pitch read atomically. Not multi-thread safe on server side. + AudioPlaybackRate getPlaybackRate(); + +private: + AudioPlaybackRate mPlaybackRate; // last observed playback rate + PlaybackRateQueue::Observer mPlaybackRateObserver; }; class StaticAudioTrackServerProxy : public AudioTrackServerProxy { @@ -447,10 +533,13 @@ public: virtual uint32_t getUnderrunFrames() const { return 0; } private: + status_t updateStateWithLoop(StaticAudioTrackState *localState, + const StaticAudioTrackState &update) const; + status_t updateStateWithPosition(StaticAudioTrackState *localState, + const StaticAudioTrackState &update) const; ssize_t pollPosition(); // poll for state queue update, and return current position StaticAudioTrackSingleStateQueue::Observer mObserver; - size_t mPosition; // server's current play position in frames, relative to 0 - + StaticAudioTrackPosLoopQueue::Mutator mPosLoopMutator; size_t mFramesReadySafe; // Assuming size_t read/writes are atomic on 32 / 64 bit // processors, this is a thread-safe version of // mFramesReady. @@ -459,7 +548,8 @@ private: // can cause a track to appear to have a large number // of frames. INT64_MAX means an infinite loop. bool mFramesReadyIsCalledByMultipleThreads; - StaticAudioTrackState mState; + StaticAudioTrackState mState; // Server side state. Any updates from client must be + // passed by the mObserver SingleStateQueue. }; // Proxy used by AudioFlinger for servicing AudioRecord diff --git a/include/private/media/StaticAudioTrackState.h b/include/private/media/StaticAudioTrackState.h deleted file mode 100644 index d483061..0000000 --- a/include/private/media/StaticAudioTrackState.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 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 STATIC_AUDIO_TRACK_STATE_H -#define STATIC_AUDIO_TRACK_STATE_H - -namespace android { - -// Represents a single state of an AudioTrack that was created in static mode (shared memory buffer -// supplied by the client). This state needs to be communicated from the client to server. As this -// state is too large to be updated atomically without a mutex, and mutexes aren't allowed here, the -// state is wrapped by a SingleStateQueue. -struct StaticAudioTrackState { - // do not define constructors, destructors, or virtual methods - - // These fields should both be size_t, but since they are located in shared memory we - // force to 32-bit. The client and server may have different typedefs for size_t. - uint32_t mLoopStart; - uint32_t mLoopEnd; - - int mLoopCount; -}; - -} // namespace android - -#endif // STATIC_AUDIO_TRACK_STATE_H diff --git a/include/radio/IRadio.h b/include/radio/IRadio.h new file mode 100644 index 0000000..1877f8f --- /dev/null +++ b/include/radio/IRadio.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_IRADIO_H +#define ANDROID_HARDWARE_IRADIO_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/IMemory.h> +#include <binder/Parcel.h> +#include <system/radio.h> + +namespace android { + +class IRadio : public IInterface +{ +public: + + DECLARE_META_INTERFACE(Radio); + + virtual void detach() = 0; + + virtual status_t setConfiguration(const struct radio_band_config *config) = 0; + + virtual status_t getConfiguration(struct radio_band_config *config) = 0; + + virtual status_t setMute(bool mute) = 0; + + virtual status_t getMute(bool *mute) = 0; + + virtual status_t step(radio_direction_t direction, bool skipSubChannel) = 0; + + virtual status_t scan(radio_direction_t direction, bool skipSubChannel) = 0; + + virtual status_t tune(unsigned int channel, unsigned int subChannel) = 0; + + virtual status_t cancel() = 0; + + virtual status_t getProgramInformation(struct radio_program_info *info) = 0; + + virtual status_t hasControl(bool *hasControl) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnRadio: public BnInterface<IRadio> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif //ANDROID_HARDWARE_IRADIO_H diff --git a/include/radio/IRadioClient.h b/include/radio/IRadioClient.h new file mode 100644 index 0000000..9062ad6 --- /dev/null +++ b/include/radio/IRadioClient.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_IRADIO_CLIENT_H +#define ANDROID_HARDWARE_IRADIO_CLIENT_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/IMemory.h> +#include <binder/Parcel.h> + +namespace android { + +class IRadioClient : public IInterface +{ +public: + + DECLARE_META_INTERFACE(RadioClient); + + virtual void onEvent(const sp<IMemory>& eventMemory) = 0; + +}; + +// ---------------------------------------------------------------------------- + +class BnRadioClient : public BnInterface<IRadioClient> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif //ANDROID_HARDWARE_IRADIO_CLIENT_H diff --git a/include/radio/IRadioService.h b/include/radio/IRadioService.h new file mode 100644 index 0000000..a946dd5 --- /dev/null +++ b/include/radio/IRadioService.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_IRADIO_SERVICE_H +#define ANDROID_HARDWARE_IRADIO_SERVICE_H + +#include <utils/RefBase.h> +#include <binder/IInterface.h> +#include <binder/Parcel.h> +#include <system/radio.h> + +namespace android { + +class IRadio; +class IRadioClient; + +class IRadioService : public IInterface +{ +public: + + DECLARE_META_INTERFACE(RadioService); + + virtual status_t listModules(struct radio_properties *properties, + uint32_t *numModules) = 0; + + virtual status_t attach(const radio_handle_t handle, + const sp<IRadioClient>& client, + const struct radio_band_config *config, + bool withAudio, + sp<IRadio>& radio) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnRadioService: public BnInterface<IRadioService> +{ +public: + virtual status_t onTransact( uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif //ANDROID_HARDWARE_IRADIO_SERVICE_H diff --git a/include/radio/Radio.h b/include/radio/Radio.h new file mode 100644 index 0000000..302bf16 --- /dev/null +++ b/include/radio/Radio.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_RADIO_H +#define ANDROID_HARDWARE_RADIO_H + +#include <binder/IBinder.h> +#include <utils/threads.h> +#include <radio/RadioCallback.h> +#include <radio/IRadio.h> +#include <radio/IRadioService.h> +#include <radio/IRadioClient.h> +#include <system/radio.h> + +namespace android { + +class MemoryDealer; + +class Radio : public BnRadioClient, + public IBinder::DeathRecipient +{ +public: + + virtual ~Radio(); + + static status_t listModules(struct radio_properties *properties, + uint32_t *numModules); + static sp<Radio> attach(radio_handle_t handle, + const struct radio_band_config *config, + bool withAudio, + const sp<RadioCallback>& callback); + + + void detach(); + + status_t setConfiguration(const struct radio_band_config *config); + + status_t getConfiguration(struct radio_band_config *config); + + status_t setMute(bool mute); + + status_t getMute(bool *mute); + + status_t step(radio_direction_t direction, bool skipSubChannel); + + status_t scan(radio_direction_t direction, bool skipSubChannel); + + status_t tune(unsigned int channel, unsigned int subChannel); + + status_t cancel(); + + status_t getProgramInformation(struct radio_program_info *info); + + status_t hasControl(bool *hasControl); + + // BpRadioClient + virtual void onEvent(const sp<IMemory>& eventMemory); + + //IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who); + +private: + Radio(radio_handle_t handle, + const sp<RadioCallback>&); + static const sp<IRadioService>& getRadioService(); + + Mutex mLock; + sp<IRadio> mIRadio; + const radio_handle_t mHandle; + sp<RadioCallback> mCallback; +}; + +}; // namespace android + +#endif //ANDROID_HARDWARE_RADIO_H diff --git a/include/radio/RadioCallback.h b/include/radio/RadioCallback.h new file mode 100644 index 0000000..4a7f1a6 --- /dev/null +++ b/include/radio/RadioCallback.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 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 ANDROID_HARDWARE_RADIO_CALLBACK_H +#define ANDROID_HARDWARE_RADIO_CALLBACK_H + +#include <utils/RefBase.h> +#include <system/radio.h> + +namespace android { + +class RadioCallback : public RefBase +{ +public: + + RadioCallback() {} + virtual ~RadioCallback() {} + + virtual void onEvent(struct radio_event *event) = 0; + +}; + +}; // namespace android + +#endif //ANDROID_HARDWARE_RADIO_CALLBACK_H |