Merge "Bug 4608375"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 01262fa..ca77185 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -66,6 +66,7 @@
static long gMaxNumFrames; // 0 means decode all available.
static long gReproduceBug; // if not -1.
static bool gPreferSoftwareCodec;
+static bool gForceToUseHardwareCodec;
static bool gPlaybackAudio;
static bool gWriteMP4;
static bool gDisplayHistogram;
@@ -144,10 +145,18 @@
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, mime)) {
rawSource = source;
} else {
+ int flags = 0;
+ if (gPreferSoftwareCodec) {
+ flags |= OMXCodec::kPreferSoftwareCodecs;
+ }
+ if (gForceToUseHardwareCodec) {
+ CHECK(!gPreferSoftwareCodec);
+ flags |= OMXCodec::kHardwareCodecsOnly;
+ }
rawSource = OMXCodec::Create(
client->interface(), meta, false /* createEncoder */, source,
NULL /* matchComponentName */,
- gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0,
+ flags,
gSurface);
if (rawSource == NULL) {
@@ -545,6 +554,7 @@
fprintf(stderr, " -p(rofiles) dump decoder profiles supported\n");
fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n");
fprintf(stderr, " -s(oftware) prefer software codec\n");
+ fprintf(stderr, " -r(hardware) force to use hardware codec\n");
fprintf(stderr, " -o playback audio\n");
fprintf(stderr, " -w(rite) filename (write to .mp4 file)\n");
fprintf(stderr, " -k seek test\n");
@@ -566,6 +576,7 @@
gMaxNumFrames = 0;
gReproduceBug = -1;
gPreferSoftwareCodec = false;
+ gForceToUseHardwareCodec = false;
gPlaybackAudio = false;
gWriteMP4 = false;
gDisplayHistogram = false;
@@ -575,7 +586,7 @@
sp<LiveSession> liveSession;
int res;
- while ((res = getopt(argc, argv, "han:lm:b:ptsow:kxS")) >= 0) {
+ while ((res = getopt(argc, argv, "han:lm:b:ptsrow:kxS")) >= 0) {
switch (res) {
case 'a':
{
@@ -636,6 +647,12 @@
break;
}
+ case 'r':
+ {
+ gForceToUseHardwareCodec = true;
+ break;
+ }
+
case 'o':
{
gPlaybackAudio = true;
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
index d430f72..07b3b47 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp
@@ -53,11 +53,11 @@
}
FwdLockEngine::FwdLockEngine() {
- LOGD("FwdLockEngine Construction");
+ LOGV("FwdLockEngine Construction");
}
FwdLockEngine::~FwdLockEngine() {
- LOGD("FwdLockEngine Destruction");
+ LOGV("FwdLockEngine Destruction");
convertSessionMap.destroyMap();
decodeSessionMap.destroyMap();
@@ -91,7 +91,7 @@
DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
DrmConstraints* drmConstraints = NULL;
- LOGD("FwdLockEngine::onGetConstraints");
+ LOGV("FwdLockEngine::onGetConstraints");
if (NULL != path &&
(RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
@@ -105,7 +105,7 @@
DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
DrmMetadata* drmMetadata = NULL;
- LOGD("FwdLockEngine::onGetMetadata");
+ LOGV("FwdLockEngine::onGetMetadata");
if (NULL != path) {
// Returns empty metadata to show no error condition.
@@ -116,11 +116,11 @@
}
android::status_t FwdLockEngine::onInitialize(int uniqueId) {
- LOGD("FwdLockEngine::onInitialize");
+ LOGV("FwdLockEngine::onInitialize");
if (FwdLockGlue_InitializeKeyEncryption()) {
- LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
+ LOGV("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
} else {
LOGD("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
"errno = %d", errno);
@@ -132,13 +132,13 @@
android::status_t
FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
// Not used
- LOGD("FwdLockEngine::onSetOnInfoListener");
+ LOGV("FwdLockEngine::onSetOnInfoListener");
return DRM_NO_ERROR;
}
android::status_t FwdLockEngine::onTerminate(int uniqueId) {
- LOGD("FwdLockEngine::onTerminate");
+ LOGV("FwdLockEngine::onTerminate");
return DRM_NO_ERROR;
}
@@ -146,7 +146,7 @@
DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
- LOGD("FwdLockEngine::onGetSupportInfo");
+ LOGV("FwdLockEngine::onGetSupportInfo");
// fill all Forward Lock mimetypes and extensions
if (NULL != pSupportInfo) {
@@ -182,7 +182,7 @@
drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
- LOGD("FwdLockEngine::onProcessDrmInfo");
+ LOGV("FwdLockEngine::onProcessDrmInfo");
return drmInfoStatus;
}
@@ -193,7 +193,7 @@
const String8& rightsPath,
const String8& contentPath) {
// No rights to save. Return
- LOGD("FwdLockEngine::onSaveRights");
+ LOGV("FwdLockEngine::onSaveRights");
return DRM_ERROR_UNKNOWN;
}
@@ -201,7 +201,7 @@
DrmInfo* drmInfo = NULL;
// Nothing to be done for Forward Lock file
- LOGD("FwdLockEngine::onAcquireDrmInfo");
+ LOGV("FwdLockEngine::onAcquireDrmInfo");
return drmInfo;
}
@@ -211,7 +211,7 @@
int action) {
int result = RightsStatus::RIGHTS_INVALID;
- LOGD("FwdLockEngine::onCheckRightsStatus");
+ LOGV("FwdLockEngine::onCheckRightsStatus");
// Only Transfer action is not allowed for forward Lock files.
if (onCanHandle(uniqueId, path)) {
@@ -241,7 +241,7 @@
int action,
bool reserve) {
// No rights consumption
- LOGD("FwdLockEngine::onConsumeRights");
+ LOGV("FwdLockEngine::onConsumeRights");
return DRM_NO_ERROR;
}
@@ -249,14 +249,14 @@
const String8& path,
int action,
const ActionDescription& description) {
- LOGD("FwdLockEngine::onValidateAction");
+ LOGV("FwdLockEngine::onValidateAction");
// For the forwardlock engine checkRights and ValidateAction are the same.
return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
}
String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
- LOGD("FwdLockEngine::onGetOriginalMimeType");
+ LOGV("FwdLockEngine::onGetOriginalMimeType");
String8 mimeString = String8("");
int fileDesc = FwdLockFile_open(path.string());
@@ -280,7 +280,7 @@
const String8& mimeType) {
String8 mimeStr = String8(mimeType);
- LOGD("FwdLockEngine::onGetDrmObjectType");
+ LOGV("FwdLockEngine::onGetDrmObjectType");
mimeStr.toLower();
@@ -301,13 +301,13 @@
status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
// No Rights to remove
- LOGD("FwdLockEngine::onRemoveRights");
+ LOGV("FwdLockEngine::onRemoveRights");
return DRM_NO_ERROR;
}
status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
// No rights to remove
- LOGD("FwdLockEngine::onRemoveAllRights");
+ LOGV("FwdLockEngine::onRemoveAllRights");
return DRM_NO_ERROR;
}
@@ -319,14 +319,14 @@
int playbackStatus, int position) {
#endif
// Not used
- LOGD("FwdLockEngine::onSetPlaybackStatus");
+ LOGV("FwdLockEngine::onSetPlaybackStatus");
return DRM_NO_ERROR;
}
status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
int convertId) {
status_t result = DRM_ERROR_UNKNOWN;
- LOGD("FwdLockEngine::onOpenConvertSession");
+ LOGV("FwdLockEngine::onOpenConvertSession");
if (!convertSessionMap.isCreated(convertId)) {
ConvertSession *newSession = new ConvertSession();
if (FwdLockConv_Status_OK ==
@@ -383,7 +383,7 @@
DrmBuffer *convResult = new DrmBuffer(NULL, 0);
int offset = -1;
- LOGD("FwdLockEngine::onCloseConvertSession");
+ LOGV("FwdLockEngine::onCloseConvertSession");
if (convertSessionMap.isCreated(convertId)) {
ConvertSession *convSession = convertSessionMap.getValue(convertId);
@@ -424,7 +424,7 @@
status_t result = DRM_ERROR_CANNOT_HANDLE;
int fileDesc = -1;
- LOGD("FwdLockEngine::onOpenDecryptSession");
+ LOGV("FwdLockEngine::onOpenDecryptSession");
if ((-1 < fd) &&
(NULL != decryptHandle) &&
@@ -455,12 +455,15 @@
} else {
LOGD("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
FwdLockFile_detach(fileDesc);
- ::close(fileDesc);
delete decodeSession;
}
}
- LOGD("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
+ if (DRM_NO_ERROR != result && -1 < fileDesc) {
+ ::close(fileDesc);
+ }
+
+ LOGV("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
return result;
}
@@ -497,7 +500,7 @@
status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
DecryptHandle* decryptHandle) {
status_t result = DRM_ERROR_UNKNOWN;
- LOGD("FwdLockEngine::onCloseDecryptSession");
+ LOGV("FwdLockEngine::onCloseDecryptSession");
if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
@@ -509,7 +512,7 @@
}
}
- LOGD("FwdLockEngine::onCloseDecryptSession Exit");
+ LOGV("FwdLockEngine::onCloseDecryptSession Exit");
return result;
}
@@ -517,13 +520,13 @@
DecryptHandle* decryptHandle,
int decryptUnitId,
const DrmBuffer* headerInfo) {
- LOGD("FwdLockEngine::onInitializeDecryptUnit");
+ LOGV("FwdLockEngine::onInitializeDecryptUnit");
return DRM_ERROR_UNKNOWN;
}
status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
- LOGD("FwdLockEngine::onDecrypt");
+ LOGV("FwdLockEngine::onDecrypt");
return DRM_ERROR_UNKNOWN;
}
@@ -532,14 +535,14 @@
int decryptUnitId,
const DrmBuffer* encBuffer,
DrmBuffer** decBuffer) {
- LOGD("FwdLockEngine::onDecrypt");
+ LOGV("FwdLockEngine::onDecrypt");
return DRM_ERROR_UNKNOWN;
}
status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
DecryptHandle* decryptHandle,
int decryptUnitId) {
- LOGD("FwdLockEngine::onFinalizeDecryptUnit");
+ LOGV("FwdLockEngine::onFinalizeDecryptUnit");
return DRM_ERROR_UNKNOWN;
}
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 68cd188..89213b7 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -22,7 +22,7 @@
#include <media/IAudioFlinger.h>
#include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
/* XXX: Should be include by all the users instead */
#include <media/AudioParameter.h>
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 09b2bfe..0fc8dbf 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -26,7 +26,7 @@
#include <binder/IInterface.h>
#include <media/AudioSystem.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
namespace android {
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 4044c5d..deade5e 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -55,6 +55,7 @@
kKeyIsSyncFrame = 'sync', // int32_t (bool)
kKeyIsCodecConfig = 'conf', // int32_t (bool)
kKeyTime = 'time', // int64_t (usecs)
+ kKeyDecodingTime = 'decT', // int64_t (decoding timestamp in usecs)
kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
kKeyTargetTime = 'tarT', // int64_t (usecs)
kKeyDriftTime = 'dftT', // int64_t (usecs)
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 70daafa..589cefd 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -202,6 +202,10 @@
bool mOnlySubmitOneBufferAtOneTime;
bool mEnableGrallocUsageProtected;
+ // Used to record the decoding time for an output picture from
+ // a video encoder.
+ List<int64_t> mDecodingTimeList;
+
OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
bool isEncoder, const char *mime, const char *componentName,
const sp<MediaSource> &source,
@@ -317,6 +321,8 @@
status_t applyRotation();
+ int64_t retrieveDecodingTimeUs(bool isCodecSpecific);
+
OMXCodec(const OMXCodec &);
OMXCodec &operator=(const OMXCodec &);
};
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 717f837..0da03d1 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -20,355 +20,12 @@
#include <stdint.h>
#include <sys/types.h>
-#include <cutils/compiler.h>
-
#include <utils/Debug.h>
-#include <utils/threads.h>
-#include <utils/String8.h>
-
-#include <ui/Rect.h>
namespace android {
// ---------------------------------------------------------------------------
-/*
- * These classes manage a stack of buffers in shared memory.
- *
- * SharedClient: represents a client with several stacks
- * SharedBufferStack: represents a stack of buffers
- * SharedBufferClient: manipulates the SharedBufferStack from the client side
- * SharedBufferServer: manipulates the SharedBufferStack from the server side
- *
- * Buffers can be dequeued until there are none available, they can be locked
- * unless they are in use by the server, which is only the case for the last
- * dequeue-able buffer. When these various conditions are not met, the caller
- * waits until the condition is met.
- *
- */
-
-// ----------------------------------------------------------------------------
-
-class Region;
-class SharedBufferStack;
-class SharedClient;
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferStack
-{
- friend class SharedClient;
- friend class SharedBufferBase;
- friend class SharedBufferClient;
- friend class SharedBufferServer;
-
-public:
- // When changing these values, the COMPILE_TIME_ASSERT at the end of this
- // file need to be updated.
- static const unsigned int NUM_LAYERS_MAX = 31;
- static const unsigned int NUM_BUFFER_MAX = 32;
- static const unsigned int NUM_BUFFER_MIN = 2;
- static const unsigned int NUM_DISPLAY_MAX = 4;
-
- struct Statistics { // 4 longs
- typedef int32_t usecs_t;
- usecs_t totalTime;
- usecs_t reserved[3];
- };
-
- struct SmallRect {
- uint16_t l, t, r, b;
- };
-
- struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
- static const unsigned int NUM_RECT_MAX = 5;
- uint32_t count;
- SmallRect rects[NUM_RECT_MAX];
- };
-
- struct BufferData {
- FlatRegion dirtyRegion;
- SmallRect crop;
- uint8_t transform;
- uint8_t reserved[3];
- };
-
- SharedBufferStack();
- void init(int32_t identity);
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint8_t transform);
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(int buffer) const;
-
- // these attributes are part of the conditions/updates
- volatile int32_t head; // server's current front buffer
- volatile int32_t available; // number of dequeue-able buffers
- volatile int32_t queued; // number of buffers waiting for post
- volatile int32_t reserved1;
- volatile status_t status; // surface's status code
-
- // not part of the conditions
- volatile int32_t reallocMask;
- volatile int8_t index[NUM_BUFFER_MAX];
-
- int32_t identity; // surface's identity (const)
- int32_t token; // surface's token (for debugging)
- Statistics stats;
- int8_t headBuf; // last retired buffer
- uint8_t reservedBytes[3];
- int32_t reserved;
- BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
-};
-
-// ----------------------------------------------------------------------------
-
-// 64 KB max
-class SharedClient
-{
-public:
- SharedClient();
- ~SharedClient();
- status_t validate(size_t token) const;
-
-private:
- friend class SharedBufferBase;
- friend class SharedBufferClient;
- friend class SharedBufferServer;
-
- // FIXME: this should be replaced by a lock-less primitive
- Mutex lock;
- Condition cv;
- SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
-};
-
-// ============================================================================
-
-class SharedBufferBase
-{
-public:
- SharedBufferBase(SharedClient* sharedClient, int surface,
- int32_t identity);
- ~SharedBufferBase();
- status_t getStatus() const;
- int32_t getIdentity() const;
- String8 dump(char const* prefix) const;
-
-protected:
- SharedClient* const mSharedClient;
- SharedBufferStack* const mSharedStack;
- const int mIdentity;
-
- friend struct Update;
- friend struct QueueUpdate;
-
- struct ConditionBase {
- SharedBufferStack& stack;
- inline ConditionBase(SharedBufferBase* sbc)
- : stack(*sbc->mSharedStack) { }
- virtual ~ConditionBase() { };
- virtual bool operator()() const = 0;
- virtual const char* name() const = 0;
- };
- status_t waitForCondition(const ConditionBase& condition);
-
- struct UpdateBase {
- SharedBufferStack& stack;
- inline UpdateBase(SharedBufferBase* sbb)
- : stack(*sbb->mSharedStack) { }
- };
- template <typename T>
- status_t updateCondition(T update);
-};
-
-template <typename T>
-status_t SharedBufferBase::updateCondition(T update) {
- SharedClient& client( *mSharedClient );
- Mutex::Autolock _l(client.lock);
- ssize_t result = update();
- client.cv.broadcast();
- return result;
-}
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferClient : public SharedBufferBase
-{
-public:
- SharedBufferClient(SharedClient* sharedClient, int surface, int num,
- int32_t identity);
-
- ssize_t dequeue();
- status_t undoDequeue(int buf);
-
- status_t lock(int buf);
- status_t cancel(int buf);
- status_t queue(int buf);
- bool needNewBuffer(int buffer) const;
- status_t setDirtyRegion(int buffer, const Region& reg);
- status_t setCrop(int buffer, const Rect& reg);
- status_t setTransform(int buffer, uint32_t transform);
-
- class SetBufferCountCallback {
- friend class SharedBufferClient;
- virtual status_t operator()(int bufferCount) const = 0;
- protected:
- virtual ~SetBufferCountCallback() { }
- };
- status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
-
-private:
- friend struct Condition;
- friend struct DequeueCondition;
- friend struct LockCondition;
-
- struct QueueUpdate : public UpdateBase {
- inline QueueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct DequeueUpdate : public UpdateBase {
- inline DequeueUpdate(SharedBufferBase* sbb);
- inline ssize_t operator()();
- };
-
- struct CancelUpdate : public UpdateBase {
- int tail, buf;
- inline CancelUpdate(SharedBufferBase* sbb, int tail, int buf);
- inline ssize_t operator()();
- };
-
- // --
-
- struct DequeueCondition : public ConditionBase {
- inline DequeueCondition(SharedBufferClient* sbc);
- inline bool operator()() const;
- inline const char* name() const { return "DequeueCondition"; }
- };
-
- struct LockCondition : public ConditionBase {
- int buf;
- inline LockCondition(SharedBufferClient* sbc, int buf);
- inline bool operator()() const;
- inline const char* name() const { return "LockCondition"; }
- };
-
- int32_t computeTail() const;
-
- mutable RWLock mLock;
- int mNumBuffers;
-
- int32_t tail;
- int32_t queued_head;
- // statistics...
- nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
-};
-
-// ----------------------------------------------------------------------------
-
-class SharedBufferServer
- : public SharedBufferBase,
- public LightRefBase<SharedBufferServer>
-{
-public:
- SharedBufferServer(SharedClient* sharedClient, int surface, int num,
- int32_t identity);
-
- ssize_t retireAndLock();
- void setStatus(status_t status);
- status_t reallocateAll();
- status_t reallocateAllExcept(int buffer);
- int32_t getQueuedCount() const;
- Region getDirtyRegion(int buffer) const;
- Rect getCrop(int buffer) const;
- uint32_t getTransform(int buffer) const;
-
- status_t resize(int newNumBuffers);
- status_t grow(int newNumBuffers);
- status_t shrink(int newNumBuffers);
-
- SharedBufferStack::Statistics getStats() const;
-
-
-private:
- friend class LightRefBase<SharedBufferServer>;
- ~SharedBufferServer();
-
- /*
- * BufferList is basically a fixed-capacity sorted-vector of
- * unsigned 5-bits ints using a 32-bits int as storage.
- * it has efficient iterators to find items in the list and not in the list.
- */
- class BufferList {
- size_t mCapacity;
- uint32_t mList;
- public:
- BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
- : mCapacity(c), mList(0) { }
- status_t add(int value);
- status_t remove(int value);
- uint32_t getMask() const { return mList; }
-
- class const_iterator {
- friend class BufferList;
- uint32_t mask, curr;
- const_iterator(uint32_t mask) :
- mask(mask), curr(__builtin_clz(mask)) {
- }
- public:
- inline bool operator == (const const_iterator& rhs) const {
- return mask == rhs.mask;
- }
- inline bool operator != (const const_iterator& rhs) const {
- return mask != rhs.mask;
- }
- inline int operator *() const { return curr; }
- inline const const_iterator& operator ++() {
- mask &= ~(1<<(31-curr));
- curr = __builtin_clz(mask);
- return *this;
- }
- };
-
- inline const_iterator begin() const {
- return const_iterator(mList);
- }
- inline const_iterator end() const {
- return const_iterator(0);
- }
- inline const_iterator free_begin() const {
- uint32_t mask = (1 << (32-mCapacity)) - 1;
- return const_iterator( ~(mList | mask) );
- }
- };
-
- // this protects mNumBuffers and mBufferList
- mutable RWLock mLock;
- int mNumBuffers;
- BufferList mBufferList;
-
- struct BuffersAvailableCondition : public ConditionBase {
- int mNumBuffers;
- inline BuffersAvailableCondition(SharedBufferServer* sbs,
- int numBuffers);
- inline bool operator()() const;
- inline const char* name() const { return "BuffersAvailableCondition"; }
- };
-
- struct RetireUpdate : public UpdateBase {
- const int numBuffers;
- inline RetireUpdate(SharedBufferBase* sbb, int numBuffers);
- inline ssize_t operator()();
- };
-
- struct StatusUpdate : public UpdateBase {
- const status_t status;
- inline StatusUpdate(SharedBufferBase* sbb, status_t status);
- inline ssize_t operator()();
- };
-};
-
-// ===========================================================================
+#define NUM_DISPLAY_MAX 4
struct display_cblk_t
{
@@ -389,12 +46,11 @@
uint8_t connected;
uint8_t reserved[3];
uint32_t pad[7];
- display_cblk_t displays[SharedBufferStack::NUM_DISPLAY_MAX];
+ display_cblk_t displays[NUM_DISPLAY_MAX];
};
// ---------------------------------------------------------------------------
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 65536)
COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
// ---------------------------------------------------------------------------
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 6b4391b..37fe182 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -40,7 +40,7 @@
#include <cutils/bitops.h>
#include <system/audio.h>
-#include <hardware/audio_policy.h>
+#include <system/audio_policy.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
diff --git a/media/libstagefright/CameraSourceTimeLapse.cpp b/media/libstagefright/CameraSourceTimeLapse.cpp
index 3689557..cc22574 100644
--- a/media/libstagefright/CameraSourceTimeLapse.cpp
+++ b/media/libstagefright/CameraSourceTimeLapse.cpp
@@ -486,7 +486,8 @@
if (mForceRead) {
LOGV("dataCallbackTimestamp timelapse: forced read");
mForceRead = false;
- *timestampUs = mLastFrameTimestampUs;
+ *timestampUs =
+ mLastFrameTimestampUs + mTimeBetweenTimeLapseVideoFramesUs;
return false;
}
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 5008b5f..28add18 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -128,7 +128,6 @@
size_t mNumStssTableEntries;
List<int32_t> mStssTableEntries;
- size_t mNumSttsTableEntries;
struct SttsTableEntry {
SttsTableEntry(uint32_t count, uint32_t duration)
@@ -137,8 +136,20 @@
uint32_t sampleCount;
uint32_t sampleDuration; // time scale based
};
+ size_t mNumSttsTableEntries;
List<SttsTableEntry> mSttsTableEntries;
+ struct CttsTableEntry {
+ CttsTableEntry(uint32_t count, int32_t timescaledDur)
+ : sampleCount(count), sampleDuration(timescaledDur) {}
+
+ uint32_t sampleCount;
+ int32_t sampleDuration; // time scale based
+ };
+ bool mHasNegativeCttsDeltaDuration;
+ size_t mNumCttsTableEntries;
+ List<CttsTableEntry> mCttsTableEntries;
+
// Sequence parameter set or picture parameter set
struct AVCParamSet {
AVCParamSet(uint16_t length, const uint8_t *data)
@@ -219,6 +230,7 @@
// Duration is time scale based
void addOneSttsTableEntry(size_t sampleCount, int32_t timescaledDur);
+ void addOneCttsTableEntry(size_t sampleCount, int32_t timescaledDur);
void sendTrackSummary(bool hasMultipleTracks);
// Write the boxes
@@ -227,6 +239,7 @@
void writeStszBox();
void writeStssBox();
void writeSttsBox();
+ void writeCttsBox();
void writeD263Box();
void writePaspBox();
void writeAvccBox();
@@ -1147,6 +1160,7 @@
mEstimatedTrackSizeBytes += mNumStscTableEntries * 12 + // stsc box size
mNumStssTableEntries * 4 + // stss box size
mNumSttsTableEntries * 8 + // stts box size
+ mNumCttsTableEntries * 8 + // ctts box size
stcoBoxSizeBytes + // stco box size
stszBoxSizeBytes; // stsz box size
}
@@ -1173,6 +1187,20 @@
++mNumSttsTableEntries;
}
+void MPEG4Writer::Track::addOneCttsTableEntry(
+ size_t sampleCount, int32_t duration) {
+
+ if (mIsAudio) {
+ return;
+ }
+ if (duration < 0 && !mHasNegativeCttsDeltaDuration) {
+ mHasNegativeCttsDeltaDuration = true;
+ }
+ CttsTableEntry cttsEntry(sampleCount, duration);
+ mCttsTableEntries.push_back(cttsEntry);
+ ++mNumCttsTableEntries;
+}
+
void MPEG4Writer::Track::addChunkOffset(off64_t offset) {
++mNumStcoTableEntries;
mChunkOffsets.push_back(offset);
@@ -1483,6 +1511,7 @@
mNumStssTableEntries = 0;
mNumStscTableEntries = 0;
mNumSttsTableEntries = 0;
+ mNumCttsTableEntries = 0;
mMdatSizeBytes = 0;
mIsMediaTimeAdjustmentOn = false;
mPrevMediaTimeAdjustTimestampUs = 0;
@@ -1491,6 +1520,7 @@
mTotalDriftTimeToAdjustUs = 0;
mPrevTotalAccumDriftTimeUs = 0;
mMaxChunkDurationUs = 0;
+ mHasNegativeCttsDeltaDuration = false;
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
@@ -1932,14 +1962,19 @@
int64_t chunkTimestampUs = 0;
int32_t nChunks = 0;
int32_t nZeroLengthFrames = 0;
- int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
- int64_t lastDurationUs = 0; // Between the previous two samples in ms
- int64_t currDurationTicks = 0; // Timescale based ticks
- int64_t lastDurationTicks = 0; // Timescale based ticks
- int32_t sampleCount = 1; // Sample count in the current stts table entry
- uint32_t previousSampleSize = 0; // Size of the previous sample
+ int64_t lastTimestampUs = 0; // Previous sample time stamp
+ int64_t lastCttsTimeUs = 0; // Previous sample time stamp
+ int64_t lastDurationUs = 0; // Between the previous two samples
+ int64_t currDurationTicks = 0; // Timescale based ticks
+ int64_t lastDurationTicks = 0; // Timescale based ticks
+ int32_t sampleCount = 1; // Sample count in the current stts table entry
+ int64_t currCttsDurTicks = 0; // Timescale based ticks
+ int64_t lastCttsDurTicks = 0; // Timescale based ticks
+ int32_t cttsSampleCount = 1; // Sample count in the current ctts table entry
+ uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
- int64_t timestampUs;
+ int64_t timestampUs = 0;
+ int64_t cttsDeltaTimeUs = 0;
if (mIsAudio) {
prctl(PR_SET_NAME, (unsigned long)"AudioTrackEncoding", 0, 0, 0);
@@ -2063,7 +2098,6 @@
*
*/
CHECK(meta_data->findInt64(kKeyTime, ×tampUs));
- LOGV("%s timestampUs: %lld", mIsAudio? "Audio": "Video", timestampUs);
////////////////////////////////////////////////////////////////////////////////
if (mNumSamples == 0) {
@@ -2084,6 +2118,24 @@
timestampUs -= previousPausedDurationUs;
CHECK(timestampUs >= 0);
+ if (!mIsAudio) {
+ /*
+ * Composition time: timestampUs
+ * Decoding time: decodingTimeUs
+ * Composition time delta = composition time - decoding time
+ *
+ * We save picture decoding time stamp delta in stts table entries,
+ * and composition time delta duration in ctts table entries.
+ */
+ int64_t decodingTimeUs;
+ CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+ decodingTimeUs -= previousPausedDurationUs;
+ int64_t timeUs = decodingTimeUs;
+ cttsDeltaTimeUs = timestampUs - decodingTimeUs;
+ timestampUs = decodingTimeUs;
+ LOGV("decoding time: %lld and ctts delta time: %lld",
+ timestampUs, cttsDeltaTimeUs);
+ }
// Media time adjustment for real-time applications
if (mIsRealTimeRecording) {
@@ -2139,6 +2191,18 @@
} else {
++sampleCount;
}
+
+ if (!mIsAudio) {
+ currCttsDurTicks =
+ ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL -
+ (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL);
+ if (currCttsDurTicks != lastCttsDurTicks) {
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+ cttsSampleCount = 1;
+ } else {
+ ++cttsSampleCount;
+ }
+ }
}
if (mSamplesHaveSameSize) {
if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
@@ -2152,6 +2216,11 @@
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
+ if (!mIsAudio) {
+ lastCttsDurTicks = currCttsDurTicks;
+ lastCttsTimeUs = cttsDeltaTimeUs;
+ }
+
if (isSync != 0) {
addOneStssTableEntry(mNumSamples);
}
@@ -2221,8 +2290,10 @@
if (mNumSamples == 1) {
lastDurationUs = 0; // A single sample's duration
lastDurationTicks = 0;
+ lastCttsDurTicks = 0;
} else {
++sampleCount; // Count for the last sample
+ ++cttsSampleCount;
}
if (mNumSamples <= 2) {
@@ -2234,6 +2305,7 @@
addOneSttsTableEntry(sampleCount, lastDurationTicks);
}
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
mTrackDurationUs += lastDurationUs;
mReachedEOS = true;
@@ -2432,6 +2504,7 @@
}
mOwner->endBox(); // stsd
writeSttsBox();
+ writeCttsBox();
if (!mIsAudio) {
writeStssBox();
}
@@ -2782,13 +2855,49 @@
int32_t dur = (trackStartTimeOffsetUs * mTimeScale + 500000LL) / 1000000LL;
mOwner->writeInt32(dur + it->sampleDuration);
+ int64_t totalCount = 1;
while (++it != mSttsTableEntries.end()) {
mOwner->writeInt32(it->sampleCount);
mOwner->writeInt32(it->sampleDuration);
+ totalCount += it->sampleCount;
}
+ CHECK(totalCount == mNumSamples);
mOwner->endBox(); // stts
}
+void MPEG4Writer::Track::writeCttsBox() {
+ if (mIsAudio) { // ctts is not for audio
+ return;
+ }
+
+ // Do not write ctts box when there is no need to have it.
+ if ((mNumCttsTableEntries == 1 &&
+ mCttsTableEntries.begin()->sampleDuration == 0) ||
+ mNumCttsTableEntries == 0) {
+ return;
+ }
+
+ LOGV("ctts box has %d entries", mNumCttsTableEntries);
+
+ mOwner->beginBox("ctts");
+ if (mHasNegativeCttsDeltaDuration) {
+ mOwner->writeInt32(0x00010000); // version=1, flags=0
+ } else {
+ mOwner->writeInt32(0); // version=0, flags=0
+ }
+ mOwner->writeInt32(mNumCttsTableEntries);
+
+ int64_t totalCount = 0;
+ for (List<CttsTableEntry>::iterator it = mCttsTableEntries.begin();
+ it != mCttsTableEntries.end(); ++it) {
+ mOwner->writeInt32(it->sampleCount);
+ mOwner->writeInt32(it->sampleDuration);
+ totalCount += it->sampleCount;
+ }
+ CHECK(totalCount == mNumSamples);
+ mOwner->endBox(); // ctts
+}
+
void MPEG4Writer::Track::writeStssBox() {
mOwner->beginBox("stss");
mOwner->writeInt32(0); // version=0, flags=0
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 72d0d08..c4fcc79 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1981,6 +1981,20 @@
return bufInfo;
}
+int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
+ CHECK(mIsEncoder);
+ CHECK(!mDecodingTimeList.empty());
+ List<int64_t>::iterator it = mDecodingTimeList.begin();
+ int64_t timeUs = *it;
+
+ // If the output buffer is codec specific configuration,
+ // do not remove the decoding time from the list.
+ if (!isCodecSpecific) {
+ mDecodingTimeList.erase(it);
+ }
+ return timeUs;
+}
+
void OMXCodec::on_message(const omx_message &msg) {
if (mState == ERROR) {
LOGW("Dropping OMX message - we're in ERROR state.");
@@ -2128,14 +2142,21 @@
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
}
+ bool isCodecSpecific = false;
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_CODECCONFIG) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+ isCodecSpecific = true;
}
if (isGraphicBuffer || mQuirks & kOutputBuffersAreUnreadable) {
buffer->meta_data()->setInt32(kKeyIsUnreadable, true);
}
+ if (mIsEncoder) {
+ int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
+ buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
+ }
+
buffer->meta_data()->setPointer(
kKeyPlatformPrivate,
msg.u.extended_buffer_data.platform_private);
@@ -2938,6 +2959,9 @@
int64_t lastBufferTimeUs;
CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
CHECK(lastBufferTimeUs >= 0);
+ if (mIsEncoder) {
+ mDecodingTimeList.push_back(lastBufferTimeUs);
+ }
if (offset == 0) {
timestampUs = lastBufferTimeUs;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d4a8ddb..44df5b5 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -44,7 +44,7 @@
#include <private/media/AudioEffectShared.h>
#include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
#include "AudioMixer.h"
#include "AudioFlinger.h"
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f3371bf..1fad987 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -39,7 +39,7 @@
#include <binder/MemoryDealer.h>
#include <system/audio.h>
-#include <hardware/audio_hal.h>
+#include <hardware/audio.h>
#include "AudioBufferProvider.h"
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd91788..47ca3a0 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -36,8 +36,8 @@
#include <hardware/hardware.h>
#include <system/audio.h>
+#include <system/audio_policy.h>
#include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
namespace android {
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index d9b5ada..b830120 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -23,8 +23,8 @@
#include <binder/BinderService.h>
#include <system/audio.h>
+#include <system/audio_policy.h>
#include <hardware/audio_policy.h>
-#include <hardware/audio_policy_hal.h>
namespace android {