Merge "remove AudioSystem::getOutputSamplingRateForAttr()" into lmp-mr1-dev
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 3629c8b..0970b2b 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -85,8 +85,6 @@
status_t initEncoder();
void releaseEncoder();
status_t feedEncoderInputBuffers();
- void scheduleDoMoreWork();
- status_t doMoreWork(int32_t numInput, int32_t numOutput);
void suspend();
void resume(int64_t skipFramesBeforeUs = -1ll);
void signalEOS(status_t err = ERROR_END_OF_STREAM);
@@ -108,8 +106,6 @@
bool mDoMoreWorkPending;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
- Vector<sp<ABuffer> > mEncoderInputBuffers;
- Vector<sp<ABuffer> > mEncoderOutputBuffers;
List<MediaBuffer *> mInputBufferQueue;
List<size_t> mAvailEncoderInputIndices;
List<int64_t> mDecodingTimeQueue; // decoding time (us) for video
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
index 450dcfe..1d0e2cb 100644
--- a/include/media/stagefright/foundation/ADebug.h
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -80,6 +80,36 @@
__FILE__ ":" LITERAL_TO_STRING(__LINE__) \
" Should not be here.");
+struct ADebug {
+ enum Level {
+ kDebugNone, // no debug
+ kDebugLifeCycle, // lifecycle events: creation/deletion
+ kDebugState, // commands and events
+ kDebugConfig, // configuration
+ kDebugInternalState, // internal state changes
+ kDebugAll, // all
+ kDebugMax = kDebugAll,
+
+ };
+
+ // parse the property or string to get the debug level for a component name
+ // string format is:
+ // <level>[:<glob>][,<level>[:<glob>]...]
+ // - <level> is 0-5 corresponding to ADebug::Level
+ // - <glob> is used to match component name case insensitively, if omitted, it
+ // matches all components
+ // - string is read left-to-right, and the last matching level is returned, or
+ // the def if no terms matched
+ static Level GetDebugLevelFromProperty(
+ const char *name, const char *propertyName, Level def = kDebugNone);
+ static Level GetDebugLevelFromString(
+ const char *name, const char *value, Level def = kDebugNone);
+
+ // remove redundant segments of a codec name, and return a newly allocated
+ // string suitable for debugging
+ static char *GetDebugName(const char *name);
+};
+
} // namespace android
#endif // A_DEBUG_H_
diff --git a/include/media/stagefright/foundation/AStringUtils.h b/include/media/stagefright/foundation/AStringUtils.h
new file mode 100644
index 0000000..76a7791
--- /dev/null
+++ b/include/media/stagefright/foundation/AStringUtils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_STRING_UTILS_H_
+#define A_STRING_UTILS_H_
+
+#include <stdlib.h>
+
+namespace android {
+
+struct AStringUtils {
+ // similar to strncmp or strcasecmp, but case sensitivity is parametric
+ static int Compare(const char *a, const char *b, size_t len, bool ignoreCase);
+
+ // matches a string (str) to a glob pattern that supports:
+ // * - matches any number of characters
+ static bool MatchesGlob(
+ const char *glob, size_t globLen, const char *str, size_t strLen, bool ignoreCase);
+};
+
+} // namespace android
+
+#endif // A_STRING_UTILS_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index d9e3ee8..73bc829 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -20,8 +20,6 @@
#include "NuPlayerRenderer.h"
-#include <cutils/properties.h>
-
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -43,16 +41,6 @@
// static
const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
-static bool sFrameAccurateAVsync = false;
-
-static void readProperties() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("persist.sys.media.avsync", value, NULL)) {
- sFrameAccurateAVsync =
- !strcmp("1", value) || !strcasecmp("true", value);
- }
-}
-
NuPlayer::Renderer::Renderer(
const sp<MediaPlayerBase::AudioSink> &sink,
const sp<AMessage> ¬ify,
@@ -87,7 +75,6 @@
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
mTotalBuffersQueued(0),
mLastAudioBufferDrained(0) {
- readProperties();
}
NuPlayer::Renderer::~Renderer() {
@@ -796,11 +783,6 @@
ALOGW_IF(delayUs > 500000, "unusually high delayUs: %" PRId64, delayUs);
// post 2 display refreshes before rendering is due
- // FIXME currently this increases power consumption, so unless frame-accurate
- // AV sync is requested, post closer to required render time (at 0.63 vsyncs)
- if (!sFrameAccurateAVsync) {
- twoVsyncsUs >>= 4;
- }
msg->post(delayUs > twoVsyncsUs ? delayUs - twoVsyncsUs : 0);
mDrainVideoQueuePending = true;
@@ -1178,8 +1160,6 @@
}
void NuPlayer::Renderer::onResume() {
- readProperties();
-
if (!mPaused) {
return;
}
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 0fecda8..c26e909 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -422,24 +422,16 @@
}
}
+ mEncoderActivityNotify = new AMessage(
+ kWhatEncoderActivity, mReflector->id());
+ mEncoder->setCallback(mEncoderActivityNotify);
+
err = mEncoder->start();
if (err != OK) {
return err;
}
- err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
-
- if (err != OK) {
- return err;
- }
-
- err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
-
- if (err != OK) {
- return err;
- }
-
mEncoderReachedEOS = false;
mErrorCode = OK;
@@ -461,14 +453,6 @@
mbuf->release();
}
}
-
- for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) {
- sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i);
- accessUnit->setMediaBufferBase(NULL);
- }
-
- mEncoderInputBuffers.clear();
- mEncoderOutputBuffers.clear();
}
status_t MediaCodecSource::postSynchronouslyAndReturnError(
@@ -539,20 +523,6 @@
}
}
-void MediaCodecSource::scheduleDoMoreWork() {
- if (mDoMoreWorkPending) {
- return;
- }
-
- mDoMoreWorkPending = true;
-
- if (mEncoderActivityNotify == NULL) {
- mEncoderActivityNotify = new AMessage(
- kWhatEncoderActivity, mReflector->id());
- }
- mEncoder->requestActivityNotification(mEncoderActivityNotify);
-}
-
status_t MediaCodecSource::feedEncoderInputBuffers() {
while (!mInputBufferQueue.empty()
&& !mAvailEncoderInputIndices.empty()) {
@@ -587,16 +557,22 @@
#endif // DEBUG_DRIFT_TIME
}
+ sp<ABuffer> inbuf;
+ status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
+ if (err != OK || inbuf == NULL) {
+ mbuf->release();
+ signalEOS();
+ break;
+ }
+
size = mbuf->size();
- memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
- mbuf->data(), size);
+ memcpy(inbuf->data(), mbuf->data(), size);
if (mIsVideo) {
// video encoder will release MediaBuffer when done
// with underlying data.
- mEncoderInputBuffers.itemAt(bufferIndex)->setMediaBufferBase(
- mbuf);
+ inbuf->setMediaBufferBase(mbuf);
} else {
mbuf->release();
}
@@ -615,50 +591,120 @@
return OK;
}
-status_t MediaCodecSource::doMoreWork(int32_t numInput, int32_t numOutput) {
+status_t MediaCodecSource::onStart(MetaData *params) {
+ if (mStopping) {
+ ALOGE("Failed to start while we're stopping");
+ return INVALID_OPERATION;
+ }
+
+ if (mStarted) {
+ ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ resume();
+ } else {
+ CHECK(mPuller != NULL);
+ mPuller->resume();
+ }
+ return OK;
+ }
+
+ ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
+
status_t err = OK;
- if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
- while (numInput-- > 0) {
- size_t bufferIndex;
- err = mEncoder->dequeueInputBuffer(&bufferIndex);
+ if (mFlags & FLAG_USE_SURFACE_INPUT) {
+ int64_t startTimeUs;
+ if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
+ startTimeUs = -1ll;
+ }
+ resume(startTimeUs);
+ } else {
+ CHECK(mPuller != NULL);
+ sp<AMessage> notify = new AMessage(
+ kWhatPullerNotify, mReflector->id());
+ err = mPuller->start(params, notify);
+ if (err != OK) {
+ return err;
+ }
+ }
- if (err != OK) {
+ ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
+
+ mStarted = true;
+ return OK;
+}
+
+void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatPullerNotify:
+ {
+ MediaBuffer *mbuf;
+ CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
+
+ if (mbuf == NULL) {
+ ALOGV("puller (%s) reached EOS",
+ mIsVideo ? "video" : "audio");
+ signalEOS();
+ }
+
+ if (mEncoder == NULL) {
+ ALOGV("got msg '%s' after encoder shutdown.",
+ msg->debugString().c_str());
+
+ if (mbuf != NULL) {
+ mbuf->release();
+ }
+
+ break;
+ }
+
+ mInputBufferQueue.push_back(mbuf);
+
+ feedEncoderInputBuffers();
+
+ break;
+ }
+ case kWhatEncoderActivity:
+ {
+ if (mEncoder == NULL) {
+ break;
+ }
+
+ int32_t cbID;
+ CHECK(msg->findInt32("callbackID", &cbID));
+ if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
+ int32_t index;
+ CHECK(msg->findInt32("index", &index));
+
+ mAvailEncoderInputIndices.push_back(index);
+ feedEncoderInputBuffers();
+ } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
+ int32_t index;
+ size_t offset;
+ size_t size;
+ int64_t timeUs;
+ int32_t flags;
+ native_handle_t* handle = NULL;
+
+ CHECK(msg->findInt32("index", &index));
+ CHECK(msg->findSize("offset", &offset));
+ CHECK(msg->findSize("size", &size));
+ CHECK(msg->findInt64("timeUs", &timeUs));
+ CHECK(msg->findInt32("flags", &flags));
+
+ if (flags & MediaCodec::BUFFER_FLAG_EOS) {
+ mEncoder->releaseOutputBuffer(index);
+ signalEOS();
break;
}
- mAvailEncoderInputIndices.push_back(bufferIndex);
- }
-
- feedEncoderInputBuffers();
- }
-
- while (numOutput-- > 0) {
- size_t bufferIndex;
- size_t offset;
- size_t size;
- int64_t timeUs;
- uint32_t flags;
- native_handle_t* handle = NULL;
- err = mEncoder->dequeueOutputBuffer(
- &bufferIndex, &offset, &size, &timeUs, &flags);
-
- if (err != OK) {
- if (err == INFO_FORMAT_CHANGED) {
- continue;
- } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
- mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
- continue;
+ sp<ABuffer> outbuf;
+ status_t err = mEncoder->getOutputBuffer(index, &outbuf);
+ if (err != OK || outbuf == NULL) {
+ signalEOS();
+ break;
}
- if (err == -EAGAIN) {
- err = OK;
- }
- break;
- }
- if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) {
- sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
-
MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
memcpy(mbuf->data(), outbuf->data(), outbuf->size());
@@ -709,121 +755,16 @@
mOutputBufferQueue.push_back(mbuf);
mOutputBufferCond.signal();
}
- }
- mEncoder->releaseOutputBuffer(bufferIndex);
-
- if (flags & MediaCodec::BUFFER_FLAG_EOS) {
- err = ERROR_END_OF_STREAM;
- break;
- }
- }
-
- return err;
-}
-
-status_t MediaCodecSource::onStart(MetaData *params) {
- if (mStopping) {
- ALOGE("Failed to start while we're stopping");
- return INVALID_OPERATION;
- }
-
- if (mStarted) {
- ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
- if (mFlags & FLAG_USE_SURFACE_INPUT) {
- resume();
- } else {
- CHECK(mPuller != NULL);
- mPuller->resume();
- }
- return OK;
- }
-
- ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
-
- status_t err = OK;
-
- if (mFlags & FLAG_USE_SURFACE_INPUT) {
- int64_t startTimeUs;
- if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
- startTimeUs = -1ll;
- }
- resume(startTimeUs);
- scheduleDoMoreWork();
- } else {
- CHECK(mPuller != NULL);
- sp<AMessage> notify = new AMessage(
- kWhatPullerNotify, mReflector->id());
- err = mPuller->start(params, notify);
- if (err != OK) {
- return err;
- }
- }
-
- ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
-
- mStarted = true;
- return OK;
-}
-
-void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
- switch (msg->what()) {
- case kWhatPullerNotify:
- {
- MediaBuffer *mbuf;
- CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
-
- if (mbuf == NULL) {
- ALOGV("puller (%s) reached EOS",
- mIsVideo ? "video" : "audio");
+ mEncoder->releaseOutputBuffer(index);
+ } else if (cbID == MediaCodec::CB_ERROR) {
+ status_t err;
+ CHECK(msg->findInt32("err", &err));
+ ALOGE("Encoder (%s) reported error : 0x%x",
+ mIsVideo ? "video" : "audio", err);
signalEOS();
- }
-
- if (mEncoder == NULL) {
- ALOGV("got msg '%s' after encoder shutdown.",
- msg->debugString().c_str());
-
- if (mbuf != NULL) {
- mbuf->release();
- }
-
- break;
- }
-
- mInputBufferQueue.push_back(mbuf);
-
- feedEncoderInputBuffers();
- scheduleDoMoreWork();
-
- break;
- }
- case kWhatEncoderActivity:
- {
- mDoMoreWorkPending = false;
-
- if (mEncoder == NULL) {
- break;
- }
-
- int32_t numInput, numOutput;
-
- if (!msg->findInt32("input-buffers", &numInput)) {
- numInput = INT32_MAX;
- }
- if (!msg->findInt32("output-buffers", &numOutput)) {
- numOutput = INT32_MAX;
- }
-
- status_t err = doMoreWork(numInput, numOutput);
-
- if (err == OK) {
- scheduleDoMoreWork();
- } else {
- // reached EOS, or error
- signalEOS(err);
- }
-
- break;
+ }
+ break;
}
case kWhatStart:
{
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 288e07a..f26563e 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -47,10 +47,11 @@
#include <media/stagefright/SkipCutBuffer.h>
#include <utils/Vector.h>
-#include <OMX_Audio.h>
#include <OMX_AudioExt.h>
#include <OMX_Component.h>
#include <OMX_IndexExt.h>
+#include <OMX_VideoExt.h>
+#include <OMX_AsString.h>
#include "include/avc_utils.h"
@@ -4078,220 +4079,6 @@
CHECK(!"should not be here.");
}
-static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
- static const char *kNames[] = {
- "OMX_IMAGE_CodingUnused",
- "OMX_IMAGE_CodingAutoDetect",
- "OMX_IMAGE_CodingJPEG",
- "OMX_IMAGE_CodingJPEG2K",
- "OMX_IMAGE_CodingEXIF",
- "OMX_IMAGE_CodingTIFF",
- "OMX_IMAGE_CodingGIF",
- "OMX_IMAGE_CodingPNG",
- "OMX_IMAGE_CodingLZW",
- "OMX_IMAGE_CodingBMP",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
- static const char *kNames[] = {
- "OMX_COLOR_FormatUnused",
- "OMX_COLOR_FormatMonochrome",
- "OMX_COLOR_Format8bitRGB332",
- "OMX_COLOR_Format12bitRGB444",
- "OMX_COLOR_Format16bitARGB4444",
- "OMX_COLOR_Format16bitARGB1555",
- "OMX_COLOR_Format16bitRGB565",
- "OMX_COLOR_Format16bitBGR565",
- "OMX_COLOR_Format18bitRGB666",
- "OMX_COLOR_Format18bitARGB1665",
- "OMX_COLOR_Format19bitARGB1666",
- "OMX_COLOR_Format24bitRGB888",
- "OMX_COLOR_Format24bitBGR888",
- "OMX_COLOR_Format24bitARGB1887",
- "OMX_COLOR_Format25bitARGB1888",
- "OMX_COLOR_Format32bitBGRA8888",
- "OMX_COLOR_Format32bitARGB8888",
- "OMX_COLOR_FormatYUV411Planar",
- "OMX_COLOR_FormatYUV411PackedPlanar",
- "OMX_COLOR_FormatYUV420Planar",
- "OMX_COLOR_FormatYUV420PackedPlanar",
- "OMX_COLOR_FormatYUV420SemiPlanar",
- "OMX_COLOR_FormatYUV422Planar",
- "OMX_COLOR_FormatYUV422PackedPlanar",
- "OMX_COLOR_FormatYUV422SemiPlanar",
- "OMX_COLOR_FormatYCbYCr",
- "OMX_COLOR_FormatYCrYCb",
- "OMX_COLOR_FormatCbYCrY",
- "OMX_COLOR_FormatCrYCbY",
- "OMX_COLOR_FormatYUV444Interleaved",
- "OMX_COLOR_FormatRawBayer8bit",
- "OMX_COLOR_FormatRawBayer10bit",
- "OMX_COLOR_FormatRawBayer8bitcompressed",
- "OMX_COLOR_FormatL2",
- "OMX_COLOR_FormatL4",
- "OMX_COLOR_FormatL8",
- "OMX_COLOR_FormatL16",
- "OMX_COLOR_FormatL24",
- "OMX_COLOR_FormatL32",
- "OMX_COLOR_FormatYUV420PackedSemiPlanar",
- "OMX_COLOR_FormatYUV422PackedSemiPlanar",
- "OMX_COLOR_Format18BitBGR666",
- "OMX_COLOR_Format24BitARGB6666",
- "OMX_COLOR_Format24BitABGR6666",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type == OMX_TI_COLOR_FormatYUV420PackedSemiPlanar) {
- return "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar";
- } else if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
- return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
- } else if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
- static const char *kNames[] = {
- "OMX_VIDEO_CodingUnused",
- "OMX_VIDEO_CodingAutoDetect",
- "OMX_VIDEO_CodingMPEG2",
- "OMX_VIDEO_CodingH263",
- "OMX_VIDEO_CodingMPEG4",
- "OMX_VIDEO_CodingWMV",
- "OMX_VIDEO_CodingRV",
- "OMX_VIDEO_CodingAVC",
- "OMX_VIDEO_CodingMJPEG",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
- static const char *kNames[] = {
- "OMX_AUDIO_CodingUnused",
- "OMX_AUDIO_CodingAutoDetect",
- "OMX_AUDIO_CodingPCM",
- "OMX_AUDIO_CodingADPCM",
- "OMX_AUDIO_CodingAMR",
- "OMX_AUDIO_CodingGSMFR",
- "OMX_AUDIO_CodingGSMEFR",
- "OMX_AUDIO_CodingGSMHR",
- "OMX_AUDIO_CodingPDCFR",
- "OMX_AUDIO_CodingPDCEFR",
- "OMX_AUDIO_CodingPDCHR",
- "OMX_AUDIO_CodingTDMAFR",
- "OMX_AUDIO_CodingTDMAEFR",
- "OMX_AUDIO_CodingQCELP8",
- "OMX_AUDIO_CodingQCELP13",
- "OMX_AUDIO_CodingEVRC",
- "OMX_AUDIO_CodingSMV",
- "OMX_AUDIO_CodingG711",
- "OMX_AUDIO_CodingG723",
- "OMX_AUDIO_CodingG726",
- "OMX_AUDIO_CodingG729",
- "OMX_AUDIO_CodingAAC",
- "OMX_AUDIO_CodingMP3",
- "OMX_AUDIO_CodingSBC",
- "OMX_AUDIO_CodingVORBIS",
- "OMX_AUDIO_CodingOPUS",
- "OMX_AUDIO_CodingWMA",
- "OMX_AUDIO_CodingRA",
- "OMX_AUDIO_CodingMIDI",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
- static const char *kNames[] = {
- "OMX_AUDIO_PCMModeLinear",
- "OMX_AUDIO_PCMModeALaw",
- "OMX_AUDIO_PCMModeMULaw",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *amrBandModeString(OMX_AUDIO_AMRBANDMODETYPE type) {
- static const char *kNames[] = {
- "OMX_AUDIO_AMRBandModeUnused",
- "OMX_AUDIO_AMRBandModeNB0",
- "OMX_AUDIO_AMRBandModeNB1",
- "OMX_AUDIO_AMRBandModeNB2",
- "OMX_AUDIO_AMRBandModeNB3",
- "OMX_AUDIO_AMRBandModeNB4",
- "OMX_AUDIO_AMRBandModeNB5",
- "OMX_AUDIO_AMRBandModeNB6",
- "OMX_AUDIO_AMRBandModeNB7",
- "OMX_AUDIO_AMRBandModeWB0",
- "OMX_AUDIO_AMRBandModeWB1",
- "OMX_AUDIO_AMRBandModeWB2",
- "OMX_AUDIO_AMRBandModeWB3",
- "OMX_AUDIO_AMRBandModeWB4",
- "OMX_AUDIO_AMRBandModeWB5",
- "OMX_AUDIO_AMRBandModeWB6",
- "OMX_AUDIO_AMRBandModeWB7",
- "OMX_AUDIO_AMRBandModeWB8",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
-static const char *amrFrameFormatString(OMX_AUDIO_AMRFRAMEFORMATTYPE type) {
- static const char *kNames[] = {
- "OMX_AUDIO_AMRFrameFormatConformance",
- "OMX_AUDIO_AMRFrameFormatIF1",
- "OMX_AUDIO_AMRFrameFormatIF2",
- "OMX_AUDIO_AMRFrameFormatFSF",
- "OMX_AUDIO_AMRFrameFormatRTPPayload",
- "OMX_AUDIO_AMRFrameFormatITU",
- };
-
- size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
-
- if (type < 0 || (size_t)type >= numNames) {
- return "UNKNOWN";
- } else {
- return kNames[type];
- }
-}
-
void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
@@ -4322,10 +4109,10 @@
printf(" nStride = %" PRIu32 "\n", imageDef->nStride);
printf(" eCompressionFormat = %s\n",
- imageCompressionFormatString(imageDef->eCompressionFormat));
+ asString(imageDef->eCompressionFormat));
printf(" eColorFormat = %s\n",
- colorFormatString(imageDef->eColorFormat));
+ asString(imageDef->eColorFormat));
break;
}
@@ -4341,10 +4128,10 @@
printf(" nStride = %" PRIu32 "\n", videoDef->nStride);
printf(" eCompressionFormat = %s\n",
- videoCompressionFormatString(videoDef->eCompressionFormat));
+ asString(videoDef->eCompressionFormat));
printf(" eColorFormat = %s\n",
- colorFormatString(videoDef->eColorFormat));
+ asString(videoDef->eColorFormat));
break;
}
@@ -4356,7 +4143,7 @@
printf("\n");
printf(" // Audio\n");
printf(" eEncoding = %s\n",
- audioCodingTypeString(audioDef->eEncoding));
+ asString(audioDef->eEncoding));
if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
OMX_AUDIO_PARAM_PCMMODETYPE params;
@@ -4376,7 +4163,7 @@
params.eNumData == OMX_NumericalDataSigned
? "signed" : "unsigned");
- printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
+ printf(" ePCMMode = %s\n", asString(params.ePCMMode));
} else if (audioDef->eEncoding == OMX_AUDIO_CodingAMR) {
OMX_AUDIO_PARAM_AMRTYPE amr;
InitOMXParams(&amr);
@@ -4388,9 +4175,9 @@
printf(" nChannels = %" PRIu32 "\n", amr.nChannels);
printf(" eAMRBandMode = %s\n",
- amrBandModeString(amr.eAMRBandMode));
+ asString(amr.eAMRBandMode));
printf(" eAMRFrameFormat = %s\n",
- amrFrameFormatString(amr.eAMRFrameFormat));
+ asString(amr.eAMRFrameFormat));
}
break;
@@ -4699,12 +4486,7 @@
const char *componentName, const char *mime,
bool isEncoder,
CodecCapabilities *caps) {
- if (strncmp(componentName, "OMX.", 4)) {
- // Not an OpenMax component but a software codec.
- caps->mFlags = 0;
- caps->mComponentName = componentName;
- return OK;
- }
+ bool isVideo = !strncasecmp(mime, "video/", 6);
sp<OMXCodecObserver> observer = new OMXCodecObserver;
IOMX::node_id node;
@@ -4719,59 +4501,62 @@
caps->mFlags = 0;
caps->mComponentName = componentName;
- OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
- InitOMXParams(¶m);
+ // NOTE: OMX does not provide a way to query AAC profile support
+ if (isVideo) {
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ InitOMXParams(¶m);
- param.nPortIndex = !isEncoder ? 0 : 1;
+ param.nPortIndex = !isEncoder ? 0 : 1;
- for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
- err = omx->getParameter(
- node, OMX_IndexParamVideoProfileLevelQuerySupported,
- ¶m, sizeof(param));
+ for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+ err = omx->getParameter(
+ node, OMX_IndexParamVideoProfileLevelQuerySupported,
+ ¶m, sizeof(param));
- if (err != OK) {
- break;
+ if (err != OK) {
+ break;
+ }
+
+ CodecProfileLevel profileLevel;
+ profileLevel.mProfile = param.eProfile;
+ profileLevel.mLevel = param.eLevel;
+
+ caps->mProfileLevels.push(profileLevel);
}
- CodecProfileLevel profileLevel;
- profileLevel.mProfile = param.eProfile;
- profileLevel.mLevel = param.eLevel;
+ // Color format query
+ // return colors in the order reported by the OMX component
+ // prefix "flexible" standard ones with the flexible equivalent
+ OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+ InitOMXParams(&portFormat);
+ portFormat.nPortIndex = !isEncoder ? 1 : 0;
+ for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
+ err = omx->getParameter(
+ node, OMX_IndexParamVideoPortFormat,
+ &portFormat, sizeof(portFormat));
+ if (err != OK) {
+ break;
+ }
- caps->mProfileLevels.push(profileLevel);
- }
-
- // Color format query
- // return colors in the order reported by the OMX component
- // prefix "flexible" standard ones with the flexible equivalent
- OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
- InitOMXParams(&portFormat);
- portFormat.nPortIndex = !isEncoder ? 1 : 0;
- for (portFormat.nIndex = 0;; ++portFormat.nIndex) {
- err = omx->getParameter(
- node, OMX_IndexParamVideoPortFormat,
- &portFormat, sizeof(portFormat));
- if (err != OK) {
- break;
- }
-
- OMX_U32 flexibleEquivalent;
- if (ACodec::isFlexibleColorFormat(
- omx, node, portFormat.eColorFormat, &flexibleEquivalent)) {
- bool marked = false;
- for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
- if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
- marked = true;
- break;
+ OMX_U32 flexibleEquivalent;
+ if (ACodec::isFlexibleColorFormat(
+ omx, node, portFormat.eColorFormat, &flexibleEquivalent)) {
+ bool marked = false;
+ for (size_t i = 0; i < caps->mColorFormats.size(); i++) {
+ if (caps->mColorFormats.itemAt(i) == flexibleEquivalent) {
+ marked = true;
+ break;
+ }
+ }
+ if (!marked) {
+ caps->mColorFormats.push(flexibleEquivalent);
}
}
- if (!marked) {
- caps->mColorFormats.push(flexibleEquivalent);
- }
+ caps->mColorFormats.push(portFormat.eColorFormat);
}
- caps->mColorFormats.push(portFormat.eColorFormat);
}
- if (!isEncoder && !strncmp(mime, "video/", 6)) {
+ if (isVideo && !isEncoder) {
if (omx->storeMetaDataInBuffers(
node, 1 /* port index */, OMX_TRUE) == OK ||
omx->prepareForAdaptivePlayback(
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 821bd81..6219053 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -38,6 +38,7 @@
int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
+ long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
}
namespace android {
@@ -84,6 +85,8 @@
private:
struct Page {
uint64_t mGranulePosition;
+ int32_t mPrevPacketSize;
+ uint64_t mPrevPacketPos;
uint32_t mSerialNo;
uint32_t mPageNo;
uint8_t mFlags;
@@ -121,6 +124,8 @@
status_t verifyHeader(
MediaBuffer *buffer, uint8_t type);
+ int32_t packetBlockSize(MediaBuffer *buffer);
+
void parseFileMetaData();
status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos);
@@ -373,6 +378,7 @@
mFirstPacketInPage = true;
mCurrentPageSamples = 0;
mCurrentPage.mNumSegments = 0;
+ mCurrentPage.mPrevPacketSize = -1;
mNextLaceIndex = 0;
// XXX what if new page continues packet from last???
@@ -489,16 +495,6 @@
tmp->set_range(0, buffer->range_length());
buffer->release();
} else {
- // XXX Not only is this not technically the correct time for
- // this packet, we also stamp every packet in this page
- // with the same time. This needs fixing later.
-
- if (mVi.rate) {
- // Rate may not have been initialized yet if we're currently
- // reading the configuration packets...
- // Fortunately, the timestamp doesn't matter for those.
- timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate;
- }
tmp->set_range(0, 0);
}
buffer = tmp;
@@ -521,16 +517,34 @@
if (gotFullPacket) {
// We've just read the entire packet.
- if (timeUs >= 0) {
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
- }
-
if (mFirstPacketInPage) {
buffer->meta_data()->setInt32(
kKeyValidSamples, mCurrentPageSamples);
mFirstPacketInPage = false;
}
+ if (mVi.rate) {
+ // Rate may not have been initialized yet if we're currently
+ // reading the configuration packets...
+ // Fortunately, the timestamp doesn't matter for those.
+ int32_t curBlockSize = packetBlockSize(buffer);
+ if (mCurrentPage.mPrevPacketSize < 0) {
+ mCurrentPage.mPrevPacketSize = curBlockSize;
+ mCurrentPage.mPrevPacketPos =
+ mCurrentPage.mGranulePosition - mCurrentPageSamples;
+ timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+ } else {
+ // The effective block size is the average of the two overlapped blocks
+ int32_t actualBlockSize =
+ (curBlockSize + mCurrentPage.mPrevPacketSize) / 2;
+ timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate;
+ // The actual size output by the decoder will be half the effective
+ // size, due to the overlap
+ mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
+ mCurrentPage.mPrevPacketSize = curBlockSize;
+ }
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ }
*out = buffer;
return OK;
@@ -686,6 +700,35 @@
}
}
+int32_t MyVorbisExtractor::packetBlockSize(MediaBuffer *buffer) {
+ const uint8_t *data =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+
+ size_t size = buffer->range_length();
+
+ ogg_buffer buf;
+ buf.data = (uint8_t *)data;
+ buf.size = size;
+ buf.refcount = 1;
+ buf.ptr.owner = NULL;
+
+ ogg_reference ref;
+ ref.buffer = &buf;
+ ref.begin = 0;
+ ref.length = size;
+ ref.next = NULL;
+
+ ogg_packet pack;
+ pack.packet = &ref;
+ pack.bytes = ref.length;
+ pack.b_o_s = 0;
+ pack.e_o_s = 0;
+ pack.granulepos = 0;
+ pack.packetno = 0;
+
+ return vorbis_packet_blocksize(&mVi, &pack);
+}
+
status_t MyVorbisExtractor::verifyHeader(
MediaBuffer *buffer, uint8_t type) {
const uint8_t *data =
@@ -730,6 +773,10 @@
ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal);
ALOGV("window-bitrate = %ld", mVi.bitrate_window);
+ ALOGV("blocksizes: %d/%d",
+ vorbis_info_blocksize(&mVi, 0),
+ vorbis_info_blocksize(&mVi, 1)
+ );
off64_t size;
if (mSource->getSize(&size) == OK) {
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
new file mode 100644
index 0000000..ec4a960
--- /dev/null
+++ b/media/libstagefright/foundation/ADebug.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#define LOG_TAG "ADebug"
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include <cutils/properties.h>
+
+#include <ADebug.h>
+#include <AStringUtils.h>
+#include <AUtils.h>
+
+namespace android {
+
+//static
+ADebug::Level ADebug::GetDebugLevelFromString(
+ const char *name, const char *value, ADebug::Level def) {
+ // split on ,
+ const char *next = value, *current;
+ const unsigned long maxLevel = (unsigned long)kDebugMax;
+ while (next != NULL) {
+ current = next;
+ next = strchr(current, ',');
+ if (next != NULL) {
+ ++next; // pass ,
+ }
+
+ while (isspace(*current)) {
+ ++current;
+ }
+ // check for :
+ char *colon = strchr(current, ':');
+
+ // get level
+ char *end;
+ errno = 0; // strtoul does not clear errno, but it can be set for any return value
+ unsigned long level = strtoul(current, &end, 10);
+ while (isspace(*end)) {
+ ++end;
+ }
+ if (errno != 0 || end == current || (end != colon && *end != '\0' && end != next)) {
+ // invalid level - skip
+ continue;
+ }
+ if (colon != NULL) {
+ // check if pattern matches
+ do { // skip colon and spaces
+ ++colon;
+ } while (isspace(*colon));
+ size_t globLen = (next == NULL ? strlen(colon) : (next - 1 - colon));
+ while (globLen > 0 && isspace(colon[globLen - 1])) {
+ --globLen; // trim glob
+ }
+
+ if (!AStringUtils::MatchesGlob(
+ colon, globLen, name, strlen(name), true /* ignoreCase */)) {
+ continue;
+ }
+ }
+
+ // update debug level
+ def = (Level)min(level, maxLevel);
+ }
+ return def;
+}
+
+//static
+ADebug::Level ADebug::GetDebugLevelFromProperty(
+ const char *name, const char *propertyName, ADebug::Level def) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get(propertyName, value, NULL)) {
+ return GetDebugLevelFromString(name, value, def);
+ }
+ return def;
+}
+
+//static
+char *ADebug::GetDebugName(const char *name) {
+ char *debugName = strdup(name);
+ const char *terms[] = { "omx", "video", "audio" };
+ for (size_t i = 0; i < NELEM(terms) && debugName != NULL; i++) {
+ const char *term = terms[i];
+ const size_t len = strlen(term);
+ char *match = strcasestr(debugName, term);
+ if (match != NULL && (match == debugName || match[-1] == '.'
+ || match[len] == '.' || match[len] == '\0')) {
+ char *src = match + len;
+ if (match == debugName || match[-1] == '.') {
+ src += (*src == '.'); // remove trailing or double .
+ }
+ memmove(match, src, debugName + strlen(debugName) - src + 1);
+ }
+ }
+
+ return debugName;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/foundation/AStringUtils.cpp b/media/libstagefright/foundation/AStringUtils.cpp
new file mode 100644
index 0000000..e5a846c
--- /dev/null
+++ b/media/libstagefright/foundation/AStringUtils.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <AStringUtils.h>
+
+namespace android {
+
+// static
+int AStringUtils::Compare(const char *a, const char *b, size_t len, bool ignoreCase) {
+ // this method relies on a trailing '\0' if a or b are shorter than len
+ return ignoreCase ? strncasecmp(a, b, len) : strncmp(a, b, len);
+}
+
+// static
+bool AStringUtils::MatchesGlob(
+ const char *glob, size_t globLen, const char *str, size_t strLen, bool ignoreCase) {
+ // this method does not assume a trailing '\0'
+ size_t ix = 0, globIx = 0;
+
+ // pattern must match until first '*'
+ while (globIx < globLen && glob[globIx] != '*') {
+ ++globIx;
+ }
+ if (strLen < globIx || Compare(str, glob, globIx /* len */, ignoreCase)) {
+ return false;
+ }
+ ix = globIx;
+
+ // process by * separated sections
+ while (globIx < globLen) {
+ ++globIx;
+ size_t start = globIx;
+ while (globIx < globLen && glob[globIx] != '*') {
+ ++globIx;
+ }
+ size_t len = globIx - start;
+ const char *pattern = glob + start;
+
+ if (globIx == globLen) {
+ // last pattern must match tail
+ if (ix + len > strLen) {
+ return false;
+ }
+ const char *tail = str + strLen - len;
+ return !Compare(tail, pattern, len, ignoreCase);
+ }
+ // progress after first occurrence of pattern
+ while (ix + len <= strLen && Compare(str + ix, pattern, len, ignoreCase)) {
+ ++ix;
+ }
+ if (ix + len > strLen) {
+ return false;
+ }
+ ix += len;
+ // we will loop around as globIx < globLen
+ }
+
+ // we only get here if there were no * in the pattern
+ return ix == strLen;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
index 90a6a23..c1dd6ce 100644
--- a/media/libstagefright/foundation/Android.mk
+++ b/media/libstagefright/foundation/Android.mk
@@ -5,6 +5,7 @@
AAtomizer.cpp \
ABitReader.cpp \
ABuffer.cpp \
+ ADebug.cpp \
AHandler.cpp \
AHierarchicalStateMachine.cpp \
ALooper.cpp \
@@ -12,6 +13,7 @@
AMessage.cpp \
ANetworkSession.cpp \
AString.cpp \
+ AStringUtils.cpp \
ParsedMessage.cpp \
base64.cpp \
hexdump.cpp
@@ -22,6 +24,7 @@
LOCAL_SHARED_LIBRARIES := \
libbinder \
libutils \
+ libcutils \
liblog
LOCAL_CFLAGS += -Wno-multichar -Werror
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index eb3154a..e4ea034 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -963,8 +963,8 @@
} while (bytesRead != 0);
if (bufferStartsWithTsSyncByte(buffer)) {
- // If we still don't see a stream after fetching a full ts segment mark it as
- // nonexistent.
+ // If we don't see a stream in the program table after fetching a full ts segment
+ // mark it as nonexistent.
const size_t kNumTypes = ATSParser::NUM_SOURCE_TYPES;
ATSParser::SourceType srcTypes[kNumTypes] =
{ ATSParser::VIDEO, ATSParser::AUDIO };
@@ -979,7 +979,7 @@
static_cast<AnotherPacketSource *>(
mTSParser->getSource(srcType).get());
- if (source == NULL) {
+ if (!mTSParser->hasSource(srcType)) {
ALOGW("MPEG2 Transport stream does not contain %s data.",
srcType == ATSParser::VIDEO ? "video" : "audio");
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 24d431c..104dcfc 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -31,7 +31,7 @@
struct OMXNodeInstance {
OMXNodeInstance(
- OMX *owner, const sp<IOMXObserver> &observer);
+ OMX *owner, const sp<IOMXObserver> &observer, const char *name);
void setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle);
@@ -149,6 +149,18 @@
KeyedVector<OMX_BUFFERHEADERTYPE *, OMX::buffer_id> mBufferHeaderToBufferID;
#endif
+ // For debug support
+ char *mName;
+ int DEBUG;
+ size_t mNumPortBuffers[2]; // modified under mLock, read outside for debug
+ Mutex mDebugLock;
+ // following are modified and read under mDebugLock
+ int DEBUG_BUMP;
+ SortedVector<OMX_BUFFERHEADERTYPE *> mInputBuffersWithCodec, mOutputBuffersWithCodec;
+ size_t mDebugLevelBumpPendingBuffers[2];
+ void bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers);
+ void unbumpDebugLevel_l(size_t portIndex);
+
~OMXNodeInstance();
void addActiveBuffer(OMX_U32 portIndex, OMX::buffer_id id);
@@ -186,6 +198,10 @@
OMX_U32 portIndex, OMX_BOOL enable,
OMX_BOOL useGraphicBuffer, OMX_BOOL *usingGraphicBufferInMeta);
+ status_t emptyBuffer_l(
+ OMX_BUFFERHEADERTYPE *header,
+ OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr);
+
sp<GraphicBufferSource> getGraphicBufferSource();
void setGraphicBufferSource(const sp<GraphicBufferSource>& bufferSource);
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index eab7616..c1dc0f9 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -63,6 +63,7 @@
void signalEOS(status_t finalResult);
sp<MediaSource> getSource(SourceType type);
+ bool hasSource(SourceType type) const;
int64_t convertPTSToTimestamp(uint64_t PTS);
@@ -119,6 +120,9 @@
sp<MediaSource> getSource(SourceType type);
+ bool isAudio() const;
+ bool isVideo() const;
+
protected:
virtual ~Stream();
@@ -146,9 +150,6 @@
void extractAACFrames(const sp<ABuffer> &buffer);
- bool isAudio() const;
- bool isVideo() const;
-
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -440,6 +441,19 @@
return NULL;
}
+bool ATSParser::Program::hasSource(SourceType type) const {
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ const sp<Stream> &stream = mStreams.valueAt(i);
+ if (type == AUDIO && stream->isAudio()) {
+ return true;
+ } else if (type == VIDEO && stream->isVideo()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
int64_t ATSParser::Program::convertPTSToTimestamp(uint64_t PTS) {
if (!(mParser->mFlags & TS_TIMESTAMPS_ARE_ABSOLUTE)) {
if (!mFirstPTSValid) {
@@ -1278,6 +1292,17 @@
return NULL;
}
+bool ATSParser::hasSource(SourceType type) const {
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ const sp<Program> &program = mPrograms.itemAt(i);
+ if (program->hasSource(type)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool ATSParser::PTSTimeDeltaEstablished() {
if (mPrograms.isEmpty()) {
return false;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 204934d..5d76cbd 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -74,6 +74,7 @@
NUM_SOURCE_TYPES = 2
};
sp<MediaSource> getSource(SourceType type);
+ bool hasSource(SourceType type) const;
bool PTSTimeDeltaEstablished();
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index ed40bdd..c579d4c 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -262,15 +262,15 @@
}
}
+ mEOSResult = OK;
+ mLastQueuedTimeUs = 0;
+ mLatestEnqueuedMeta = NULL;
+
if (type == ATSParser::DISCONTINUITY_NONE) {
return;
}
- mEOSResult = OK;
- mLastQueuedTimeUs = 0;
- mLatestEnqueuedMeta = NULL;
++mQueuedDiscontinuityCount;
-
sp<ABuffer> buffer = new ABuffer(0);
buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
buffer->meta()->setMessage("extra", extra);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 41407e4..6d46eee 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -225,7 +225,7 @@
*node = 0;
- OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
+ OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name);
OMX_COMPONENTTYPE *handle;
OMX_ERRORTYPE err = mMaster->makeComponentInstance(
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index f9c84e2..c04d95f 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -18,11 +18,15 @@
#define LOG_TAG "OMXNodeInstance"
#include <utils/Log.h>
+#include <inttypes.h>
+
#include "../include/OMXNodeInstance.h"
#include "OMXMaster.h"
#include "GraphicBufferSource.h"
#include <OMX_Component.h>
+#include <OMX_IndexExt.h>
+#include <OMX_AsString.h>
#include <binder/IMemory.h>
#include <gui/BufferQueue.h>
@@ -30,7 +34,68 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
+#include <utils/misc.h>
+
static const OMX_U32 kPortIndexInput = 0;
+static const OMX_U32 kPortIndexOutput = 1;
+
+#define CLOGW(fmt, ...) ALOGW("[%x:%s] " fmt, mNodeID, mName, ##__VA_ARGS__)
+
+#define CLOG_ERROR_IF(cond, fn, err, fmt, ...) \
+ ALOGE_IF(cond, #fn "(%x:%s, " fmt ") ERROR: %s(%#x)", \
+ mNodeID, mName, ##__VA_ARGS__, asString(err), err)
+#define CLOG_ERROR(fn, err, fmt, ...) CLOG_ERROR_IF(true, fn, err, fmt, ##__VA_ARGS__)
+#define CLOG_IF_ERROR(fn, err, fmt, ...) \
+ CLOG_ERROR_IF((err) != OMX_ErrorNone, fn, err, fmt, ##__VA_ARGS__)
+
+#define CLOGI_(level, fn, fmt, ...) \
+ ALOGI_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+#define CLOGD_(level, fn, fmt, ...) \
+ ALOGD_IF(DEBUG >= (level), #fn "(%x:%s, " fmt ")", mNodeID, mName, ##__VA_ARGS__)
+
+#define CLOG_LIFE(fn, fmt, ...) CLOGI_(ADebug::kDebugLifeCycle, fn, fmt, ##__VA_ARGS__)
+#define CLOG_STATE(fn, fmt, ...) CLOGI_(ADebug::kDebugState, fn, fmt, ##__VA_ARGS__)
+#define CLOG_CONFIG(fn, fmt, ...) CLOGI_(ADebug::kDebugConfig, fn, fmt, ##__VA_ARGS__)
+#define CLOG_INTERNAL(fn, fmt, ...) CLOGD_(ADebug::kDebugInternalState, fn, fmt, ##__VA_ARGS__)
+
+#define CLOG_DEBUG_IF(cond, fn, fmt, ...) \
+ ALOGD_IF(cond, #fn "(%x, " fmt ")", mNodeID, ##__VA_ARGS__)
+
+#define CLOG_BUFFER(fn, fmt, ...) \
+ CLOG_DEBUG_IF(DEBUG >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
+#define CLOG_BUMPED_BUFFER(fn, fmt, ...) \
+ CLOG_DEBUG_IF(DEBUG_BUMP >= ADebug::kDebugAll, fn, fmt, ##__VA_ARGS__)
+
+/* buffer formatting */
+#define BUFFER_FMT(port, fmt, ...) "%s:%u " fmt, portString(port), (port), ##__VA_ARGS__
+#define NEW_BUFFER_FMT(buffer_id, port, fmt, ...) \
+ BUFFER_FMT(port, fmt ") (#%zu => %#x", ##__VA_ARGS__, mActiveBuffers.size(), (buffer_id))
+
+#define SIMPLE_BUFFER(port, size, data) BUFFER_FMT(port, "%zu@%p", (size), (data))
+#define SIMPLE_NEW_BUFFER(buffer_id, port, size, data) \
+ NEW_BUFFER_FMT(buffer_id, port, "%zu@%p", (size), (data))
+
+#define EMPTY_BUFFER(addr, header) "%#x [%u@%p]", \
+ (addr), (header)->nAllocLen, (header)->pBuffer
+#define FULL_BUFFER(addr, header) "%#" PRIxPTR " [%u@%p (%u..+%u) f=%x ts=%lld]", \
+ (intptr_t)(addr), (header)->nAllocLen, (header)->pBuffer, \
+ (header)->nOffset, (header)->nFilledLen, (header)->nFlags, (header)->nTimeStamp
+
+#define WITH_STATS_WRAPPER(fmt, ...) fmt " { IN=%zu/%zu OUT=%zu/%zu }", ##__VA_ARGS__, \
+ mInputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexInput], \
+ mOutputBuffersWithCodec.size(), mNumPortBuffers[kPortIndexOutput]
+// TRICKY: this is needed so formatting macros expand before substitution
+#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)
+
+template<class T>
+static void InitOMXParams(T *params) {
+ memset(params, 0, sizeof(T));
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
namespace android {
@@ -56,8 +121,8 @@
}
memcpy((OMX_U8 *)mMem->pointer() + header->nOffset,
- header->pBuffer + header->nOffset,
- header->nFilledLen);
+ header->pBuffer + header->nOffset,
+ header->nFilledLen);
}
void CopyToOMX(const OMX_BUFFERHEADERTYPE *header) {
@@ -66,8 +131,8 @@
}
memcpy(header->pBuffer + header->nOffset,
- (const OMX_U8 *)mMem->pointer() + header->nOffset,
- header->nFilledLen);
+ (const OMX_U8 *)mMem->pointer() + header->nOffset,
+ header->nFilledLen);
}
void setGraphicBuffer(const sp<GraphicBuffer> &graphicBuffer) {
@@ -89,8 +154,17 @@
&OnEvent, &OnEmptyBufferDone, &OnFillBufferDone
};
+static inline const char *portString(OMX_U32 portIndex) {
+ switch (portIndex) {
+ case kPortIndexInput: return "Input";
+ case kPortIndexOutput: return "Output";
+ case ~0: return "All";
+ default: return "port";
+ }
+}
+
OMXNodeInstance::OMXNodeInstance(
- OMX *owner, const sp<IOMXObserver> &observer)
+ OMX *owner, const sp<IOMXObserver> &observer, const char *name)
: mOwner(owner),
mNodeID(0),
mHandle(NULL),
@@ -100,15 +174,25 @@
, mBufferIDCount(0)
#endif
{
+ mName = ADebug::GetDebugName(name);
+ DEBUG = ADebug::GetDebugLevelFromProperty(name, "debug.stagefright.omx-debug");
+ ALOGV("debug level for %s is %d", name, DEBUG);
+ DEBUG_BUMP = DEBUG;
+ mNumPortBuffers[0] = 0;
+ mNumPortBuffers[1] = 0;
+ mDebugLevelBumpPendingBuffers[0] = 0;
+ mDebugLevelBumpPendingBuffers[1] = 0;
}
OMXNodeInstance::~OMXNodeInstance() {
+ free(mName);
CHECK(mHandle == NULL);
}
void OMXNodeInstance::setHandle(OMX::node_id node_id, OMX_HANDLETYPE handle) {
- CHECK(mHandle == NULL);
mNodeID = node_id;
+ CLOG_LIFE(allocateNode, "handle=%p", handle);
+ CHECK(mHandle == NULL);
mHandle = handle;
}
@@ -120,6 +204,7 @@
void OMXNodeInstance::setGraphicBufferSource(
const sp<GraphicBufferSource>& bufferSource) {
Mutex::Autolock autoLock(mGraphicBufferSourceLock);
+ CLOG_INTERNAL(setGraphicBufferSource, "%p", bufferSource.get());
mGraphicBufferSource = bufferSource;
}
@@ -140,6 +225,7 @@
case OMX_ErrorNone:
return OK;
case OMX_ErrorUnsupportedSetting:
+ case OMX_ErrorUnsupportedIndex:
return ERROR_UNSUPPORTED;
default:
return UNKNOWN_ERROR;
@@ -147,6 +233,7 @@
}
status_t OMXNodeInstance::freeNode(OMXMaster *master) {
+ CLOG_LIFE(freeNode, "handle=%p", mHandle);
static int32_t kMaxNumIterations = 10;
// exit if we have already freed the node
@@ -175,10 +262,11 @@
OMX_ERRORTYPE err;
int32_t iteration = 0;
while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
- && state != OMX_StateIdle
- && state != OMX_StateInvalid) {
+ && state != OMX_StateIdle
+ && state != OMX_StateInvalid) {
if (++iteration > kMaxNumIterations) {
- ALOGE("component failed to enter Idle state, aborting.");
+ CLOGW("failed to enter Idle state (now %s(%d), aborting.",
+ asString(state), state);
state = OMX_StateInvalid;
break;
}
@@ -204,10 +292,11 @@
OMX_ERRORTYPE err;
int32_t iteration = 0;
while ((err = OMX_GetState(mHandle, &state)) == OMX_ErrorNone
- && state != OMX_StateLoaded
- && state != OMX_StateInvalid) {
+ && state != OMX_StateLoaded
+ && state != OMX_StateInvalid) {
if (++iteration > kMaxNumIterations) {
- ALOGE("component failed to enter Loaded state, aborting.");
+ CLOGW("failed to enter Loaded state (now %s(%d), aborting.",
+ asString(state), state);
state = OMX_StateInvalid;
break;
}
@@ -225,20 +314,18 @@
break;
default:
- CHECK(!"should not be here, unknown state.");
+ LOG_ALWAYS_FATAL("unknown state %s(%#x).", asString(state), state);
break;
}
- ALOGV("calling destroyComponentInstance");
+ ALOGV("[%x:%s] calling destroyComponentInstance", mNodeID, mName);
OMX_ERRORTYPE err = master->destroyComponentInstance(
static_cast<OMX_COMPONENTTYPE *>(mHandle));
- ALOGV("destroyComponentInstance returned err %d", err);
mHandle = NULL;
-
- if (err != OMX_ErrorNone) {
- ALOGE("FreeHandle FAILED with error 0x%08x.", err);
- }
+ CLOG_IF_ERROR(freeNode, err, "");
+ free(mName);
+ mName = NULL;
mOwner->invalidateNodeID(mNodeID);
mNodeID = 0;
@@ -270,7 +357,17 @@
Mutex::Autolock autoLock(mLock);
+ // bump internal-state debug level for 2 input and output frames past a command
+ {
+ Mutex::Autolock _l(mDebugLock);
+ bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
+ }
+
+ const char *paramString =
+ cmd == OMX_CommandStateSet ? asString((OMX_STATETYPE)param) : portString(param);
+ CLOG_STATE(sendCommand, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
OMX_ERRORTYPE err = OMX_SendCommand(mHandle, cmd, param, NULL);
+ CLOG_IF_ERROR(sendCommand, err, "%s(%d), %s(%d)", asString(cmd), cmd, paramString, param);
return StatusFromOMXError(err);
}
@@ -279,17 +376,23 @@
Mutex::Autolock autoLock(mLock);
OMX_ERRORTYPE err = OMX_GetParameter(mHandle, index, params);
- ALOGE_IF(err != OMX_ErrorNone, "getParameter(%d) ERROR: %#x", index, err);
+ OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+ // some errors are expected for getParameter
+ if (err != OMX_ErrorNoMore) {
+ CLOG_IF_ERROR(getParameter, err, "%s(%#x)", asString(extIndex), index);
+ }
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::setParameter(
- OMX_INDEXTYPE index, const void *params, size_t /* size */) {
+ OMX_INDEXTYPE index, const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
+ OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+ CLOG_CONFIG(setParameter, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
OMX_ERRORTYPE err = OMX_SetParameter(
mHandle, index, const_cast<void *>(params));
- ALOGE_IF(err != OMX_ErrorNone, "setParameter(%d) ERROR: %#x", index, err);
+ CLOG_IF_ERROR(setParameter, err, "%s(%#x)", asString(extIndex), index);
return StatusFromOMXError(err);
}
@@ -298,16 +401,23 @@
Mutex::Autolock autoLock(mLock);
OMX_ERRORTYPE err = OMX_GetConfig(mHandle, index, params);
+ OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+ // some errors are expected for getConfig
+ if (err != OMX_ErrorNoMore) {
+ CLOG_IF_ERROR(getConfig, err, "%s(%#x)", asString(extIndex), index);
+ }
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::setConfig(
- OMX_INDEXTYPE index, const void *params, size_t /* size */) {
+ OMX_INDEXTYPE index, const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
+ OMX_INDEXEXTTYPE extIndex = (OMX_INDEXEXTTYPE)index;
+ CLOG_CONFIG(setConfig, "%s(%#x), %zu@%p)", asString(extIndex), index, size, params);
OMX_ERRORTYPE err = OMX_SetConfig(
mHandle, index, const_cast<void *>(params));
-
+ CLOG_IF_ERROR(setConfig, err, "%s(%#x)", asString(extIndex), index);
return StatusFromOMXError(err);
}
@@ -315,13 +425,14 @@
Mutex::Autolock autoLock(mLock);
OMX_ERRORTYPE err = OMX_GetState(mHandle, state);
-
+ CLOG_IF_ERROR(getState, err, "");
return StatusFromOMXError(err);
}
status_t OMXNodeInstance::enableGraphicBuffers(
OMX_U32 portIndex, OMX_BOOL enable) {
Mutex::Autolock autoLock(mLock);
+ CLOG_CONFIG(enableGraphicBuffers, "%s:%u, %d", portString(portIndex), portIndex, enable);
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.enableAndroidNativeBuffers");
@@ -329,32 +440,19 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- if (enable) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
- }
-
+ CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
- OMX_VERSIONTYPE ver;
- ver.s.nVersionMajor = 1;
- ver.s.nVersionMinor = 0;
- ver.s.nRevision = 0;
- ver.s.nStep = 0;
- EnableAndroidNativeBuffersParams params = {
- sizeof(EnableAndroidNativeBuffersParams), ver, portIndex, enable,
- };
+ EnableAndroidNativeBuffersParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = portIndex;
+ params.enable = enable;
err = OMX_SetParameter(mHandle, index, ¶ms);
-
- if (err != OMX_ErrorNone) {
- ALOGE("OMX_EnableAndroidNativeBuffers failed with error %d (0x%08x)",
- err, err);
-
- return UNKNOWN_ERROR;
- }
-
- return OK;
+ CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
+ portString(portIndex), portIndex, enable);
+ return StatusFromOMXError(err);
}
status_t OMXNodeInstance::getGraphicBufferUsage(
@@ -367,26 +465,19 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
-
+ CLOG_ERROR(getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
- OMX_VERSIONTYPE ver;
- ver.s.nVersionMajor = 1;
- ver.s.nVersionMinor = 0;
- ver.s.nRevision = 0;
- ver.s.nStep = 0;
- GetAndroidNativeBufferUsageParams params = {
- sizeof(GetAndroidNativeBufferUsageParams), ver, portIndex, 0,
- };
+ GetAndroidNativeBufferUsageParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = portIndex;
err = OMX_GetParameter(mHandle, index, ¶ms);
-
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetAndroidNativeBufferUsage failed with error %d (0x%08x)",
- err, err);
- return UNKNOWN_ERROR;
+ CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u", name, index,
+ portString(portIndex), portIndex);
+ return StatusFromOMXError(err);
}
*usage = params.nUsage;
@@ -398,6 +489,7 @@
OMX_U32 portIndex,
OMX_BOOL enable) {
Mutex::Autolock autolock(mLock);
+ CLOG_CONFIG(storeMetaDataInBuffers, "%s:%u en:%d", portString(portIndex), portIndex, enable);
return storeMetaDataInBuffers_l(
portIndex, enable,
OMX_FALSE /* useGraphicBuffer */, NULL /* usingGraphicBufferInMetadata */);
@@ -424,37 +516,42 @@
: OMX_ErrorBadParameter;
if (err == OMX_ErrorNone) {
*usingGraphicBufferInMetadata = OMX_TRUE;
+ name = graphicBufferName;
} else {
- *usingGraphicBufferInMetadata = OMX_FALSE;
err = OMX_GetExtensionIndex(mHandle, name, &index);
}
+ OMX_ERRORTYPE xerr = err;
+ if (err == OMX_ErrorNone) {
+ StoreMetaDataInBuffersParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = portIndex;
+ params.bStoreMetaData = enable;
+
+ err = OMX_SetParameter(mHandle, index, ¶ms);
+ }
+
+ // don't log loud error if component does not support metadata mode on the output
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
- return StatusFromOMXError(err);
- }
-
- StoreMetaDataInBuffersParams params;
- memset(¶ms, 0, sizeof(params));
- params.nSize = sizeof(params);
-
- // Version: 1.0.0.0
- params.nVersion.s.nVersionMajor = 1;
-
- params.nPortIndex = portIndex;
- params.bStoreMetaData = enable;
- if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) {
- ALOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
*usingGraphicBufferInMetadata = OMX_FALSE;
- return UNKNOWN_ERROR;
+ if (err == OMX_ErrorUnsupportedIndex && portIndex == kPortIndexOutput) {
+ CLOGW("component does not support metadata mode; using fallback");
+ } else if (xerr != OMX_ErrorNone) {
+ CLOG_ERROR(getExtensionIndex, xerr, "%s", name);
+ } else {
+ CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d GB=%d", name, index,
+ portString(portIndex), portIndex, enable, useGraphicBuffer);
+ }
}
- return err;
+ return StatusFromOMXError(err);
}
status_t OMXNodeInstance::prepareForAdaptivePlayback(
OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth,
OMX_U32 maxFrameHeight) {
Mutex::Autolock autolock(mLock);
+ CLOG_CONFIG(prepareForAdaptivePlayback, "%s:%u en=%d max=%ux%u",
+ portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
@@ -462,33 +559,29 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGW_IF(enable, "OMX_GetExtensionIndex %s failed", name);
+ CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
PrepareForAdaptivePlaybackParams params;
- params.nSize = sizeof(params);
- params.nVersion.s.nVersionMajor = 1;
- params.nVersion.s.nVersionMinor = 0;
- params.nVersion.s.nRevision = 0;
- params.nVersion.s.nStep = 0;
-
+ InitOMXParams(¶ms);
params.nPortIndex = portIndex;
params.bEnable = enable;
params.nMaxFrameWidth = maxFrameWidth;
params.nMaxFrameHeight = maxFrameHeight;
- if ((err = OMX_SetParameter(mHandle, index, ¶ms)) != OMX_ErrorNone) {
- ALOGW("OMX_SetParameter failed for PrepareForAdaptivePlayback "
- "with error %d (0x%08x)", err, err);
- return UNKNOWN_ERROR;
- }
- return err;
+
+ err = OMX_SetParameter(mHandle, index, ¶ms);
+ CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d max=%ux%u", name, index,
+ portString(portIndex), portIndex, enable, maxFrameWidth, maxFrameHeight);
+ return StatusFromOMXError(err);
}
status_t OMXNodeInstance::configureVideoTunnelMode(
OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync,
native_handle_t **sidebandHandle) {
Mutex::Autolock autolock(mLock);
+ CLOG_CONFIG(configureVideoTunnelMode, "%s:%u tun=%d sync=%u",
+ portString(portIndex), portIndex, tunneled, audioHwSync);
OMX_INDEXTYPE index;
OMX_STRING name = const_cast<OMX_STRING>(
@@ -496,36 +589,33 @@
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
if (err != OMX_ErrorNone) {
- ALOGE("configureVideoTunnelMode extension is missing!");
+ CLOG_ERROR_IF(tunneled, getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
ConfigureVideoTunnelModeParams tunnelParams;
- tunnelParams.nSize = sizeof(tunnelParams);
- tunnelParams.nVersion.s.nVersionMajor = 1;
- tunnelParams.nVersion.s.nVersionMinor = 0;
- tunnelParams.nVersion.s.nRevision = 0;
- tunnelParams.nVersion.s.nStep = 0;
-
+ InitOMXParams(&tunnelParams);
tunnelParams.nPortIndex = portIndex;
tunnelParams.bTunneled = tunneled;
tunnelParams.nAudioHwSync = audioHwSync;
err = OMX_SetParameter(mHandle, index, &tunnelParams);
if (err != OMX_ErrorNone) {
- ALOGE("configureVideoTunnelMode failed! (err %d).", err);
- return UNKNOWN_ERROR;
+ CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
+ portString(portIndex), portIndex, tunneled, audioHwSync);
+ return StatusFromOMXError(err);
}
err = OMX_GetParameter(mHandle, index, &tunnelParams);
if (err != OMX_ErrorNone) {
- ALOGE("GetVideoTunnelWindow failed! (err %d).", err);
- return UNKNOWN_ERROR;
+ CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u tun=%d sync=%u", name, index,
+ portString(portIndex), portIndex, tunneled, audioHwSync);
+ return StatusFromOMXError(err);
}
if (sidebandHandle) {
*sidebandHandle = (native_handle_t*)tunnelParams.pSidebandWindow;
}
- return err;
+ return OK;
}
status_t OMXNodeInstance::useBuffer(
@@ -542,14 +632,14 @@
params->size(), static_cast<OMX_U8 *>(params->pointer()));
if (err != OMX_ErrorNone) {
- ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+ CLOG_ERROR(useBuffer, err, SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
delete buffer_meta;
buffer_meta = NULL;
*buffer = 0;
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -563,6 +653,8 @@
bufferSource->addCodecBuffer(header);
}
+ CLOG_BUFFER(useBuffer, NEW_BUFFER_FMT(
+ *buffer, portIndex, "%zu@%p", params->size(), params->pointer()));
return OK;
}
@@ -572,17 +664,14 @@
// port definition
OMX_PARAM_PORTDEFINITIONTYPE def;
- def.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
- def.nVersion.s.nVersionMajor = 1;
- def.nVersion.s.nVersionMinor = 0;
- def.nVersion.s.nRevision = 0;
- def.nVersion.s.nStep = 0;
+ InitOMXParams(&def);
def.nPortIndex = portIndex;
OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
- if (err != OMX_ErrorNone)
- {
- ALOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
- return err;
+ if (err != OMX_ErrorNone) {
+ OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
+ CLOG_ERROR(getParameter, err, "%s(%#x): %s:%u",
+ asString(index), index, portString(portIndex), portIndex);
+ return UNKNOWN_ERROR;
}
BufferMeta *bufferMeta = new BufferMeta(graphicBuffer);
@@ -600,11 +689,11 @@
bufferHandle);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_UseBuffer failed with error %d (0x%08x)", err, err);
+ CLOG_ERROR(useBuffer, err, BUFFER_FMT(portIndex, "%u@%p", def.nBufferSize, bufferHandle));
delete bufferMeta;
bufferMeta = NULL;
*buffer = 0;
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
CHECK_EQ(header->pBuffer, bufferHandle);
@@ -613,7 +702,8 @@
*buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
-
+ CLOG_BUFFER(useGraphicBuffer2, NEW_BUFFER_FMT(
+ *buffer, portIndex, "%u@%p", def.nBufferSize, bufferHandle));
return OK;
}
@@ -637,10 +727,8 @@
OMX_STRING name = const_cast<OMX_STRING>(
"OMX.google.android.index.useAndroidNativeBuffer");
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
-
if (err != OMX_ErrorNone) {
- ALOGE("OMX_GetExtensionIndex %s failed", name);
-
+ CLOG_ERROR(getExtensionIndex, err, "%s", name);
return StatusFromOMXError(err);
}
@@ -661,15 +749,15 @@
err = OMX_SetParameter(mHandle, index, ¶ms);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_UseAndroidNativeBuffer failed with error %d (0x%08x)", err,
- err);
+ CLOG_ERROR(setParameter, err, "%s(%#x): %s:%u meta=%p GB=%p", name, index,
+ portString(portIndex), portIndex, bufferMeta, graphicBuffer->handle);
delete bufferMeta;
bufferMeta = NULL;
*buffer = 0;
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
CHECK_EQ(header->pAppPrivate, bufferMeta);
@@ -677,12 +765,13 @@
*buffer = makeBufferID(header);
addActiveBuffer(portIndex, *buffer);
-
+ CLOG_BUFFER(useGraphicBuffer, NEW_BUFFER_FMT(
+ *buffer, portIndex, "GB=%p", graphicBuffer->handle));
return OK;
}
status_t OMXNodeInstance::updateGraphicBufferInMeta(
- OMX_U32 /* portIndex */, const sp<GraphicBuffer>& graphicBuffer,
+ OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
@@ -693,7 +782,8 @@
bufferMeta->setGraphicBuffer(graphicBuffer);
metadata->eType = kMetadataBufferTypeGrallocSource;
metadata->pHandle = graphicBuffer->handle;
-
+ CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
+ portString(portIndex), portIndex, buffer, graphicBuffer->handle);
return OK;
}
@@ -719,19 +809,21 @@
// Retrieve the width and height of the graphic buffer, set when the
// codec was configured.
OMX_PARAM_PORTDEFINITIONTYPE def;
- def.nSize = sizeof(def);
- def.nVersion.s.nVersionMajor = 1;
- def.nVersion.s.nVersionMinor = 0;
- def.nVersion.s.nRevision = 0;
- def.nVersion.s.nStep = 0;
+ InitOMXParams(&def);
def.nPortIndex = portIndex;
OMX_ERRORTYPE oerr = OMX_GetParameter(
mHandle, OMX_IndexParamPortDefinition, &def);
- CHECK(oerr == OMX_ErrorNone);
+ if (oerr != OMX_ErrorNone) {
+ OMX_INDEXTYPE index = OMX_IndexParamPortDefinition;
+ CLOG_ERROR(getParameter, oerr, "%s(%#x): %s:%u",
+ asString(index), index, portString(portIndex), portIndex);
+ return UNKNOWN_ERROR;
+ }
if (def.format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque) {
- ALOGE("createInputSurface requires COLOR_FormatSurface "
- "(AndroidOpaque) color format");
+ CLOGW("createInputSurface requires COLOR_FormatSurface "
+ "(AndroidOpaque) color format instead of %s(%#x)",
+ asString(def.format.video.eColorFormat), def.format.video.eColorFormat);
return INVALID_OPERATION;
}
@@ -754,9 +846,9 @@
// flag set). Seems easier than doing the equivalent from here.
sp<GraphicBufferSource> bufferSource(getGraphicBufferSource());
if (bufferSource == NULL) {
- ALOGW("signalEndOfInputStream can only be used with Surface input");
+ CLOGW("signalEndOfInputStream can only be used with Surface input");
return INVALID_OPERATION;
- };
+ }
return bufferSource->signalEndOfInputStream();
}
@@ -773,14 +865,13 @@
mHandle, &header, portIndex, buffer_meta, size);
if (err != OMX_ErrorNone) {
- ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
-
+ CLOG_ERROR(allocateBuffer, err, BUFFER_FMT(portIndex, "%zu@", size));
delete buffer_meta;
buffer_meta = NULL;
*buffer = 0;
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -794,6 +885,7 @@
if (bufferSource != NULL && portIndex == kPortIndexInput) {
bufferSource->addCodecBuffer(header);
}
+ CLOG_BUFFER(allocateBuffer, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p", size, *buffer_data));
return OK;
}
@@ -811,14 +903,14 @@
mHandle, &header, portIndex, buffer_meta, params->size());
if (err != OMX_ErrorNone) {
- ALOGE("OMX_AllocateBuffer failed with error %d (0x%08x)", err, err);
-
+ CLOG_ERROR(allocateBufferWithBackup, err,
+ SIMPLE_BUFFER(portIndex, params->size(), params->pointer()));
delete buffer_meta;
buffer_meta = NULL;
*buffer = 0;
- return UNKNOWN_ERROR;
+ return StatusFromOMXError(err);
}
CHECK_EQ(header->pAppPrivate, buffer_meta);
@@ -832,12 +924,16 @@
bufferSource->addCodecBuffer(header);
}
+ CLOG_BUFFER(allocateBufferWithBackup, NEW_BUFFER_FMT(*buffer, portIndex, "%zu@%p :> %p",
+ params->size(), params->pointer(), header->pBuffer));
+
return OK;
}
status_t OMXNodeInstance::freeBuffer(
OMX_U32 portIndex, OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
+ CLOG_BUFFER(freeBuffer, "%s:%u %#x", portString(portIndex), portIndex, buffer);
removeActiveBuffer(portIndex, buffer);
@@ -845,6 +941,7 @@
BufferMeta *buffer_meta = static_cast<BufferMeta *>(header->pAppPrivate);
OMX_ERRORTYPE err = OMX_FreeBuffer(mHandle, portIndex, header);
+ CLOG_IF_ERROR(freeBuffer, err, "%s:%u %#x", portString(portIndex), portIndex, buffer);
delete buffer_meta;
buffer_meta = NULL;
@@ -861,8 +958,18 @@
header->nOffset = 0;
header->nFlags = 0;
- OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+ {
+ Mutex::Autolock _l(mDebugLock);
+ mOutputBuffersWithCodec.add(header);
+ CLOG_BUMPED_BUFFER(fillBuffer, WITH_STATS(EMPTY_BUFFER(buffer, header)));
+ }
+ OMX_ERRORTYPE err = OMX_FillThisBuffer(mHandle, header);
+ if (err != OMX_ErrorNone) {
+ CLOG_ERROR(fillBuffer, err, EMPTY_BUFFER(buffer, header));
+ Mutex::Autolock _l(mDebugLock);
+ mOutputBuffersWithCodec.remove(header);
+ }
return StatusFromOMXError(err);
}
@@ -875,14 +982,66 @@
OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
header->nFilledLen = rangeLength;
header->nOffset = rangeOffset;
- header->nFlags = flags;
- header->nTimeStamp = timestamp;
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(header->pAppPrivate);
buffer_meta->CopyToOMX(header);
+ return emptyBuffer_l(header, flags, timestamp, (intptr_t)buffer);
+}
+
+// log queued buffer activity for the next few input and/or output frames
+// if logging at internal state level
+void OMXNodeInstance::bumpDebugLevel_l(size_t numInputBuffers, size_t numOutputBuffers) {
+ if (DEBUG == ADebug::kDebugInternalState) {
+ DEBUG_BUMP = ADebug::kDebugAll;
+ if (numInputBuffers > 0) {
+ mDebugLevelBumpPendingBuffers[kPortIndexInput] = numInputBuffers;
+ }
+ if (numOutputBuffers > 0) {
+ mDebugLevelBumpPendingBuffers[kPortIndexOutput] = numOutputBuffers;
+ }
+ }
+}
+
+void OMXNodeInstance::unbumpDebugLevel_l(size_t portIndex) {
+ if (mDebugLevelBumpPendingBuffers[portIndex]) {
+ --mDebugLevelBumpPendingBuffers[portIndex];
+ }
+ if (!mDebugLevelBumpPendingBuffers[0]
+ && !mDebugLevelBumpPendingBuffers[1]) {
+ DEBUG_BUMP = DEBUG;
+ }
+}
+
+status_t OMXNodeInstance::emptyBuffer_l(
+ OMX_BUFFERHEADERTYPE *header, OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr) {
+ header->nFlags = flags;
+ header->nTimeStamp = timestamp;
+
+ {
+ Mutex::Autolock _l(mDebugLock);
+ mInputBuffersWithCodec.add(header);
+
+ // bump internal-state debug level for 2 input frames past a buffer with CSD
+ if ((flags & OMX_BUFFERFLAG_CODECCONFIG) != 0) {
+ bumpDebugLevel_l(2 /* numInputBuffers */, 0 /* numOutputBuffers */);
+ }
+
+ CLOG_BUMPED_BUFFER(emptyBuffer, WITH_STATS(FULL_BUFFER(debugAddr, header)));
+ }
+
OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
+ CLOG_IF_ERROR(emptyBuffer, err, FULL_BUFFER(debugAddr, header));
+
+ {
+ Mutex::Autolock _l(mDebugLock);
+ if (err != OMX_ErrorNone) {
+ mInputBuffersWithCodec.remove(header);
+ } else if (!(flags & OMX_BUFFERFLAG_CODECCONFIG)) {
+ unbumpDebugLevel_l(kPortIndexInput);
+ }
+ }
return StatusFromOMXError(err);
}
@@ -896,15 +1055,8 @@
header->nFilledLen = rangeLength;
header->nOffset = rangeOffset;
- header->nFlags = flags;
- header->nTimeStamp = timestamp;
- OMX_ERRORTYPE err = OMX_EmptyThisBuffer(mHandle, header);
- if (err != OMX_ErrorNone) {
- ALOGW("emptyDirectBuffer failed, OMX err=0x%x", err);
- }
-
- return StatusFromOMXError(err);
+ return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer);
}
status_t OMXNodeInstance::getExtensionIndex(
@@ -917,11 +1069,25 @@
return StatusFromOMXError(err);
}
+inline static const char *asString(IOMX::InternalOptionType i, const char *def = "??") {
+ switch (i) {
+ case IOMX::INTERNAL_OPTION_SUSPEND: return "SUSPEND";
+ case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
+ return "REPEAT_PREVIOUS_FRAME_DELAY";
+ case IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP: return "MAX_TIMESTAMP_GAP";
+ case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME";
+ case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE";
+ default: return def;
+ }
+}
+
status_t OMXNodeInstance::setInternalOption(
OMX_U32 portIndex,
IOMX::InternalOptionType type,
const void *data,
size_t size) {
+ CLOG_CONFIG(setInternalOption, "%s(%d): %s:%u %zu@%p",
+ asString(type), type, portString(portIndex), portIndex, size, data);
switch (type) {
case IOMX::INTERNAL_OPTION_SUSPEND:
case IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY:
@@ -933,6 +1099,7 @@
getGraphicBufferSource();
if (bufferSource == NULL || portIndex != kPortIndexInput) {
+ CLOGW("setInternalOption is only for Surface input");
return ERROR_UNSUPPORTED;
}
@@ -942,6 +1109,7 @@
}
bool suspend = *(bool *)data;
+ CLOG_CONFIG(setInternalOption, "suspend=%d", suspend);
bufferSource->suspend(suspend);
} else if (type ==
IOMX::INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY){
@@ -950,7 +1118,7 @@
}
int64_t delayUs = *(int64_t *)data;
-
+ CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs);
return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
} else if (type ==
IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP){
@@ -959,7 +1127,7 @@
}
int64_t maxGapUs = *(int64_t *)data;
-
+ CLOG_CONFIG(setInternalOption, "gapUs=%lld", (long long)maxGapUs);
return bufferSource->setMaxTimestampGapUs(maxGapUs);
} else if (type == IOMX::INTERNAL_OPTION_START_TIME) {
if (size != sizeof(int64_t)) {
@@ -967,13 +1135,18 @@
}
int64_t skipFramesBeforeUs = *(int64_t *)data;
-
+ CLOG_CONFIG(setInternalOption, "beforeUs=%lld", (long long)skipFramesBeforeUs);
bufferSource->setSkipFramesBeforeUs(skipFramesBeforeUs);
} else { // IOMX::INTERNAL_OPTION_TIME_LAPSE
if (size != sizeof(int64_t) * 2) {
return INVALID_OPERATION;
}
+ int64_t timePerFrameUs = ((int64_t *)data)[0];
+ int64_t timePerCaptureUs = ((int64_t *)data)[1];
+ CLOG_CONFIG(setInternalOption, "perFrameUs=%lld perCaptureUs=%lld",
+ (long long)timePerFrameUs, (long long)timePerCaptureUs);
+
bufferSource->setTimeLapseUs((int64_t *)data);
}
@@ -992,6 +1165,16 @@
OMX_BUFFERHEADERTYPE *buffer =
findBufferHeader(msg.u.extended_buffer_data.buffer);
+ {
+ Mutex::Autolock _l(mDebugLock);
+ mOutputBuffersWithCodec.remove(buffer);
+
+ CLOG_BUMPED_BUFFER(
+ FBD, WITH_STATS(FULL_BUFFER(msg.u.extended_buffer_data.buffer, buffer)));
+
+ unbumpDebugLevel_l(kPortIndexOutput);
+ }
+
BufferMeta *buffer_meta =
static_cast<BufferMeta *>(buffer->pAppPrivate);
@@ -1007,16 +1190,23 @@
return;
}
} else if (msg.type == omx_message::EMPTY_BUFFER_DONE) {
+ OMX_BUFFERHEADERTYPE *buffer =
+ findBufferHeader(msg.u.buffer_data.buffer);
+
+ {
+ Mutex::Autolock _l(mDebugLock);
+ mInputBuffersWithCodec.remove(buffer);
+
+ CLOG_BUMPED_BUFFER(
+ EBD, WITH_STATS(EMPTY_BUFFER(msg.u.buffer_data.buffer, buffer)));
+ }
+
if (bufferSource != NULL) {
// This is one of the buffers used exclusively by
// GraphicBufferSource.
// Don't dispatch a message back to ACodec, since it doesn't
// know that anyone asked to have the buffer emptied and will
// be very confused.
-
- OMX_BUFFERHEADERTYPE *buffer =
- findBufferHeader(msg.u.buffer_data.buffer);
-
bufferSource->codecBufferEmptied(buffer);
return;
}
@@ -1040,6 +1230,43 @@
// Don't try to acquire mLock here -- in rare circumstances this will hang.
void OMXNodeInstance::onEvent(
OMX_EVENTTYPE event, OMX_U32 arg1, OMX_U32 arg2) {
+ const char *arg1String = "??";
+ const char *arg2String = "??";
+ ADebug::Level level = ADebug::kDebugInternalState;
+
+ switch (event) {
+ case OMX_EventCmdComplete:
+ arg1String = asString((OMX_COMMANDTYPE)arg1);
+ switch (arg1) {
+ case OMX_CommandStateSet:
+ arg2String = asString((OMX_STATETYPE)arg2);
+ level = ADebug::kDebugState;
+ break;
+ case OMX_CommandFlush:
+ case OMX_CommandPortEnable:
+ {
+ // bump internal-state debug level for 2 input and output frames
+ Mutex::Autolock _l(mDebugLock);
+ bumpDebugLevel_l(2 /* numInputBuffers */, 2 /* numOutputBuffers */);
+ }
+ // fall through
+ default:
+ arg2String = portString(arg2);
+ }
+ break;
+ case OMX_EventError:
+ arg1String = asString((OMX_ERRORTYPE)arg1);
+ level = ADebug::kDebugLifeCycle;
+ break;
+ case OMX_EventPortSettingsChanged:
+ arg2String = asString((OMX_INDEXEXTTYPE)arg2);
+ // fall through
+ default:
+ arg1String = portString(arg1);
+ }
+
+ CLOGI_(level, onEvent, "%s(%x), %s(%x), %s(%x)",
+ asString(event), event, arg1String, arg1, arg2String, arg2);
const sp<GraphicBufferSource>& bufferSource(getGraphicBufferSource());
if (bufferSource != NULL
@@ -1097,23 +1324,27 @@
active.mPortIndex = portIndex;
active.mID = id;
mActiveBuffers.push(active);
+
+ if (portIndex < NELEM(mNumPortBuffers)) {
+ ++mNumPortBuffers[portIndex];
+ }
}
void OMXNodeInstance::removeActiveBuffer(
OMX_U32 portIndex, OMX::buffer_id id) {
- bool found = false;
for (size_t i = 0; i < mActiveBuffers.size(); ++i) {
if (mActiveBuffers[i].mPortIndex == portIndex
- && mActiveBuffers[i].mID == id) {
- found = true;
+ && mActiveBuffers[i].mID == id) {
mActiveBuffers.removeItemsAt(i);
- break;
+
+ if (portIndex < NELEM(mNumPortBuffers)) {
+ --mNumPortBuffers[portIndex];
+ }
+ return;
}
}
- if (!found) {
- ALOGW("Attempt to remove an active buffer we know nothing about...");
- }
+ CLOGW("Attempt to remove an active buffer [%#x] we know nothing about...", id);
}
void OMXNodeInstance::freeActiveBuffers() {
@@ -1134,7 +1365,7 @@
OMX::buffer_id buffer;
do { // handle the very unlikely case of ID overflow
if (++mBufferIDCount == 0) {
- ++mBufferIDCount;
+ ++mBufferIDCount;
}
buffer = (OMX::buffer_id)mBufferIDCount;
} while (mBufferIDToBufferHeader.indexOfKey(buffer) >= 0);
diff --git a/media/libstagefright/omx/SoftOMXComponent.cpp b/media/libstagefright/omx/SoftOMXComponent.cpp
index 646cd32..df978f8 100644
--- a/media/libstagefright/omx/SoftOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftOMXComponent.cpp
@@ -283,7 +283,7 @@
OMX_ERRORTYPE SoftOMXComponent::getExtensionIndex(
const char * /* name */, OMX_INDEXTYPE * /* index */) {
- return OMX_ErrorUndefined;
+ return OMX_ErrorUnsupportedIndex;
}
OMX_ERRORTYPE SoftOMXComponent::useBuffer(
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index f2825dd..43e0269 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -24,6 +24,7 @@
#include <unistd.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AStringUtils.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/Utils.h>
@@ -32,6 +33,100 @@
class UtilsTest : public ::testing::Test {
};
+TEST_F(UtilsTest, TestStringUtils) {
+ ASSERT_EQ(AStringUtils::Compare("Audio", "AudioExt", 5, false), 0);
+ ASSERT_EQ(AStringUtils::Compare("Audio", "audiOExt", 5, true), 0);
+ ASSERT_NE(AStringUtils::Compare("Audio", "audioExt", 5, false), 0);
+ ASSERT_NE(AStringUtils::Compare("Audio", "AudiOExt", 5, false), 0);
+
+ ASSERT_LT(AStringUtils::Compare("Audio", "AudioExt", 7, false), 0);
+ ASSERT_LT(AStringUtils::Compare("Audio", "audiOExt", 7, true), 0);
+
+ ASSERT_GT(AStringUtils::Compare("AudioExt", "Audio", 7, false), 0);
+ ASSERT_GT(AStringUtils::Compare("audiOext", "Audio", 7, true), 0);
+
+ ASSERT_LT(AStringUtils::Compare("Audio", "Video", 5, false), 0);
+ ASSERT_LT(AStringUtils::Compare("Audio1", "Audio2", 6, false), 0);
+ ASSERT_LT(AStringUtils::Compare("audio", "VIDEO", 5, true), 0);
+ ASSERT_LT(AStringUtils::Compare("audio1", "AUDIO2", 6, true), 0);
+
+ ASSERT_GT(AStringUtils::Compare("Video", "Audio", 5, false), 0);
+ ASSERT_GT(AStringUtils::Compare("Audio2", "Audio1", 6, false), 0);
+ ASSERT_GT(AStringUtils::Compare("VIDEO", "audio", 5, true), 0);
+ ASSERT_GT(AStringUtils::Compare("AUDIO2", "audio1", 6, true), 0);
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("AudioA", 5, "AudioB", 5, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 6, "AudioA", 5, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "AudioA", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "audiOB", 5, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("AudioA", 5, "audiOB", 5, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 6, "AudioA", 5, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("AudioA", 5, "AudioA", 6, true));
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 6, true));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 6, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 0, true));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*1", 1, "String8", 0, false));
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*ring1", 5, "String8", 6, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*ring2", 5, "STRING8", 6, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*ring4", 5, "StRing8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*ring5", 5, "StrinG8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*ring8", 5, "String8", 7, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*ring8", 5, "String8", 7, true));
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*1", 4, "String8", 6, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*2", 4, "STRING8", 6, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*3", 4, "string8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*4", 4, "StRing8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*5", 4, "AString8", 7, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*6", 4, "AString8", 7, true));
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ng1", 6, "String8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng2", 6, "string8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng3", 6, "StRing8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng4", 6, "StriNg8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng5", 6, "StrinG8", 6, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ng6", 6, "STRING8", 6, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng8", 6, "AString8", 7, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng1", 6, "String16", 7, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ing9", 7, "String8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ringA", 8, "String8", 6, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng8", 6, "AString8", 7, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ng1", 6, "String16", 7, true));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("Str*ing9", 7, "STRING8", 6, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("Str*ringA", 8, "String8", 6, true));
+
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "bestrestroom", 9, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "bestrestrestroom", 13, false));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*str*stro", 8, "bestrestrestroom", 14, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str*1", 9, "bestrestrestroom", 14, false));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "beSTReSTRoom", 9, true));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str1", 8, "beSTRestreSTRoom", 13, true));
+ ASSERT_FALSE(AStringUtils::MatchesGlob("*str*stro", 8, "bestreSTReSTRoom", 14, true));
+ ASSERT_TRUE(AStringUtils::MatchesGlob("*str*str*1", 9, "bestreSTReSTRoom", 14, true));
+}
+
+TEST_F(UtilsTest, TestDebug) {
+#define LVL(x) (ADebug::Level)(x)
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "", LVL(5)), LVL(5));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", " \t \n ", LVL(2)), LVL(2));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3:*deo", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString(
+ "video", "\t\n 3 \t\n:\t\n video \t\n", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "3:*deo,2:vid*", LVL(5)), LVL(2));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString(
+ "avideo", "\t\n 3 \t\n:\t\n avideo \t\n,\t\n 2 \t\n:\t\n video \t\n", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString(
+ "audio.omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(2));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString(
+ "video.omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("video", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(3));
+ ASSERT_EQ(ADebug::GetDebugLevelFromString("omx", "4:*omx,3:*d*o*,2:audio*", LVL(5)), LVL(4));
+#undef LVL
+}
+
TEST_F(UtilsTest, TestFourCC) {
ASSERT_EQ(FOURCC('s', 't', 'm' , 'u'), 'stmu');
}
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index e6e19e3..052b700 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -51,104 +51,178 @@
MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
}
-uint16_t MtpDataPacket::getUInt16() {
- int offset = mOffset;
- uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
- mOffset += 2;
- return result;
+bool MtpDataPacket::getUInt8(uint8_t& value) {
+ if (mPacketSize - mOffset < sizeof(value))
+ return false;
+ value = mBuffer[mOffset++];
+ return true;
}
-uint32_t MtpDataPacket::getUInt32() {
+bool MtpDataPacket::getUInt16(uint16_t& value) {
+ if (mPacketSize - mOffset < sizeof(value))
+ return false;
int offset = mOffset;
- uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
+ value = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
+ mOffset += sizeof(value);
+ return true;
+}
+
+bool MtpDataPacket::getUInt32(uint32_t& value) {
+ if (mPacketSize - mOffset < sizeof(value))
+ return false;
+ int offset = mOffset;
+ value = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);
- mOffset += 4;
- return result;
+ mOffset += sizeof(value);
+ return true;
}
-uint64_t MtpDataPacket::getUInt64() {
+bool MtpDataPacket::getUInt64(uint64_t& value) {
+ if (mPacketSize - mOffset < sizeof(value))
+ return false;
int offset = mOffset;
- uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
+ value = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);
- mOffset += 8;
- return result;
+ mOffset += sizeof(value);
+ return true;
}
-void MtpDataPacket::getUInt128(uint128_t& value) {
- value[0] = getUInt32();
- value[1] = getUInt32();
- value[2] = getUInt32();
- value[3] = getUInt32();
+bool MtpDataPacket::getUInt128(uint128_t& value) {
+ return getUInt32(value[0]) && getUInt32(value[1]) && getUInt32(value[2]) && getUInt32(value[3]);
}
-void MtpDataPacket::getString(MtpStringBuffer& string)
+bool MtpDataPacket::getString(MtpStringBuffer& string)
{
- string.readFromPacket(this);
+ return string.readFromPacket(this);
}
Int8List* MtpDataPacket::getAInt8() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
Int8List* result = new Int8List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getInt8());
+ for (uint32_t i = 0; i < count; i++) {
+ int8_t value;
+ if (!getInt8(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
UInt8List* MtpDataPacket::getAUInt8() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
UInt8List* result = new UInt8List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getUInt8());
+ for (uint32_t i = 0; i < count; i++) {
+ uint8_t value;
+ if (!getUInt8(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
Int16List* MtpDataPacket::getAInt16() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
Int16List* result = new Int16List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getInt16());
+ for (uint32_t i = 0; i < count; i++) {
+ int16_t value;
+ if (!getInt16(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
UInt16List* MtpDataPacket::getAUInt16() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
UInt16List* result = new UInt16List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getUInt16());
+ for (uint32_t i = 0; i < count; i++) {
+ uint16_t value;
+ if (!getUInt16(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
Int32List* MtpDataPacket::getAInt32() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
Int32List* result = new Int32List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getInt32());
+ for (uint32_t i = 0; i < count; i++) {
+ int32_t value;
+ if (!getInt32(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
UInt32List* MtpDataPacket::getAUInt32() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
UInt32List* result = new UInt32List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getUInt32());
+ for (uint32_t i = 0; i < count; i++) {
+ uint32_t value;
+ if (!getUInt32(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
Int64List* MtpDataPacket::getAInt64() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
Int64List* result = new Int64List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getInt64());
+ for (uint32_t i = 0; i < count; i++) {
+ int64_t value;
+ if (!getInt64(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
UInt64List* MtpDataPacket::getAUInt64() {
+ uint32_t count;
+ if (!getUInt32(count))
+ return NULL;
UInt64List* result = new UInt64List;
- int count = getUInt32();
- for (int i = 0; i < count; i++)
- result->push(getUInt64());
+ for (uint32_t i = 0; i < count; i++) {
+ uint64_t value;
+ if (!getUInt64(value)) {
+ delete result;
+ return NULL;
+ }
+ result->push(value);
+ }
return result;
}
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 2b81063..13d3bd9 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -30,7 +30,7 @@
class MtpDataPacket : public MtpPacket {
private:
// current offset for get/put methods
- int mOffset;
+ size_t mOffset;
public:
MtpDataPacket();
@@ -42,17 +42,18 @@
void setTransactionID(MtpTransactionID id);
inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
- inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; }
- inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; }
- uint16_t getUInt16();
- inline int16_t getInt16() { return (int16_t)getUInt16(); }
- uint32_t getUInt32();
- inline int32_t getInt32() { return (int32_t)getUInt32(); }
- uint64_t getUInt64();
- inline int64_t getInt64() { return (int64_t)getUInt64(); }
- void getUInt128(uint128_t& value);
- inline void getInt128(int128_t& value) { getUInt128((uint128_t&)value); }
- void getString(MtpStringBuffer& string);
+
+ bool getUInt8(uint8_t& value);
+ inline bool getInt8(int8_t& value) { return getUInt8((uint8_t&)value); }
+ bool getUInt16(uint16_t& value);
+ inline bool getInt16(int16_t& value) { return getUInt16((uint16_t&)value); }
+ bool getUInt32(uint32_t& value);
+ inline bool getInt32(int32_t& value) { return getUInt32((uint32_t&)value); }
+ bool getUInt64(uint64_t& value);
+ inline bool getInt64(int64_t& value) { return getUInt64((uint64_t&)value); }
+ bool getUInt128(uint128_t& value);
+ inline bool getInt128(int128_t& value) { return getUInt128((uint128_t&)value); }
+ bool getString(MtpStringBuffer& string);
Int8List* getAInt8();
UInt8List* getAUInt8();
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index d6d5dd5..e0d679d 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -313,8 +313,10 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpDeviceInfo* info = new MtpDeviceInfo;
- info->read(mData);
- return info;
+ if (info->read(mData))
+ return info;
+ else
+ delete info;
}
return NULL;
}
@@ -346,8 +348,10 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpStorageInfo* info = new MtpStorageInfo(storageID);
- info->read(mData);
- return info;
+ if (info->read(mData))
+ return info;
+ else
+ delete info;
}
return NULL;
}
@@ -385,8 +389,10 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpObjectInfo* info = new MtpObjectInfo(handle);
- info->read(mData);
- return info;
+ if (info->read(mData))
+ return info;
+ else
+ delete info;
}
return NULL;
}
@@ -547,8 +553,10 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpProperty* property = new MtpProperty;
- property->read(mData);
- return property;
+ if (property->read(mData))
+ return property;
+ else
+ delete property;
}
return NULL;
}
@@ -566,15 +574,17 @@
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpProperty* property = new MtpProperty;
- property->read(mData);
- return property;
+ if (property->read(mData))
+ return property;
+ else
+ delete property;
}
return NULL;
}
bool MtpDevice::readObject(MtpObjectHandle handle,
bool (* callback)(void* data, int offset, int length, void* clientData),
- int objectSize, void* clientData) {
+ size_t objectSize, void* clientData) {
Mutex::Autolock autoLock(mMutex);
bool result = false;
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index b69203e..9b0acbf 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -98,7 +98,7 @@
bool readObject(MtpObjectHandle handle,
bool (* callback)(void* data, int offset,
int length, void* clientData),
- int objectSize, void* clientData);
+ size_t objectSize, void* clientData);
bool readObject(MtpObjectHandle handle, const char* destPath, int group,
int perm);
diff --git a/media/mtp/MtpDeviceInfo.cpp b/media/mtp/MtpDeviceInfo.cpp
index 108e2b8..3e1dff7 100644
--- a/media/mtp/MtpDeviceInfo.cpp
+++ b/media/mtp/MtpDeviceInfo.cpp
@@ -28,7 +28,7 @@
mVendorExtensionID(0),
mVendorExtensionVersion(0),
mVendorExtensionDesc(NULL),
- mFunctionalCode(0),
+ mFunctionalMode(0),
mOperations(NULL),
mEvents(NULL),
mDeviceProperties(NULL),
@@ -59,39 +59,46 @@
free(mSerial);
}
-void MtpDeviceInfo::read(MtpDataPacket& packet) {
+bool MtpDeviceInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
// read the device info
- mStandardVersion = packet.getUInt16();
- mVendorExtensionID = packet.getUInt32();
- mVendorExtensionVersion = packet.getUInt16();
+ if (!packet.getUInt16(mStandardVersion)) return false;
+ if (!packet.getUInt32(mVendorExtensionID)) return false;
+ if (!packet.getUInt16(mVendorExtensionVersion)) return false;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mVendorExtensionDesc = strdup((const char *)string);
- mFunctionalCode = packet.getUInt16();
+ if (!packet.getUInt16(mFunctionalMode)) return false;
mOperations = packet.getAUInt16();
+ if (!mOperations) return false;
mEvents = packet.getAUInt16();
+ if (!mEvents) return false;
mDeviceProperties = packet.getAUInt16();
+ if (!mDeviceProperties) return false;
mCaptureFormats = packet.getAUInt16();
+ if (!mCaptureFormats) return false;
mPlaybackFormats = packet.getAUInt16();
+ if (!mCaptureFormats) return false;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mManufacturer = strdup((const char *)string);
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mModel = strdup((const char *)string);
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mVersion = strdup((const char *)string);
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mSerial = strdup((const char *)string);
+
+ return true;
}
void MtpDeviceInfo::print() {
ALOGV("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
mStandardVersion, mVendorExtensionID, mVendorExtensionVersion);
- ALOGV("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
- mVendorExtensionDesc, mFunctionalCode, mManufacturer, mModel, mVersion, mSerial);
+ ALOGV("\tmVendorExtensionDesc: %s\n\tmFunctionalMode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
+ mVendorExtensionDesc, mFunctionalMode, mManufacturer, mModel, mVersion, mSerial);
}
} // namespace android
diff --git a/media/mtp/MtpDeviceInfo.h b/media/mtp/MtpDeviceInfo.h
index 2abaa10..bcda9a5 100644
--- a/media/mtp/MtpDeviceInfo.h
+++ b/media/mtp/MtpDeviceInfo.h
@@ -29,7 +29,7 @@
uint32_t mVendorExtensionID;
uint16_t mVendorExtensionVersion;
char* mVendorExtensionDesc;
- uint16_t mFunctionalCode;
+ uint16_t mFunctionalMode;
UInt16List* mOperations;
UInt16List* mEvents;
MtpDevicePropertyList* mDeviceProperties;
@@ -44,7 +44,7 @@
MtpDeviceInfo();
virtual ~MtpDeviceInfo();
- void read(MtpDataPacket& packet);
+ bool read(MtpDataPacket& packet);
void print();
};
diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp
index cd15343..0573104 100644
--- a/media/mtp/MtpObjectInfo.cpp
+++ b/media/mtp/MtpObjectInfo.cpp
@@ -55,39 +55,41 @@
free(mKeywords);
}
-void MtpObjectInfo::read(MtpDataPacket& packet) {
+bool MtpObjectInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
time_t time;
- mStorageID = packet.getUInt32();
- mFormat = packet.getUInt16();
- mProtectionStatus = packet.getUInt16();
- mCompressedSize = packet.getUInt32();
- mThumbFormat = packet.getUInt16();
- mThumbCompressedSize = packet.getUInt32();
- mThumbPixWidth = packet.getUInt32();
- mThumbPixHeight = packet.getUInt32();
- mImagePixWidth = packet.getUInt32();
- mImagePixHeight = packet.getUInt32();
- mImagePixDepth = packet.getUInt32();
- mParent = packet.getUInt32();
- mAssociationType = packet.getUInt16();
- mAssociationDesc = packet.getUInt32();
- mSequenceNumber = packet.getUInt32();
+ if (!packet.getUInt32(mStorageID)) return false;
+ if (!packet.getUInt16(mFormat)) return false;
+ if (!packet.getUInt16(mProtectionStatus)) return false;
+ if (!packet.getUInt32(mCompressedSize)) return false;
+ if (!packet.getUInt16(mThumbFormat)) return false;
+ if (!packet.getUInt32(mThumbCompressedSize)) return false;
+ if (!packet.getUInt32(mThumbPixWidth)) return false;
+ if (!packet.getUInt32(mThumbPixHeight)) return false;
+ if (!packet.getUInt32(mImagePixWidth)) return false;
+ if (!packet.getUInt32(mImagePixHeight)) return false;
+ if (!packet.getUInt32(mImagePixDepth)) return false;
+ if (!packet.getUInt32(mParent)) return false;
+ if (!packet.getUInt16(mAssociationType)) return false;
+ if (!packet.getUInt32(mAssociationDesc)) return false;
+ if (!packet.getUInt32(mSequenceNumber)) return false;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mName = strdup((const char *)string);
- packet.getString(string);
+ if (!packet.getString(string)) return false;
if (parseDateTime((const char*)string, time))
mDateCreated = time;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
if (parseDateTime((const char*)string, time))
mDateModified = time;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mKeywords = strdup((const char *)string);
+
+ return true;
}
void MtpObjectInfo::print() {
diff --git a/media/mtp/MtpObjectInfo.h b/media/mtp/MtpObjectInfo.h
index c7a449c..86780f1 100644
--- a/media/mtp/MtpObjectInfo.h
+++ b/media/mtp/MtpObjectInfo.h
@@ -50,7 +50,7 @@
MtpObjectInfo(MtpObjectHandle handle);
virtual ~MtpObjectInfo();
- void read(MtpDataPacket& packet);
+ bool read(MtpDataPacket& packet);
void print();
};
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index dd07843..bab1335 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -52,7 +52,7 @@
memset(mBuffer, 0, mBufferSize);
}
-void MtpPacket::allocate(int length) {
+void MtpPacket::allocate(size_t length) {
if (length > mBufferSize) {
int newLength = length + mAllocationIncrement;
mBuffer = (uint8_t *)realloc(mBuffer, newLength);
diff --git a/media/mtp/MtpPacket.h b/media/mtp/MtpPacket.h
index 0ffb1d3..037722a 100644
--- a/media/mtp/MtpPacket.h
+++ b/media/mtp/MtpPacket.h
@@ -28,11 +28,11 @@
protected:
uint8_t* mBuffer;
// current size of the buffer
- int mBufferSize;
+ size_t mBufferSize;
// number of bytes to add when resizing the buffer
- int mAllocationIncrement;
+ size_t mAllocationIncrement;
// size of the data in the packet
- int mPacketSize;
+ size_t mPacketSize;
public:
MtpPacket(int bufferSize);
@@ -41,7 +41,7 @@
// sets packet size to the default container size and sets buffer to zero
virtual void reset();
- void allocate(int length);
+ void allocate(size_t length);
void dump();
void copyFrom(const MtpPacket& src);
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index c500901..d58e2a4 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -106,15 +106,15 @@
free(mMinimumValue.str);
free(mMaximumValue.str);
if (mDefaultArrayValues) {
- for (int i = 0; i < mDefaultArrayLength; i++)
+ for (uint32_t i = 0; i < mDefaultArrayLength; i++)
free(mDefaultArrayValues[i].str);
}
if (mCurrentArrayValues) {
- for (int i = 0; i < mCurrentArrayLength; i++)
+ for (uint32_t i = 0; i < mCurrentArrayLength; i++)
free(mCurrentArrayValues[i].str);
}
if (mEnumValues) {
- for (int i = 0; i < mEnumLength; i++)
+ for (uint16_t i = 0; i < mEnumLength; i++)
free(mEnumValues[i].str);
}
}
@@ -123,11 +123,14 @@
delete[] mEnumValues;
}
-void MtpProperty::read(MtpDataPacket& packet) {
- mCode = packet.getUInt16();
+bool MtpProperty::read(MtpDataPacket& packet) {
+ uint8_t temp8;
+
+ if (!packet.getUInt16(mCode)) return false;
bool deviceProp = isDeviceProperty();
- mType = packet.getUInt16();
- mWriteable = (packet.getUInt8() == 1);
+ if (!packet.getUInt16(mType)) return false;
+ if (!packet.getUInt8(temp8)) return false;
+ mWriteable = (temp8 == 1);
switch (mType) {
case MTP_TYPE_AINT8:
case MTP_TYPE_AUINT8:
@@ -140,28 +143,36 @@
case MTP_TYPE_AINT128:
case MTP_TYPE_AUINT128:
mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
- if (deviceProp)
+ if (!mDefaultArrayValues) return false;
+ if (deviceProp) {
mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
+ if (!mCurrentArrayValues) return false;
+ }
break;
default:
- readValue(packet, mDefaultValue);
- if (deviceProp)
- readValue(packet, mCurrentValue);
+ if (!readValue(packet, mDefaultValue)) return false;
+ if (deviceProp) {
+ if (!readValue(packet, mCurrentValue)) return false;
+ }
}
- if (!deviceProp)
- mGroupCode = packet.getUInt32();
- mFormFlag = packet.getUInt8();
+ if (!deviceProp) {
+ if (!packet.getUInt32(mGroupCode)) return false;
+ }
+ if (!packet.getUInt8(mFormFlag)) return false;
if (mFormFlag == kFormRange) {
- readValue(packet, mMinimumValue);
- readValue(packet, mMaximumValue);
- readValue(packet, mStepSize);
+ if (!readValue(packet, mMinimumValue)) return false;
+ if (!readValue(packet, mMaximumValue)) return false;
+ if (!readValue(packet, mStepSize)) return false;
} else if (mFormFlag == kFormEnum) {
- mEnumLength = packet.getUInt16();
+ if (!packet.getUInt16(mEnumLength)) return false;
mEnumValues = new MtpPropertyValue[mEnumLength];
- for (int i = 0; i < mEnumLength; i++)
- readValue(packet, mEnumValues[i]);
+ for (int i = 0; i < mEnumLength; i++) {
+ if (!readValue(packet, mEnumValues[i])) return false;
+ }
}
+
+ return true;
}
void MtpProperty::write(MtpDataPacket& packet) {
@@ -409,57 +420,59 @@
}
}
-void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
+bool MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
MtpStringBuffer stringBuffer;
switch (mType) {
case MTP_TYPE_INT8:
case MTP_TYPE_AINT8:
- value.u.i8 = packet.getInt8();
+ if (!packet.getInt8(value.u.i8)) return false;
break;
case MTP_TYPE_UINT8:
case MTP_TYPE_AUINT8:
- value.u.u8 = packet.getUInt8();
+ if (!packet.getUInt8(value.u.u8)) return false;
break;
case MTP_TYPE_INT16:
case MTP_TYPE_AINT16:
- value.u.i16 = packet.getInt16();
+ if (!packet.getInt16(value.u.i16)) return false;
break;
case MTP_TYPE_UINT16:
case MTP_TYPE_AUINT16:
- value.u.u16 = packet.getUInt16();
+ if (!packet.getUInt16(value.u.u16)) return false;
break;
case MTP_TYPE_INT32:
case MTP_TYPE_AINT32:
- value.u.i32 = packet.getInt32();
+ if (!packet.getInt32(value.u.i32)) return false;
break;
case MTP_TYPE_UINT32:
case MTP_TYPE_AUINT32:
- value.u.u32 = packet.getUInt32();
+ if (!packet.getUInt32(value.u.u32)) return false;
break;
case MTP_TYPE_INT64:
case MTP_TYPE_AINT64:
- value.u.i64 = packet.getInt64();
+ if (!packet.getInt64(value.u.i64)) return false;
break;
case MTP_TYPE_UINT64:
case MTP_TYPE_AUINT64:
- value.u.u64 = packet.getUInt64();
+ if (!packet.getUInt64(value.u.u64)) return false;
break;
case MTP_TYPE_INT128:
case MTP_TYPE_AINT128:
- packet.getInt128(value.u.i128);
+ if (!packet.getInt128(value.u.i128)) return false;
break;
case MTP_TYPE_UINT128:
case MTP_TYPE_AUINT128:
- packet.getUInt128(value.u.u128);
+ if (!packet.getUInt128(value.u.u128)) return false;
break;
case MTP_TYPE_STR:
- packet.getString(stringBuffer);
+ if (!packet.getString(stringBuffer)) return false;
value.str = strdup(stringBuffer);
break;
default:
ALOGE("unknown type %04X in MtpProperty::readValue", mType);
+ return false;
}
+ return true;
}
void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
@@ -517,8 +530,9 @@
}
}
-MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
- length = packet.getUInt32();
+MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, uint32_t& length) {
+ if (!packet.getUInt32(length)) return NULL;
+
// Fail if resulting array is over 2GB. This is because the maximum array
// size may be less than SIZE_MAX on some platforms.
if ( CC_UNLIKELY(
@@ -528,14 +542,17 @@
return NULL;
}
MtpPropertyValue* result = new MtpPropertyValue[length];
- for (int i = 0; i < length; i++)
- readValue(packet, result[i]);
+ for (uint32_t i = 0; i < length; i++)
+ if (!readValue(packet, result[i])) {
+ delete result;
+ return NULL;
+ }
return result;
}
-void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
+void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, uint32_t length) {
packet.putUInt32(length);
- for (int i = 0; i < length; i++)
+ for (uint32_t i = 0; i < length; i++)
writeValue(packet, values[i]);
}
diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h
index 06ca56e..2e2ead1 100644
--- a/media/mtp/MtpProperty.h
+++ b/media/mtp/MtpProperty.h
@@ -49,9 +49,9 @@
MtpPropertyValue mCurrentValue;
// for array types
- int mDefaultArrayLength;
+ uint32_t mDefaultArrayLength;
MtpPropertyValue* mDefaultArrayValues;
- int mCurrentArrayLength;
+ uint32_t mCurrentArrayLength;
MtpPropertyValue* mCurrentArrayValues;
enum {
@@ -70,7 +70,7 @@
MtpPropertyValue mStepSize;
// for enum form
- int mEnumLength;
+ uint16_t mEnumLength;
MtpPropertyValue* mEnumValues;
public:
@@ -83,7 +83,7 @@
inline MtpPropertyCode getPropertyCode() const { return mCode; }
- void read(MtpDataPacket& packet);
+ bool read(MtpDataPacket& packet);
void write(MtpDataPacket& packet);
void setDefaultValue(const uint16_t* string);
@@ -102,11 +102,11 @@
}
private:
- void readValue(MtpDataPacket& packet, MtpPropertyValue& value);
+ bool readValue(MtpDataPacket& packet, MtpPropertyValue& value);
void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
- MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);
+ MtpPropertyValue* readArrayValues(MtpDataPacket& packet, uint32_t& length);
void writeArrayValues(MtpDataPacket& packet,
- MtpPropertyValue* values, int length);
+ MtpPropertyValue* values, uint32_t length);
};
}; // namespace android
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 0e58e01..40b11b0 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -27,7 +27,8 @@
namespace android {
MtpRequestPacket::MtpRequestPacket()
- : MtpPacket(512)
+ : MtpPacket(512),
+ mParameterCount(0)
{
}
@@ -37,10 +38,21 @@
#ifdef MTP_DEVICE
int MtpRequestPacket::read(int fd) {
int ret = ::read(fd, mBuffer, mBufferSize);
- if (ret >= 0)
+ if (ret < 0) {
+ // file read error
+ return ret;
+ }
+
+ // request packet should have 12 byte header followed by 0 to 5 32-bit arguments
+ if (ret >= MTP_CONTAINER_HEADER_SIZE
+ && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
+ && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
mPacketSize = ret;
- else
- mPacketSize = 0;
+ mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
+ } else {
+ ALOGE("Malformed MTP request packet");
+ ret = -1;
+ }
return ret;
}
#endif
diff --git a/media/mtp/MtpRequestPacket.h b/media/mtp/MtpRequestPacket.h
index 1201f11..79b798d 100644
--- a/media/mtp/MtpRequestPacket.h
+++ b/media/mtp/MtpRequestPacket.h
@@ -43,6 +43,10 @@
inline MtpOperationCode getOperationCode() const { return getContainerCode(); }
inline void setOperationCode(MtpOperationCode code)
{ return setContainerCode(code); }
+ inline int getParameterCount() const { return mParameterCount; }
+
+private:
+ int mParameterCount;
};
}; // namespace android
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index aa43967..931a09d 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -495,6 +495,9 @@
mResponse.setParameter(1, mSessionID);
return MTP_RESPONSE_SESSION_ALREADY_OPEN;
}
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
+
mSessionID = mRequest.getParameter(1);
mSessionOpen = true;
@@ -529,6 +532,9 @@
if (!mSessionOpen)
return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
+
MtpStorageID id = mRequest.getParameter(1);
MtpStorage* storage = getStorage(id);
if (!storage)
@@ -550,6 +556,8 @@
MtpResponseCode MtpServer::doGetObjectPropsSupported() {
if (!mSessionOpen)
return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectFormat format = mRequest.getParameter(1);
MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
mData.putAUInt16(properties);
@@ -560,6 +568,8 @@
MtpResponseCode MtpServer::doGetObjectHandles() {
if (!mSessionOpen)
return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (mRequest.getParameterCount() < 3)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
@@ -577,6 +587,8 @@
MtpResponseCode MtpServer::doGetNumObjects() {
if (!mSessionOpen)
return MTP_RESPONSE_SESSION_NOT_OPEN;
+ if (mRequest.getParameterCount() < 3)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
@@ -599,6 +611,8 @@
return MTP_RESPONSE_SESSION_NOT_OPEN;
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
// FIXME - check for invalid object handle
@@ -617,9 +631,13 @@
return MTP_RESPONSE_SESSION_NOT_OPEN;
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID handle = mRequest.getParameter(1);
MtpObjectHandleList* references = mData.getAUInt32();
+ if (!references)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
delete references;
return result;
@@ -628,6 +646,8 @@
MtpResponseCode MtpServer::doGetObjectPropValue() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 2)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
MtpObjectProperty property = mRequest.getParameter(2);
ALOGV("GetObjectPropValue %d %s\n", handle,
@@ -639,6 +659,8 @@
MtpResponseCode MtpServer::doSetObjectPropValue() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 2)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
MtpObjectProperty property = mRequest.getParameter(2);
ALOGV("SetObjectPropValue %d %s\n", handle,
@@ -648,6 +670,8 @@
}
MtpResponseCode MtpServer::doGetDevicePropValue() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpDeviceProperty property = mRequest.getParameter(1);
ALOGV("GetDevicePropValue %s\n",
MtpDebug::getDevicePropCodeName(property));
@@ -656,6 +680,8 @@
}
MtpResponseCode MtpServer::doSetDevicePropValue() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpDeviceProperty property = mRequest.getParameter(1);
ALOGV("SetDevicePropValue %s\n",
MtpDebug::getDevicePropCodeName(property));
@@ -664,6 +690,8 @@
}
MtpResponseCode MtpServer::doResetDevicePropValue() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpDeviceProperty property = mRequest.getParameter(1);
ALOGV("ResetDevicePropValue %s\n",
MtpDebug::getDevicePropCodeName(property));
@@ -674,6 +702,8 @@
MtpResponseCode MtpServer::doGetObjectPropList() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 5)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
// use uint32_t so we can support 0xFFFFFFFF
@@ -691,6 +721,8 @@
MtpResponseCode MtpServer::doGetObjectInfo() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
MtpObjectInfo info(handle);
MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
@@ -732,6 +764,8 @@
MtpResponseCode MtpServer::doGetObject() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
MtpString pathBuf;
int64_t fileLength;
@@ -765,6 +799,8 @@
}
MtpResponseCode MtpServer::doGetThumb() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
size_t thumbSize;
void* thumb = mDatabase->getThumbnail(handle, thumbSize);
@@ -783,6 +819,8 @@
MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 4)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
uint64_t offset;
uint32_t length;
@@ -832,6 +870,11 @@
MtpResponseCode MtpServer::doSendObjectInfo() {
MtpString path;
+ uint16_t temp16;
+ uint32_t temp32;
+
+ if (mRequest.getParameterCount() < 2)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpStorageID storageID = mRequest.getParameter(1);
MtpStorage* storage = getStorage(storageID);
MtpObjectHandle parent = mRequest.getParameter(2);
@@ -853,25 +896,29 @@
}
// read only the fields we need
- mData.getUInt32(); // storage ID
- MtpObjectFormat format = mData.getUInt16();
- mData.getUInt16(); // protection status
- mSendObjectFileSize = mData.getUInt32();
- mData.getUInt16(); // thumb format
- mData.getUInt32(); // thumb compressed size
- mData.getUInt32(); // thumb pix width
- mData.getUInt32(); // thumb pix height
- mData.getUInt32(); // image pix width
- mData.getUInt32(); // image pix height
- mData.getUInt32(); // image bit depth
- mData.getUInt32(); // parent
- uint16_t associationType = mData.getUInt16();
- uint32_t associationDesc = mData.getUInt32(); // association desc
- mData.getUInt32(); // sequence number
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // storage ID
+ if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
+ MtpObjectFormat format = temp16;
+ if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // protection status
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
+ mSendObjectFileSize = temp32;
+ if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb format
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb compressed size
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix width
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix height
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix width
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix height
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image bit depth
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // parent
+ if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
+ uint16_t associationType = temp16;
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
+ uint32_t associationDesc = temp32; // association desc
+ if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // sequence number
MtpStringBuffer name, created, modified;
- mData.getString(name); // file name
- mData.getString(created); // date created
- mData.getString(modified); // date modified
+ if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER; // file name
+ if (!mData.getString(created)) return MTP_RESPONSE_INVALID_PARAMETER; // date created
+ if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER; // date modified
// keywords follow
ALOGV("name: %s format: %04X\n", (const char *)name, format);
@@ -1066,6 +1113,8 @@
MtpResponseCode MtpServer::doDeleteObject() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 2)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
MtpObjectFormat format = mRequest.getParameter(2);
// FIXME - support deleting all objects if handle is 0xFFFFFFFF
@@ -1087,6 +1136,8 @@
}
MtpResponseCode MtpServer::doGetObjectPropDesc() {
+ if (mRequest.getParameterCount() < 2)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectProperty propCode = mRequest.getParameter(1);
MtpObjectFormat format = mRequest.getParameter(2);
ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
@@ -1100,6 +1151,8 @@
}
MtpResponseCode MtpServer::doGetDevicePropDesc() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpDeviceProperty propCode = mRequest.getParameter(1);
ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
@@ -1113,6 +1166,8 @@
MtpResponseCode MtpServer::doSendPartialObject() {
if (!hasStorage())
return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+ if (mRequest.getParameterCount() < 4)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
uint64_t offset = mRequest.getParameter(2);
uint64_t offset2 = mRequest.getParameter(3);
@@ -1180,6 +1235,8 @@
}
MtpResponseCode MtpServer::doTruncateObject() {
+ if (mRequest.getParameterCount() < 3)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
ObjectEdit* edit = getEditObject(handle);
if (!edit) {
@@ -1199,6 +1256,8 @@
}
MtpResponseCode MtpServer::doBeginEditObject() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
if (getEditObject(handle)) {
ALOGE("object already open for edit in doBeginEditObject");
@@ -1223,6 +1282,8 @@
}
MtpResponseCode MtpServer::doEndEditObject() {
+ if (mRequest.getParameterCount() < 1)
+ return MTP_RESPONSE_INVALID_PARAMETER;
MtpObjectHandle handle = mRequest.getParameter(1);
ObjectEdit* edit = getEditObject(handle);
if (!edit) {
diff --git a/media/mtp/MtpStorageInfo.cpp b/media/mtp/MtpStorageInfo.cpp
index 2b1a9ae..5d4ebbf 100644
--- a/media/mtp/MtpStorageInfo.cpp
+++ b/media/mtp/MtpStorageInfo.cpp
@@ -45,21 +45,23 @@
free(mVolumeIdentifier);
}
-void MtpStorageInfo::read(MtpDataPacket& packet) {
+bool MtpStorageInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
// read the device info
- mStorageType = packet.getUInt16();
- mFileSystemType = packet.getUInt16();
- mAccessCapability = packet.getUInt16();
- mMaxCapacity = packet.getUInt64();
- mFreeSpaceBytes = packet.getUInt64();
- mFreeSpaceObjects = packet.getUInt32();
+ if (!packet.getUInt16(mStorageType)) return false;
+ if (!packet.getUInt16(mFileSystemType)) return false;
+ if (!packet.getUInt16(mAccessCapability)) return false;
+ if (!packet.getUInt64(mMaxCapacity)) return false;
+ if (!packet.getUInt64(mFreeSpaceBytes)) return false;
+ if (!packet.getUInt32(mFreeSpaceObjects)) return false;
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mStorageDescription = strdup((const char *)string);
- packet.getString(string);
+ if (!packet.getString(string)) return false;
mVolumeIdentifier = strdup((const char *)string);
+
+ return true;
}
void MtpStorageInfo::print() {
diff --git a/media/mtp/MtpStorageInfo.h b/media/mtp/MtpStorageInfo.h
index 2cb626e..35a8189 100644
--- a/media/mtp/MtpStorageInfo.h
+++ b/media/mtp/MtpStorageInfo.h
@@ -39,7 +39,7 @@
MtpStorageInfo(MtpStorageID id);
virtual ~MtpStorageInfo();
- void read(MtpDataPacket& packet);
+ bool read(MtpDataPacket& packet);
void print();
};
diff --git a/media/mtp/MtpStringBuffer.cpp b/media/mtp/MtpStringBuffer.cpp
index f3420a4..df04694 100644
--- a/media/mtp/MtpStringBuffer.cpp
+++ b/media/mtp/MtpStringBuffer.cpp
@@ -123,11 +123,17 @@
mByteCount = dest - mBuffer;
}
-void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
- int count = packet->getUInt8();
+bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
+ uint8_t count;
+ if (!packet->getUInt8(count))
+ return false;
+
uint8_t* dest = mBuffer;
for (int i = 0; i < count; i++) {
- uint16_t ch = packet->getUInt16();
+ uint16_t ch;
+
+ if (!packet->getUInt16(ch))
+ return false;
if (ch >= 0x0800) {
*dest++ = (uint8_t)(0xE0 | (ch >> 12));
*dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
@@ -142,6 +148,7 @@
*dest++ = 0;
mCharCount = count;
mByteCount = dest - mBuffer;
+ return true;
}
void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index e5150df..85d91e8 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -46,7 +46,7 @@
void set(const char* src);
void set(const uint16_t* src);
- void readFromPacket(MtpDataPacket* packet);
+ bool readFromPacket(MtpDataPacket* packet);
void writeToPacket(MtpDataPacket* packet) const;
inline int getCharCount() const { return mCharCount; }
diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp
index 8caadd6..d1158d6 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.cpp
+++ b/services/camera/libcameraservice/device2/Camera2Device.cpp
@@ -793,11 +793,6 @@
mStreamSlotCount = 0;
return OK;
}
- camera_metadata_t *buf2 = clone_camera_metadata(buf);
- if (!buf2) {
- ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
- return NO_MEMORY;
- }
if (mStreamSlotCount > 1) {
List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
@@ -806,9 +801,9 @@
}
if (mStreamSlotCount == 1) {
free_camera_metadata( *(mStreamSlot.begin()) );
- *(mStreamSlot.begin()) = buf2;
+ *(mStreamSlot.begin()) = buf;
} else {
- mStreamSlot.push_front(buf2);
+ mStreamSlot.push_front(buf);
mStreamSlotCount = 1;
}
return signalConsumerLocked();
@@ -827,12 +822,7 @@
mStreamSlotCount = 0;
for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
r != bufs.end(); r++) {
- camera_metadata_t *r2 = clone_camera_metadata(*r);
- if (!r2) {
- ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
- return NO_MEMORY;
- }
- mStreamSlot.push_back(r2);
+ mStreamSlot.push_back(*r);
mStreamSlotCount++;
}
return signalConsumerLocked();
diff --git a/services/camera/libcameraservice/device2/Camera2Device.h b/services/camera/libcameraservice/device2/Camera2Device.h
index 2a3f1d9..4def8ae 100644
--- a/services/camera/libcameraservice/device2/Camera2Device.h
+++ b/services/camera/libcameraservice/device2/Camera2Device.h
@@ -124,8 +124,8 @@
// Set repeating buffer(s); if the queue is empty on a dequeue call, the
// queue copies the contents of the stream slot into the queue, and then
- // dequeues the first new entry. The metadata buffers passed in are
- // copied.
+ // dequeues the first new entry. The methods take the ownership of the
+ // metadata buffers passed in.
status_t setStreamSlot(camera_metadata_t *buf);
status_t setStreamSlot(const List<camera_metadata_t*> &bufs);