Merge "AudioTrack: fix stall if setBufferSizeInFrames() called before play()" into nyc-dev
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 5af6c10..6af1962 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -139,7 +139,7 @@
* of descriptors to return.
* *count is limited to kMaxPreProcessing on return.
*/
- static status_t queryDefaultPreProcessing(int audioSession,
+ static status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count);
@@ -237,7 +237,7 @@
int32_t priority = 0,
effect_callback_t cbf = NULL,
void* user = NULL,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
);
@@ -250,7 +250,7 @@
int32_t priority = 0,
effect_callback_t cbf = NULL,
void* user = NULL,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
);
@@ -272,7 +272,7 @@
int32_t priority = 0,
effect_callback_t cbf = NULL,
void* user = NULL,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
audio_io_handle_t io = AUDIO_IO_HANDLE_NONE
);
@@ -405,7 +405,7 @@
protected:
bool mEnabled; // enable state
- int32_t mSessionId; // audio session ID
+ audio_session_t mSessionId; // audio session ID
int32_t mPriority; // priority for effect control
status_t mStatus; // effect status
effect_callback_t mCbf; // callback function for status, control and
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index c769a62..8528c7a 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -51,6 +51,7 @@
#define MIX_ROUTE_FLAG_RENDER 0x1
#define MIX_ROUTE_FLAG_LOOP_BACK (0x1 << 1)
+#define MIX_ROUTE_FLAG_ALL (MIX_ROUTE_FLAG_RENDER | MIX_ROUTE_FLAG_LOOP_BACK)
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20
@@ -81,7 +82,7 @@
AudioMix(Vector<AudioMixMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
uint32_t routeFlags, String8 registrationId, uint32_t flags) :
mCriteria(criteria), mMixType(mixType), mFormat(format),
- mRouteFlags(routeFlags), mRegistrationId(registrationId), mCbFlags(flags){}
+ mRouteFlags(routeFlags), mDeviceAddress(registrationId), mCbFlags(flags){}
status_t readFromParcel(Parcel *parcel);
status_t writeToParcel(Parcel *parcel) const;
@@ -90,7 +91,8 @@
uint32_t mMixType;
audio_config_t mFormat;
uint32_t mRouteFlags;
- String8 mRegistrationId;
+ audio_devices_t mDeviceType;
+ String8 mDeviceAddress;
uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
};
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index b034c8e..2fa1a4e 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -177,7 +177,7 @@
callback_t cbf = NULL,
void* user = NULL,
uint32_t notificationFrames = 0,
- int sessionId = AUDIO_SESSION_ALLOCATE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
int uid = -1,
@@ -215,7 +215,7 @@
void* user = NULL,
uint32_t notificationFrames = 0,
bool threadCanCallJava = false,
- int sessionId = AUDIO_SESSION_ALLOCATE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
int uid = -1,
@@ -249,7 +249,7 @@
* the specified event occurs on the specified trigger session.
*/
status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
- int triggerSession = 0);
+ audio_session_t triggerSession = AUDIO_SESSION_NONE);
/* Stop a track. The callback will cease being called. Note that obtainBuffer() still
* works and will drain buffers until the pool is exhausted, and then will return WOULD_BLOCK.
@@ -352,7 +352,7 @@
*
* No lock needed because session ID doesn't change after first set().
*/
- int getSessionId() const { return mSessionId; }
+ audio_session_t getSessionId() const { return mSessionId; }
/* Public API for TRANSFER_OBTAIN mode.
* Obtains a buffer of up to "audioBuffer->frameCount" full frames.
@@ -603,7 +603,7 @@
// held to read or write those bits reliably.
audio_input_flags_t mOrigFlags; // as specified in constructor or set(), const
- int mSessionId;
+ audio_session_t mSessionId;
transfer_type mTransfer;
// Next 5 fields may be changed if IAudioRecord is re-created, but always != 0
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 91e2bbd..c9eac2e 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -31,7 +31,7 @@
typedef void (*audio_error_callback)(status_t err);
typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
-typedef void (*record_config_callback)(int event, int session, int source,
+typedef void (*record_config_callback)(int event, audio_session_t session, int source,
const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
audio_patch_handle_t patchHandle);
@@ -155,8 +155,8 @@
// or an unspecified existing unique ID.
static audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
- static void acquireAudioSessionId(int audioSession, pid_t pid);
- static void releaseAudioSessionId(int audioSession, pid_t pid);
+ static void acquireAudioSessionId(audio_session_t audioSession, pid_t pid);
+ static void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
// Get the HW synchronization source used for an audio session.
// Return a valid source or AUDIO_HW_SYNC_INVALID if an error occurs
@@ -260,7 +260,7 @@
static status_t registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id);
static status_t unregisterEffect(int id);
static status_t setEffectEnabled(int id, bool enabled);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 69dc062..9e0e98b 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -213,7 +213,7 @@
callback_t cbf = NULL,
void* user = NULL,
uint32_t notificationFrames = 0,
- int sessionId = AUDIO_SESSION_ALLOCATE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
int uid = -1,
@@ -242,7 +242,7 @@
callback_t cbf = NULL,
void* user = NULL,
uint32_t notificationFrames = 0,
- int sessionId = AUDIO_SESSION_ALLOCATE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
int uid = -1,
@@ -287,7 +287,7 @@
uint32_t notificationFrames = 0,
const sp<IMemory>& sharedBuffer = 0,
bool threadCanCallJava = false,
- int sessionId = AUDIO_SESSION_ALLOCATE,
+ audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
transfer_type transferType = TRANSFER_DEFAULT,
const audio_offload_info_t *offloadInfo = NULL,
int uid = -1,
@@ -583,7 +583,7 @@
* Returned value:
* AudioTrack session ID.
*/
- int getSessionId() const { return mSessionId; }
+ audio_session_t getSessionId() const { return mSessionId; }
/* Attach track auxiliary output to specified effect. Use effectId = 0
* to detach track from effect.
@@ -836,6 +836,8 @@
// check sample rate and speed is compatible with AudioTrack
bool isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) const;
+ void restartIfDisabled();
+
// Next 4 fields may be changed if IAudioTrack is re-created, but always != 0
sp<IAudioTrack> mAudioTrack;
sp<IMemory> mCblkMemory;
@@ -957,7 +959,7 @@
bool mDoNotReconnect;
- int mSessionId;
+ audio_session_t mSessionId;
int mAuxEffectId;
mutable Mutex mLock;
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 0d9bc3b..e48aa1c 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -74,7 +74,7 @@
// However on failure, the client is responsible for release.
audio_io_handle_t output,
pid_t tid, // -1 means unused, otherwise must be valid non-0
- int *sessionId,
+ audio_session_t *sessionId,
int clientUid,
status_t *status) = 0;
@@ -91,7 +91,7 @@
track_flags_t *flags,
pid_t tid, // -1 means unused, otherwise must be valid non-0
int clientUid,
- int *sessionId,
+ audio_session_t *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
sp<IMemory>& buffers, // return value 0 means it follows cblk
@@ -184,8 +184,8 @@
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
- virtual void acquireAudioSessionId(int audioSession, pid_t pid) = 0;
- virtual void releaseAudioSessionId(int audioSession, pid_t pid) = 0;
+ virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
+ virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) = 0;
virtual status_t queryNumberEffects(uint32_t *numEffects) const = 0;
@@ -200,13 +200,13 @@
int32_t priority,
// AudioFlinger doesn't take over handle reference from client
audio_io_handle_t output,
- int sessionId,
+ audio_session_t sessionId,
const String16& callingPackage,
status_t *status,
int *id,
int *enabled) = 0;
- virtual status_t moveEffects(int session, audio_io_handle_t srcOutput,
+ virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
virtual audio_module_handle_t loadHwModule(const char *name) = 0;
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index ceca71a..80437dc 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -59,16 +59,16 @@
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL) = 0;
virtual status_t getOutputForAttr(const audio_attributes_t *attr,
- 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;
+ 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,
audio_session_t session) = 0;
@@ -108,7 +108,7 @@
virtual status_t registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual status_t setEffectEnabled(int id, bool enabled) = 0;
@@ -116,7 +116,7 @@
virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0)
const = 0;
virtual bool isSourceActive(audio_source_t source) const = 0;
- virtual status_t queryDefaultPreProcessing(int audioSession,
+ virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count) = 0;
// Check if offload is possible for given format, stream type, sample rate,
diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h
index 2003985..7768176 100644
--- a/include/media/IAudioRecord.h
+++ b/include/media/IAudioRecord.h
@@ -24,6 +24,7 @@
#include <utils/Errors.h>
#include <binder/IInterface.h>
#include <binder/IMemory.h>
+#include <system/audio.h>
namespace android {
@@ -37,7 +38,8 @@
/* After it's created the track is not active. Call start() to
* make it active.
*/
- virtual status_t start(int /*AudioSystem::sync_event_t*/ event, int triggerSession) = 0;
+ virtual status_t start(int /*AudioSystem::sync_event_t*/ event,
+ audio_session_t triggerSession) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 99ca6f0..e5d3cda 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -49,8 +49,8 @@
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,
+ audio_session_t audioSessionId = AUDIO_SESSION_ALLOCATE) = 0;
virtual sp<IOMX> getOMX() = 0;
virtual sp<ICrypto> makeCrypto() = 0;
virtual sp<IDrm> makeDrm() = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9e5056f..54862d1 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -101,7 +101,7 @@
virtual status_t getTimestamp(AudioTimestamp &ts) const = 0;
virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const = 0;
virtual status_t getFramesWritten(uint32_t *frameswritten) const = 0;
- virtual int getSessionId() const = 0;
+ virtual audio_session_t getSessionId() const = 0;
virtual audio_stream_type_t getAudioStreamType() const = 0;
virtual uint32_t getSampleRate() const = 0;
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index 186e018..ec0dad5 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -69,7 +69,7 @@
int32_t priority = 0,
effect_callback_t cbf = NULL,
void* user = NULL,
- int sessionId = 0);
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
~Visualizer();
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 00df523..cec9d99 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -246,8 +246,8 @@
status_t invoke(const Parcel& request, Parcel *reply);
status_t setMetadataFilter(const Parcel& filter);
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
- status_t setAudioSessionId(int sessionId);
- int getAudioSessionId();
+ status_t setAudioSessionId(audio_session_t sessionId);
+ audio_session_t getAudioSessionId();
status_t setAuxEffectSendLevel(float level);
status_t attachAuxEffect(int effectId);
status_t setParameter(int key, const Parcel& request);
@@ -284,7 +284,7 @@
float mRightVolume;
int mVideoWidth;
int mVideoHeight;
- int mAudioSessionId;
+ audio_session_t mAudioSessionId;
float mSendLevel;
struct sockaddr_in mRetransmitEndpoint;
bool mRetransmitEndpointValid;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index bd633f7..2365323 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -242,8 +242,10 @@
IOMX::node_id mNode;
sp<MemoryDealer> mDealer[2];
+ bool mUsingNativeWindow;
sp<ANativeWindow> mNativeWindow;
int mNativeWindowUsageBits;
+ sp<AMessage> mConfigFormat;
sp<AMessage> mInputFormat;
sp<AMessage> mOutputFormat;
sp<AMessage> mBaseOutputFormat;
@@ -343,21 +345,72 @@
status_t setSupportedOutputFormat(bool getLegacyFlexibleFormat);
status_t setupVideoDecoder(
- const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers,
+ const char *mime, const sp<AMessage> &msg, bool usingNativeBuffers, bool haveSwRenderer,
sp<AMessage> &outputformat);
status_t setupVideoEncoder(
- const char *mime, const sp<AMessage> &msg, sp<AMessage> &outputformat);
+ const char *mime, const sp<AMessage> &msg,
+ sp<AMessage> &outputformat, sp<AMessage> &inputformat);
status_t setVideoFormatOnPort(
OMX_U32 portIndex,
int32_t width, int32_t height,
OMX_VIDEO_CODINGTYPE compressionFormat, float frameRate = -1.0);
- status_t setColorAspects(
- OMX_U32 portIndex, int32_t width, int32_t height, const sp<AMessage> &msg,
- sp<AMessage> &format);
- status_t getColorAspects(OMX_U32 portIndex, sp<AMessage> &format);
+ // gets index or sets it to 0 on error. Returns error from codec.
+ status_t initDescribeColorAspectsIndex();
+
+ // sets |params|. If |readBack| is true, it re-gets them afterwards if set succeeded.
+ // returns the codec error.
+ status_t setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool readBack = false);
+
+ // gets |params|; returns the codec error. |param| should not change on error.
+ status_t getCodecColorAspects(DescribeColorAspectsParams ¶ms);
+
+ // gets dataspace guidance from codec and platform. |params| should be set up with the color
+ // aspects to use. If |tryCodec| is true, the codec is queried first. If it succeeds, we
+ // return OK. Otherwise, we fall back to the platform guidance and return the codec error;
+ // though, we return OK if the codec failed with UNSUPPORTED, as codec guidance is optional.
+ status_t getDataSpace(
+ DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */,
+ bool tryCodec);
+
+ // sets color aspects for the encoder for certain |width/height| based on |configFormat|, and
+ // set resulting color config into |outputFormat|. If |usingNativeWindow| is true, we use
+ // video defaults if config is unspecified. Returns error from the codec.
+ status_t setColorAspectsForVideoDecoder(
+ int32_t width, int32_t height, bool usingNativeWindow,
+ const sp<AMessage> &configFormat, sp<AMessage> &outputFormat);
+
+ // gets color aspects for the encoder for certain |width/height| based on |configFormat|, and
+ // set resulting color config into |outputFormat|. If |dataSpace| is non-null, it requests
+ // dataspace guidance from the codec and platform and sets it into |dataSpace|. Returns the
+ // error from the codec.
+ status_t getColorAspectsAndDataSpaceForVideoDecoder(
+ int32_t width, int32_t height, const sp<AMessage> &configFormat,
+ sp<AMessage> &outputFormat, android_dataspace *dataSpace);
+
+ // sets color aspects for the video encoder assuming bytebuffer mode for certain |configFormat|
+ // and sets resulting color config into |outputFormat|. For mediarecorder, also set dataspace
+ // into |inputFormat|. Returns the error from the codec.
+ status_t setColorAspectsForVideoEncoder(
+ const sp<AMessage> &configFormat,
+ sp<AMessage> &outputFormat, sp<AMessage> &inputFormat);
+
+ // sets color aspects for the video encoder in surface mode. This basically sets the default
+ // video values for unspecified aspects and sets the dataspace to use in the input format.
+ // Also sets the dataspace into |dataSpace|.
+ // Returns any codec errors during this configuration, except for optional steps.
+ status_t setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
+ android_dataspace *dataSpace /* nonnull */);
+
+ // gets color aspects for the video encoder input port and sets them into the |format|.
+ // Returns any codec errors.
+ status_t getInputColorAspectsForVideoEncoder(sp<AMessage> &format);
+
+ // updates the encoder output format with |aspects| defaulting to |dataSpace| for
+ // unspecified values.
+ void onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects);
typedef struct drcParams {
int32_t drcCut;
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index e3f3f5e..5f10487 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -115,8 +115,8 @@
bool mStopping;
bool mDoMoreWorkPending;
bool mSetEncoderFormat;
- int mEncoderFormat;
- int mEncoderDataSpace;
+ int32_t mEncoderFormat;
+ int32_t mEncoderDataSpace;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
sp<IGraphicBufferConsumer> mGraphicBufferConsumer;
diff --git a/include/media/stagefright/foundation/ALookup.h b/include/media/stagefright/foundation/ALookup.h
index d8af407..5a68806 100644
--- a/include/media/stagefright/foundation/ALookup.h
+++ b/include/media/stagefright/foundation/ALookup.h
@@ -27,14 +27,14 @@
struct ALookup {
ALookup(std::initializer_list<std::pair<T, U>> list);
- bool lookup(const T& from, U *to);
- bool rlookup(const U& from, T *to);
+ bool lookup(const T& from, U *to) const;
+ bool rlookup(const U& from, T *to) const;
template<typename V, typename = typename std::enable_if<!std::is_same<T, V>::value>::type>
- inline bool map(const T& from, V *to) { return lookup(from, to); }
+ inline bool map(const T& from, V *to) const { return lookup(from, to); }
template<typename V, typename = typename std::enable_if<!std::is_same<T, V>::value>::type>
- inline bool map(const V& from, T *to) { return rlookup(from, to); }
+ inline bool map(const V& from, T *to) const { return rlookup(from, to); }
private:
std::vector<std::pair<T, U>> mTable;
@@ -46,7 +46,7 @@
}
template<typename T, typename U>
-bool ALookup<T, U>::lookup(const T& from, U *to) {
+bool ALookup<T, U>::lookup(const T& from, U *to) const {
for (auto elem : mTable) {
if (elem.first == from) {
*to = elem.second;
@@ -57,7 +57,7 @@
}
template<typename T, typename U>
-bool ALookup<T, U>::rlookup(const U& from, T *to) {
+bool ALookup<T, U>::rlookup(const U& from, T *to) const {
for (auto elem : mTable) {
if (elem.second == from) {
*to = elem.first;
diff --git a/include/media/stagefright/foundation/ColorUtils.h b/include/media/stagefright/foundation/ColorUtils.h
index b95c80b..f01a210 100644
--- a/include/media/stagefright/foundation/ColorUtils.h
+++ b/include/media/stagefright/foundation/ColorUtils.h
@@ -129,11 +129,46 @@
static status_t convertCodecColorAspectsToPlatformAspects(
const ColorAspects &aspects, int32_t *range, int32_t *standard, int32_t *transfer);
- // updates unspecified range, standard and transfer values to their defaults
- static void setDefaultPlatformColorAspectsIfNeeded(
- int32_t &range, int32_t &standard, int32_t &transfer, int32_t width, int32_t height);
+ // converts Other values to Unspecified
+ static void convertCodecColorAspectsToIsoAspects(
+ const ColorAspects &aspects,
+ int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange);
+ // converts unsupported values to Other
+ static void convertIsoColorAspectsToCodecAspects(
+ int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
+ ColorAspects &aspects);
+
+ // updates Unspecified color aspects to their defaults based on the video size
static void setDefaultCodecColorAspectsIfNeeded(
ColorAspects &aspects, int32_t width, int32_t height);
+
+ // it returns the closest dataSpace for given color |aspects|. if |mayExpand| is true, it allows
+ // returning a larger dataSpace that contains the color space given by |aspects|, and is better
+ // suited to blending. This requires implicit color space conversion on part of the device.
+ static android_dataspace getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand);
+
+ // converts |dataSpace| to a V0 enum, and returns true if dataSpace is an aspect-only value
+ static bool convertDataSpaceToV0(android_dataspace &dataSpace);
+
+ // compares |aspect| to |orig|. Returns |true| if any aspects have changed, except if they
+ // changed to Unspecified value. It also sets the changed values to Unspecified in |aspect|.
+ static bool checkIfAspectsChangedAndUnspecifyThem(
+ ColorAspects &aspects, const ColorAspects &orig, bool usePlatformAspects = false);
+
+ // finds color config in format, defaulting them to 0.
+ static void getColorConfigFromFormat(
+ const sp<AMessage> &format, int *range, int *standard, int *transfer);
+
+ // copies existing color config from |source| to |target|.
+ static void copyColorConfig(const sp<AMessage> &source, sp<AMessage> &target);
+
+ // finds color config in format as ColorAspects, defaulting them to 0.
+ static void getColorAspectsFromFormat(const sp<AMessage> &format, ColorAspects &aspects);
+
+ // writes |aspects| into format. iff |force| is false, Unspecified values are not
+ // written.
+ static void setColorAspectsIntoFormat(
+ const ColorAspects &aspects, sp<AMessage> &format, bool force = false);
};
inline static const char *asString(android::ColorUtils::ColorStandard i, const char *def = "??") {
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 24784ea..92cf6bb 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -272,6 +272,8 @@
// DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
// -EINTR Call has been interrupted. Look around to see why, and then perhaps try again.
// NO_INIT Shared memory is corrupt.
+ // NOT_ENOUGH_DATA Server has disabled the track because of underrun: restart the track
+ // if still in active state.
// Assertion failure on entry, if buffer == NULL or buffer->mFrameCount == 0.
status_t obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
struct timespec *elapsed = NULL);
diff --git a/media/img_utils/src/NOTICE b/media/img_utils/src/NOTICE
new file mode 100644
index 0000000..90cea57
--- /dev/null
+++ b/media/img_utils/src/NOTICE
@@ -0,0 +1,2 @@
+This product includes DNG technology under license by Adobe Systems
+Incorporated.
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index ff82544..590952f 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -47,7 +47,7 @@
int32_t priority,
effect_callback_t cbf,
void* user,
- int sessionId,
+ audio_session_t sessionId,
audio_io_handle_t io
)
: mStatus(NO_INIT), mOpPackageName(opPackageName)
@@ -61,7 +61,7 @@
int32_t priority,
effect_callback_t cbf,
void* user,
- int sessionId,
+ audio_session_t sessionId,
audio_io_handle_t io
)
: mStatus(NO_INIT), mOpPackageName(opPackageName)
@@ -93,7 +93,7 @@
int32_t priority,
effect_callback_t cbf,
void* user,
- int sessionId,
+ audio_session_t sessionId,
audio_io_handle_t io)
{
sp<IEffect> iEffect;
@@ -433,7 +433,7 @@
}
-status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+status_t AudioEffect::queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
index ea22b6c..d1f7525 100644
--- a/media/libmedia/AudioPolicy.cpp
+++ b/media/libmedia/AudioPolicy.cpp
@@ -67,7 +67,8 @@
mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
mFormat.format = (audio_format_t)parcel->readInt32();
mRouteFlags = parcel->readInt32();
- mRegistrationId = parcel->readString8();
+ mDeviceType = (audio_devices_t) parcel->readInt32();
+ mDeviceAddress = parcel->readString8();
mCbFlags = (uint32_t)parcel->readInt32();
size_t size = (size_t)parcel->readInt32();
if (size > MAX_CRITERIA_PER_MIX) {
@@ -89,7 +90,8 @@
parcel->writeInt32(mFormat.channel_mask);
parcel->writeInt32(mFormat.format);
parcel->writeInt32(mRouteFlags);
- parcel->writeString8(mRegistrationId);
+ parcel->writeInt32(mDeviceType);
+ parcel->writeString8(mDeviceAddress);
parcel->writeInt32(mCbFlags);
size_t size = mCriteria.size();
if (size > MAX_CRITERIA_PER_MIX) {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 9eb5ec7..79ce75e 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -82,7 +82,7 @@
callback_t cbf,
void* user,
uint32_t notificationFrames,
- int sessionId,
+ audio_session_t sessionId,
transfer_type transferType,
audio_input_flags_t flags,
int uid,
@@ -139,7 +139,7 @@
void* user,
uint32_t notificationFrames,
bool threadCanCallJava,
- int sessionId,
+ audio_session_t sessionId,
transfer_type transferType,
audio_input_flags_t flags,
int uid,
@@ -227,7 +227,7 @@
// mNotificationFramesAct is initialized in openRecord_l
if (sessionId == AUDIO_SESSION_ALLOCATE) {
- mSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
} else {
mSessionId = sessionId;
}
@@ -288,7 +288,7 @@
// -------------------------------------------------------------------------
-status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
+status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
{
ALOGV("start, sync event %d trigger session %d", event, triggerSession);
@@ -522,8 +522,16 @@
// After fast request is denied, we will request again if IAudioRecord is re-created.
status_t status;
+
+ // Not a conventional loop, but a retry loop for at most two iterations total.
+ // Try first maybe with FAST flag then try again without FAST flag if that fails.
+ // Exits loop normally via a return at the bottom, or with error via a break.
+ // The sp<> references will be dropped when re-entering scope.
+ // The lack of indentation is deliberate, to reduce code churn and ease merges.
+ for (;;) {
+
status = AudioSystem::getInputForAttr(&mAttributes, &input,
- (audio_session_t)mSessionId,
+ mSessionId,
// FIXME compare to AudioTrack
IPCThreadState::self()->getCallingUid(),
mSampleRate, mFormat, mChannelMask,
@@ -535,7 +543,7 @@
mSessionId, mAttributes.source, mSampleRate, mFormat, mChannelMask, mFlags);
return BAD_VALUE;
}
- {
+
// Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
// we must release it ourselves if anything goes wrong.
@@ -544,7 +552,7 @@
status = AudioSystem::getFrameCount(input, &afFrameCount);
if (status != NO_ERROR) {
ALOGE("getFrameCount(input=%d) status %d", input, status);
- goto release;
+ break;
}
#endif
@@ -552,7 +560,7 @@
status = AudioSystem::getSamplingRate(input, &afSampleRate);
if (status != NO_ERROR) {
ALOGE("getSamplingRate(input=%d) status %d", input, status);
- goto release;
+ break;
}
if (mSampleRate == 0) {
mSampleRate = afSampleRate;
@@ -572,7 +580,10 @@
ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, "
"track %u Hz, input %u Hz",
mTransfer, mSampleRate, afSampleRate);
- mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
+ mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
+ AUDIO_INPUT_FLAG_RAW));
+ AudioSystem::releaseInput(input, mSessionId);
+ continue; // retry
}
}
@@ -593,7 +604,7 @@
size_t temp = frameCount; // temp may be replaced by a revised value of frameCount,
// but we will still need the original value also
- int originalSessionId = mSessionId;
+ audio_session_t originalSessionId = mSessionId;
sp<IMemory> iMem; // for cblk
sp<IMemory> bufferMem;
@@ -616,13 +627,26 @@
if (status != NO_ERROR) {
ALOGE("AudioFlinger could not create record track, status: %d", status);
- goto release;
+ break;
}
ALOG_ASSERT(record != 0);
// AudioFlinger now owns the reference to the I/O handle,
// so we are no longer responsible for releasing it.
+ mAwaitBoost = false;
+ if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+ if (trackFlags & IAudioFlinger::TRACK_FAST) {
+ ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
+ mAwaitBoost = true;
+ } else {
+ ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
+ mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
+ AUDIO_INPUT_FLAG_RAW));
+ continue; // retry
+ }
+ }
+
if (iMem == 0) {
ALOGE("Could not get control block");
return NO_INIT;
@@ -665,17 +689,6 @@
}
frameCount = temp;
- mAwaitBoost = false;
- if (mFlags & AUDIO_INPUT_FLAG_FAST) {
- if (trackFlags & IAudioFlinger::TRACK_FAST) {
- ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
- mAwaitBoost = true;
- } else {
- ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
- mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST);
- }
- }
-
// Make sure that application is notified with sufficient margin before overrun.
// The computation is done on server side.
if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) {
@@ -708,10 +721,13 @@
}
return NO_ERROR;
+
+ // End of retry loop.
+ // The lack of indentation is deliberate, to reduce code churn and ease merges.
}
-release:
- AudioSystem::releaseInput(input, (audio_session_t)mSessionId);
+// Arrive here on error, via a break
+ AudioSystem::releaseInput(input, mSessionId);
if (status == NO_ERROR) {
status = NO_INIT;
}
@@ -1153,7 +1169,7 @@
if (mActive) {
// callback thread or sync event hasn't changed
// FIXME this fails if we have a new AudioFlinger instance
- result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
+ result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE);
}
mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index c55a90b..3a5dee6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -399,7 +399,7 @@
return af->newAudioUniqueId(use);
}
-void AudioSystem::acquireAudioSessionId(int audioSession, pid_t pid)
+void AudioSystem::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af != 0) {
@@ -407,7 +407,7 @@
}
}
-void AudioSystem::releaseAudioSessionId(int audioSession, pid_t pid)
+void AudioSystem::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af != 0) {
@@ -902,7 +902,7 @@
status_t AudioSystem::registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 272b0cd..ef0ccc2 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -184,7 +184,7 @@
callback_t cbf,
void* user,
uint32_t notificationFrames,
- int sessionId,
+ audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
@@ -213,7 +213,7 @@
callback_t cbf,
void* user,
uint32_t notificationFrames,
- int sessionId,
+ audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
@@ -272,7 +272,7 @@
uint32_t notificationFrames,
const sp<IMemory>& sharedBuffer,
bool threadCanCallJava,
- int sessionId,
+ audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
int uid,
@@ -438,7 +438,7 @@
mNotificationFramesReq = notificationFrames;
mNotificationFramesAct = 0;
if (sessionId == AUDIO_SESSION_ALLOCATE) {
- mSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
} else {
mSessionId = sessionId;
}
@@ -1155,7 +1155,7 @@
status_t status;
status = AudioSystem::getOutputForAttr(attr, &output,
- (audio_session_t)mSessionId, &streamType, mClientUid,
+ mSessionId, &streamType, mClientUid,
mSampleRate, mFormat, mChannelMask,
mFlags, mSelectedDeviceId, mOffloadInfo);
@@ -1288,7 +1288,7 @@
size_t temp = frameCount; // temp may be replaced by a revised value of frameCount,
// but we will still need the original value also
- int originalSessionId = mSessionId;
+ audio_session_t originalSessionId = mSessionId;
sp<IAudioTrack> track = audioFlinger->createTrack(streamType,
mSampleRate,
mFormat,
@@ -1448,7 +1448,7 @@
}
release:
- AudioSystem::releaseOutput(output, streamType, (audio_session_t)mSessionId);
+ AudioSystem::releaseOutput(output, streamType, mSessionId);
if (status == NO_ERROR) {
status = NO_INIT;
}
@@ -1529,6 +1529,10 @@
}
oldSequence = newSequence;
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ }
+
// Keep the extra references
proxy = mProxy;
iMem = mCblkMemory;
@@ -1551,8 +1555,7 @@
buffer.mFrameCount = audioBuffer->frameCount;
// FIXME starts the requested timeout and elapsed over from scratch
status = proxy->obtainBuffer(&buffer, requested, elapsed);
-
- } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
+ } while (((status == DEAD_OBJECT) || (status == NOT_ENOUGH_DATA)) && (tryCounter-- > 0));
audioBuffer->frameCount = buffer.mFrameCount;
audioBuffer->size = buffer.mFrameCount * mFrameSize;
@@ -1585,13 +1588,16 @@
mProxy->releaseBuffer(&buffer);
// restart track if it was disabled by audioflinger due to previous underrun
- if (mState == STATE_ACTIVE) {
- audio_track_cblk_t* cblk = mCblk;
- if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) {
- ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this);
- // FIXME ignoring status
- mAudioTrack->start();
- }
+ restartIfDisabled();
+}
+
+void AudioTrack::restartIfDisabled()
+{
+ int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ if ((mState == STATE_ACTIVE) && (flags & CBLK_DISABLED)) {
+ ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this);
+ // FIXME ignoring status
+ mAudioTrack->start();
}
}
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 7d7134a..e5d6fc3 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -151,6 +151,11 @@
status = DEAD_OBJECT;
goto end;
}
+ if (flags & CBLK_DISABLED) {
+ ALOGV("Track disabled");
+ status = NOT_ENOUGH_DATA;
+ goto end;
+ }
// check for obtainBuffer interrupted by client
if (!ignoreInitialPendingInterrupt && (flags & CBLK_INTERRUPT)) {
ALOGV("obtainBuffer() interrupted by client");
@@ -433,7 +438,8 @@
status = DEAD_OBJECT;
goto end;
}
- if (flags & CBLK_STREAM_END_DONE) {
+ // a track is not supposed to underrun at this stage but consider it done
+ if (flags & (CBLK_STREAM_END_DONE | CBLK_DISABLED)) {
ALOGV("stream end received");
status = NO_ERROR;
goto end;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 6da4524..042eac5 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -104,7 +104,7 @@
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
pid_t tid,
- int *sessionId,
+ audio_session_t *sessionId,
int clientUid,
status_t *status)
{
@@ -128,7 +128,7 @@
}
data.writeInt32((int32_t) output);
data.writeInt32((int32_t) tid);
- int lSessionId = AUDIO_SESSION_ALLOCATE;
+ audio_session_t lSessionId = AUDIO_SESSION_ALLOCATE;
if (sessionId != NULL) {
lSessionId = *sessionId;
}
@@ -146,7 +146,7 @@
if (flags != NULL) {
*flags = lFlags;
}
- lSessionId = reply.readInt32();
+ lSessionId = (audio_session_t) reply.readInt32();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -180,7 +180,7 @@
track_flags_t *flags,
pid_t tid,
int clientUid,
- int *sessionId,
+ audio_session_t *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
sp<IMemory>& buffers,
@@ -200,7 +200,7 @@
data.writeInt32(lFlags);
data.writeInt32((int32_t) tid);
data.writeInt32((int32_t) clientUid);
- int lSessionId = AUDIO_SESSION_ALLOCATE;
+ audio_session_t lSessionId = AUDIO_SESSION_ALLOCATE;
if (sessionId != NULL) {
lSessionId = *sessionId;
}
@@ -220,7 +220,7 @@
if (flags != NULL) {
*flags = lFlags;
}
- lSessionId = reply.readInt32();
+ lSessionId = (audio_session_t) reply.readInt32();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -625,7 +625,7 @@
return id;
}
- virtual void acquireAudioSessionId(int audioSession, int pid)
+ virtual void acquireAudioSessionId(audio_session_t audioSession, int pid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
@@ -634,7 +634,7 @@
remote()->transact(ACQUIRE_AUDIO_SESSION_ID, data, &reply);
}
- virtual void releaseAudioSessionId(int audioSession, int pid)
+ virtual void releaseAudioSessionId(audio_session_t audioSession, int pid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
@@ -707,7 +707,7 @@
const sp<IEffectClient>& client,
int32_t priority,
audio_io_handle_t output,
- int sessionId,
+ audio_session_t sessionId,
const String16& opPackageName,
status_t *status,
int *id,
@@ -754,7 +754,7 @@
return effect;
}
- virtual status_t moveEffects(int session, audio_io_handle_t srcOutput,
+ virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput)
{
Parcel data, reply;
@@ -936,7 +936,7 @@
}
audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
pid_t tid = (pid_t) data.readInt32();
- int sessionId = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
int clientUid = data.readInt32();
status_t status = NO_ERROR;
sp<IAudioTrack> track;
@@ -969,7 +969,7 @@
track_flags_t flags = (track_flags_t) data.readInt32();
pid_t tid = (pid_t) data.readInt32();
int clientUid = data.readInt32();
- int sessionId = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
size_t notificationFrames = data.readInt64();
sp<IMemory> cblk;
sp<IMemory> buffers;
@@ -1214,14 +1214,14 @@
} break;
case ACQUIRE_AUDIO_SESSION_ID: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int audioSession = data.readInt32();
+ audio_session_t audioSession = (audio_session_t) data.readInt32();
int pid = data.readInt32();
acquireAudioSessionId(audioSession, pid);
return NO_ERROR;
} break;
case RELEASE_AUDIO_SESSION_ID: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int audioSession = data.readInt32();
+ audio_session_t audioSession = (audio_session_t) data.readInt32();
int pid = data.readInt32();
releaseAudioSessionId(audioSession, pid);
return NO_ERROR;
@@ -1267,7 +1267,7 @@
sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder());
int32_t priority = data.readInt32();
audio_io_handle_t output = (audio_io_handle_t) data.readInt32();
- int sessionId = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
const String16 opPackageName = data.readString16();
status_t status = NO_ERROR;
int id = 0;
@@ -1284,7 +1284,7 @@
} break;
case MOVE_EFFECTS: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- int session = data.readInt32();
+ audio_session_t session = (audio_session_t) data.readInt32();
audio_io_handle_t srcOutput = (audio_io_handle_t) data.readInt32();
audio_io_handle_t dstOutput = (audio_io_handle_t) data.readInt32();
reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
@@ -1411,7 +1411,7 @@
} break;
case GET_AUDIO_HW_SYNC: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(getAudioHwSyncForSession((audio_session_t)data.readInt32()));
+ reply->writeInt32(getAudioHwSyncForSession((audio_session_t) data.readInt32()));
return NO_ERROR;
} break;
case SYSTEM_READY: {
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index c95d4c4..16e8f11 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -247,7 +247,7 @@
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(output);
data.writeInt32((int32_t) stream);
- data.writeInt32((int32_t)session);
+ data.writeInt32((int32_t) session);
remote()->transact(START_OUTPUT, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -260,7 +260,7 @@
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(output);
data.writeInt32((int32_t) stream);
- data.writeInt32((int32_t)session);
+ data.writeInt32((int32_t) session);
remote()->transact(STOP_OUTPUT, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -420,7 +420,7 @@
virtual status_t registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id)
{
Parcel data, reply;
@@ -482,7 +482,7 @@
return reply.readInt32();
}
- virtual status_t queryDefaultPreProcessing(int audioSession,
+ virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
@@ -1065,7 +1065,7 @@
data.read(&desc, sizeof(effect_descriptor_t));
audio_io_handle_t io = data.readInt32();
uint32_t strategy = data.readInt32();
- int session = data.readInt32();
+ audio_session_t session = (audio_session_t) data.readInt32();
int id = data.readInt32();
reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
io,
@@ -1115,7 +1115,7 @@
case QUERY_DEFAULT_PRE_PROCESSING: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- int audioSession = data.readInt32();
+ audio_session_t audioSession = (audio_session_t) data.readInt32();
uint32_t count = data.readInt32();
if (count > AudioEffect::kMaxPreProcessing) {
count = AudioEffect::kMaxPreProcessing;
diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp
index 9d80753..ae66436 100644
--- a/media/libmedia/IAudioRecord.cpp
+++ b/media/libmedia/IAudioRecord.cpp
@@ -42,7 +42,7 @@
{
}
- virtual status_t start(int /*AudioSystem::sync_event_t*/ event, int triggerSession)
+ virtual status_t start(int /*AudioSystem::sync_event_t*/ event, audio_session_t triggerSession)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
@@ -77,7 +77,7 @@
case START: {
CHECK_INTERFACE(IAudioRecord, data, reply);
int /*AudioSystem::sync_event_t*/ event = data.readInt32();
- int triggerSession = data.readInt32();
+ audio_session_t triggerSession = (audio_session_t) data.readInt32();
reply->writeInt32(start(event, triggerSession));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index afc94ab..27b9edd 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -68,7 +68,7 @@
}
virtual sp<IMediaPlayer> create(
- const sp<IMediaPlayerClient>& client, int audioSessionId) {
+ const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(client));
@@ -161,7 +161,7 @@
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
- int audioSessionId = data.readInt32();
+ audio_session_t audioSessionId = (audio_session_t) data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 1ac098c..ea4a966 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -24,6 +24,7 @@
#include <binder/Parcel.h>
#include <media/IOMX.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/openmax/OMX_IndexExt.h>
namespace android {
@@ -717,7 +718,8 @@
void *params = NULL;
size_t pageSize = 0;
size_t allocSize = 0;
- if (code != SET_INTERNAL_OPTION && size < 8) {
+ if ((index == (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits && size < 4) ||
+ (code != SET_INTERNAL_OPTION && size < 8)) {
// we expect the structure to contain at least the size and
// version, 8 bytes total
ALOGE("b/27207275 (%zu)", size);
@@ -739,7 +741,9 @@
} else {
err = NOT_ENOUGH_DATA;
OMX_U32 declaredSize = *(OMX_U32*)params;
- if (code != SET_INTERNAL_OPTION && declaredSize > size) {
+ if (code != SET_INTERNAL_OPTION &&
+ index != (OMX_INDEXTYPE) OMX_IndexParamConsumerUsageBits &&
+ declaredSize > size) {
// the buffer says it's bigger than it actually is
ALOGE("b/27207275 (%u/%zu)", declaredSize, size);
android_errorWriteLog(0x534e4554, "27207275");
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index f5c1b1f..31e310b 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -38,7 +38,7 @@
int32_t priority,
effect_callback_t cbf,
void* user,
- int sessionId)
+ audio_session_t sessionId)
: AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
mCaptureRate(CAPTURE_RATE_DEF),
mCaptureSize(CAPTURE_SIZE_DEF),
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 7e502af..53b6df6 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -63,7 +63,7 @@
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
- mAudioSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
mSendLevel = 0;
mRetransmitEndpointValid = false;
@@ -648,7 +648,7 @@
return OK;
}
-status_t MediaPlayer::setAudioSessionId(int sessionId)
+status_t MediaPlayer::setAudioSessionId(audio_session_t sessionId)
{
ALOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
Mutex::Autolock _l(mLock);
@@ -667,7 +667,7 @@
return NO_ERROR;
}
-int MediaPlayer::getAudioSessionId()
+audio_session_t MediaPlayer::getAudioSessionId()
{
Mutex::Autolock _l(mLock);
return mAudioSessionId;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index bb24403..0025660 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -321,7 +321,7 @@
}
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
- int audioSessionId)
+ audio_session_t audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);
@@ -556,7 +556,7 @@
MediaPlayerService::Client::Client(
const sp<MediaPlayerService>& service, pid_t pid,
int32_t connId, const sp<IMediaPlayerClient>& client,
- int audioSessionId, uid_t uid)
+ audio_session_t audioSessionId, uid_t uid)
{
ALOGV("Client(%d) constructor", connId);
mPid = pid;
@@ -1332,7 +1332,7 @@
#undef LOG_TAG
#define LOG_TAG "AudioSink"
-MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid,
+MediaPlayerService::AudioOutput::AudioOutput(audio_session_t sessionId, int uid, int pid,
const audio_attributes_t* attr)
: mCallback(NULL),
mCallbackCookie(NULL),
@@ -2111,7 +2111,7 @@
data->unlock();
}
-int MediaPlayerService::AudioOutput::getSessionId() const
+audio_session_t MediaPlayerService::AudioOutput::getSessionId() const
{
Mutex::Autolock lock(mLock);
return mSessionId;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index bd98ef1..1dd2ddd 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -75,7 +75,7 @@
class CallbackData;
public:
- AudioOutput(int sessionId, int uid, int pid,
+ AudioOutput(audio_session_t sessionId, int uid, int pid,
const audio_attributes_t * attr);
virtual ~AudioOutput();
@@ -90,7 +90,7 @@
virtual status_t getTimestamp(AudioTimestamp &ts) const;
virtual int64_t getPlayedOutDurationUs(int64_t nowUs) const;
virtual status_t getFramesWritten(uint32_t *frameswritten) const;
- virtual int getSessionId() const;
+ virtual audio_session_t getSessionId() const;
virtual uint32_t getSampleRate() const;
virtual status_t open(
@@ -150,7 +150,7 @@
uint32_t mSampleRateHz; // sample rate of the content, as set in open()
float mMsecsPerFrame;
size_t mFrameSize;
- int mSessionId;
+ audio_session_t mSessionId;
int mUid;
int mPid;
float mSendLevel;
@@ -214,7 +214,8 @@
void removeMediaRecorderClient(wp<MediaRecorderClient> client);
virtual sp<IMediaMetadataRetriever> createMetadataRetriever();
- virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId);
+ virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client,
+ audio_session_t audioSessionId);
virtual sp<IMediaCodecList> getCodecList() const;
virtual sp<IOMX> getOMX();
@@ -332,7 +333,7 @@
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args);
- int getAudioSessionId() { return mAudioSessionId; }
+ audio_session_t getAudioSessionId() { return mAudioSessionId; }
private:
friend class MediaPlayerService;
@@ -340,7 +341,7 @@
pid_t pid,
int32_t connId,
const sp<IMediaPlayerClient>& client,
- int audioSessionId,
+ audio_session_t audioSessionId,
uid_t uid);
Client();
virtual ~Client();
@@ -375,7 +376,7 @@
status_t mStatus;
bool mLoop;
int32_t mConnId;
- int mAudioSessionId;
+ audio_session_t mAudioSessionId;
audio_attributes_t * mAudioAttributes;
uid_t mUID;
sp<ANativeWindow> mConnectedWindow;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 26362ec..1b248db 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1571,6 +1571,9 @@
if (cameraSource == NULL) {
flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT;
+ } else {
+ // require dataspace setup even if not using surface input
+ format->setInt32("android._using-recorder", 1);
}
sp<MediaCodecSource> encoder = MediaCodecSource::Create(
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 9eab66f..520f599 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -488,6 +488,7 @@
ACodec::ACodec()
: mQuirks(0),
mNode(0),
+ mUsingNativeWindow(false),
mNativeWindowUsageBits(0),
mIsVideo(false),
mIsEncoder(false),
@@ -1647,6 +1648,7 @@
sp<AMessage> inputFormat = new AMessage;
sp<AMessage> outputFormat = new AMessage;
+ mConfigFormat = msg;
mIsEncoder = encoder;
@@ -1764,6 +1766,7 @@
sp<RefBase> obj;
bool haveNativeWindow = msg->findObject("native-window", &obj)
&& obj != NULL && video && !encoder;
+ mUsingNativeWindow = haveNativeWindow;
mLegacyAdaptiveExperiment = false;
if (video && !encoder) {
inputFormat->setInt32("adaptive-playback", false);
@@ -1940,9 +1943,9 @@
}
if (encoder) {
- err = setupVideoEncoder(mime, msg, outputFormat);
+ err = setupVideoEncoder(mime, msg, outputFormat, inputFormat);
} else {
- err = setupVideoDecoder(mime, msg, haveNativeWindow, outputFormat);
+ err = setupVideoDecoder(mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
}
if (err != OK) {
@@ -2003,7 +2006,8 @@
// fallback is not supported for protected playback
err = PERMISSION_DENIED;
} else if (err == OK) {
- err = setupVideoDecoder(mime, msg, false, outputFormat);
+ err = setupVideoDecoder(
+ mime, msg, haveNativeWindow, usingSwRenderer, outputFormat);
}
}
}
@@ -2551,6 +2555,7 @@
: OMX_AUDIO_AACStreamFormatMP4FF;
OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE presentation;
+ InitOMXParams(&presentation);
presentation.nMaxOutputChannels = maxOutputChannelCount;
presentation.nDrcCut = drc.drcCut;
presentation.nDrcBoost = drc.drcBoost;
@@ -3013,7 +3018,7 @@
status_t ACodec::setupVideoDecoder(
const char *mime, const sp<AMessage> &msg, bool haveNativeWindow,
- sp<AMessage> &outputFormat) {
+ bool usingSwRenderer, sp<AMessage> &outputFormat) {
int32_t width, height;
if (!msg->findInt32("width", &width)
|| !msg->findInt32("height", &height)) {
@@ -3076,113 +3081,262 @@
return err;
}
- err = setColorAspects(
- kPortIndexOutput, width, height, msg, outputFormat);
- if (err != OK) {
- ALOGI("Falling back to presets as component does not describe color aspects.");
+ err = setColorAspectsForVideoDecoder(
+ width, height, haveNativeWindow | usingSwRenderer, msg, outputFormat);
+ if (err == ERROR_UNSUPPORTED) { // support is optional
err = OK;
}
+ return err;
+}
+
+status_t ACodec::initDescribeColorAspectsIndex() {
+ status_t err = mOMX->getExtensionIndex(
+ mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
+ if (err != OK) {
+ mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
+ }
+ return err;
+}
+
+status_t ACodec::setCodecColorAspects(DescribeColorAspectsParams ¶ms, bool verify) {
+ status_t err = ERROR_UNSUPPORTED;
+ if (mDescribeColorAspectsIndex) {
+ err = mOMX->setConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
+ }
+ ALOGV("[%s] setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ mComponentName.c_str(),
+ params.sAspects.mRange, asString(params.sAspects.mRange),
+ params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
+ params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
+ params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
+ err, asString(err));
+
+ if (verify && err == OK) {
+ err = getCodecColorAspects(params);
+ }
+
+ ALOGW_IF(err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex,
+ "[%s] getting color aspects failed even though codec advertises support",
+ mComponentName.c_str());
+ return err;
+}
+
+status_t ACodec::setColorAspectsForVideoDecoder(
+ int32_t width, int32_t height, bool usingNativeWindow,
+ const sp<AMessage> &configFormat, sp<AMessage> &outputFormat) {
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexOutput;
+
+ getColorAspectsFromFormat(configFormat, params.sAspects);
+ if (usingNativeWindow) {
+ setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
+ // The default aspects will be set back to the output format during the
+ // getFormat phase of configure(). Set non-Unspecified values back into the
+ // format, in case component does not support this enumeration.
+ setColorAspectsIntoFormat(params.sAspects, outputFormat);
+ }
+
+ (void)initDescribeColorAspectsIndex();
+
+ // communicate color aspects to codec
+ return setCodecColorAspects(params);
+}
+
+status_t ACodec::getCodecColorAspects(DescribeColorAspectsParams ¶ms) {
+ status_t err = ERROR_UNSUPPORTED;
+ if (mDescribeColorAspectsIndex) {
+ err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
+ }
+ ALOGV("[%s] got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ mComponentName.c_str(),
+ params.sAspects.mRange, asString(params.sAspects.mRange),
+ params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
+ params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
+ params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
+ err, asString(err));
+ if (params.bRequestingDataSpace) {
+ ALOGV("for dataspace %#x", params.nDataSpace);
+ }
+ if (err == ERROR_UNSUPPORTED && mDescribeColorAspectsIndex
+ && !params.bRequestingDataSpace && !params.bDataSpaceChanged) {
+ ALOGW("[%s] getting color aspects failed even though codec advertises support",
+ mComponentName.c_str());
+ }
+ return err;
+}
+
+status_t ACodec::getInputColorAspectsForVideoEncoder(sp<AMessage> &format) {
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexInput;
+ status_t err = getCodecColorAspects(params);
+ if (err == OK) {
+ // we only set encoder input aspects if codec supports them
+ setColorAspectsIntoFormat(params.sAspects, format, true /* force */);
+ }
+ return err;
+}
+
+status_t ACodec::getDataSpace(
+ DescribeColorAspectsParams ¶ms, android_dataspace *dataSpace /* nonnull */,
+ bool tryCodec) {
+ status_t err = OK;
+ if (tryCodec) {
+ // request dataspace guidance from codec.
+ params.bRequestingDataSpace = OMX_TRUE;
+ err = getCodecColorAspects(params);
+ params.bRequestingDataSpace = OMX_FALSE;
+ if (err == OK && params.nDataSpace != HAL_DATASPACE_UNKNOWN) {
+ *dataSpace = (android_dataspace)params.nDataSpace;
+ return err;
+ } else if (err == ERROR_UNSUPPORTED) {
+ // ignore not-implemented error for dataspace requests
+ err = OK;
+ }
+ }
+
+ // this returns legacy versions if available
+ *dataSpace = getDataSpaceForColorAspects(params.sAspects, true /* mayexpand */);
+ ALOGV("[%s] using color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
+ "and dataspace %#x",
+ mComponentName.c_str(),
+ params.sAspects.mRange, asString(params.sAspects.mRange),
+ params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
+ params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
+ params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
+ *dataSpace);
+ return err;
+}
+
+
+status_t ACodec::getColorAspectsAndDataSpaceForVideoDecoder(
+ int32_t width, int32_t height, const sp<AMessage> &configFormat, sp<AMessage> &outputFormat,
+ android_dataspace *dataSpace) {
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexOutput;
+
+ // reset default format and get resulting format
+ getColorAspectsFromFormat(configFormat, params.sAspects);
+ if (dataSpace != NULL) {
+ setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
+ }
+ status_t err = setCodecColorAspects(params, true /* readBack */);
+
+ // we always set specified aspects for decoders
+ setColorAspectsIntoFormat(params.sAspects, outputFormat);
+
+ if (dataSpace != NULL) {
+ status_t res = getDataSpace(params, dataSpace, err == OK /* tryCodec */);
+ if (err == OK) {
+ err = res;
+ }
+ }
return err;
}
-status_t ACodec::setColorAspects(
- OMX_U32 portIndex, int32_t width, int32_t height, const sp<AMessage> &msg,
- sp<AMessage> &format) {
- DescribeColorAspectsParams params;
- InitOMXParams(¶ms);
- params.nPortIndex = portIndex;
-
- // 0 values are unspecified
- int32_t range = 0, standard = 0, transfer = 0;
- if (portIndex == kPortIndexInput) {
- // Encoders allow overriding default aspects with 0 if specified by format. Decoders do not.
- setDefaultPlatformColorAspectsIfNeeded(range, standard, transfer, width, height);
- }
- (void)msg->findInt32("color-range", &range);
- (void)msg->findInt32("color-standard", &standard);
- (void)msg->findInt32("color-transfer", &transfer);
-
- if (convertPlatformColorAspectsToCodecAspects(
- range, standard, transfer, params.sAspects) != OK) {
- ALOGW("[%s] Ignoring illegal color aspects(range=%d, standard=%d, transfer=%d)",
- mComponentName.c_str(), range, standard, transfer);
- // Invalid values were converted to unspecified !params!, but otherwise were not changed
- // For encoders, we leave these as is. For decoders, we will use default values.
- }
-
- // set defaults for decoders.
- if (portIndex != kPortIndexInput) {
- setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
- convertCodecColorAspectsToPlatformAspects(params.sAspects, &range, &standard, &transfer);
- }
-
- // save updated values to base output format (encoder input format will read back actually
- // supported values by the codec)
- if (range != 0) {
- format->setInt32("color-range", range);
- }
- if (standard != 0) {
- format->setInt32("color-standard", standard);
- }
- if (transfer != 0) {
- format->setInt32("color-transfer", transfer);
- }
-
- // communicate color aspects to codec
- status_t err = mOMX->getExtensionIndex(
- mNode, "OMX.google.android.index.describeColorAspects", &mDescribeColorAspectsIndex);
- if (err != OK) {
- mDescribeColorAspectsIndex = (OMX_INDEXTYPE)0;
- return err;
- }
-
- return mOMX->setConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
-}
-
-status_t ACodec::getColorAspects(OMX_U32 portIndex, sp<AMessage> &format) {
- if (!mDescribeColorAspectsIndex) {
- return ERROR_UNSUPPORTED;
- }
+// initial video encoder setup for bytebuffer mode
+status_t ACodec::setColorAspectsForVideoEncoder(
+ const sp<AMessage> &configFormat, sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
+ // copy config to output format as this is not exposed via getFormat
+ copyColorConfig(configFormat, outputFormat);
DescribeColorAspectsParams params;
InitOMXParams(¶ms);
- params.nPortIndex = portIndex;
- ColorAspects &aspects = params.sAspects;
- aspects.mRange = ColorAspects::RangeUnspecified;
- aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
- aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
- aspects.mTransfer = ColorAspects::TransferUnspecified;
+ params.nPortIndex = kPortIndexInput;
+ getColorAspectsFromFormat(configFormat, params.sAspects);
- status_t err = mOMX->getConfig(mNode, mDescribeColorAspectsIndex, ¶ms, sizeof(params));
- if (err != OK) {
- return err;
+ (void)initDescribeColorAspectsIndex();
+
+ int32_t usingRecorder;
+ if (configFormat->findInt32("android._using-recorder", &usingRecorder) && usingRecorder) {
+ android_dataspace dataSpace = HAL_DATASPACE_BT709;
+ int32_t width, height;
+ if (configFormat->findInt32("width", &width)
+ && configFormat->findInt32("height", &height)) {
+ setDefaultCodecColorAspectsIfNeeded(params.sAspects, width, height);
+ status_t err = getDataSpace(
+ params, &dataSpace, mDescribeColorAspectsIndex /* tryCodec */);
+ if (err != OK) {
+ return err;
+ }
+ setColorAspectsIntoFormat(params.sAspects, outputFormat);
+ }
+ inputFormat->setInt32("android._dataspace", (int32_t)dataSpace);
}
- // keep non-standard codec values in extension ranges
- int32_t range, standard, transfer;
- if (convertCodecColorAspectsToPlatformAspects(
- params.sAspects, &range, &standard, &transfer) != OK) {
- ALOGW("[%s] Ignoring invalid color aspects(range=%u, primaries=%u, coeffs=%u, transfer=%u)",
- mComponentName.c_str(),
- aspects.mRange, aspects.mPrimaries, aspects.mMatrixCoeffs, aspects.mTransfer);
- }
-
- // save specified values to format
- if (range != 0) {
- format->setInt32("color-range", range);
- }
- if (standard != 0) {
- format->setInt32("color-standard", standard);
- }
- if (transfer != 0) {
- format->setInt32("color-transfer", transfer);
+ // communicate color aspects to codec, but do not allow change of the platform aspects
+ ColorAspects origAspects = params.sAspects;
+ for (int triesLeft = 2; --triesLeft >= 0; ) {
+ status_t err = setCodecColorAspects(params, true /* readBack */);
+ if (err != OK
+ || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
+ params.sAspects, origAspects, true /* usePlatformAspects */)) {
+ return err;
+ }
+ ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
+ mComponentName.c_str());
}
return OK;
}
+// subsequent initial video encoder setup for surface mode
+status_t ACodec::setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(
+ android_dataspace *dataSpace /* nonnull */) {
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexInput;
+ ColorAspects &aspects = params.sAspects;
+
+ // reset default format and store resulting format into both input and output formats
+ getColorAspectsFromFormat(mConfigFormat, aspects);
+ int32_t width, height;
+ if (mInputFormat->findInt32("width", &width) && mInputFormat->findInt32("height", &height)) {
+ setDefaultCodecColorAspectsIfNeeded(aspects, width, height);
+ }
+ setColorAspectsIntoFormat(aspects, mInputFormat);
+ setColorAspectsIntoFormat(aspects, mOutputFormat);
+
+ // communicate color aspects to codec, but do not allow any change
+ ColorAspects origAspects = aspects;
+ status_t err = OK;
+ for (int triesLeft = 2; mDescribeColorAspectsIndex && --triesLeft >= 0; ) {
+ status_t err = setCodecColorAspects(params, true /* readBack */);
+ if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(aspects, origAspects)) {
+ break;
+ }
+ ALOGW_IF(triesLeft == 0, "[%s] Codec repeatedly changed requested ColorAspects.",
+ mComponentName.c_str());
+ }
+
+ *dataSpace = HAL_DATASPACE_BT709;
+ aspects = origAspects; // restore desired color aspects
+ status_t res = getDataSpace(
+ params, dataSpace, err == OK && mDescribeColorAspectsIndex /* tryCodec */);
+ if (err == OK) {
+ err = res;
+ }
+ mInputFormat->setInt32("android._dataspace", (int32_t)*dataSpace);
+ mInputFormat->setBuffer(
+ "android._color-aspects", ABuffer::CreateAsCopy(&aspects, sizeof(aspects)));
+
+ // update input format with codec supported color aspects (basically set unsupported
+ // aspects to Unspecified)
+ if (err == OK) {
+ (void)getInputColorAspectsForVideoEncoder(mInputFormat);
+ }
+
+ ALOGV("set default color aspects, updated input format to %s, output format to %s",
+ mInputFormat->debugString(4).c_str(), mOutputFormat->debugString(4).c_str());
+
+ return err;
+}
+
status_t ACodec::setupVideoEncoder(
- const char *mime, const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
+ const char *mime, const sp<AMessage> &msg,
+ sp<AMessage> &outputFormat, sp<AMessage> &inputFormat) {
int32_t tmp;
if (!msg->findInt32("color-format", &tmp)) {
return INVALID_OPERATION;
@@ -3355,9 +3509,8 @@
// Set up color aspects on input, but propagate them to the output format, as they will
// not be read back from encoder.
- err = setColorAspects(
- kPortIndexInput, width, height, msg, outputFormat);
- if (err != OK) {
+ err = setColorAspectsForVideoEncoder(msg, outputFormat, inputFormat);
+ if (err == ERROR_UNSUPPORTED) {
ALOGI("[%s] cannot encode color aspects. Ignoring.", mComponentName.c_str());
err = OK;
}
@@ -3694,13 +3847,6 @@
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(level);
}
- // XXX
- if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
- ALOGW("Use baseline profile instead of %d for AVC recording",
- h264type.eProfile);
- h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
- }
-
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
h264type.nSliceHeaderSpacing = 0;
h264type.bUseHadamard = OMX_TRUE;
@@ -3718,6 +3864,23 @@
h264type.bDirect8x8Inference = OMX_FALSE;
h264type.bDirectSpatialTemporal = OMX_FALSE;
h264type.nCabacInitIdc = 0;
+ } else if (h264type.eProfile == OMX_VIDEO_AVCProfileMain ||
+ h264type.eProfile == OMX_VIDEO_AVCProfileHigh) {
+ h264type.nSliceHeaderSpacing = 0;
+ h264type.bUseHadamard = OMX_TRUE;
+ h264type.nRefFrames = 2;
+ h264type.nBFrames = 1;
+ h264type.nPFrames = setPFramesSpacing(iFrameInterval, frameRate);
+ h264type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP | OMX_VIDEO_PictureTypeB;
+ h264type.nRefIdx10ActiveMinus1 = 0;
+ h264type.nRefIdx11ActiveMinus1 = 0;
+ h264type.bEntropyCodingCABAC = OMX_TRUE;
+ h264type.bWeightedPPrediction = OMX_TRUE;
+ h264type.bconstIpred = OMX_TRUE;
+ h264type.bDirect8x8Inference = OMX_TRUE;
+ h264type.bDirectSpatialTemporal = OMX_TRUE;
+ h264type.nCabacInitIdc = 1;
}
if (h264type.nBFrames != 0) {
@@ -4330,47 +4493,58 @@
}
}
- if (portIndex != kPortIndexOutput) {
- // TODO: also get input crop
- break;
+ int32_t width = (int32_t)videoDef->nFrameWidth;
+ int32_t height = (int32_t)videoDef->nFrameHeight;
+
+ if (portIndex == kPortIndexOutput) {
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = portIndex;
+
+ if (mOMX->getConfig(
+ mNode,
+ (portIndex == kPortIndexOutput ?
+ OMX_IndexConfigCommonOutputCrop :
+ OMX_IndexConfigCommonInputCrop),
+ &rect, sizeof(rect)) != OK) {
+ rect.nLeft = 0;
+ rect.nTop = 0;
+ rect.nWidth = videoDef->nFrameWidth;
+ rect.nHeight = videoDef->nFrameHeight;
+ }
+
+ if (rect.nLeft < 0 ||
+ rect.nTop < 0 ||
+ rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
+ rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
+ ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
+ rect.nLeft, rect.nTop,
+ rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
+ videoDef->nFrameWidth, videoDef->nFrameHeight);
+ return BAD_VALUE;
+ }
+
+ notify->setRect(
+ "crop",
+ rect.nLeft,
+ rect.nTop,
+ rect.nLeft + rect.nWidth - 1,
+ rect.nTop + rect.nHeight - 1);
+
+ width = rect.nWidth;
+ height = rect.nHeight;
+
+ android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+ (void)getColorAspectsAndDataSpaceForVideoDecoder(
+ width, height, mConfigFormat, notify,
+ mUsingNativeWindow ? &dataSpace : NULL);
+ if (mUsingNativeWindow) {
+ notify->setInt32("android._dataspace", dataSpace);
+ }
+ } else {
+ (void)getInputColorAspectsForVideoEncoder(notify);
}
- (void)getColorAspects(portIndex, notify);
-
- OMX_CONFIG_RECTTYPE rect;
- InitOMXParams(&rect);
- rect.nPortIndex = portIndex;
-
- if (mOMX->getConfig(
- mNode,
- (portIndex == kPortIndexOutput ?
- OMX_IndexConfigCommonOutputCrop :
- OMX_IndexConfigCommonInputCrop),
- &rect, sizeof(rect)) != OK) {
- rect.nLeft = 0;
- rect.nTop = 0;
- rect.nWidth = videoDef->nFrameWidth;
- rect.nHeight = videoDef->nFrameHeight;
- }
-
- if (rect.nLeft < 0 ||
- rect.nTop < 0 ||
- rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
- rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
- ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
- rect.nLeft, rect.nTop,
- rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
- videoDef->nFrameWidth, videoDef->nFrameHeight);
- return BAD_VALUE;
- }
-
- notify->setRect(
- "crop",
- rect.nLeft,
- rect.nTop,
- rect.nLeft + rect.nWidth - 1,
- rect.nTop + rect.nHeight - 1);
-
break;
}
@@ -4703,6 +4877,45 @@
return OK;
}
+void ACodec::onDataSpaceChanged(android_dataspace dataSpace, const ColorAspects &aspects) {
+ // aspects are normally communicated in ColorAspects
+ int32_t range, standard, transfer;
+ convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
+
+ // if some aspects are unspecified, use dataspace fields
+ if (range != 0) {
+ range = (dataSpace & HAL_DATASPACE_RANGE_MASK) >> HAL_DATASPACE_RANGE_SHIFT;
+ }
+ if (standard != 0) {
+ standard = (dataSpace & HAL_DATASPACE_STANDARD_MASK) >> HAL_DATASPACE_STANDARD_SHIFT;
+ }
+ if (transfer != 0) {
+ transfer = (dataSpace & HAL_DATASPACE_TRANSFER_MASK) >> HAL_DATASPACE_TRANSFER_SHIFT;
+ }
+
+ mOutputFormat = mOutputFormat->dup(); // trigger an output format changed event
+ if (range != 0) {
+ mOutputFormat->setInt32("color-range", range);
+ }
+ if (standard != 0) {
+ mOutputFormat->setInt32("color-standard", standard);
+ }
+ if (transfer != 0) {
+ mOutputFormat->setInt32("color-transfer", transfer);
+ }
+
+ ALOGD("dataspace changed to %#x (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
+ "(R:%d(%s), S:%d(%s), T:%d(%s))",
+ dataSpace,
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer),
+ range, asString((ColorRange)range),
+ standard, asString((ColorStandard)standard),
+ transfer, asString((ColorTransfer)transfer));
+}
+
void ACodec::onOutputFormatChanged() {
// store new output format
mOutputFormat = mBaseOutputFormat->dup();
@@ -4717,17 +4930,22 @@
}
}
-void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> &reply) {
+void ACodec::addKeyFormatChangesToRenderBufferNotification(sp<AMessage> ¬ify) {
AString mime;
CHECK(mOutputFormat->findString("mime", &mime));
- int32_t left, top, right, bottom;
- if (mime == MEDIA_MIMETYPE_VIDEO_RAW &&
- mNativeWindow != NULL &&
- mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
- // notify renderer of the crop change
+ if (mime == MEDIA_MIMETYPE_VIDEO_RAW && mNativeWindow != NULL) {
+ // notify renderer of the crop change and dataspace change
// NOTE: native window uses extended right-bottom coordinate
- reply->setRect("crop", left, top, right + 1, bottom + 1);
+ int32_t left, top, right, bottom;
+ if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
+ notify->setRect("crop", left, top, right + 1, bottom + 1);
+ }
+
+ int32_t dataSpace;
+ if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
+ notify->setInt32("dataspace", dataSpace);
+ }
}
}
@@ -5054,6 +5272,17 @@
bool ACodec::BaseState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ if (event == OMX_EventDataSpaceChanged) {
+ ColorAspects aspects;
+ aspects.mRange = (ColorAspects::Range)((data2 >> 24) & 0xFF);
+ aspects.mPrimaries = (ColorAspects::Primaries)((data2 >> 16) & 0xFF);
+ aspects.mMatrixCoeffs = (ColorAspects::MatrixCoeffs)((data2 >> 8) & 0xFF);
+ aspects.mTransfer = (ColorAspects::Transfer)(data2 & 0xFF);
+
+ mCodec->onDataSpaceChanged((android_dataspace)data1, aspects);
+ return true;
+ }
+
if (event != OMX_EventError) {
ALOGV("[%s] EVENT(%d, 0x%08x, 0x%08x)",
mCodec->mComponentName.c_str(), event, data1, data2);
@@ -5559,6 +5788,13 @@
ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
}
+ int32_t dataSpace;
+ if (msg->findInt32("dataspace", &dataSpace)) {
+ status_t err = native_window_set_buffers_data_space(
+ mCodec->mNativeWindow.get(), (android_dataspace)dataSpace);
+ ALOGW_IF(err != NO_ERROR, "failed to set dataspace: %d", err);
+ }
+
int32_t render;
if (mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
@@ -5682,6 +5918,7 @@
mDeathNotifier.clear();
}
+ mCodec->mUsingNativeWindow = false;
mCodec->mNativeWindow.clear();
mCodec->mNativeWindowUsageBits = 0;
mCodec->mNode = 0;
@@ -6114,6 +6351,17 @@
"using-sw-read-often", !!(usageBits & GRALLOC_USAGE_SW_READ_OFTEN));
}
+ sp<ABuffer> colorAspectsBuffer;
+ if (mCodec->mInputFormat->findBuffer("android._color-aspects", &colorAspectsBuffer)) {
+ err = mCodec->mOMX->setInternalOption(
+ mCodec->mNode, kPortIndexInput, IOMX::INTERNAL_OPTION_COLOR_ASPECTS,
+ colorAspectsBuffer->base(), colorAspectsBuffer->capacity());
+ if (err != OK) {
+ ALOGE("[%s] Unable to configure color aspects (err %d)",
+ mCodec->mComponentName.c_str(), err);
+ return err;
+ }
+ }
return OK;
}
@@ -6124,11 +6372,17 @@
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatInputSurfaceCreated);
- android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
+ android_dataspace dataSpace;
+ status_t err =
+ mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
sp<IGraphicBufferProducer> bufferProducer;
- status_t err = mCodec->mOMX->createInputSurface(
- mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType);
+ if (err == OK) {
+ err = mCodec->mOMX->createInputSurface(
+ mCodec->mNode, kPortIndexInput, dataSpace, &bufferProducer, &mCodec->mInputMetadataType);
+ }
if (err == OK) {
err = setupInputSurface();
@@ -6159,11 +6413,20 @@
CHECK(msg->findObject("input-surface", &obj));
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
- status_t err = mCodec->mOMX->setInputSurface(
- mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
- &mCodec->mInputMetadataType);
+ android_dataspace dataSpace;
+ status_t err =
+ mCodec->setInitialColorAspectsForVideoEncoderSurfaceAndGetDataSpace(&dataSpace);
+ notify->setMessage("input-format", mCodec->mInputFormat);
+ notify->setMessage("output-format", mCodec->mOutputFormat);
if (err == OK) {
+ err = mCodec->mOMX->setInputSurface(
+ mCodec->mNode, kPortIndexInput, surface->getBufferConsumer(),
+ &mCodec->mInputMetadataType);
+ }
+
+ if (err == OK) {
+ surface->getBufferConsumer()->setDefaultBufferDataSpace(dataSpace);
err = setupInputSurface();
}
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 39f73c3..cb974ae 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -758,7 +758,7 @@
mStartTimeUs = 0;
mNumInputBuffers = 0;
mEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- mEncoderDataSpace = HAL_DATASPACE_BT709;
+ mEncoderDataSpace = HAL_DATASPACE_V0_BT709;
if (meta) {
int64_t startTimeUs;
@@ -774,10 +774,10 @@
// apply encoder color format if specified
if (meta->findInt32(kKeyPixelFormat, &mEncoderFormat)) {
- ALOGV("Using encoder format: %#x", mEncoderFormat);
+ ALOGI("Using encoder format: %#x", mEncoderFormat);
}
if (meta->findInt32(kKeyColorSpace, &mEncoderDataSpace)) {
- ALOGV("Using encoder data space: %#x", mEncoderDataSpace);
+ ALOGI("Using encoder data space: %#x", mEncoderDataSpace);
}
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d5a869d..322eab9 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -34,6 +34,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -2083,6 +2084,21 @@
break;
}
+ case FOURCC('c', 'o', 'l', 'r'):
+ {
+ *offset += chunk_size;
+ // this must be in a VisualSampleEntry box under the Sample Description Box ('stsd')
+ // ignore otherwise
+ if (depth >= 2 && mPath[depth - 2] == FOURCC('s', 't', 's', 'd')) {
+ status_t err = parseColorInfo(data_offset, chunk_data_size);
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ break;
+ }
+
case FOURCC('t', 'i', 't', 'l'):
case FOURCC('p', 'e', 'r', 'f'):
case FOURCC('a', 'u', 't', 'h'):
@@ -2663,6 +2679,49 @@
return OK;
}
+status_t MPEG4Extractor::parseColorInfo(off64_t offset, size_t size) {
+ if (size < 4 || size == SIZE_MAX || mLastTrack == NULL) {
+ return ERROR_MALFORMED;
+ }
+
+ uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
+ if (buffer == NULL) {
+ return ERROR_MALFORMED;
+ }
+ if (mDataSource->readAt(offset, buffer, size) != (ssize_t)size) {
+ delete[] buffer;
+ buffer = NULL;
+
+ return ERROR_IO;
+ }
+
+ int32_t type = U32_AT(&buffer[0]);
+ if ((type == FOURCC('n', 'c', 'l', 'x') && size >= 11)
+ || (type == FOURCC('n', 'c', 'l', 'c' && size >= 10))) {
+ int32_t primaries = U16_AT(&buffer[4]);
+ int32_t transfer = U16_AT(&buffer[6]);
+ int32_t coeffs = U16_AT(&buffer[8]);
+ bool fullRange = (type == FOURCC('n', 'c', 'l', 'x')) && (buffer[10] & 128);
+
+ ColorAspects aspects;
+ ColorUtils::convertIsoColorAspectsToCodecAspects(
+ primaries, transfer, coeffs, fullRange, aspects);
+
+ // only store the first color specification
+ if (!mLastTrack->meta->hasData(kKeyColorPrimaries)) {
+ mLastTrack->meta->setInt32(kKeyColorPrimaries, aspects.mPrimaries);
+ mLastTrack->meta->setInt32(kKeyTransferFunction, aspects.mTransfer);
+ mLastTrack->meta->setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
+ mLastTrack->meta->setInt32(kKeyColorRange, aspects.mRange);
+ }
+ }
+
+ delete[] buffer;
+ buffer = NULL;
+
+ return OK;
+}
+
status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
if (size < 4 || size == SIZE_MAX) {
return ERROR_MALFORMED;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index ef0e17f..58bfa67 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
@@ -371,6 +372,7 @@
void writeVmhdBox();
void writeHdlrBox();
void writeTkhdBox(uint32_t now);
+ void writeColrBox();
void writeMp4aEsdsBox();
void writeMp4vEsdsBox();
void writeAudioFourCCBox();
@@ -2300,6 +2302,7 @@
const bool hasMultipleTracks = (mOwner->numTracks() > 1);
int64_t chunkTimestampUs = 0;
int32_t nChunks = 0;
+ int32_t nActualFrames = 0; // frames containing non-CSD data (non-0 length)
int32_t nZeroLengthFrames = 0;
int64_t lastTimestampUs = 0; // Previous sample time stamp
int64_t lastDurationUs = 0; // Between the previous two samples
@@ -2352,23 +2355,31 @@
int32_t isCodecConfig;
if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
&& isCodecConfig) {
- CHECK(!mGotAllCodecSpecificData);
+ // if config format (at track addition) already had CSD, keep that
+ // UNLESS we have not received any frames yet.
+ // TODO: for now the entire CSD has to come in one frame for encoders, even though
+ // they need to be spread out for decoders.
+ if (mGotAllCodecSpecificData && nActualFrames > 0) {
+ ALOGI("ignoring additional CSD for video track after first frame");
+ } else {
+ mMeta = mSource->getFormat(); // get output format after format change
- if (mIsAvc) {
- status_t err = makeAVCCodecSpecificData(
- (const uint8_t *)buffer->data()
- + buffer->range_offset(),
- buffer->range_length());
- CHECK_EQ((status_t)OK, err);
- } else if (mIsHevc) {
- status_t err = makeHEVCCodecSpecificData(
- (const uint8_t *)buffer->data()
- + buffer->range_offset(),
- buffer->range_length());
- CHECK_EQ((status_t)OK, err);
- } else if (mIsMPEG4) {
- copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
- buffer->range_length());
+ if (mIsAvc) {
+ status_t err = makeAVCCodecSpecificData(
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+ CHECK_EQ((status_t)OK, err);
+ } else if (mIsHevc) {
+ status_t err = makeHEVCCodecSpecificData(
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+ CHECK_EQ((status_t)OK, err);
+ } else if (mIsMPEG4) {
+ copyCodecSpecificData((const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+ }
}
buffer->release();
@@ -2378,6 +2389,8 @@
continue;
}
+ ++nActualFrames;
+
// Make a deep copy of the MediaBuffer and Metadata and release
// the original as soon as we can
MediaBuffer *copy = new MediaBuffer(buffer->range_length());
@@ -2960,9 +2973,32 @@
}
writePaspBox();
+ writeColrBox();
mOwner->endBox(); // mp4v, s263 or avc1
}
+void MPEG4Writer::Track::writeColrBox() {
+ ColorAspects aspects;
+ memset(&aspects, 0, sizeof(aspects));
+ // TRICKY: using | instead of || because we want to execute all findInt32-s
+ if (mMeta->findInt32(kKeyColorPrimaries, (int32_t*)&aspects.mPrimaries)
+ | mMeta->findInt32(kKeyTransferFunction, (int32_t*)&aspects.mTransfer)
+ | mMeta->findInt32(kKeyColorMatrix, (int32_t*)&aspects.mMatrixCoeffs)
+ | mMeta->findInt32(kKeyColorRange, (int32_t*)&aspects.mRange)) {
+ int32_t primaries, transfer, coeffs;
+ bool fullRange;
+ ColorUtils::convertCodecColorAspectsToIsoAspects(
+ aspects, &primaries, &transfer, &coeffs, &fullRange);
+ mOwner->beginBox("colr");
+ mOwner->writeFourcc("nclx");
+ mOwner->writeInt16(primaries);
+ mOwner->writeInt16(transfer);
+ mOwner->writeInt16(coeffs);
+ mOwner->writeInt8(fullRange ? 128 : 0);
+ mOwner->endBox(); // colr
+ }
+}
+
void MPEG4Writer::Track::writeAudioFourCCBox() {
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 84ccd2d..e8cd58a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1266,7 +1266,10 @@
CHECK(msg->findMessage("input-format", &mInputFormat));
CHECK(msg->findMessage("output-format", &mOutputFormat));
-
+ ALOGV("[%s] configured as input format: %s, output format: %s",
+ mComponentName.c_str(),
+ mInputFormat->debugString(4).c_str(),
+ mOutputFormat->debugString(4).c_str());
int32_t usingSwRenderer;
if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
&& usingSwRenderer) {
@@ -1285,6 +1288,12 @@
if (!msg->findInt32("err", &err)) {
sp<RefBase> obj;
msg->findObject("input-surface", &obj);
+ CHECK(msg->findMessage("input-format", &mInputFormat));
+ CHECK(msg->findMessage("output-format", &mOutputFormat));
+ ALOGV("[%s] input surface created as input format: %s, output format: %s",
+ mComponentName.c_str(),
+ mInputFormat->debugString(4).c_str(),
+ mOutputFormat->debugString(4).c_str());
CHECK(obj != NULL);
response->setObject("input-surface", obj);
mHaveInputSurface = true;
@@ -1398,16 +1407,29 @@
case CodecBase::kWhatOutputFormatChanged:
{
- ALOGV("codec output format changed");
-
CHECK(msg->findMessage("format", &mOutputFormat));
+ ALOGV("[%s] output format changed to: %s",
+ mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
+
if (mSoftRenderer == NULL &&
mSurface != NULL &&
(mFlags & kFlagUsesSoftwareRenderer)) {
AString mime;
CHECK(mOutputFormat->findString("mime", &mime));
+ // TODO: propagate color aspects to software renderer to allow better
+ // color conversion to RGB. For now, just mark dataspace for YUV
+ // rendering.
+ int32_t dataSpace;
+ if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
+ ALOGD("[%s] setting dataspace on output surface to #%x",
+ mComponentName.c_str(), dataSpace);
+ int err = native_window_set_buffers_data_space(
+ mSurface.get(), (android_dataspace)dataSpace);
+ ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
+ }
+
if (mime.startsWithIgnoreCase("video/")) {
mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
}
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 5f9a1c0..0a052d2 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -40,8 +40,9 @@
namespace android {
-const int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
-const int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
+const int32_t kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
+const int32_t kDefaultHwVideoEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+const int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_V0_BT709;
const int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
@@ -515,13 +516,19 @@
sp<AMessage> inputFormat;
int32_t usingSwReadOften;
mSetEncoderFormat = false;
- if (mEncoder->getInputFormat(&inputFormat) == OK
- && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
- && usingSwReadOften) {
- // this is a SW encoder; signal source to allocate SW readable buffers
+ if (mEncoder->getInputFormat(&inputFormat) == OK) {
mSetEncoderFormat = true;
- mEncoderFormat = kDefaultSwVideoEncoderFormat;
- mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace;
+ if (inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
+ && usingSwReadOften) {
+ // this is a SW encoder; signal source to allocate SW readable buffers
+ mEncoderFormat = kDefaultSwVideoEncoderFormat;
+ } else {
+ mEncoderFormat = kDefaultHwVideoEncoderFormat;
+ }
+ if (!inputFormat->findInt32("android._dataspace", &mEncoderDataSpace)) {
+ mEncoderDataSpace = kDefaultVideoEncoderDataSpace;
+ }
+ ALOGV("setting dataspace %#x, format %#x", mEncoderDataSpace, mEncoderFormat);
}
err = mEncoder->start();
@@ -774,6 +781,13 @@
mAvailEncoderInputIndices.push_back(index);
feedEncoderInputBuffers();
+ } else if (cbID == MediaCodec::CB_OUTPUT_FORMAT_CHANGED) {
+ status_t err = mEncoder->getOutputFormat(&mOutputFormat);
+ if (err != OK) {
+ signalEOS(err);
+ break;
+ }
+ convertMessageToMetaData(mOutputFormat, mMeta);
} else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
int32_t index;
size_t offset;
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
index db3e058..8165f69 100644
--- a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -51,11 +51,11 @@
#define vo_shr_r(var1, var2) ((var1+((Word16)(1L<<(var2-1))))>>var2)
#define vo_sub(a,b) (a - b)
#define vo_L_deposit_h(a) ((Word32)((a) << 16))
-#define vo_round(a) ((a + 0x00008000) >> 16)
+#define vo_round(a) ((((a) >> 15) + 1) >> 1)
#define vo_extract_l(a) ((Word16)(a))
#define vo_L_add(a,b) (a + b)
#define vo_L_sub(a,b) (a - b)
-#define vo_mult_r(a,b) ((( a * b ) + 0x4000 ) >> 15 )
+#define vo_mult_r(a,b) (((( a * b ) >> 14) + 1 ) >> 1 )
#define vo_negate(a) (-a)
#define vo_L_shr_r(L_var1, var2) ((L_var1+((Word32)(1L<<(var2-1))))>>var2)
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
index 8bf15ea..4d877f1 100644
--- a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -267,13 +267,13 @@
for (i = 0; i < L_SUBFR/4; i++)
{
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
- s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ s = L_add((k_cn* (*p0++)), (k_dn * (*p1++)));
*p2++ = s >> 7;
}
@@ -342,7 +342,7 @@
{
*h++ = 0;
*h_inv++ = 0;
- L_tmp += (H[i] * H[i]) << 1;
+ L_tmp = L_add(L_tmp, (H[i] * H[i]) << 1);
}
/* scale h[] down (/2) when energy of h[] is high with many pulses used */
val = extract_h(L_tmp);
@@ -386,16 +386,16 @@
cor = 0x00008000L; /* for rounding */
for (i = 0; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p3-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p2-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p1-- = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h1)));
ptr_h1++;
*p0-- = extract_h(cor);
}
@@ -425,19 +425,19 @@
for (i = k + 1; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p0 = extract_h(cor);
@@ -447,15 +447,15 @@
p1 -= (NB_POS + 1);
p0 -= (NB_POS + 1);
}
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
@@ -482,19 +482,19 @@
for (i = k + 1; i < NB_POS; i++)
{
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p2 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p1 = extract_h(cor);
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p0 = extract_h(cor);
@@ -504,7 +504,7 @@
p1 -= (NB_POS + 1);
p0 -= (NB_POS + 1);
}
- cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ cor = L_add(cor, vo_L_mult((*ptr_h1), (*ptr_h2)));
ptr_h1++;
ptr_h2++;
*p3 = extract_h(cor);
@@ -698,7 +698,7 @@
}
/* memorise the best codevector */
ps = vo_mult(ps, ps);
- s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp);
+ s = L_sub(vo_L_mult(alpk, ps), vo_L_mult(psk, alp));
if (s > 0)
{
psk = ps;
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 2008574..6ec8c41 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -1020,6 +1020,7 @@
}
mIInterval = avcType->nPFrames + avcType->nBFrames;
+ mConstrainedIntraFlag = avcType->bconstIpred;
if (OMX_VIDEO_AVCLoopFilterDisable == avcType->eLoopFilterMode)
mDisableDeblkLevel = 4;
@@ -1029,7 +1030,6 @@
|| avcType->nRefIdx10ActiveMinus1 != 0
|| avcType->nRefIdx11ActiveMinus1 != 0
|| avcType->bWeightedPPrediction != OMX_FALSE
- || avcType->bconstIpred != OMX_FALSE
|| avcType->bDirect8x8Inference != OMX_FALSE
|| avcType->bDirectSpatialTemporal != OMX_FALSE
|| avcType->nCabacInitIdc != 0) {
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index e92c192..bbc4d26 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -363,6 +363,16 @@
}
}
+ // TODO: propagate color aspects to software renderer to allow better
+ // color conversion to RGB. For now, just mark dataspace for YUV rendering.
+ android_dataspace dataSpace;
+ if (format->findInt32("android._dataspace", (int32_t *)&dataSpace) && dataSpace != mDataSpace) {
+ ALOGD("setting dataspace on output surface to #%x", dataSpace);
+ if ((err = native_window_set_buffers_data_space(mNativeWindow.get(), dataSpace))) {
+ ALOGW("failed to set dataspace on surface (%d)", err);
+ }
+ mDataSpace = dataSpace;
+ }
if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf, -1)) != 0) {
ALOGW("Surface::queueBuffer returned error %d", err);
} else {
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
index 2b86b0e..99031ca 100644
--- a/media/libstagefright/foundation/ColorUtils.cpp
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -29,6 +29,7 @@
typedef ColorAspects CA;
typedef ColorUtils CU;
+const static
ALookup<CU::ColorRange, CA::Range> sRanges{
{
{ CU::kColorRangeLimited, CA::RangeLimited },
@@ -37,6 +38,7 @@
}
};
+const static
ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandards {
{
{ CU::kColorStandardUnspecified, { CA::PrimariesUnspecified, CA::MatrixUnspecified } },
@@ -56,6 +58,7 @@
}
};
+const static
ALookup<CU::ColorTransfer, CA::Transfer> sTransfers{
{
{ CU::kColorTransferUnspecified, CA::TransferUnspecified },
@@ -243,31 +246,95 @@
}
}
+const static
+ALookup<int32_t, ColorAspects::Primaries> sIsoPrimaries {
+ {
+ { 1, ColorAspects::PrimariesBT709_5 },
+ { 2, ColorAspects::PrimariesUnspecified },
+ { 4, ColorAspects::PrimariesBT470_6M },
+ { 5, ColorAspects::PrimariesBT601_6_625 },
+ { 6, ColorAspects::PrimariesBT601_6_525 /* main */},
+ { 7, ColorAspects::PrimariesBT601_6_525 },
+ // -- ITU T.832 201201 ends here
+ { 8, ColorAspects::PrimariesGenericFilm },
+ { 9, ColorAspects::PrimariesBT2020 },
+ { 10, ColorAspects::PrimariesOther /* XYZ */ },
+ }
+};
+
+const static
+ALookup<int32_t, ColorAspects::Transfer> sIsoTransfers {
+ {
+ { 1, ColorAspects::TransferSMPTE170M /* main */},
+ { 2, ColorAspects::TransferUnspecified },
+ { 4, ColorAspects::TransferGamma22 },
+ { 5, ColorAspects::TransferGamma28 },
+ { 6, ColorAspects::TransferSMPTE170M },
+ { 7, ColorAspects::TransferSMPTE240M },
+ { 8, ColorAspects::TransferLinear },
+ { 9, ColorAspects::TransferOther /* log 100:1 */ },
+ { 10, ColorAspects::TransferOther /* log 316:1 */ },
+ { 11, ColorAspects::TransferXvYCC },
+ { 12, ColorAspects::TransferBT1361 },
+ { 13, ColorAspects::TransferSRGB },
+ // -- ITU T.832 201201 ends here
+ { 14, ColorAspects::TransferSMPTE170M },
+ { 15, ColorAspects::TransferSMPTE170M },
+ { 16, ColorAspects::TransferST2084 },
+ { 17, ColorAspects::TransferST428 },
+ }
+};
+
+const static
+ALookup<int32_t, ColorAspects::MatrixCoeffs> sIsoMatrixCoeffs {
+ {
+ { 0, ColorAspects::MatrixOther },
+ { 1, ColorAspects::MatrixBT709_5 },
+ { 2, ColorAspects::MatrixUnspecified },
+ { 4, ColorAspects::MatrixBT470_6M },
+ { 6, ColorAspects::MatrixBT601_6 /* main */ },
+ { 5, ColorAspects::MatrixBT601_6 },
+ { 7, ColorAspects::MatrixSMPTE240M },
+ { 8, ColorAspects::MatrixOther /* YCgCo */ },
+ // -- ITU T.832 201201 ends here
+ { 9, ColorAspects::MatrixBT2020 },
+ { 10, ColorAspects::MatrixBT2020Constant },
+ }
+};
+
// static
-void ColorUtils::setDefaultPlatformColorAspectsIfNeeded(
- int32_t &range, int32_t &standard, int32_t &transfer,
- int32_t width, int32_t height) {
- if (range == ColorUtils::kColorRangeUnspecified) {
- range = ColorUtils::kColorRangeLimited;
+void ColorUtils::convertCodecColorAspectsToIsoAspects(
+ const ColorAspects &aspects,
+ int32_t *primaries, int32_t *transfer, int32_t *coeffs, bool *fullRange) {
+ if (aspects.mPrimaries == ColorAspects::PrimariesOther ||
+ !sIsoPrimaries.map(aspects.mPrimaries, primaries)) {
+ CHECK(sIsoPrimaries.map(ColorAspects::PrimariesUnspecified, primaries));
}
+ if (aspects.mTransfer == ColorAspects::TransferOther ||
+ !sIsoTransfers.map(aspects.mTransfer, transfer)) {
+ CHECK(sIsoTransfers.map(ColorAspects::TransferUnspecified, transfer));
+ }
+ if (aspects.mMatrixCoeffs == ColorAspects::MatrixOther ||
+ !sIsoMatrixCoeffs.map(aspects.mMatrixCoeffs, coeffs)) {
+ CHECK(sIsoMatrixCoeffs.map(ColorAspects::MatrixUnspecified, coeffs));
+ }
+ *fullRange = aspects.mRange == ColorAspects::RangeFull;
+}
- if (standard == ColorUtils::kColorStandardUnspecified) {
- // Default to BT2020, BT709 or BT601 based on size. Allow 2.35:1 aspect ratio. Limit BT601
- // to PAL or smaller, BT2020 to 4K or larger, leaving BT709 for all resolutions in between.
- if (width >= 3840 || height >= 3840 || width * (int64_t)height >= 3840 * 1634) {
- standard = ColorUtils::kColorStandardBT2020;
- } else if ((width <= 720 && height > 480) || (height <= 720 && width > 480)) {
- standard = ColorUtils::kColorStandardBT601_625;
- } else if ((width <= 720 && height <= 480) || (height <= 720 && width <= 480)) {
- standard = ColorUtils::kColorStandardBT601_525;
- } else {
- standard = ColorUtils::kColorStandardBT709;
- }
+// static
+void ColorUtils::convertIsoColorAspectsToCodecAspects(
+ int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
+ ColorAspects &aspects) {
+ if (!sIsoPrimaries.map(primaries, &aspects.mPrimaries)) {
+ aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
}
-
- if (transfer == ColorUtils::kColorTransferUnspecified) {
- transfer = ColorUtils::kColorTransferSMPTE_170M;
+ if (!sIsoTransfers.map(transfer, &aspects.mTransfer)) {
+ aspects.mTransfer = ColorAspects::TransferUnspecified;
}
+ if (!sIsoMatrixCoeffs.map(coeffs, &aspects.mMatrixCoeffs)) {
+ aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ }
+ aspects.mRange = fullRange ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
}
// static
@@ -308,5 +375,208 @@
}
}
+// TODO: move this into a Video HAL
+ALookup<CU::ColorStandard, std::pair<CA::Primaries, CA::MatrixCoeffs>> sStandardFallbacks {
+ {
+ { CU::kColorStandardBT601_625, { CA::PrimariesBT709_5, CA::MatrixBT470_6M } },
+ { CU::kColorStandardBT601_625, { CA::PrimariesBT709_5, CA::MatrixBT601_6 } },
+ { CU::kColorStandardBT709, { CA::PrimariesBT709_5, CA::MatrixSMPTE240M } },
+ { CU::kColorStandardBT709, { CA::PrimariesBT709_5, CA::MatrixBT2020 } },
+ { CU::kColorStandardBT601_525, { CA::PrimariesBT709_5, CA::MatrixBT2020Constant } },
+
+ { CU::kColorStandardBT2020Constant,
+ { CA::PrimariesBT470_6M, CA::MatrixBT2020Constant } },
+
+ { CU::kColorStandardBT601_625, { CA::PrimariesBT601_6_625, CA::MatrixBT470_6M } },
+ { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_625, CA::MatrixBT2020Constant } },
+
+ { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_525, CA::MatrixBT470_6M } },
+ { CU::kColorStandardBT601_525, { CA::PrimariesBT601_6_525, CA::MatrixBT2020Constant } },
+
+ { CU::kColorStandardBT2020Constant,
+ { CA::PrimariesGenericFilm, CA::MatrixBT2020Constant } },
+ }
+};
+
+ALookup<CU::ColorStandard, CA::Primaries> sStandardPrimariesFallbacks {
+ {
+ { CU::kColorStandardFilm, CA::PrimariesGenericFilm },
+ { CU::kColorStandardBT470M, CA::PrimariesBT470_6M },
+ { CU::kColorStandardBT2020, CA::PrimariesBT2020 },
+ { CU::kColorStandardBT601_525_Unadjusted, CA::PrimariesBT601_6_525 },
+ { CU::kColorStandardBT601_625_Unadjusted, CA::PrimariesBT601_6_625 },
+ }
+};
+
+static ALookup<android_dataspace, android_dataspace> sLegacyDataSpaceToV0 {
+ {
+ { HAL_DATASPACE_SRGB, HAL_DATASPACE_V0_SRGB },
+ { HAL_DATASPACE_BT709, HAL_DATASPACE_V0_BT709 },
+ { HAL_DATASPACE_SRGB_LINEAR, HAL_DATASPACE_V0_SRGB_LINEAR },
+ { HAL_DATASPACE_BT601_525, HAL_DATASPACE_V0_BT601_525 },
+ { HAL_DATASPACE_BT601_625, HAL_DATASPACE_V0_BT601_625 },
+ { HAL_DATASPACE_JFIF, HAL_DATASPACE_V0_JFIF },
+ }
+};
+
+bool ColorUtils::convertDataSpaceToV0(android_dataspace &dataSpace) {
+ (void)sLegacyDataSpaceToV0.lookup(dataSpace, &dataSpace);
+ return (dataSpace & 0xC000FFFF) == 0;
+}
+
+bool ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
+ ColorAspects &aspects, const ColorAspects &orig, bool usePlatformAspects) {
+ // remove changed aspects (change them to Unspecified)
+ bool changed = false;
+ if (aspects.mRange && aspects.mRange != orig.mRange) {
+ aspects.mRange = ColorAspects::RangeUnspecified;
+ changed = true;
+ }
+ if (aspects.mPrimaries && aspects.mPrimaries != orig.mPrimaries) {
+ aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+ if (usePlatformAspects) {
+ aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ }
+ changed = true;
+ }
+ if (aspects.mMatrixCoeffs && aspects.mMatrixCoeffs != orig.mMatrixCoeffs) {
+ aspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified;
+ if (usePlatformAspects) {
+ aspects.mPrimaries = ColorAspects::PrimariesUnspecified;
+ }
+ changed = true;
+ }
+ if (aspects.mTransfer && aspects.mTransfer != orig.mTransfer) {
+ aspects.mTransfer = ColorAspects::TransferUnspecified;
+ changed = true;
+ }
+ return changed;
+}
+
+// static
+android_dataspace ColorUtils::getDataSpaceForColorAspects(ColorAspects &aspects, bool mayExpand) {
+ // This platform implementation never expands color space (e.g. returns an expanded
+ // dataspace to use where the codec does in-the-background color space conversion)
+ mayExpand = false;
+
+ if (aspects.mRange == ColorAspects::RangeUnspecified
+ || aspects.mPrimaries == ColorAspects::PrimariesUnspecified
+ || aspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified
+ || aspects.mTransfer == ColorAspects::TransferUnspecified) {
+ ALOGW("expected specified color aspects (%u:%u:%u:%u)",
+ aspects.mRange, aspects.mPrimaries, aspects.mMatrixCoeffs, aspects.mTransfer);
+ }
+
+ // default to video range and transfer
+ ColorRange range = kColorRangeLimited;
+ ColorTransfer transfer = kColorTransferSMPTE_170M;
+ (void)sRanges.map(aspects.mRange, &range);
+ (void)sTransfers.map(aspects.mTransfer, &transfer);
+
+ ColorStandard standard = kColorStandardBT709;
+ auto pair = std::make_pair(aspects.mPrimaries, aspects.mMatrixCoeffs);
+ if (!sStandards.map(pair, &standard)) {
+ if (!sStandardFallbacks.map(pair, &standard)) {
+ (void)sStandardPrimariesFallbacks.map(aspects.mPrimaries, &standard);
+
+ if (aspects.mMatrixCoeffs == ColorAspects::MatrixBT2020Constant) {
+ range = kColorRangeFull;
+ }
+ }
+ }
+
+ android_dataspace dataSpace = (android_dataspace)(
+ (range << HAL_DATASPACE_RANGE_SHIFT) | (standard << HAL_DATASPACE_STANDARD_SHIFT) |
+ (transfer << HAL_DATASPACE_TRANSFER_SHIFT));
+ (void)sLegacyDataSpaceToV0.rlookup(dataSpace, &dataSpace);
+
+ if (!mayExpand) {
+ // update codec aspects based on dataspace
+ convertPlatformColorAspectsToCodecAspects(range, standard, transfer, aspects);
+ }
+ return dataSpace;
+}
+
+// static
+void ColorUtils::getColorConfigFromFormat(
+ const sp<AMessage> &format, int32_t *range, int32_t *standard, int32_t *transfer) {
+ if (!format->findInt32("color-range", range)) {
+ *range = kColorRangeUnspecified;
+ }
+ if (!format->findInt32("color-standard", standard)) {
+ *standard = kColorStandardUnspecified;
+ }
+ if (!format->findInt32("color-transfer", transfer)) {
+ *transfer = kColorTransferUnspecified;
+ }
+}
+
+// static
+void ColorUtils::copyColorConfig(const sp<AMessage> &source, sp<AMessage> &target) {
+ // 0 values are unspecified
+ int32_t value;
+ if (source->findInt32("color-range", &value)) {
+ target->setInt32("color-range", value);
+ }
+ if (source->findInt32("color-standard", &value)) {
+ target->setInt32("color-standard", value);
+ }
+ if (source->findInt32("color-transfer", &value)) {
+ target->setInt32("color-transfer", value);
+ }
+}
+
+// static
+void ColorUtils::getColorAspectsFromFormat(const sp<AMessage> &format, ColorAspects &aspects) {
+ int32_t range, standard, transfer;
+ getColorConfigFromFormat(format, &range, &standard, &transfer);
+
+ if (convertPlatformColorAspectsToCodecAspects(
+ range, standard, transfer, aspects) != OK) {
+ ALOGW("Ignoring illegal color aspects(R:%d(%s), S:%d(%s), T:%d(%s))",
+ range, asString((ColorRange)range),
+ standard, asString((ColorStandard)standard),
+ transfer, asString((ColorTransfer)transfer));
+ // Invalid values were converted to unspecified !params!, but otherwise were not changed
+ // For encoders, we leave these as is. For decoders, we will use default values.
+ }
+ ALOGV("Got color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
+ "from format (out:R:%d(%s), S:%d(%s), T:%d(%s))",
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer),
+ range, asString((ColorRange)range),
+ standard, asString((ColorStandard)standard),
+ transfer, asString((ColorTransfer)transfer));
+}
+
+// static
+void ColorUtils::setColorAspectsIntoFormat(
+ const ColorAspects &aspects, sp<AMessage> &format, bool force) {
+ int32_t range = 0, standard = 0, transfer = 0;
+ convertCodecColorAspectsToPlatformAspects(aspects, &range, &standard, &transfer);
+ // save set values to base output format
+ // (encoder input format will read back actually supported values by the codec)
+ if (range != 0 || force) {
+ format->setInt32("color-range", range);
+ }
+ if (standard != 0 || force) {
+ format->setInt32("color-standard", standard);
+ }
+ if (transfer != 0 || force) {
+ format->setInt32("color-transfer", transfer);
+ }
+ ALOGV("Setting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) "
+ "into format (out:R:%d(%s), S:%d(%s), T:%d(%s))",
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer),
+ range, asString((ColorRange)range),
+ standard, asString((ColorStandard)standard),
+ transfer, asString((ColorTransfer)transfer));
+}
+
} // namespace android
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index 3e8fb7c..18b14e1 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -110,6 +110,7 @@
status_t readMetaData();
status_t parseChunk(off64_t *offset, int depth);
status_t parseITunesMetaData(off64_t offset, size_t size);
+ status_t parseColorInfo(off64_t offset, size_t size);
status_t parse3GPPMetaData(off64_t offset, size_t size, int depth);
void parseID3v2MetaData(off64_t offset);
status_t parseQTMetaKey(off64_t data_offset, size_t data_size);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 4220358..25c3773 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -94,6 +94,8 @@
status_t signalEndOfInputStream();
+ void signalEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2);
+
status_t allocateSecureBuffer(
OMX_U32 portIndex, size_t size, OMX::buffer_id *buffer,
void **buffer_data, native_handle_t **native_handle);
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 757b308..258511a 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -54,6 +54,7 @@
int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
int32_t mCropWidth, mCropHeight;
int32_t mRotationDegrees;
+ android_dataspace mDataSpace;
FrameRenderTracker mRenderTracker;
SoftwareRenderer(const SoftwareRenderer &);
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index a7c2279..995e50e 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -20,12 +20,16 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
+
#include "GraphicBufferSource.h"
+#include "OMXUtils.h"
#include <OMX_Core.h>
#include <OMX_IndexExt.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
#include <media/hardware/MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
@@ -39,6 +43,8 @@
static const bool EXTRA_CHECK = true;
+static const OMX_U32 kPortIndexInput = 0;
+
GraphicBufferSource::PersistentProxyListener::PersistentProxyListener(
const wp<IGraphicBufferConsumer> &consumer,
const wp<ConsumerListener>& consumerListener) :
@@ -218,6 +224,8 @@
mNumFramesAvailable, mCodecBuffers.size());
CHECK(!mExecuting);
mExecuting = true;
+ mLastDataSpace = HAL_DATASPACE_UNKNOWN;
+ ALOGV("clearing last dataSpace");
// Start by loading up as many buffers as possible. We want to do this,
// rather than just submit the first buffer, to avoid a degenerate case:
@@ -498,6 +506,76 @@
}
}
+void GraphicBufferSource::onDataSpaceChanged_l(
+ android_dataspace dataSpace, android_pixel_format pixelFormat) {
+ ALOGD("got buffer with new dataSpace #%x", dataSpace);
+ mLastDataSpace = dataSpace;
+
+ if (ColorUtils::convertDataSpaceToV0(dataSpace)) {
+ ColorAspects aspects = mColorAspects; // initially requested aspects
+
+ // request color aspects to encode
+ OMX_INDEXTYPE index;
+ status_t err = mNodeInstance->getExtensionIndex(
+ "OMX.google.android.index.describeColorAspects", &index);
+ if (err == OK) {
+ // V0 dataspace
+ DescribeColorAspectsParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = kPortIndexInput;
+ params.nDataSpace = mLastDataSpace;
+ params.nPixelFormat = pixelFormat;
+ params.bDataSpaceChanged = OMX_TRUE;
+ params.sAspects = mColorAspects;
+
+ err = mNodeInstance->getConfig(index, ¶ms, sizeof(params));
+ if (err == OK) {
+ aspects = params.sAspects;
+ ALOGD("Codec resolved it to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ params.sAspects.mRange, asString(params.sAspects.mRange),
+ params.sAspects.mPrimaries, asString(params.sAspects.mPrimaries),
+ params.sAspects.mMatrixCoeffs, asString(params.sAspects.mMatrixCoeffs),
+ params.sAspects.mTransfer, asString(params.sAspects.mTransfer),
+ err, asString(err));
+ } else {
+ params.sAspects = aspects;
+ err = OK;
+ }
+ params.bDataSpaceChanged = OMX_FALSE;
+ for (int triesLeft = 2; --triesLeft >= 0; ) {
+ status_t err = mNodeInstance->setConfig(index, ¶ms, sizeof(params));
+ if (err == OK) {
+ err = mNodeInstance->getConfig(index, ¶ms, sizeof(params));
+ }
+ if (err != OK || !ColorUtils::checkIfAspectsChangedAndUnspecifyThem(
+ params.sAspects, aspects)) {
+ // if we can't set or get color aspects, still communicate dataspace to client
+ break;
+ }
+
+ ALOGW_IF(triesLeft == 0, "Codec repeatedly changed requested ColorAspects.");
+ }
+ }
+
+ ALOGV("Set color aspects to (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s)) err=%d(%s)",
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer),
+ err, asString(err));
+
+ // signal client that the dataspace has changed; this will update the output format
+ // TODO: we should tie this to an output buffer somehow, and signal the change
+ // just before the output buffer is returned to the client, but there are many
+ // ways this could fail (e.g. flushing), and we are not yet supporting this scenario.
+
+ mNodeInstance->signalEvent(
+ OMX_EventDataSpaceChanged, dataSpace,
+ (aspects.mRange << 24) | (aspects.mPrimaries << 16)
+ | (aspects.mMatrixCoeffs << 8) | aspects.mTransfer);
+ }
+}
+
bool GraphicBufferSource::fillCodecBuffer_l() {
CHECK(mExecuting && mNumFramesAvailable > 0);
@@ -537,6 +615,12 @@
mBufferSlot[item.mSlot] = item.mGraphicBuffer;
}
+ if (item.mDataSpace != mLastDataSpace) {
+ onDataSpaceChanged_l(
+ item.mDataSpace, (android_pixel_format)mBufferSlot[item.mSlot]->getPixelFormat());
+ }
+
+
err = UNKNOWN_ERROR;
// only submit sample if start time is unspecified, or sample
@@ -929,6 +1013,7 @@
}
void GraphicBufferSource::setDefaultDataSpace(android_dataspace dataSpace) {
+ // no need for mutex as we are not yet running
ALOGD("setting dataspace: %#x", dataSpace);
mConsumer->setDefaultBufferDataSpace(dataSpace);
mLastDataSpace = dataSpace;
@@ -999,6 +1084,11 @@
void GraphicBufferSource::setColorAspects(const ColorAspects &aspects) {
Mutex::Autolock autoLock(mMutex);
mColorAspects = aspects;
+ ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
+ aspects.mRange, asString(aspects.mRange),
+ aspects.mPrimaries, asString(aspects.mPrimaries),
+ aspects.mMatrixCoeffs, asString(aspects.mMatrixCoeffs),
+ aspects.mTransfer, asString(aspects.mTransfer));
}
void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 87f4a60..c8b0e62 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -248,6 +248,9 @@
bool repeatLatestBuffer_l();
int64_t getTimestamp(const BufferItem &item);
+ // called when the data space of the input buffer changes
+ void onDataSpaceChanged_l(android_dataspace dataSpace, android_pixel_format pixelFormat);
+
// Lock, covers all member variables.
mutable Mutex mMutex;
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 278d23c..6b7a871 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -991,6 +991,10 @@
return createGraphicBufferSource(portIndex, bufferConsumer, type);
}
+void OMXNodeInstance::signalEvent(OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
+ mOwner->OnEvent(mNodeID, event, arg1, arg2, NULL);
+}
+
status_t OMXNodeInstance::signalEndOfInputStream() {
// For non-Surface input, the MediaCodec should convert the call to a
// pair of requests (dequeue input buffer, queue input buffer with EOS
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 5980b58..d07ca85 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -552,7 +552,7 @@
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
pid_t tid,
- int *sessionId,
+ audio_session_t *sessionId,
int clientUid,
status_t *status)
{
@@ -560,7 +560,7 @@
sp<TrackHandle> trackHandle;
sp<Client> client;
status_t lStatus;
- int lSessionId;
+ audio_session_t lSessionId;
// client AudioTrack::set already implements AUDIO_STREAM_DEFAULT => AUDIO_STREAM_MUSIC,
// but if someone uses binder directly they could bypass that and cause us to crash
@@ -631,7 +631,7 @@
}
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -667,7 +667,7 @@
}
}
- setAudioHwSyncForSession_l(thread, (audio_session_t)lSessionId);
+ setAudioHwSyncForSession_l(thread, lSessionId);
}
if (lStatus != NO_ERROR) {
@@ -1075,10 +1075,10 @@
audio_devices_t device = thread->inDevice();
bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff;
// collect all of the thread's session IDs
- KeyedVector<int, bool> ids = thread->sessionIds();
+ KeyedVector<audio_session_t, bool> ids = thread->sessionIds();
// suspend effects associated with those session IDs
for (size_t j = 0; j < ids.size(); ++j) {
- int sessionId = ids.keyAt(j);
+ audio_session_t sessionId = ids.keyAt(j);
thread->setEffectSuspended(FX_IID_AEC,
suspend,
sessionId);
@@ -1344,7 +1344,8 @@
}
// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId, int EffectId)
+sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+ int EffectId)
{
sp<PlaybackThread> thread;
@@ -1423,7 +1424,7 @@
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int clientUid,
- int *sessionId,
+ audio_session_t *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
sp<IMemory>& buffers,
@@ -1433,7 +1434,7 @@
sp<RecordHandle> recordHandle;
sp<Client> client;
status_t lStatus;
- int lSessionId;
+ audio_session_t lSessionId;
cblk.clear();
buffers.clear();
@@ -1493,7 +1494,7 @@
lSessionId = *sessionId;
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ lSessionId = (audio_session_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -1508,7 +1509,7 @@
if (lStatus == NO_ERROR) {
// Check if one effect chain was awaiting for an AudioRecord to be created on this
// session and move it to this thread.
- sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)lSessionId);
+ sp<EffectChain> chain = getOrphanEffectChain_l(lSessionId);
if (chain != 0) {
Mutex::Autolock _l(thread->mLock);
thread->addEffectChain_l(chain);
@@ -2270,7 +2271,7 @@
return nextUniqueId(use);
}
-void AudioFlinger::acquireAudioSessionId(int audioSession, pid_t pid)
+void AudioFlinger::acquireAudioSessionId(audio_session_t audioSession, pid_t pid)
{
Mutex::Autolock _l(mLock);
pid_t caller = IPCThreadState::self()->getCallingPid();
@@ -2304,7 +2305,7 @@
ALOGV(" added new entry for %d", audioSession);
}
-void AudioFlinger::releaseAudioSessionId(int audioSession, pid_t pid)
+void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
{
Mutex::Autolock _l(mLock);
pid_t caller = IPCThreadState::self()->getCallingPid();
@@ -2462,8 +2463,8 @@
}
sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
- int triggerSession,
- int listenerSession,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
sync_event_callback_t callBack,
wp<RefBase> cookie)
{
@@ -2523,7 +2524,7 @@
const sp<IEffectClient>& effectClient,
int32_t priority,
audio_io_handle_t io,
- int sessionId,
+ audio_session_t sessionId,
const String16& opPackageName,
status_t *status,
int *id,
@@ -2684,7 +2685,7 @@
} else {
// Check if one effect chain was awaiting for an effect to be created on this
// session and used it instead of creating a new one.
- sp<EffectChain> chain = getOrphanEffectChain_l((audio_session_t)sessionId);
+ sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
Mutex::Autolock _l(thread->mLock);
thread->addEffectChain_l(chain);
@@ -2711,7 +2712,7 @@
return handle;
}
-status_t AudioFlinger::moveEffects(int sessionId, audio_io_handle_t srcOutput,
+status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput)
{
ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
@@ -2738,7 +2739,7 @@
}
// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
-status_t AudioFlinger::moveEffectChain_l(int sessionId,
+status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread,
bool reRegister)
@@ -2864,7 +2865,7 @@
status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
{
- audio_session_t session = (audio_session_t)chain->sessionId();
+ audio_session_t session = chain->sessionId();
ssize_t index = mOrphanEffectChains.indexOfKey(session);
ALOGV("putOrphanEffectChain_l session %d index %d", session, index);
if (index >= 0) {
@@ -2890,7 +2891,7 @@
bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
{
Mutex::Autolock _l(mLock);
- audio_session_t session = (audio_session_t)effect->sessionId();
+ audio_session_t session = effect->sessionId();
ssize_t index = mOrphanEffectChains.indexOfKey(session);
ALOGV("updateOrphanEffectChains session %d index %d", session, index);
if (index >= 0) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fb1ece4..f11fd1c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -108,7 +108,7 @@
const sp<IMemory>& sharedBuffer,
audio_io_handle_t output,
pid_t tid,
- int *sessionId,
+ audio_session_t *sessionId,
int clientUid,
status_t *status /*non-NULL*/);
@@ -122,7 +122,7 @@
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int clientUid,
- int *sessionId,
+ audio_session_t *sessionId,
size_t *notificationFrames,
sp<IMemory>& cblk,
sp<IMemory>& buffers,
@@ -198,9 +198,9 @@
virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
- virtual void acquireAudioSessionId(int audioSession, pid_t pid);
+ virtual void acquireAudioSessionId(audio_session_t audioSession, pid_t pid);
- virtual void releaseAudioSessionId(int audioSession, pid_t pid);
+ virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
virtual status_t queryNumberEffects(uint32_t *numEffects) const;
@@ -214,13 +214,13 @@
const sp<IEffectClient>& effectClient,
int32_t priority,
audio_io_handle_t io,
- int sessionId,
+ audio_session_t sessionId,
const String16& opPackageName,
status_t *status /*non-NULL*/,
int *id,
int *enabled);
- virtual status_t moveEffects(int sessionId, audio_io_handle_t srcOutput,
+ virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
virtual audio_module_handle_t loadHwModule(const char *name);
@@ -283,8 +283,8 @@
class SyncEvent : public RefBase {
public:
SyncEvent(AudioSystem::sync_event_t type,
- int triggerSession,
- int listenerSession,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
sync_event_callback_t callBack,
wp<RefBase> cookie)
: mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
@@ -297,22 +297,22 @@
bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
AudioSystem::sync_event_t type() const { return mType; }
- int triggerSession() const { return mTriggerSession; }
- int listenerSession() const { return mListenerSession; }
+ audio_session_t triggerSession() const { return mTriggerSession; }
+ audio_session_t listenerSession() const { return mListenerSession; }
wp<RefBase> cookie() const { return mCookie; }
private:
const AudioSystem::sync_event_t mType;
- const int mTriggerSession;
- const int mListenerSession;
+ const audio_session_t mTriggerSession;
+ const audio_session_t mListenerSession;
sync_event_callback_t mCallback;
const wp<RefBase> mCookie;
mutable Mutex mLock;
};
sp<SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
- int triggerSession,
- int listenerSession,
+ audio_session_t triggerSession,
+ audio_session_t listenerSession,
sync_event_callback_t callBack,
wp<RefBase> cookie);
@@ -505,7 +505,8 @@
public:
RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
virtual ~RecordHandle();
- virtual status_t start(int /*AudioSystem::sync_event_t*/ event, int triggerSession);
+ virtual status_t start(int /*AudioSystem::sync_event_t*/ event,
+ audio_session_t triggerSession);
virtual void stop();
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
@@ -560,7 +561,7 @@
// or by returning a non-unique ID.
audio_unique_id_t nextUniqueId(audio_unique_id_use_t use);
- status_t moveEffectChain_l(int sessionId,
+ status_t moveEffectChain_l(audio_session_t sessionId,
PlaybackThread *srcThread,
PlaybackThread *dstThread,
bool reRegister);
@@ -569,7 +570,7 @@
PlaybackThread *primaryPlaybackThread_l() const;
audio_devices_t primaryOutputDevice_l() const;
- sp<PlaybackThread> getEffectThread_l(int sessionId, int EffectId);
+ sp<PlaybackThread> getEffectThread_l(audio_session_t sessionId, int EffectId);
void removeClient_l(pid_t pid);
@@ -612,9 +613,9 @@
// for mAudioSessionRefs only
struct AudioSessionRef {
- AudioSessionRef(int sessionid, pid_t pid) :
+ AudioSessionRef(audio_session_t sessionid, pid_t pid) :
mSessionid(sessionid), mPid(pid), mCnt(1) {}
- const int mSessionid;
+ const audio_session_t mSessionid;
const pid_t mPid;
int mCnt;
};
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 949c91d..060ffe9 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -59,7 +59,7 @@
const wp<AudioFlinger::EffectChain>& chain,
effect_descriptor_t *desc,
int id,
- int sessionId)
+ audio_session_t sessionId)
: mPinned(sessionId > AUDIO_SESSION_OUTPUT_MIX),
mThread(thread), mChain(chain), mId(id), mSessionId(sessionId),
mDescriptor(*desc),
@@ -1341,7 +1341,7 @@
#define LOG_TAG "AudioFlinger::EffectChain"
AudioFlinger::EffectChain::EffectChain(ThreadBase *thread,
- int sessionId)
+ audio_session_t sessionId)
: mThread(thread), mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
mOwnInBuffer(false), mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX), mForceVolume(false)
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 6f93f81..bc9bc94 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -45,7 +45,7 @@
const wp<AudioFlinger::EffectChain>& chain,
effect_descriptor_t *desc,
int id,
- int sessionId);
+ audio_session_t sessionId);
virtual ~EffectModule();
enum effect_state {
@@ -76,7 +76,7 @@
uint32_t status() {
return mStatus;
}
- int sessionId() const {
+ audio_session_t sessionId() const {
return mSessionId;
}
status_t setEnabled(bool enabled);
@@ -141,7 +141,7 @@
wp<ThreadBase> mThread; // parent thread
wp<EffectChain> mChain; // parent effect chain
const int mId; // this instance unique ID
- const int mSessionId; // audio session ID
+ const audio_session_t mSessionId; // audio session ID
const effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
effect_config_t mConfig; // input and output audio configuration
effect_handle_t mEffectInterface; // Effect module C API
@@ -235,15 +235,17 @@
// the EffectChain class represents a group of effects associated to one audio session.
// There can be any number of EffectChain objects per output mixer thread (PlaybackThread).
-// The EffecChain with session ID 0 contains global effects applied to the output mix.
+// The EffectChain with session ID AUDIO_SESSION_OUTPUT_MIX contains global effects applied
+// to the output mix.
// Effects in this chain can be insert or auxiliary. Effects in other chains (attached to
// tracks) are insert only. The EffectChain maintains an ordered list of effect module, the
-// order corresponding in the effect process order. When attached to a track (session ID != 0),
+// order corresponding in the effect process order. When attached to a track (session ID !=
+// AUDIO_SESSION_OUTPUT_MIX),
// it also provide it's own input buffer used by the track as accumulation buffer.
class EffectChain : public RefBase {
public:
- EffectChain(const wp<ThreadBase>& wThread, int sessionId);
- EffectChain(ThreadBase *thread, int sessionId);
+ EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
+ EffectChain(ThreadBase *thread, audio_session_t sessionId);
virtual ~EffectChain();
// special key used for an entry in mSuspendedEffects keyed vector
@@ -266,8 +268,8 @@
status_t addEffect_l(const sp<EffectModule>& handle);
size_t removeEffect_l(const sp<EffectModule>& handle);
- int sessionId() const { return mSessionId; }
- void setSessionId(int sessionId) { mSessionId = sessionId; }
+ audio_session_t sessionId() const { return mSessionId; }
+ void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
sp<EffectModule> getEffectFromId_l(int id);
@@ -362,7 +364,7 @@
wp<ThreadBase> mThread; // parent mixer thread
Mutex mLock; // mutex protecting effect list
Vector< sp<EffectModule> > mEffects; // list of effect modules
- int mSessionId; // audio session ID
+ audio_session_t mSessionId; // audio session ID
int16_t *mInBuffer; // chain input buffer
int16_t *mOutBuffer; // chain output buffer
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 5fcc0fe..a99becf 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -139,18 +139,18 @@
status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle)
{
- ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d",
- patch->num_sources, patch->num_sinks, *handle);
status_t status = NO_ERROR;
audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE;
sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
+ if (handle == NULL || patch == NULL) {
+ return BAD_VALUE;
+ }
+ ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d",
+ patch->num_sources, patch->num_sinks, *handle);
if (audioflinger == 0) {
return NO_INIT;
}
- if (handle == NULL || patch == NULL) {
- return BAD_VALUE;
- }
if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX ||
(patch->num_sinks == 0 && patch->num_sources != 2) ||
patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
@@ -453,7 +453,7 @@
patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get());
// start capture and playback
- patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, 0);
+ patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE);
patch->mPatchTrack->start();
return status;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index fa61af2..270e27f 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -31,7 +31,7 @@
size_t frameCount,
void *buffer,
const sp<IMemory>& sharedBuffer,
- int sessionId,
+ audio_session_t sessionId,
int uid,
IAudioFlinger::track_flags_t flags,
track_type type);
@@ -42,7 +42,7 @@
void dump(char* buffer, size_t size, bool active);
virtual status_t start(AudioSystem::sync_event_t event =
AudioSystem::SYNC_EVENT_NONE,
- int triggerSession = 0);
+ audio_session_t triggerSession = AUDIO_SESSION_NONE);
virtual void stop();
void pause();
@@ -110,10 +110,13 @@
// audioHalFrames is derived from output latency
// FIXME parameters not needed, could get them from the thread
bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
+ void signalClientFlag(int32_t flag);
public:
void triggerEvents(AudioSystem::sync_event_t type);
void invalidate();
+ void disable();
+
bool isInvalid() const { return mIsInvalid; }
int fastIndex() const { return mFastIndex; }
@@ -187,7 +190,7 @@
virtual status_t start(AudioSystem::sync_event_t event =
AudioSystem::SYNC_EVENT_NONE,
- int triggerSession = 0);
+ audio_session_t triggerSession = AUDIO_SESSION_NONE);
virtual void stop();
bool write(void* data, uint32_t frames);
bool bufferQueueEmpty() const { return mBufferQueue.size() == 0; }
@@ -200,6 +203,8 @@
uint32_t waitTimeMs);
void clearBufferQueue();
+ void restartIfDisabled();
+
// Maximum number of pending buffers allocated by OutputTrack::write()
static const uint8_t kMaxOverFlowBuffers = 10;
@@ -224,6 +229,10 @@
IAudioFlinger::track_flags_t flags);
virtual ~PatchTrack();
+ virtual status_t start(AudioSystem::sync_event_t event =
+ AudioSystem::SYNC_EVENT_NONE,
+ audio_session_t triggerSession = AUDIO_SESSION_NONE);
+
// AudioBufferProvider interface
virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
@@ -236,6 +245,8 @@
void setPeerProxy(PatchProxyBufferProvider *proxy) { mPeerProxy = proxy; }
private:
+ void restartIfDisabled();
+
sp<ClientProxy> mProxy;
PatchProxyBufferProvider* mPeerProxy;
struct timespec mPeerTimeout;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 6f84af1..13396a6 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -29,14 +29,14 @@
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
- int sessionId,
+ audio_session_t sessionId,
int uid,
IAudioFlinger::track_flags_t flags,
track_type type);
virtual ~RecordTrack();
virtual status_t initCheck() const;
- virtual status_t start(AudioSystem::sync_event_t event, int triggerSession);
+ virtual status_t start(AudioSystem::sync_event_t event, audio_session_t triggerSession);
virtual void stop();
void destroy();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 96c5f59..e2932f1 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1113,7 +1113,7 @@
status_t status;
status = mPowerManager->updateWakeLockUids(mWakeLockToken, uids.size(), uids.array(),
true /* FIXME force oneway contrary to .aidl */);
- ALOGV("acquireWakeLock_l() %s status %d", mThreadName, status);
+ ALOGV("updateWakeLockUids_l() %s status %d", mThreadName, status);
}
}
@@ -1134,14 +1134,14 @@
}
void AudioFlinger::ThreadBase::setEffectSuspended(
- const effect_uuid_t *type, bool suspend, int sessionId)
+ const effect_uuid_t *type, bool suspend, audio_session_t sessionId)
{
Mutex::Autolock _l(mLock);
setEffectSuspended_l(type, suspend, sessionId);
}
void AudioFlinger::ThreadBase::setEffectSuspended_l(
- const effect_uuid_t *type, bool suspend, int sessionId)
+ const effect_uuid_t *type, bool suspend, audio_session_t sessionId)
{
sp<EffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
@@ -1181,7 +1181,7 @@
void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
- int sessionId)
+ audio_session_t sessionId)
{
ssize_t index = mSuspendedSessions.indexOfKey(sessionId);
@@ -1242,7 +1242,7 @@
void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled,
- int sessionId)
+ audio_session_t sessionId)
{
Mutex::Autolock _l(mLock);
checkSuspendOnEffectEnabled_l(effect, enabled, sessionId);
@@ -1250,7 +1250,7 @@
void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
bool enabled,
- int sessionId)
+ audio_session_t sessionId)
{
if (mType != RECORD) {
// suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
@@ -1274,7 +1274,7 @@
const sp<AudioFlinger::Client>& client,
const sp<IEffectClient>& effectClient,
int32_t priority,
- int sessionId,
+ audio_session_t sessionId,
effect_descriptor_t *desc,
int *enabled,
status_t *status)
@@ -1413,13 +1413,15 @@
return handle;
}
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(int sessionId, int effectId)
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
+ int effectId)
{
Mutex::Autolock _l(mLock);
return getEffect_l(sessionId, effectId);
}
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId)
+sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
+ int effectId)
{
sp<EffectChain> chain = getEffectChain_l(sessionId);
return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
@@ -1430,7 +1432,7 @@
status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
{
// check for existing effect chain with the requested audio session
- int sessionId = effect->sessionId();
+ audio_session_t sessionId = effect->sessionId();
sp<EffectChain> chain = getEffectChain_l(sessionId);
bool chainCreated = false;
@@ -1507,13 +1509,14 @@
}
}
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(int sessionId)
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
{
Mutex::Autolock _l(mLock);
return getEffectChain_l(sessionId);
}
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(int sessionId) const
+sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+ const
{
size_t size = mEffectChains.size();
for (size_t i = 0; i < size; i++) {
@@ -1769,7 +1772,7 @@
audio_channel_mask_t channelMask,
size_t *pFrameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId,
+ audio_session_t sessionId,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int uid,
@@ -2039,14 +2042,14 @@
TrackBase::track_state state = track->mState;
mLock.unlock();
status = AudioSystem::startOutput(mId, track->streamType(),
- (audio_session_t)track->sessionId());
+ track->sessionId());
mLock.lock();
// abort track was stopped/paused while we released the lock
if (state != track->mState) {
if (status == NO_ERROR) {
mLock.unlock();
AudioSystem::stopOutput(mId, track->streamType(),
- (audio_session_t)track->sessionId());
+ track->sessionId());
mLock.lock();
}
return INVALID_OPERATION;
@@ -2421,7 +2424,7 @@
}
}
-uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId) const
+uint32_t AudioFlinger::PlaybackThread::hasAudioSession(audio_session_t sessionId) const
{
Mutex::Autolock _l(mLock);
uint32_t result = 0;
@@ -2440,7 +2443,7 @@
return result;
}
-uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
+uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(audio_session_t sessionId)
{
// session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
// it is moved to correct output by audio policy manager when A2DP is connected or disconnected
@@ -2523,14 +2526,14 @@
const sp<Track>& track = tracksToRemove.itemAt(i);
if (track->isExternalTrack()) {
AudioSystem::stopOutput(mId, track->streamType(),
- (audio_session_t)track->sessionId());
+ track->sessionId());
#ifdef ADD_BATTERY_DATA
// to track the speaker usage
addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
#endif
if (track->isTerminated()) {
AudioSystem::releaseOutput(mId, track->streamType(),
- (audio_session_t)track->sessionId());
+ track->sessionId());
}
}
}
@@ -2696,13 +2699,13 @@
status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
{
- int session = chain->sessionId();
+ audio_session_t session = chain->sessionId();
int16_t* buffer = reinterpret_cast<int16_t*>(mEffectBufferEnabled
? mEffectBuffer : mSinkBuffer);
bool ownsBuffer = false;
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
- if (session > 0) {
+ if (session > AUDIO_SESSION_OUTPUT_MIX) {
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
if (mType != DIRECT) {
@@ -2741,15 +2744,18 @@
chain->setOutBuffer(reinterpret_cast<int16_t*>(mEffectBufferEnabled
? mEffectBuffer : mSinkBuffer));
// Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
- // chains list in order to be processed last as it contains output stage effects
+ // chains list in order to be processed last as it contains output stage effects.
// Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
// session AUDIO_SESSION_OUTPUT_STAGE to be processed
- // after track specific effects and before output stage
+ // after track specific effects and before output stage.
// It is therefore mandatory that AUDIO_SESSION_OUTPUT_MIX == 0 and
- // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX
+ // that AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX.
// Effect chain for other sessions are inserted at beginning of effect
// chains list to be processed before output mix effects. Relative order between other
- // sessions is not important
+ // sessions is not important.
+ static_assert(AUDIO_SESSION_OUTPUT_MIX == 0 &&
+ AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX,
+ "audio_session_t constants misdefined");
size_t size = mEffectChains.size();
size_t i = 0;
for (i = 0; i < size; i++) {
@@ -2765,7 +2771,7 @@
size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
{
- int session = chain->sessionId();
+ audio_session_t session = chain->sessionId();
ALOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
@@ -3961,7 +3967,7 @@
}
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &track->mCblk->mFlags);
+ track->disable();
// remove from active list, but state remains ACTIVE [confusing but true]
isActive = false;
break;
@@ -4322,7 +4328,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
// If one track is not ready, mark the mixer also not ready if:
// - the mixer was ready during previous round OR
// - no other track is ready
@@ -4427,7 +4433,7 @@
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, int sessionId)
+ audio_format_t format, audio_session_t sessionId)
{
return mAudioMixer->getTrackName(channelMask, format, sessionId);
}
@@ -4869,7 +4875,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
} else if (last) {
ALOGW("pause because of UNDERRUN, framesReady = %zu,"
"minFrames = %u, mFormat = %#x",
@@ -5003,7 +5009,7 @@
// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask __unused,
- audio_format_t format __unused, int sessionId __unused)
+ audio_format_t format __unused, audio_session_t sessionId __unused)
{
return 0;
}
@@ -5423,7 +5429,7 @@
tracksToRemove->add(track);
// indicate to client process that the track was disabled because of underrun;
// it will then automatically call start() when data is available
- android_atomic_or(CBLK_DISABLED, &cblk->mFlags);
+ track->disable();
} else if (last){
mixerStatus = MIXER_TRACKS_ENABLED;
}
@@ -6201,7 +6207,8 @@
(activeTrack->mFramesToDrop >= 0) ? "timed out" : "cancelled",
activeTrack->sessionId(),
(activeTrack->mSyncStartEvent != 0) ?
- activeTrack->mSyncStartEvent->triggerSession() : 0);
+ activeTrack->mSyncStartEvent->triggerSession() :
+ AUDIO_SESSION_NONE);
activeTrack->clearSyncStartEvent();
}
}
@@ -6307,7 +6314,7 @@
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
- int sessionId,
+ audio_session_t sessionId,
size_t *notificationFrames,
int uid,
IAudioFlinger::track_flags_t *flags,
@@ -6426,7 +6433,7 @@
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
- int triggerSession)
+ audio_session_t triggerSession)
{
ALOGV("RecordThread::start event %d, triggerSession %d", event, triggerSession);
sp<ThreadBase> strongMe = this;
@@ -6473,7 +6480,7 @@
status_t status = NO_ERROR;
if (recordTrack->isExternalTrack()) {
mLock.unlock();
- status = AudioSystem::startInput(mId, (audio_session_t)recordTrack->sessionId());
+ status = AudioSystem::startInput(mId, recordTrack->sessionId());
mLock.lock();
// FIXME should verify that recordTrack is still in mActiveTracks
if (status != NO_ERROR) {
@@ -6505,7 +6512,7 @@
startError:
if (recordTrack->isExternalTrack()) {
- AudioSystem::stopInput(mId, (audio_session_t)recordTrack->sessionId());
+ AudioSystem::stopInput(mId, recordTrack->sessionId());
}
recordTrack->clearSyncStartEvent();
// FIXME I wonder why we do not reset the state here?
@@ -6559,7 +6566,7 @@
return BAD_VALUE;
}
- int eventSession = event->triggerSession();
+ audio_session_t eventSession = event->triggerSession();
status_t ret = NAME_NOT_FOUND;
Mutex::Autolock _l(mLock);
@@ -7225,7 +7232,7 @@
return mInput->stream->get_input_frames_lost(mInput->stream);
}
-uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId) const
+uint32_t AudioFlinger::RecordThread::hasAudioSession(audio_session_t sessionId) const
{
Mutex::Autolock _l(mLock);
uint32_t result = 0;
@@ -7243,13 +7250,13 @@
return result;
}
-KeyedVector<int, bool> AudioFlinger::RecordThread::sessionIds() const
+KeyedVector<audio_session_t, bool> AudioFlinger::RecordThread::sessionIds() const
{
- KeyedVector<int, bool> ids;
+ KeyedVector<audio_session_t, bool> ids;
Mutex::Autolock _l(mLock);
for (size_t j = 0; j < mTracks.size(); ++j) {
sp<RecordThread::RecordTrack> track = mTracks[j];
- int sessionId = track->sessionId();
+ audio_session_t sessionId = track->sessionId();
if (ids.indexOfKey(sessionId) < 0) {
ids.add(sessionId, true);
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index d1613db..761fc71 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -288,7 +288,7 @@
const sp<AudioFlinger::Client>& client,
const sp<IEffectClient>& effectClient,
int32_t priority,
- int sessionId,
+ audio_session_t sessionId,
effect_descriptor_t *desc,
int *enabled,
status_t *status /*non-NULL*/);
@@ -302,9 +302,9 @@
};
// get effect chain corresponding to session Id.
- sp<EffectChain> getEffectChain(int sessionId);
+ sp<EffectChain> getEffectChain(audio_session_t sessionId);
// same as getEffectChain() but must be called with ThreadBase mutex locked
- sp<EffectChain> getEffectChain_l(int sessionId) const;
+ sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const;
// add an effect chain to the chain list (mEffectChains)
virtual status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
// remove an effect chain from the chain list (mEffectChains)
@@ -321,8 +321,8 @@
// set audio mode to all effect chains
void setMode(audio_mode_t mode);
// get effect module with corresponding ID on specified audio session
- sp<AudioFlinger::EffectModule> getEffect(int sessionId, int effectId);
- sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
+ sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
+ sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId);
// add and effect module. Also creates the effect chain is none exists for
// the effects audio session
status_t addEffect_l(const sp< EffectModule>& effect);
@@ -333,24 +333,27 @@
virtual void detachAuxEffect_l(int effectId __unused) {}
// returns either EFFECT_SESSION if effects on this audio session exist in one
// chain, or TRACK_SESSION if tracks on this audio session exist, or both
- virtual uint32_t hasAudioSession(int sessionId) const = 0;
+ virtual uint32_t hasAudioSession(audio_session_t sessionId) const = 0;
// the value returned by default implementation is not important as the
// strategy is only meaningful for PlaybackThread which implements this method
- virtual uint32_t getStrategyForSession_l(int sessionId __unused) { return 0; }
+ virtual uint32_t getStrategyForSession_l(audio_session_t sessionId __unused)
+ { return 0; }
// suspend or restore effect according to the type of effect passed. a NULL
// type pointer means suspend all effects in the session
void setEffectSuspended(const effect_uuid_t *type,
bool suspend,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
// check if some effects must be suspended/restored when an effect is enabled
// or disabled
void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ audio_session_t sessionId =
+ AUDIO_SESSION_OUTPUT_MIX);
void checkSuspendOnEffectEnabled_l(const sp<EffectModule>& effect,
bool enabled,
- int sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ audio_session_t sessionId =
+ AUDIO_SESSION_OUTPUT_MIX);
virtual status_t setSyncEvent(const sp<SyncEvent>& event) = 0;
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
@@ -389,11 +392,11 @@
void getPowerManager_l();
void setEffectSuspended_l(const effect_uuid_t *type,
bool suspend,
- int sessionId);
+ audio_session_t sessionId);
// updated mSuspendedSessions when an effect suspended or restored
void updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
- int sessionId);
+ audio_session_t sessionId);
// check if some effects must be suspended when an effect chain is added
void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
@@ -452,9 +455,9 @@
sp<IPowerManager> mPowerManager;
sp<IBinder> mWakeLockToken;
const sp<PMDeathRecipient> mDeathRecipient;
- // list of suspended effects per session and per type. The first vector is
- // keyed by session ID, the second by type UUID timeLow field
- KeyedVector< int, KeyedVector< int, sp<SuspendedSessionDesc> > >
+ // list of suspended effects per session and per type. The first (outer) vector is
+ // keyed by session ID, the second (inner) by type UUID timeLow field
+ KeyedVector< audio_session_t, KeyedVector< int, sp<SuspendedSessionDesc> > >
mSuspendedSessions;
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
@@ -549,7 +552,7 @@
audio_channel_mask_t channelMask,
size_t *pFrameCount,
const sp<IMemory>& sharedBuffer,
- int sessionId,
+ audio_session_t sessionId,
IAudioFlinger::track_flags_t *flags,
pid_t tid,
int uid,
@@ -589,8 +592,8 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession(int sessionId) const;
- virtual uint32_t getStrategyForSession_l(int sessionId);
+ virtual uint32_t hasAudioSession(audio_session_t sessionId) const;
+ virtual uint32_t getStrategyForSession_l(audio_session_t sessionId);
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
@@ -704,7 +707,7 @@
// Allocate a track name for a given channel mask.
// Returns name >= 0 if successful, -1 on failure.
virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, int sessionId) = 0;
+ audio_format_t format, audio_session_t sessionId) = 0;
virtual void deleteTrackName_l(int name) = 0;
// Time to sleep between cycles when:
@@ -859,7 +862,7 @@
protected:
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, int sessionId);
+ audio_format_t format, audio_session_t sessionId);
virtual void deleteTrackName_l(int name);
virtual uint32_t idleSleepTimeUs() const;
virtual uint32_t suspendSleepTimeUs() const;
@@ -940,7 +943,7 @@
protected:
virtual int getTrackName_l(audio_channel_mask_t channelMask,
- audio_format_t format, int sessionId);
+ audio_format_t format, audio_session_t sessionId);
virtual void deleteTrackName_l(int name);
virtual uint32_t activeSleepTimeUs() const;
virtual uint32_t idleSleepTimeUs() const;
@@ -1243,7 +1246,7 @@
audio_format_t format,
audio_channel_mask_t channelMask,
size_t *pFrameCount,
- int sessionId,
+ audio_session_t sessionId,
size_t *notificationFrames,
int uid,
IAudioFlinger::track_flags_t *flags,
@@ -1252,7 +1255,7 @@
status_t start(RecordTrack* recordTrack,
AudioSystem::sync_event_t event,
- int triggerSession);
+ audio_session_t triggerSession);
// ask the thread to stop the specified track, and
// return true if the caller should then do it's part of the stopping process
@@ -1280,12 +1283,12 @@
virtual status_t addEffectChain_l(const sp<EffectChain>& chain);
virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
- virtual uint32_t hasAudioSession(int sessionId) const;
+ virtual uint32_t hasAudioSession(audio_session_t sessionId) const;
// Return the set of unique session IDs across all tracks.
// The keys are the session IDs, and the associated values are meaningless.
// FIXME replace by Set [and implement Bag/Multiset for other uses].
- KeyedVector<int, bool> sessionIds() const;
+ KeyedVector<audio_session_t, bool> sessionIds() const;
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 26067e3..67a5e58 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -61,7 +61,7 @@
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
- int sessionId,
+ audio_session_t sessionId,
int uid,
IAudioFlinger::track_flags_t flags,
bool isOut,
@@ -71,11 +71,11 @@
virtual status_t initCheck() const;
virtual status_t start(AudioSystem::sync_event_t event,
- int triggerSession) = 0;
+ audio_session_t triggerSession) = 0;
virtual void stop() = 0;
sp<IMemory> getCblk() const { return mCblkMemory; }
audio_track_cblk_t* cblk() const { return mCblk; }
- int sessionId() const { return mSessionId; }
+ audio_session_t sessionId() const { return mSessionId; }
int uid() const { return mUid; }
virtual status_t setSyncEvent(const sp<SyncEvent>& event);
@@ -153,7 +153,7 @@
const size_t mFrameCount;// size of track buffer given at createTrack() or
// openRecord(), and then adjusted as needed
- const int mSessionId;
+ const audio_session_t mSessionId;
int mUid;
Vector < sp<SyncEvent> >mSyncEvents;
const IAudioFlinger::track_flags_t mFlags;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a75ca77..f575918 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -71,7 +71,7 @@
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
- int sessionId,
+ audio_session_t sessionId,
int clientUid,
IAudioFlinger::track_flags_t flags,
bool isOut,
@@ -343,7 +343,7 @@
size_t frameCount,
void *buffer,
const sp<IMemory>& sharedBuffer,
- int sessionId,
+ audio_session_t sessionId,
int uid,
IAudioFlinger::track_flags_t flags,
track_type type)
@@ -454,7 +454,7 @@
wasActive = playbackThread->destroyTrack_l(this);
}
if (isExternalTrack() && !wasActive) {
- AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, (audio_session_t)mSessionId);
+ AudioSystem::releaseOutput(mThreadIoHandle, mStreamType, mSessionId);
}
}
}
@@ -627,7 +627,7 @@
}
status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
- int triggerSession __unused)
+ audio_session_t triggerSession __unused)
{
status_t status = NO_ERROR;
ALOGV("start(%d), calling pid %d session %d",
@@ -1027,13 +1027,23 @@
void AudioFlinger::PlaybackThread::Track::invalidate()
{
+ signalClientFlag(CBLK_INVALID);
+ mIsInvalid = true;
+}
+
+void AudioFlinger::PlaybackThread::Track::disable()
+{
+ signalClientFlag(CBLK_DISABLED);
+}
+
+void AudioFlinger::PlaybackThread::Track::signalClientFlag(int32_t flag)
+{
// FIXME should use proxy, and needs work
audio_track_cblk_t* cblk = mCblk;
- android_atomic_or(CBLK_INVALID, &cblk->mFlags);
+ android_atomic_or(flag, &cblk->mFlags);
android_atomic_release_store(0x40000000, &cblk->mFutex);
// client is not in server, so FUTEX_WAKE is needed instead of FUTEX_WAKE_PRIVATE
(void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
- mIsInvalid = true;
}
void AudioFlinger::PlaybackThread::Track::signal()
@@ -1118,7 +1128,8 @@
int uid)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
sampleRate, format, channelMask, frameCount,
- NULL, 0, 0, uid, IAudioFlinger::TRACK_DEFAULT, TYPE_OUTPUT),
+ NULL, 0, AUDIO_SESSION_NONE, uid, IAudioFlinger::TRACK_DEFAULT,
+ TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread), mClientProxy(NULL)
{
@@ -1149,7 +1160,7 @@
}
status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
- int triggerSession)
+ audio_session_t triggerSession)
{
status_t status = Track::start(event, triggerSession);
if (status != NO_ERROR) {
@@ -1199,7 +1210,7 @@
mOutBuffer.frameCount = pInBuffer->frameCount;
nsecs_t startTime = systemTime();
status_t status = obtainBuffer(&mOutBuffer, waitTimeLeftMs);
- if (status != NO_ERROR) {
+ if (status != NO_ERROR && status != NOT_ENOUGH_DATA) {
ALOGV("OutputTrack::write() %p thread %p no more output buffers; status %d", this,
mThread.unsafe_get(), status);
outputBufferFull = true;
@@ -1211,6 +1222,10 @@
} else {
waitTimeLeftMs = 0;
}
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ continue;
+ }
}
uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount :
@@ -1220,6 +1235,7 @@
buf.mFrameCount = outFrames;
buf.mRaw = NULL;
mClientProxy->releaseBuffer(&buf);
+ restartIfDisabled();
pInBuffer->frameCount -= outFrames;
pInBuffer->raw = (int8_t *)pInBuffer->raw + outFrames * mFrameSize;
mOutBuffer.frameCount -= outFrames;
@@ -1293,6 +1309,13 @@
mBufferQueue.clear();
}
+void AudioFlinger::PlaybackThread::OutputTrack::restartIfDisabled()
+{
+ int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ if (mActive && (flags & CBLK_DISABLED)) {
+ start();
+ }
+}
AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
audio_stream_type_t streamType,
@@ -1304,7 +1327,7 @@
IAudioFlinger::track_flags_t flags)
: Track(playbackThread, NULL, streamType,
sampleRate, format, channelMask, frameCount,
- buffer, 0, 0, getuid(), flags, TYPE_PATCH),
+ buffer, 0, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
{
uint64_t mixBufferNs = ((uint64_t)2 * playbackThread->frameCount() * 1000000000) /
@@ -1322,6 +1345,17 @@
{
}
+status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
+ audio_session_t triggerSession)
+{
+ status_t status = Track::start(event, triggerSession);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
+ return status;
+}
+
// AudioBufferProvider interface
status_t AudioFlinger::PlaybackThread::PatchTrack::getNextBuffer(
AudioBufferProvider::Buffer* buffer)
@@ -1352,17 +1386,31 @@
status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
const struct timespec *timeOut)
{
- return mProxy->obtainBuffer(buffer, timeOut);
+ status_t status = NO_ERROR;
+ static const int32_t kMaxTries = 5;
+ int32_t tryCounter = kMaxTries;
+ do {
+ if (status == NOT_ENOUGH_DATA) {
+ restartIfDisabled();
+ }
+ status = mProxy->obtainBuffer(buffer, timeOut);
+ } while ((status == NOT_ENOUGH_DATA) && (tryCounter-- > 0));
+ return status;
}
void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
{
mProxy->releaseBuffer(buffer);
+ restartIfDisabled();
+ android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
+}
+
+void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
+{
if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
ALOGW("PatchTrack::releaseBuffer() disabled due to previous underrun, restarting");
start();
}
- android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
}
// ----------------------------------------------------------------------------
@@ -1382,7 +1430,7 @@
}
status_t AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
- int triggerSession) {
+ audio_session_t triggerSession) {
ALOGV("RecordHandle::start()");
return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession);
}
@@ -1413,7 +1461,7 @@
audio_channel_mask_t channelMask,
size_t frameCount,
void *buffer,
- int sessionId,
+ audio_session_t sessionId,
int uid,
IAudioFlinger::track_flags_t flags,
track_type type)
@@ -1490,7 +1538,7 @@
}
status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
- int triggerSession)
+ audio_session_t triggerSession)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
@@ -1507,7 +1555,7 @@
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
if (recordThread->stop(this) && isExternalTrack()) {
- AudioSystem::stopInput(mThreadIoHandle, (audio_session_t)mSessionId);
+ AudioSystem::stopInput(mThreadIoHandle, mSessionId);
}
}
}
@@ -1519,9 +1567,9 @@
{
if (isExternalTrack()) {
if (mState == ACTIVE || mState == RESUMING) {
- AudioSystem::stopInput(mThreadIoHandle, (audio_session_t)mSessionId);
+ AudioSystem::stopInput(mThreadIoHandle, mSessionId);
}
- AudioSystem::releaseInput(mThreadIoHandle, (audio_session_t)mSessionId);
+ AudioSystem::releaseInput(mThreadIoHandle, mSessionId);
}
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
@@ -1613,7 +1661,7 @@
void *buffer,
IAudioFlinger::track_flags_t flags)
: RecordTrack(recordThread, NULL, sampleRate, format, channelMask, frameCount,
- buffer, 0, getuid(), flags, TYPE_PATCH),
+ buffer, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
{
uint64_t mixBufferNs = ((uint64_t)2 * recordThread->frameCount() * 1000000000) /
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 1c41ce1..b1347f4 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -312,7 +312,7 @@
virtual status_t setVoiceVolume(float volume, int delayMs = 0) = 0;
// move effect to the specified output
- virtual status_t moveEffects(int session,
+ virtual status_t moveEffects(audio_session_t session,
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index 6968a74..f73548d 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -42,9 +42,9 @@
* A device mask for all audio input and output devices where matching inputs/outputs on device
* type alone is not enough: the address must match too
*/
-#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_OUT_MATCH_ADDRESS_ALL (AUDIO_DEVICE_OUT_REMOTE_SUBMIX|AUDIO_DEVICE_OUT_BUS)
-#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX)
+#define APM_AUDIO_DEVICE_IN_MATCH_ADDRESS_ALL (AUDIO_DEVICE_IN_REMOTE_SUBMIX|AUDIO_DEVICE_IN_BUS)
/**
* Check if the state given correspond to an in call state.
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index c952831..8f5ebef 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -54,7 +54,7 @@
public:
status_t getAudioPolicyMix(String8 address, sp<AudioPolicyMix> &policyMix) const;
- status_t registerMix(String8 address, AudioMix mix);
+ status_t registerMix(String8 address, AudioMix mix, sp<SwAudioOutputDescriptor> desc);
status_t unregisterMix(String8 address);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 0fe1a84..c5fee50 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -315,14 +315,14 @@
if ((oldGlobalRefCount == 0) && (mGlobalRefCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
} else if ((oldGlobalRefCount > 0) && (mGlobalRefCount == 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
}
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 3735c05..4af3d54 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -51,7 +51,8 @@
return &mMix;
}
-status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix)
+status_t AudioPolicyMixCollection::registerMix(String8 address, AudioMix mix,
+ sp<SwAudioOutputDescriptor> desc)
{
ssize_t index = indexOfKey(address);
if (index >= 0) {
@@ -61,6 +62,11 @@
sp<AudioPolicyMix> policyMix = new AudioPolicyMix();
policyMix->setMix(mix);
add(address, policyMix);
+
+ if (desc != 0) {
+ desc->mPolicyMix = policyMix->getMix();
+ policyMix->setOutput(desc);
+ }
return NO_ERROR;
}
@@ -128,7 +134,7 @@
// if there is an address match, prioritize that match
if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attributes.tags + strlen("addr="),
- mix->mRegistrationId.string(),
+ mix->mDeviceAddress.string(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
hasAddrMatch = true;
break;
@@ -207,7 +213,7 @@
if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
strncmp(attributes.tags + strlen("addr="),
- mix->mRegistrationId.string(),
+ mix->mDeviceAddress.string(),
AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
desc = policyMix->getOutput();
}
@@ -260,7 +266,7 @@
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = valueAt(i);
AudioMix *mix = policyMix->getMix();
- ALOGV("\tmix %zu address=%s", i, mix->mRegistrationId.string());
+ ALOGV("\tmix %zu address=%s", i, mix->mDeviceAddress.string());
}
#endif
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index ce9c170..da983c5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -79,7 +79,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
+ mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mDeviceAddress,
(event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c3b1529..b2b014a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -954,6 +954,13 @@
}
non_direct_output:
+
+ // A request for HW A/V sync cannot fallback to a mixed output because time
+ // stamps are embedded in audio data
+ if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
+ return AUDIO_IO_HANDLE_NONE;
+ }
+
// ignoring channel mask due to downmix capability in mixer
// open a non direct output
@@ -1096,7 +1103,7 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
+ outputDesc->mPolicyMix->mDeviceAddress,
"remote-submix");
}
@@ -1213,7 +1220,7 @@
outputDesc->mPolicyMix->mMixType == MIX_TYPE_RECORDERS) {
setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- outputDesc->mPolicyMix->mRegistrationId,
+ outputDesc->mPolicyMix->mDeviceAddress,
"remote-submix");
}
}
@@ -1388,7 +1395,7 @@
return BAD_VALUE;
}
if (policyMix != NULL) {
- address = policyMix->mRegistrationId;
+ address = policyMix->mDeviceAddress;
if (policyMix->mMixType == MIX_TYPE_RECORDERS) {
// there is an external policy, but this input is attached to a mix of recorders,
// meaning it receives audio injected into the framework, so the recorder doesn't
@@ -1622,7 +1629,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((inputDesc->mPolicyMix != NULL)
&& ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
MIX_STATE_MIXING);
}
@@ -1639,7 +1646,7 @@
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
} else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mRegistrationId;
+ address = inputDesc->mPolicyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -1686,7 +1693,7 @@
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((inputDesc->mPolicyMix != NULL)
&& ((inputDesc->mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0)) {
- mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mRegistrationId,
+ mpClientInterface->onDynamicPolicyMixStateUpdate(inputDesc->mPolicyMix->mDeviceAddress,
MIX_STATE_IDLE);
}
@@ -1697,7 +1704,7 @@
if (inputDesc->mPolicyMix == NULL) {
address = String8("0");
} else if (inputDesc->mPolicyMix->mMixType == MIX_TYPE_PLAYERS) {
- address = inputDesc->mPolicyMix->mRegistrationId;
+ address = inputDesc->mPolicyMix->mDeviceAddress;
}
if (address != "") {
setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
@@ -2010,94 +2017,152 @@
status_t AudioPolicyManager::registerPolicyMixes(Vector<AudioMix> mixes)
{
- sp<HwModule> module;
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
- mHwModules[i]->mHandle != 0) {
- module = mHwModules[i];
+ ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
+ status_t res = NO_ERROR;
+
+ sp<HwModule> rSubmixModule;
+ // examine each mix's route type
+ for (size_t i = 0; i < mixes.size(); i++) {
+ // we only support MIX_ROUTE_FLAG_LOOP_BACK or MIX_ROUTE_FLAG_RENDER, not the combination
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_ALL) == MIX_ROUTE_FLAG_ALL) {
+ res = INVALID_OPERATION;
break;
}
- }
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
+ // Loop back through "remote submix"
+ if (rSubmixModule == 0) {
+ for (size_t j = 0; i < mHwModules.size(); j++) {
+ if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+ && mHwModules[j]->mHandle != 0) {
+ rSubmixModule = mHwModules[j];
+ break;
+ }
+ }
+ }
- if (module == 0) {
- return INVALID_OPERATION;
- }
+ ALOGV("registerPolicyMixes() mix %zu of %zu is LOOP_BACK", i, mixes.size());
- ALOGV("registerPolicyMixes() num mixes %zu", mixes.size());
+ if (rSubmixModule == 0) {
+ ALOGE(" Unable to find audio module for submix, aborting mix %zu registration", i);
+ res = INVALID_OPERATION;
+ break;
+ }
- for (size_t i = 0; i < mixes.size(); i++) {
- String8 address = mixes[i].mRegistrationId;
+ String8 address = mixes[i].mDeviceAddress;
- if (mPolicyMixes.registerMix(address, mixes[i]) != NO_ERROR) {
- continue;
- }
- audio_config_t outputConfig = mixes[i].mFormat;
- audio_config_t inputConfig = mixes[i].mFormat;
- // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
- // stereo and let audio flinger do the channel conversion if needed.
- outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
- inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
- module->addOutputProfile(address, &outputConfig,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
- module->addInputProfile(address, &inputConfig,
- AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
+ if (mPolicyMixes.registerMix(address, mixes[i], 0 /*output desc*/) != NO_ERROR) {
+ ALOGE(" Error regisering mix %zu for address %s", i, address.string());
+ res = INVALID_OPERATION;
+ break;
+ }
+ audio_config_t outputConfig = mixes[i].mFormat;
+ audio_config_t inputConfig = mixes[i].mFormat;
+ // NOTE: audio flinger mixer does not support mono output: configure remote submix HAL in
+ // stereo and let audio flinger do the channel conversion if needed.
+ outputConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ inputConfig.channel_mask = AUDIO_CHANNEL_IN_STEREO;
+ rSubmixModule->addOutputProfile(address, &outputConfig,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address);
+ rSubmixModule->addInputProfile(address, &inputConfig,
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, address);
- if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
- } else {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- address.string(), "remote-submix");
+ if (mixes[i].mMixType == MIX_TYPE_PLAYERS) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.string(), "remote-submix");
+ } else {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ address.string(), "remote-submix");
+ }
+ } else if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ ALOGV("registerPolicyMixes() mix %zu of %zu is RENDER", i, mixes.size());
+ String8 address = mixes[i].mDeviceAddress;
+
+ audio_devices_t device = mixes[i].mDeviceType;
+
+ for (size_t j = 0 ; j < mOutputs.size() ; j++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(j);
+ sp<AudioPatch> patch = mAudioPatches.valueFor(desc->getPatchHandle());
+ if ((patch != 0) && (patch->mPatch.num_sinks != 0)
+ && (patch->mPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE)
+ && (patch->mPatch.sinks[0].ext.device.type == device)
+ && (patch->mPatch.sinks[0].ext.device.address == address)) {
+
+ if (mPolicyMixes.registerMix(address, mixes[i], desc) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ }
+ break;
+ }
+ }
+
+ if (res != NO_ERROR) {
+ ALOGE(" Error registering mix %zu for device 0x%X addr %s",
+ i,device, address.string());
+ res = INVALID_OPERATION;
+ break;
+ }
}
}
- return NO_ERROR;
+ if (res != NO_ERROR) {
+ unregisterPolicyMixes(mixes);
+ }
+ return res;
}
status_t AudioPolicyManager::unregisterPolicyMixes(Vector<AudioMix> mixes)
{
- sp<HwModule> module;
- for (size_t i = 0; i < mHwModules.size(); i++) {
- if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[i]->mName) == 0 &&
- mHwModules[i]->mHandle != 0) {
- module = mHwModules[i];
- break;
- }
- }
-
- if (module == 0) {
- return INVALID_OPERATION;
- }
-
ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
-
+ status_t res = NO_ERROR;
+ sp<HwModule> rSubmixModule;
+ // examine each mix's route type
for (size_t i = 0; i < mixes.size(); i++) {
- String8 address = mixes[i].mRegistrationId;
+ if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_LOOP_BACK) == MIX_ROUTE_FLAG_LOOP_BACK) {
- if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
- continue;
- }
+ if (rSubmixModule == 0) {
+ for (size_t j = 0; i < mHwModules.size(); j++) {
+ if (strcmp(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, mHwModules[j]->mName) == 0
+ && mHwModules[j]->mHandle != 0) {
+ rSubmixModule = mHwModules[j];
+ break;
+ }
+ }
+ }
+ if (rSubmixModule == 0) {
+ res = INVALID_OPERATION;
+ continue;
+ }
- if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
- {
- setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
- }
+ String8 address = mixes[i].mDeviceAddress;
- if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
- AUDIO_POLICY_DEVICE_STATE_AVAILABLE)
- {
- setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- address.string(), "remote-submix");
+ if (mPolicyMixes.unregisterMix(address) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ continue;
+ }
+
+ if (getDeviceConnectionState(AUDIO_DEVICE_IN_REMOTE_SUBMIX, address.string()) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.string(), "remote-submix");
+ }
+ if (getDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, address.string()) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ address.string(), "remote-submix");
+ }
+ rSubmixModule->removeOutputProfile(address);
+ rSubmixModule->removeInputProfile(address);
+
+ } if ((mixes[i].mRouteFlags & MIX_ROUTE_FLAG_RENDER) == MIX_ROUTE_FLAG_RENDER) {
+ if (mPolicyMixes.unregisterMix(mixes[i].mDeviceAddress) != NO_ERROR) {
+ res = INVALID_OPERATION;
+ continue;
+ }
}
- module->removeOutputProfile(address);
- module->removeInputProfile(address);
}
- return NO_ERROR;
+ return res;
}
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index f1c0d1a..08f9cc1 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -171,7 +171,7 @@
return mAudioPolicyService->setVoiceVolume(volume, delay_ms);
}
-status_t AudioPolicyService::AudioPolicyClient::moveEffects(int session,
+status_t AudioPolicyService::AudioPolicyClient::moveEffects(audio_session_t session,
audio_io_handle_t src_output,
audio_io_handle_t dst_output)
{
diff --git a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
index a79f8ae..580d740 100644
--- a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
@@ -252,7 +252,7 @@
return af->invalidateStream(stream);
}
-int aps_move_effects(void *service __unused, int session,
+int aps_move_effects(void *service __unused, audio_session_t session,
audio_io_handle_t src_output,
audio_io_handle_t dst_output)
{
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index ce77814..b732b20 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -79,7 +79,7 @@
status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input,
audio_source_t inputSource,
- int audioSession)
+ audio_session_t audioSession)
{
status_t status = NO_ERROR;
@@ -152,7 +152,7 @@
return status;
}
-status_t AudioPolicyEffects::queryDefaultInputEffects(int audioSession,
+status_t AudioPolicyEffects::queryDefaultInputEffects(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
@@ -185,7 +185,7 @@
}
-status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(int audioSession,
+status_t AudioPolicyEffects::queryDefaultOutputSessionEffects(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
@@ -220,7 +220,7 @@
status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
- int audioSession)
+ audio_session_t audioSession)
{
status_t status = NO_ERROR;
@@ -275,7 +275,7 @@
status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
- int audioSession)
+ audio_session_t audioSession)
{
status_t status = NO_ERROR;
(void) output; // argument not used for now
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 266a45e..ee9bd50 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -51,7 +51,7 @@
// Return a list of effect descriptors for default input effects
// associated with audioSession
- status_t queryDefaultInputEffects(int audioSession,
+ status_t queryDefaultInputEffects(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count);
@@ -59,7 +59,7 @@
// Effects are attached depending on the audio_source_t
status_t addInputEffects(audio_io_handle_t input,
audio_source_t inputSource,
- int audioSession);
+ audio_session_t audioSession);
// Add all input effects associated to this input
status_t releaseInputEffects(audio_io_handle_t input);
@@ -67,7 +67,7 @@
// Return a list of effect descriptors for default output effects
// associated with audioSession
- status_t queryDefaultOutputSessionEffects(int audioSession,
+ status_t queryDefaultOutputSessionEffects(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count);
@@ -75,12 +75,12 @@
// Effects are attached depending on the audio_stream_type_t
status_t addOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
- int audioSession);
+ audio_session_t audioSession);
// release all output effects associated with this output stream and audiosession
status_t releaseOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
- int audioSession);
+ audio_session_t audioSession);
private:
@@ -135,13 +135,13 @@
// class to store voctor of AudioEffects
class EffectVector {
public:
- EffectVector(int session) : mSessionId(session), mRefCount(0) {}
+ EffectVector(audio_session_t session) : mSessionId(session), mRefCount(0) {}
/*virtual*/ ~EffectVector() {}
// Enable or disable all effects in effect vector
void setProcessorEnabled(bool enabled);
- const int mSessionId;
+ const audio_session_t mSessionId;
// AudioPolicyManager keeps mLock, no need for lock on reference count here
int mRefCount;
Vector< sp<AudioEffect> >mEffects;
@@ -188,7 +188,7 @@
// Automatic output effects are organized per audio_stream_type_t
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
// Automatic output effects are unique for audiosession ID
- KeyedVector< int32_t, EffectVector* > mOutputSessions;
+ KeyedVector< audio_session_t, EffectVector* > mOutputSessions;
};
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fdd6dd2..92a1285 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -476,7 +476,7 @@
status_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id)
{
if (mAudioPolicyManager == NULL) {
@@ -537,7 +537,7 @@
return mAudioPolicyManager->isSourceActive(source);
}
-status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 08b2a3b..c830454 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
@@ -427,7 +427,7 @@
status_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id)
{
if (mpAudioPolicy == NULL) {
@@ -488,7 +488,7 @@
return mpAudioPolicy->is_source_active(mpAudioPolicy, source);
}
-status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 94e0701..a6cd50e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1182,7 +1182,7 @@
audio_channel_mask_t *pChannelMask);
int aps_close_input(void *service __unused, audio_io_handle_t input);
int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream);
-int aps_move_effects(void *service __unused, int session,
+int aps_move_effects(void *service __unused, audio_session_t session,
audio_io_handle_t src_output,
audio_io_handle_t dst_output);
char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index cecd617..2710ac7 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -128,7 +128,7 @@
virtual status_t registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
uint32_t strategy,
- int session,
+ audio_session_t session,
int id);
virtual status_t unregisterEffect(int id);
virtual status_t setEffectEnabled(int id, bool enabled);
@@ -136,7 +136,7 @@
virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
virtual bool isSourceActive(audio_source_t source) const;
- virtual status_t queryDefaultPreProcessing(int audioSession,
+ virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count);
virtual status_t onTransact(
@@ -498,7 +498,7 @@
virtual status_t setVoiceVolume(float volume, int delayMs = 0);
// move effect to the specified output
- virtual status_t moveEffects(int session,
+ virtual status_t moveEffects(audio_session_t session,
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index 5f4fb22..b4b269a 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -155,7 +155,7 @@
callbackFormat, params.previewFormat);
res = device->createStream(mCallbackWindow,
params.previewWidth, params.previewHeight, callbackFormat,
- HAL_DATASPACE_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
+ HAL_DATASPACE_V0_JFIF, CAMERA3_STREAM_ROTATION_0, &mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
"%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 3923853..e97618c 100644
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -145,7 +145,7 @@
// Create stream for HAL production
res = device->createStream(mCaptureWindow,
params.pictureWidth, params.pictureHeight,
- HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_JFIF,
+ HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
CAMERA3_STREAM_ROTATION_0, &mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for capture: "
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index d4022cd..5779176 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -872,7 +872,7 @@
// Set up initial state for non-Camera.Parameters state variables
videoFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- videoDataSpace = HAL_DATASPACE_BT709;
+ videoDataSpace = HAL_DATASPACE_V0_BT709;
videoBufferMode = hardware::ICamera::VIDEO_BUFFER_MODE_DATA_CALLBACK_YUV;
playShutterSound = true;
enableFaceDetect = false;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 05c5323..331f10d 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -410,6 +410,31 @@
return measured;
}
+/**
+ * Map Android N dataspace definitions back to Android M definitions, for
+ * use with HALv3.3 or older.
+ *
+ * Only map where correspondences exist, and otherwise preserve the value.
+ */
+android_dataspace Camera3Device::mapToLegacyDataspace(android_dataspace dataSpace) {
+ switch (dataSpace) {
+ case HAL_DATASPACE_V0_SRGB_LINEAR:
+ return HAL_DATASPACE_SRGB_LINEAR;
+ case HAL_DATASPACE_V0_SRGB:
+ return HAL_DATASPACE_SRGB;
+ case HAL_DATASPACE_V0_JFIF:
+ return HAL_DATASPACE_JFIF;
+ case HAL_DATASPACE_V0_BT601_625:
+ return HAL_DATASPACE_BT601_625;
+ case HAL_DATASPACE_V0_BT601_525:
+ return HAL_DATASPACE_BT601_525;
+ case HAL_DATASPACE_V0_BT709:
+ return HAL_DATASPACE_BT709;
+ default:
+ return dataSpace;
+ }
+}
+
ssize_t Camera3Device::getJpegBufferSize(uint32_t width, uint32_t height) const {
// Get max jpeg size (area-wise).
Size maxJpegResolution = getMaxJpegResolution();
@@ -1006,6 +1031,10 @@
if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2) {
streamSetId = CAMERA3_STREAM_SET_ID_INVALID;
}
+ // Use legacy dataspace values for older HALs
+ if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
+ dataSpace = mapToLegacyDataspace(dataSpace);
+ }
if (format == HAL_PIXEL_FORMAT_BLOB) {
ssize_t blobBufferSize;
if (dataSpace != HAL_DATASPACE_DEPTH) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5b1c87e..ba092d0 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -404,6 +404,11 @@
*/
static nsecs_t getMonoToBoottimeOffset();
+ /**
+ * Helper function to map between legacy and new dataspace enums
+ */
+ static android_dataspace mapToLegacyDataspace(android_dataspace dataSpace);
+
struct RequestTrigger {
// Metadata tag number, e.g. android.control.aePrecaptureTrigger
uint32_t metadataTag;
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 98a71bb..f85aa13 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -26,6 +26,8 @@
namespace android {
+static const char kDeadlockedString[] = "MediaLogService may be deadlocked\n";
+
void MediaLogService::registerWriter(const sp<IMemory>& shared, size_t size, const char *name)
{
if (IPCThreadState::self()->getCallingUid() != AID_AUDIOSERVER || shared == 0 ||
@@ -54,6 +56,19 @@
}
}
+bool MediaLogService::dumpTryLock(Mutex& mutex)
+{
+ bool locked = false;
+ for (int i = 0; i < kDumpLockRetries; ++i) {
+ if (mutex.tryLock() == NO_ERROR) {
+ locked = true;
+ break;
+ }
+ usleep(kDumpLockSleepUs);
+ }
+ return locked;
+}
+
status_t MediaLogService::dump(int fd, const Vector<String16>& args __unused)
{
// FIXME merge with similar but not identical code at services/audioflinger/ServiceUtilities.cpp
@@ -68,9 +83,22 @@
Vector<NamedReader> namedReaders;
{
- Mutex::Autolock _l(mLock);
+ bool locked = dumpTryLock(mLock);
+
+ // failed to lock - MediaLogService is probably deadlocked
+ if (!locked) {
+ String8 result(kDeadlockedString);
+ if (fd >= 0) {
+ write(fd, result.string(), result.size());
+ } else {
+ ALOGW("%s:", result.string());
+ }
+ return NO_ERROR;
+ }
namedReaders = mNamedReaders;
+ mLock.unlock();
}
+
for (size_t i = 0; i < namedReaders.size(); i++) {
const NamedReader& namedReader = namedReaders[i];
if (fd >= 0) {
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index 2d89a41..c9bf2eb 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -43,6 +43,12 @@
uint32_t flags);
private:
+
+ // Internal dump
+ static const int kDumpLockRetries = 50;
+ static const int kDumpLockSleepUs = 20000;
+ static bool dumpTryLock(Mutex& mutex);
+
Mutex mLock;
class NamedReader {
public: