summaryrefslogtreecommitdiffstats
path: root/media/libmedia
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmedia')
-rw-r--r--media/libmedia/Android.mk4
-rw-r--r--media/libmedia/AudioTrack.cpp169
-rw-r--r--media/libmedia/IOMX.cpp85
-rw-r--r--media/libmedia/IResourceManagerService.cpp2
-rw-r--r--media/libmedia/MediaProfiles.cpp126
5 files changed, 183 insertions, 203 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 0c18828..a3c3d3c 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -7,7 +7,7 @@ LOCAL_SRC_FILES:= \
LOCAL_MODULE:= libmedia_helper
LOCAL_MODULE_TAGS := optional
-LOCAL_C_FLAGS += -Werror -Wall
+LOCAL_C_FLAGS += -Werror -Wno-error=deprecated-declarations -Wall
LOCAL_CLANG := true
include $(BUILD_STATIC_LIBRARY)
@@ -87,7 +87,7 @@ LOCAL_C_INCLUDES := \
$(call include-path-for, audio-effects) \
$(call include-path-for, audio-utils)
-LOCAL_CFLAGS += -Werror -Wall
+LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall
LOCAL_CLANG := true
include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index faf5935..81ae6d7 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -38,11 +38,23 @@ static const int kMaxLoopCountNotifications = 32;
namespace android {
// ---------------------------------------------------------------------------
+// TODO: Move to a separate .h
+
template <typename T>
-const T &min(const T &x, const T &y) {
+static inline const T &min(const T &x, const T &y) {
return x < y ? x : y;
}
+template <typename T>
+static inline const T &max(const T &x, const T &y) {
+ return x > y ? x : y;
+}
+
+static inline nsecs_t framesToNanoseconds(ssize_t frames, uint32_t sampleRate, float speed)
+{
+ return ((double)frames * 1000000000) / ((double)sampleRate * speed);
+}
+
static int64_t convertTimespecToUs(const struct timespec &tv)
{
return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000;
@@ -480,6 +492,8 @@ status_t AudioTrack::set(
mObservedSequence = mSequence;
mInUnderrun = false;
mPreviousTimestampValid = false;
+ mTimestampStartupGlitchReported = false;
+ mRetrogradeMotionReported = false;
return NO_ERROR;
}
@@ -507,6 +521,8 @@ status_t AudioTrack::start()
// reset current position as seen by client to 0
mPosition = 0;
mPreviousTimestampValid = false;
+ mTimestampStartupGlitchReported = false;
+ mRetrogradeMotionReported = false;
// For offloaded tracks, we don't know if the hardware counters are really zero here,
// since the flush is asynchronous and stop may not fully drain.
@@ -1111,31 +1127,27 @@ status_t AudioTrack::createTrack_l()
// we must release it ourselves if anything goes wrong.
// Not all of these values are needed under all conditions, but it is easier to get them all
-
- uint32_t afLatency;
- status = AudioSystem::getLatency(output, &afLatency);
+ status = AudioSystem::getLatency(output, &mAfLatency);
if (status != NO_ERROR) {
ALOGE("getLatency(%d) failed status %d", output, status);
goto release;
}
- ALOGV("createTrack_l() output %d afLatency %u", output, afLatency);
+ ALOGV("createTrack_l() output %d afLatency %u", output, mAfLatency);
- size_t afFrameCount;
- status = AudioSystem::getFrameCount(output, &afFrameCount);
+ status = AudioSystem::getFrameCount(output, &mAfFrameCount);
if (status != NO_ERROR) {
ALOGE("getFrameCount(output=%d) status %d", output, status);
goto release;
}
- uint32_t afSampleRate;
- status = AudioSystem::getSamplingRate(output, &afSampleRate);
+ status = AudioSystem::getSamplingRate(output, &mAfSampleRate);
if (status != NO_ERROR) {
ALOGE("getSamplingRate(output=%d) status %d", output, status);
goto release;
}
if (mSampleRate == 0) {
- mSampleRate = afSampleRate;
- mOriginalSampleRate = afSampleRate;
+ mSampleRate = mAfSampleRate;
+ mOriginalSampleRate = mAfSampleRate;
}
// Client decides whether the track is TIMED (see below), but can only express a preference
// for FAST. Server will perform additional tests.
@@ -1148,9 +1160,9 @@ status_t AudioTrack::createTrack_l()
// use case 3: obtain/release mode
(mTransfer == TRANSFER_OBTAIN)) &&
// matching sample rate
- (mSampleRate == afSampleRate))) {
+ (mSampleRate == mAfSampleRate))) {
ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client; transfer %d, track %u Hz, output %u Hz",
- mTransfer, mSampleRate, afSampleRate);
+ mTransfer, mSampleRate, mAfSampleRate);
// once denied, do not request again if IAudioTrack is re-created
mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
}
@@ -1171,7 +1183,7 @@ status_t AudioTrack::createTrack_l()
// Same comment as below about ignoring frameCount parameter for set()
frameCount = mSharedBuffer->size();
} else if (frameCount == 0) {
- frameCount = afFrameCount;
+ frameCount = mAfFrameCount;
}
if (mNotificationFramesAct != frameCount) {
mNotificationFramesAct = frameCount;
@@ -1207,7 +1219,7 @@ status_t AudioTrack::createTrack_l()
if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
// for normal tracks precompute the frame count based on speed.
const size_t minFrameCount = calculateMinFrameCount(
- afLatency, afFrameCount, afSampleRate, mSampleRate,
+ mAfLatency, mAfFrameCount, mAfSampleRate, mSampleRate,
mPlaybackRate.mSpeed);
if (frameCount < minFrameCount) {
frameCount = minFrameCount;
@@ -1357,7 +1369,7 @@ status_t AudioTrack::createTrack_l()
mAudioTrack->attachAuxEffect(mAuxEffectId);
// FIXME doesn't take into account speed or future sample rate changes (until restoreTrack)
// FIXME don't believe this lie
- mLatency = afLatency + (1000*frameCount) / mSampleRate;
+ mLatency = mAfLatency + (1000*frameCount) / mSampleRate;
mFrameCount = frameCount;
// If IAudioTrack is re-created, don't let the requested frameCount
@@ -1763,7 +1775,7 @@ nsecs_t AudioTrack::processAudioBuffer()
// Cache other fields that will be needed soon
uint32_t sampleRate = mSampleRate;
float speed = mPlaybackRate.mSpeed;
- uint32_t notificationFrames = mNotificationFramesAct;
+ const uint32_t notificationFrames = mNotificationFramesAct;
if (mRefreshRemaining) {
mRefreshRemaining = false;
mRemainingFrames = notificationFrames;
@@ -1801,7 +1813,14 @@ nsecs_t AudioTrack::processAudioBuffer()
mLock.unlock();
+ // get anchor time to account for callbacks.
+ const nsecs_t timeBeforeCallbacks = systemTime();
+
if (waitStreamEnd) {
+ // FIXME: Instead of blocking in proxy->waitStreamEndDone(), Callback thread
+ // should wait on proxy futex and handle CBLK_STREAM_END_DONE within this function
+ // (and make sure we don't callback for more data while we're stopping).
+ // This helps with position, marker notifications, and track invalidation.
struct timespec timeout;
timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
timeout.tv_nsec = 0;
@@ -1886,12 +1905,17 @@ nsecs_t AudioTrack::processAudioBuffer()
minFrames = kPoll * notificationFrames;
}
+ // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
+ static const nsecs_t kWaitPeriodNs = WAIT_PERIOD_MS * 1000000LL;
+ const nsecs_t timeAfterCallbacks = systemTime();
+
// Convert frame units to time units
nsecs_t ns = NS_WHENEVER;
if (minFrames != (uint32_t) ~0) {
- // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
- static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
- ns = ((double)minFrames * 1000000000) / ((double)sampleRate * speed) + kFudgeNs;
+ ns = framesToNanoseconds(minFrames, sampleRate, speed) + kWaitPeriodNs;
+ ns -= (timeAfterCallbacks - timeBeforeCallbacks); // account for callback time
+ // TODO: Should we warn if the callback time is too long?
+ if (ns < 0) ns = 0;
}
// If not supplying data by EVENT_MORE_DATA, then we're done
@@ -1899,6 +1923,13 @@ nsecs_t AudioTrack::processAudioBuffer()
return ns;
}
+ // EVENT_MORE_DATA callback handling.
+ // Timing for linear pcm audio data formats can be derived directly from the
+ // buffer fill level.
+ // Timing for compressed data is not directly available from the buffer fill level,
+ // rather indirectly from waiting for blocking mode callbacks or waiting for obtain()
+ // to return a certain fill level.
+
struct timespec timeout;
const struct timespec *requested = &ClientProxy::kForever;
if (ns != NS_WHENEVER) {
@@ -1929,12 +1960,15 @@ nsecs_t AudioTrack::processAudioBuffer()
return NS_NEVER;
}
- if (mRetryOnPartialBuffer && !isOffloaded()) {
+ if (mRetryOnPartialBuffer && audio_is_linear_pcm(mFormat)) {
mRetryOnPartialBuffer = false;
if (avail < mRemainingFrames) {
- int64_t myns = ((double)(mRemainingFrames - avail) * 1100000000)
- / ((double)sampleRate * speed);
- if (ns < 0 || myns < ns) {
+ if (ns > 0) { // account for obtain time
+ const nsecs_t timeNow = systemTime();
+ ns = max((nsecs_t)0, ns - (timeNow - timeAfterCallbacks));
+ }
+ nsecs_t myns = framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed);
+ if (ns < 0 /* NS_WHENEVER */ || myns < ns) {
ns = myns;
}
return ns;
@@ -1957,7 +1991,42 @@ nsecs_t AudioTrack::processAudioBuffer()
// Keep this thread going to handle timed events and
// still try to get more data in intervals of WAIT_PERIOD_MS
// but don't just loop and block the CPU, so wait
- return WAIT_PERIOD_MS * 1000000LL;
+
+ // mCbf(EVENT_MORE_DATA, ...) might either
+ // (1) Block until it can fill the buffer, returning 0 size on EOS.
+ // (2) Block until it can fill the buffer, returning 0 data (silence) on EOS.
+ // (3) Return 0 size when no data is available, does not wait for more data.
+ //
+ // (1) and (2) occurs with AudioPlayer/AwesomePlayer; (3) occurs with NuPlayer.
+ // We try to compute the wait time to avoid a tight sleep-wait cycle,
+ // especially for case (3).
+ //
+ // The decision to support (1) and (2) affect the sizing of mRemainingFrames
+ // and this loop; whereas for case (3) we could simply check once with the full
+ // buffer size and skip the loop entirely.
+
+ nsecs_t myns;
+ if (audio_is_linear_pcm(mFormat)) {
+ // time to wait based on buffer occupancy
+ const nsecs_t datans = mRemainingFrames <= avail ? 0 :
+ framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed);
+ // audio flinger thread buffer size (TODO: adjust for fast tracks)
+ const nsecs_t afns = framesToNanoseconds(mAfFrameCount, mAfSampleRate, speed);
+ // add a half the AudioFlinger buffer time to avoid soaking CPU if datans is 0.
+ myns = datans + (afns / 2);
+ } else {
+ // FIXME: This could ping quite a bit if the buffer isn't full.
+ // Note that when mState is stopping we waitStreamEnd, so it never gets here.
+ myns = kWaitPeriodNs;
+ }
+ if (ns > 0) { // account for obtain and callback time
+ const nsecs_t timeNow = systemTime();
+ ns = max((nsecs_t)0, ns - (timeNow - timeAfterCallbacks));
+ }
+ if (ns < 0 /* NS_WHENEVER */ || myns < ns) {
+ ns = myns;
+ }
+ return ns;
}
size_t releasedFrames = writtenSize / mFrameSize;
@@ -2089,30 +2158,8 @@ bool AudioTrack::isSampleRateSpeedAllowed_l(uint32_t sampleRate, float speed) co
if (mStaticProxy != 0) {
return true; // static tracks do not have issues with buffer sizing.
}
- status_t status;
- uint32_t afLatency;
- status = AudioSystem::getLatency(mOutput, &afLatency);
- if (status != NO_ERROR) {
- ALOGE("getLatency(%d) failed status %d", mOutput, status);
- return false;
- }
-
- size_t afFrameCount;
- status = AudioSystem::getFrameCount(mOutput, &afFrameCount);
- if (status != NO_ERROR) {
- ALOGE("getFrameCount(output=%d) status %d", mOutput, status);
- return false;
- }
-
- uint32_t afSampleRate;
- status = AudioSystem::getSamplingRate(mOutput, &afSampleRate);
- if (status != NO_ERROR) {
- ALOGE("getSamplingRate(output=%d) status %d", mOutput, status);
- return false;
- }
-
const size_t minFrameCount =
- calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, speed);
+ calculateMinFrameCount(mAfLatency, mAfFrameCount, mAfSampleRate, sampleRate, speed);
ALOGV("isSampleRateSpeedAllowed_l mFrameCount %zu minFrameCount %zu",
mFrameCount, minFrameCount);
return mFrameCount >= minFrameCount;
@@ -2175,7 +2222,12 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
}
// Check whether a pending flush or stop has completed, as those commands may
- // be asynchronous or return near finish.
+ // be asynchronous or return near finish or exhibit glitchy behavior.
+ //
+ // Originally this showed up as the first timestamp being a continuation of
+ // the previous song under gapless playback.
+ // However, we sometimes see zero timestamps, then a glitch of
+ // the previous song's position, and then correct timestamps afterwards.
if (mStartUs != 0 && mSampleRate != 0) {
static const int kTimeJitterUs = 100000; // 100 ms
static const int k1SecUs = 1000000;
@@ -2193,16 +2245,29 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) {
// Verify that the counter can't count faster than the sample rate
- // since the start time. If greater, then that means we have failed
+ // since the start time. If greater, then that means we may have failed
// to completely flush or stop the previous playing track.
- ALOGW("incomplete flush or stop:"
+ ALOGW_IF(!mTimestampStartupGlitchReported,
+ "getTimestamp startup glitch detected"
" deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)",
(long long)deltaTimeUs, (long long)deltaPositionByUs,
timestamp.mPosition);
+ mTimestampStartupGlitchReported = true;
+ if (previousTimestampValid
+ && mPreviousTimestamp.mPosition == 0 /* should be true if valid */) {
+ timestamp = mPreviousTimestamp;
+ mPreviousTimestampValid = true;
+ return NO_ERROR;
+ }
return WOULD_BLOCK;
}
+ if (deltaPositionByUs != 0) {
+ mStartUs = 0; // don't check again, we got valid nonzero position.
+ }
+ } else {
+ mStartUs = 0; // don't check again, start time expired.
}
- mStartUs = 0; // no need to check again, start timestamp has either expired or unneeded.
+ mTimestampStartupGlitchReported = false;
}
} else {
// Update the mapping between local consumed (mPosition) and server consumed (mServer)
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index c14debf..ca1cdc7 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -245,12 +245,13 @@ public:
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(params));
+ data.writeInt32(allottedSize);
remote()->transact(USE_BUFFER, data, &reply);
status_t err = reply.readInt32();
@@ -305,7 +306,7 @@ public:
virtual status_t createInputSurface(
node_id node, OMX_U32 port_index,
- sp<IGraphicBufferProducer> *bufferProducer) {
+ sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) {
Parcel data, reply;
status_t err;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
@@ -317,6 +318,12 @@ public:
return err;
}
+ // read type even if createInputSurface failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
err = reply.readInt32();
if (err != OK) {
return err;
@@ -355,7 +362,7 @@ public:
virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
- const sp<IGraphicBufferConsumer> &bufferConsumer) {
+ const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
status_t err;
@@ -369,6 +376,13 @@ public:
ALOGW("binder transaction failed: %d", err);
return err;
}
+
+ // read type even if setInputSurface failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
return reply.readInt32();
}
@@ -387,7 +401,7 @@ public:
}
virtual status_t storeMetaDataInBuffers(
- node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
@@ -395,8 +409,13 @@ public:
data.writeInt32((uint32_t)enable);
remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
- status_t err = reply.readInt32();
- return err;
+ // read type even storeMetaDataInBuffers failed
+ int negotiatedType = reply.readInt32();
+ if (type != NULL) {
+ *type = (MetadataBufferType)negotiatedType;
+ }
+
+ return reply.readInt32();
}
virtual status_t prepareForAdaptivePlayback(
@@ -459,12 +478,13 @@ public:
virtual status_t allocateBufferWithBackup(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
- buffer_id *buffer) {
+ buffer_id *buffer, OMX_U32 allottedSize) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(params));
+ data.writeInt32(allottedSize);
remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
status_t err = reply.readInt32();
@@ -491,11 +511,15 @@ public:
return reply.readInt32();
}
- virtual status_t fillBuffer(node_id node, buffer_id buffer) {
+ virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
data.writeInt32((int32_t)buffer);
+ data.writeInt32(fenceFd >= 0);
+ if (fenceFd >= 0) {
+ data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
+ }
remote()->transact(FILL_BUFFER, data, &reply);
return reply.readInt32();
@@ -505,7 +529,7 @@ public:
node_id node,
buffer_id buffer,
OMX_U32 range_offset, OMX_U32 range_length,
- OMX_U32 flags, OMX_TICKS timestamp) {
+ OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
data.writeInt32((int32_t)node);
@@ -514,6 +538,10 @@ public:
data.writeInt32(range_length);
data.writeInt32(flags);
data.writeInt64(timestamp);
+ data.writeInt32(fenceFd >= 0);
+ if (fenceFd >= 0) {
+ data.writeFileDescriptor(fenceFd, true /* takeOwnership */);
+ }
remote()->transact(EMPTY_BUFFER, data, &reply);
return reply.readInt32();
@@ -757,9 +785,10 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
+ OMX_U32 allottedSize = data.readInt32();
buffer_id buffer;
- status_t err = useBuffer(node, port_index, params, &buffer);
+ status_t err = useBuffer(node, port_index, params, &buffer, allottedSize);
reply->writeInt32(err);
if (err == OK) {
@@ -815,9 +844,10 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IGraphicBufferProducer> bufferProducer;
- status_t err = createInputSurface(node, port_index,
- &bufferProducer);
+ MetadataBufferType type;
+ status_t err = createInputSurface(node, port_index, &bufferProducer, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
if (err == OK) {
@@ -856,8 +886,10 @@ status_t BnOMX::onTransact(
sp<IGraphicBufferConsumer> bufferConsumer =
interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
- status_t err = setInputSurface(node, port_index, bufferConsumer);
+ MetadataBufferType type;
+ status_t err = setInputSurface(node, port_index, bufferConsumer, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
return NO_ERROR;
}
@@ -882,7 +914,9 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
OMX_BOOL enable = (OMX_BOOL)data.readInt32();
- status_t err = storeMetaDataInBuffers(node, port_index, enable);
+ MetadataBufferType type;
+ status_t err = storeMetaDataInBuffers(node, port_index, enable, &type);
+ reply->writeInt32(type);
reply->writeInt32(err);
return NO_ERROR;
@@ -953,10 +987,11 @@ status_t BnOMX::onTransact(
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
+ OMX_U32 allottedSize = data.readInt32();
buffer_id buffer;
status_t err = allocateBufferWithBackup(
- node, port_index, params, &buffer);
+ node, port_index, params, &buffer, allottedSize);
reply->writeInt32(err);
@@ -985,7 +1020,9 @@ status_t BnOMX::onTransact(
node_id node = (node_id)data.readInt32();
buffer_id buffer = (buffer_id)data.readInt32();
- reply->writeInt32(fillBuffer(node, buffer));
+ bool haveFence = data.readInt32();
+ int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
+ reply->writeInt32(fillBuffer(node, buffer, fenceFd));
return NO_ERROR;
}
@@ -1000,11 +1037,10 @@ status_t BnOMX::onTransact(
OMX_U32 range_length = data.readInt32();
OMX_U32 flags = data.readInt32();
OMX_TICKS timestamp = data.readInt64();
-
- reply->writeInt32(
- emptyBuffer(
- node, buffer, range_offset, range_length,
- flags, timestamp));
+ bool haveFence = data.readInt32();
+ int fenceFd = haveFence ? ::dup(data.readFileDescriptor()) : -1;
+ reply->writeInt32(emptyBuffer(
+ node, buffer, range_offset, range_length, flags, timestamp, fenceFd));
return NO_ERROR;
}
@@ -1045,7 +1081,9 @@ public:
Parcel data, reply;
data.writeInterfaceToken(IOMXObserver::getInterfaceDescriptor());
data.write(&msg, sizeof(msg));
-
+ if (msg.fenceFd >= 0) {
+ data.writeFileDescriptor(msg.fenceFd, true /* takeOwnership */);
+ }
ALOGV("onMessage writing message %d, size %zu", msg.type, sizeof(msg));
remote()->transact(OBSERVER_ON_MSG, data, &reply, IBinder::FLAG_ONEWAY);
@@ -1063,6 +1101,9 @@ status_t BnOMXObserver::onTransact(
omx_message msg;
data.read(&msg, sizeof(msg));
+ if (msg.fenceFd >= 0) {
+ msg.fenceFd = ::dup(data.readFileDescriptor());
+ }
ALOGV("onTransact reading message %d, size %zu", msg.type, sizeof(msg));
diff --git a/media/libmedia/IResourceManagerService.cpp b/media/libmedia/IResourceManagerService.cpp
index 7cb0f79..6902e99 100644
--- a/media/libmedia/IResourceManagerService.cpp
+++ b/media/libmedia/IResourceManagerService.cpp
@@ -48,7 +48,7 @@ static void writeToParcel(Parcel *data, const Vector<T> &items) {
template <typename T>
static void readFromParcel(const Parcel &data, Vector<T> *items) {
size_t size = (size_t)data.readUint32();
- for (size_t i = 0; i < size; i++) {
+ for (size_t i = 0; i < size && data.dataAvail() > 0; i++) {
T item;
item.readFromParcel(data);
items->add(item);
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index ae0061f..c5790fb 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -152,16 +152,6 @@ MediaProfiles::logAudioDecoderCap(const MediaProfiles::AudioDecoderCap& cap UNUS
ALOGV("codec = %d", cap.mCodec);
}
-/*static*/ void
-MediaProfiles::logVideoEditorCap(const MediaProfiles::VideoEditorCap& cap UNUSED)
-{
- ALOGV("videoeditor cap:");
- ALOGV("mMaxInputFrameWidth = %d", cap.mMaxInputFrameWidth);
- ALOGV("mMaxInputFrameHeight = %d", cap.mMaxInputFrameHeight);
- ALOGV("mMaxOutputFrameWidth = %d", cap.mMaxOutputFrameWidth);
- ALOGV("mMaxOutputFrameHeight = %d", cap.mMaxOutputFrameHeight);
-}
-
/*static*/ int
MediaProfiles::findTagForName(const MediaProfiles::NameToTagMap *map, size_t nMappings,
const char *name)
@@ -398,42 +388,6 @@ void MediaProfiles::addStartTimeOffset(int cameraId, const char** atts)
ALOGV("%s: cameraId=%d, offset=%d ms", __func__, cameraId, offsetTimeMs);
mStartTimeOffsets.replaceValueFor(cameraId, offsetTimeMs);
}
-/*static*/ MediaProfiles::ExportVideoProfile*
-MediaProfiles::createExportVideoProfile(const char **atts)
-{
- CHECK(!strcmp("name", atts[0]) &&
- !strcmp("profile", atts[2]) &&
- !strcmp("level", atts[4]));
-
- const size_t nMappings =
- sizeof(sVideoEncoderNameMap)/sizeof(sVideoEncoderNameMap[0]);
- const int codec = findTagForName(sVideoEncoderNameMap, nMappings, atts[1]);
- CHECK(codec != -1);
-
- MediaProfiles::ExportVideoProfile *profile =
- new MediaProfiles::ExportVideoProfile(
- codec, atoi(atts[3]), atoi(atts[5]));
-
- return profile;
-}
-/*static*/ MediaProfiles::VideoEditorCap*
-MediaProfiles::createVideoEditorCap(const char **atts, MediaProfiles *profiles)
-{
- CHECK(!strcmp("maxInputFrameWidth", atts[0]) &&
- !strcmp("maxInputFrameHeight", atts[2]) &&
- !strcmp("maxOutputFrameWidth", atts[4]) &&
- !strcmp("maxOutputFrameHeight", atts[6]) &&
- !strcmp("maxPrefetchYUVFrames", atts[8]));
-
- MediaProfiles::VideoEditorCap *pVideoEditorCap =
- new MediaProfiles::VideoEditorCap(atoi(atts[1]), atoi(atts[3]),
- atoi(atts[5]), atoi(atts[7]), atoi(atts[9]));
-
- logVideoEditorCap(*pVideoEditorCap);
- profiles->mVideoEditorCap = pVideoEditorCap;
-
- return pVideoEditorCap;
-}
/*static*/ void
MediaProfiles::startElementHandler(void *userData, const char *name, const char **atts)
@@ -465,10 +419,6 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char
createCamcorderProfile(profiles->mCurrentCameraId, atts, profiles->mCameraIds));
} else if (strcmp("ImageEncoding", name) == 0) {
profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
- } else if (strcmp("VideoEditorCap", name) == 0) {
- createVideoEditorCap(atts, profiles);
- } else if (strcmp("ExportVideoProfile", name) == 0) {
- profiles->mVideoEditorExportProfiles.add(createExportVideoProfile(atts));
}
}
@@ -873,32 +823,6 @@ MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
profiles->mImageEncodingQualityLevels.add(levels);
}
-/*static*/ void
-MediaProfiles::createDefaultVideoEditorCap(MediaProfiles *profiles)
-{
- profiles->mVideoEditorCap =
- new MediaProfiles::VideoEditorCap(
- VIDEOEDITOR_DEFAULT_MAX_INPUT_FRAME_WIDTH,
- VIDEOEDITOR_DEFUALT_MAX_INPUT_FRAME_HEIGHT,
- VIDEOEDITOR_DEFAULT_MAX_OUTPUT_FRAME_WIDTH,
- VIDEOEDITOR_DEFUALT_MAX_OUTPUT_FRAME_HEIGHT,
- VIDEOEDITOR_DEFAULT_MAX_PREFETCH_YUV_FRAMES);
-}
-/*static*/ void
-MediaProfiles::createDefaultExportVideoProfiles(MediaProfiles *profiles)
-{
- // Create default video export profiles
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_H263,
- OMX_VIDEO_H263ProfileBaseline, OMX_VIDEO_H263Level10));
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_MPEG_4_SP,
- OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level1));
- profiles->mVideoEditorExportProfiles.add(
- new ExportVideoProfile(VIDEO_ENCODER_H264,
- OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13));
-}
-
/*static*/ MediaProfiles*
MediaProfiles::createDefaultInstance()
{
@@ -910,8 +834,6 @@ MediaProfiles::createDefaultInstance()
createDefaultAudioDecoders(profiles);
createDefaultEncoderOutputFileFormats(profiles);
createDefaultImageEncodingQualityLevels(profiles);
- createDefaultVideoEditorCap(profiles);
- createDefaultExportVideoProfiles(profiles);
return profiles;
}
@@ -1009,54 +931,6 @@ int MediaProfiles::getVideoEncoderParamByName(const char *name, video_encoder co
ALOGE("The given video encoder param name %s is not found", name);
return -1;
}
-int MediaProfiles::getVideoEditorExportParamByName(
- const char *name, int codec) const
-{
- ALOGV("getVideoEditorExportParamByName: name %s codec %d", name, codec);
- ExportVideoProfile *exportProfile = NULL;
- int index = -1;
- for (size_t i =0; i < mVideoEditorExportProfiles.size(); i++) {
- exportProfile = mVideoEditorExportProfiles[i];
- if (exportProfile->mCodec == codec) {
- index = i;
- break;
- }
- }
- if (index == -1) {
- ALOGE("The given video decoder %d is not found", codec);
- return -1;
- }
- if (!strcmp("videoeditor.export.profile", name))
- return exportProfile->mProfile;
- if (!strcmp("videoeditor.export.level", name))
- return exportProfile->mLevel;
-
- ALOGE("The given video editor export param name %s is not found", name);
- return -1;
-}
-int MediaProfiles::getVideoEditorCapParamByName(const char *name) const
-{
- ALOGV("getVideoEditorCapParamByName: %s", name);
-
- if (mVideoEditorCap == NULL) {
- ALOGE("The mVideoEditorCap is not created, then create default cap.");
- createDefaultVideoEditorCap(sInstance);
- }
-
- if (!strcmp("videoeditor.input.width.max", name))
- return mVideoEditorCap->mMaxInputFrameWidth;
- if (!strcmp("videoeditor.input.height.max", name))
- return mVideoEditorCap->mMaxInputFrameHeight;
- if (!strcmp("videoeditor.output.width.max", name))
- return mVideoEditorCap->mMaxOutputFrameWidth;
- if (!strcmp("videoeditor.output.height.max", name))
- return mVideoEditorCap->mMaxOutputFrameHeight;
- if (!strcmp("maxPrefetchYUVFrames", name))
- return mVideoEditorCap->mMaxPrefetchYUVFrames;
-
- ALOGE("The given video editor param name %s is not found", name);
- return -1;
-}
Vector<audio_encoder> MediaProfiles::getAudioEncoders() const
{