Loading media/libmedia/MediaResource.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ MediaResource::MediaResource(Type type, const std::vector<uint8_t> &id, int64_t } //static MediaResource MediaResource::CodecResource(bool secure, bool video, int64_t instanceCount) { MediaResource MediaResource::CodecResource(bool secure, SubType subType, int64_t instanceCount) { return MediaResource( secure ? Type::kSecureCodec : Type::kNonSecureCodec, video ? SubType::kVideoCodec : SubType::kAudioCodec, subType, instanceCount); } Loading media/libmedia/include/media/MediaResource.h +2 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ public: MediaResource(Type type, SubType subType, int64_t value); MediaResource(Type type, const std::vector<uint8_t> &id, int64_t value); static MediaResource CodecResource(bool secure, bool video, int64_t instanceCount = 1); static MediaResource CodecResource(bool secure, MediaResourceSubType subType, int64_t instanceCount = 1); static MediaResource GraphicMemoryResource(int64_t value); static MediaResource CpuBoostResource(); static MediaResource VideoBatteryResource(); Loading media/libstagefright/MediaCodec.cpp +71 −42 Original line number Diff line number Diff line Loading @@ -102,6 +102,8 @@ static const char *kCodecMime = "android.media.mediacodec.mime"; /* e.g. audi static const char *kCodecMode = "android.media.mediacodec.mode"; /* audio, video */ static const char *kCodecModeVideo = "video"; /* values returned for kCodecMode */ static const char *kCodecModeAudio = "audio"; static const char *kCodecModeImage = "image"; static const char *kCodecModeUnknown = "unknown"; static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */ static const char *kCodecSecure = "android.media.mediacodec.secure"; /* 0, 1 */ static const char *kCodecWidth = "android.media.mediacodec.width"; /* 0..n */ Loading Loading @@ -656,6 +658,24 @@ void CodecCallback::onFirstTunnelFrameReady() { notify->post(); } static MediaResourceSubType toMediaResourceSubType(MediaCodec::Domain domain) { switch (domain) { case MediaCodec::DOMAIN_VIDEO: return MediaResourceSubType::kVideoCodec; case MediaCodec::DOMAIN_AUDIO: return MediaResourceSubType::kAudioCodec; case MediaCodec::DOMAIN_IMAGE: return MediaResourceSubType::kImageCodec; default: return MediaResourceSubType::kUnspecifiedSubType; } } static const char * toCodecMode(MediaCodec::Domain domain) { switch (domain) { case MediaCodec::DOMAIN_VIDEO: return kCodecModeVideo; case MediaCodec::DOMAIN_AUDIO: return kCodecModeAudio; case MediaCodec::DOMAIN_IMAGE: return kCodecModeImage; default: return kCodecModeUnknown; } } } // namespace //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -751,9 +771,9 @@ MediaCodec::MediaCodec( mFlags(0), mStickyError(OK), mSoftRenderer(NULL), mIsVideo(false), mVideoWidth(0), mVideoHeight(0), mDomain(DOMAIN_UNKNOWN), mWidth(0), mHeight(0), mRotationDegrees(0), mHDRMetadataFlags(0), mDequeueInputTimeoutGeneration(0), Loading Loading @@ -1165,7 +1185,7 @@ void MediaCodec::statsBufferSent(int64_t presentationUs, const sp<MediaCodecBuff }); } if (mIsVideo && (mFlags & kFlagIsEncoder)) { if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) { mBytesInput += buffer->size(); mFramesInput++; } Loading Loading @@ -1194,7 +1214,7 @@ void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodec CHECK_NE(mState, UNINITIALIZED); if (mIsVideo && (mFlags & kFlagIsEncoder)) { if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) { int32_t flags = 0; (void) buffer->meta()->findInt32("flags", &flags); Loading Loading @@ -1402,7 +1422,13 @@ status_t MediaCodec::init(const AString &name) { mCodecInfo->getSupportedMediaTypes(&mediaTypes); for (size_t i = 0; i < mediaTypes.size(); ++i) { if (mediaTypes[i].startsWith("video/")) { mIsVideo = true; mDomain = DOMAIN_VIDEO; break; } else if (mediaTypes[i].startsWith("audio/")) { mDomain = DOMAIN_AUDIO; break; } else if (mediaTypes[i].startsWith("image/")) { mDomain = DOMAIN_IMAGE; break; } } Loading @@ -1415,7 +1441,7 @@ status_t MediaCodec::init(const AString &name) { return NAME_NOT_FOUND; } if (mIsVideo) { if (mDomain == DOMAIN_VIDEO) { // video codec needs dedicated looper if (mCodecLooper == NULL) { mCodecLooper = new ALooper; Loading Loading @@ -1448,17 +1474,16 @@ status_t MediaCodec::init(const AString &name) { if (mMetricsHandle != 0) { mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str()); mediametrics_setCString(mMetricsHandle, kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio); mediametrics_setCString(mMetricsHandle, kCodecMode, toCodecMode(mDomain)); } if (mIsVideo) { if (mDomain == DOMAIN_VIDEO) { mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this)); } status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo)); resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain))); for (int i = 0; i <= kMaxRetry; ++i) { if (i > 0) { // Don't try to reclaim resource for the first time. Loading Loading @@ -1539,16 +1564,16 @@ status_t MediaCodec::configure( mediametrics_setCString(mMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str()); } if (mIsVideo) { format->findInt32("width", &mVideoWidth); format->findInt32("height", &mVideoHeight); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { format->findInt32("width", &mWidth); format->findInt32("height", &mHeight); if (!format->findInt32("rotation-degrees", &mRotationDegrees)) { mRotationDegrees = 0; } if (mMetricsHandle != 0) { mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth); mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight); mediametrics_setInt32(mMetricsHandle, kCodecWidth, mWidth); mediametrics_setInt32(mMetricsHandle, kCodecHeight, mHeight); mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees); int32_t maxWidth = 0; if (format->findInt32("max-width", &maxWidth)) { Loading @@ -1562,6 +1587,7 @@ status_t MediaCodec::configure( if (format->findInt32("color-format", &colorFormat)) { mediametrics_setInt32(mMetricsHandle, kCodecColorFormat, colorFormat); } if (mDomain == DOMAIN_VIDEO) { float frameRate = -1.0; if (format->findFloat("frame-rate", &frameRate)) { mediametrics_setDouble(mMetricsHandle, kCodecFrameRate, frameRate); Loading @@ -1578,6 +1604,7 @@ status_t MediaCodec::configure( if (format->findInt32("priority", &priority)) { mediametrics_setInt32(mMetricsHandle, kCodecPriority, priority); } } int32_t colorStandard = -1; if (format->findInt32(KEY_COLOR_STANDARD, &colorStandard)) { mediametrics_setInt32(mMetricsHandle, kCodecConfigColorStandard, colorStandard); Loading @@ -1598,9 +1625,9 @@ status_t MediaCodec::configure( } // Prevent possible integer overflow in downstream code. if (mVideoWidth < 0 || mVideoHeight < 0 || (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) { ALOGE("Invalid size(s), width=%d, height=%d", mVideoWidth, mVideoHeight); if (mWidth < 0 || mHeight < 0 || (uint64_t)mWidth * mHeight > (uint64_t)INT32_MAX / 4) { ALOGE("Invalid size(s), width=%d, height=%d", mWidth, mHeight); return BAD_VALUE; } Loading Loading @@ -1633,7 +1660,7 @@ status_t MediaCodec::configure( } // push min/max QP to MediaMetrics after shaping if (mIsVideo && mMetricsHandle != 0) { if (mDomain == DOMAIN_VIDEO && mMetricsHandle != 0) { int32_t qpIMin = -1; if (format->findInt32("video-qp-i-min", &qpIMin)) { mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin); Loading Loading @@ -1686,7 +1713,8 @@ status_t MediaCodec::configure( status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); Loading Loading @@ -2267,7 +2295,7 @@ status_t MediaCodec::createInputSurface( } uint64_t MediaCodec::getGraphicBufferSize() { if (!mIsVideo) { if (mDomain != DOMAIN_VIDEO && mDomain != DOMAIN_IMAGE) { return 0; } Loading @@ -2275,7 +2303,7 @@ uint64_t MediaCodec::getGraphicBufferSize() { size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]); for (size_t i = 0; i < portNum; ++i) { // TODO: this is just an estimation, we should get the real buffer size from ACodec. size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2; size += mPortBuffers[i].size() * mWidth * mHeight * 3 / 2; } return size; } Loading @@ -2287,7 +2315,8 @@ status_t MediaCodec::start() { status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); Loading Loading @@ -3219,8 +3248,8 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { : MediaCodecInfo::Attributes(0); if (!(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) { // software codec is currently ignored. mResourceManagerProxy->addResource( MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); mResourceManagerProxy->addResource(MediaResource::CodecResource( mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); } postPendingRepliesAndDeferredMessages("kWhatComponentAllocated"); Loading Loading @@ -3386,7 +3415,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } CHECK_EQ(mState, STARTING); if (mIsVideo) { if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { mResourceManagerProxy->addResource( MediaResource::GraphicMemoryResource(getGraphicBufferSize())); } Loading media/libstagefright/include/media/stagefright/MediaCodec.h +10 −3 Original line number Diff line number Diff line Loading @@ -70,6 +70,13 @@ using hardware::cas::native::V1_0::IDescrambler; using aidl::android::media::MediaResourceParcel; struct MediaCodec : public AHandler { enum Domain { DOMAIN_UNKNOWN = 0, DOMAIN_VIDEO = 1, DOMAIN_AUDIO = 2, DOMAIN_IMAGE = 3 }; enum ConfigureFlags { CONFIGURE_FLAG_ENCODE = 1, CONFIGURE_FLAG_USE_BLOCK_MODEL = 2, Loading Loading @@ -438,10 +445,10 @@ private: sp<ResourceManagerServiceProxy> mResourceManagerProxy; bool mIsVideo; Domain mDomain; AString mLogSessionId; int32_t mVideoWidth; int32_t mVideoHeight; int32_t mWidth; int32_t mHeight; int32_t mRotationDegrees; int32_t mAllowFrameDroppingBySurface; Loading services/mediaresourcemanager/test/ResourceObserverService_test.cpp +48 −28 Original line number Diff line number Diff line Loading @@ -116,6 +116,26 @@ private: const EventTracker::Event EventTracker::NoEvent; static MediaResource createSecureVideoCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, amount); } static MediaResource createNonSecureVideoCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kNonSecureCodec, MediaResource::SubType::kVideoCodec, amount); } static MediaResource createSecureAudioCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kAudioCodec, amount); } static MediaResource createNonSecureAudioCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kNonSecureCodec, MediaResource::SubType::kAudioCodec, amount); } // Operators for GTest macros. bool operator==(const EventTracker::Event& lhs, const EventTracker::Event& rhs) { return lhs.type == rhs.type && lhs.uid == rhs.uid && lhs.pid == rhs.pid && Loading Loading @@ -233,30 +253,30 @@ TEST_F(ResourceObserverServiceTest, testAddResourceBasic) { std::vector<MediaResourceParcel> resources; // Add secure video codec. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource()}; mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); // Add non-secure video codec. resources = {MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); // Add secure & non-secure video codecs. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Add additional audio codecs, should be ignored. resources.push_back(MediaResource::CodecResource(1 /*secure*/, 0 /*video*/)); resources.push_back(MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)); resources.push_back(createSecureAudioCodecResource()); resources.push_back(createNonSecureAudioCodecResource()); mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables2)); Loading @@ -276,9 +296,9 @@ TEST_F(ResourceObserverServiceTest, testAddResourceMultiple) { // Add multiple secure & non-secure video codecs. // Multiple entries of the same type should be merged, count should be propagated correctly. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 3 /*count*/)}; resources = {createSecureVideoCodecResource(), createSecureVideoCodecResource(), createNonSecureVideoCodecResource(3)}; observables1 = {{MediaObservableType::kVideoSecureCodec, 2}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 3}}; observables3 = {{MediaObservableType::kVideoSecureCodec, 2}, Loading @@ -300,7 +320,7 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { std::vector<MediaResourceParcel> resources; // Add secure video codec to client1. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource()}; mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading @@ -322,7 +342,7 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Add non-secure video codec to client2. resources = {MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); Loading @@ -344,24 +364,24 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Add secure & non-secure video codecs, plus audio codecs (that's ignored). resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 0 /*video*/), MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource(), createSecureAudioCodecResource(), createNonSecureAudioCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Remove one audio codec, should have no event. resources = {MediaResource::CodecResource(1 /*secure*/, 0 /*video*/)}; resources = {createSecureAudioCodecResource()}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Remove the other audio codec and the secure video codec, only secure video codec // removal should be reported. resources = {MediaResource::CodecResource(0 /*secure*/, 0 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createNonSecureAudioCodecResource(), createSecureVideoCodecResource()}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading @@ -386,10 +406,10 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceMultiple) { // Add multiple secure & non-secure video codecs, plus audio codecs (that's ignored). // (ResourceManager will merge these internally.) resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 4 /*count*/), MediaResource::CodecResource(1 /*secure*/, 0 /*video*/), MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource(4), createSecureAudioCodecResource(), createNonSecureAudioCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); observables1 = {{MediaObservableType::kVideoSecureCodec, 1}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 4}}; Loading @@ -400,10 +420,10 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceMultiple) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Remove one audio codec, 2 secure video codecs and 2 non-secure video codecs. // 1 secure video codec removal and 2 non-secure video codec removals should be reported. resources = {MediaResource::CodecResource(0 /*secure*/, 0 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 2 /*count*/)}; resources = {createNonSecureAudioCodecResource(), createSecureVideoCodecResource(), createSecureVideoCodecResource(), createNonSecureVideoCodecResource(2)}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); observables1 = {{MediaObservableType::kVideoSecureCodec, 1}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 2}}; Loading Loading @@ -443,8 +463,8 @@ TEST_F(ResourceObserverServiceTest, testEventFilters) { std::vector<MediaResourceParcel> resources; // Add secure & non-secure video codecs. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading Loading
media/libmedia/MediaResource.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -43,10 +43,10 @@ MediaResource::MediaResource(Type type, const std::vector<uint8_t> &id, int64_t } //static MediaResource MediaResource::CodecResource(bool secure, bool video, int64_t instanceCount) { MediaResource MediaResource::CodecResource(bool secure, SubType subType, int64_t instanceCount) { return MediaResource( secure ? Type::kSecureCodec : Type::kNonSecureCodec, video ? SubType::kVideoCodec : SubType::kAudioCodec, subType, instanceCount); } Loading
media/libmedia/include/media/MediaResource.h +2 −1 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ public: MediaResource(Type type, SubType subType, int64_t value); MediaResource(Type type, const std::vector<uint8_t> &id, int64_t value); static MediaResource CodecResource(bool secure, bool video, int64_t instanceCount = 1); static MediaResource CodecResource(bool secure, MediaResourceSubType subType, int64_t instanceCount = 1); static MediaResource GraphicMemoryResource(int64_t value); static MediaResource CpuBoostResource(); static MediaResource VideoBatteryResource(); Loading
media/libstagefright/MediaCodec.cpp +71 −42 Original line number Diff line number Diff line Loading @@ -102,6 +102,8 @@ static const char *kCodecMime = "android.media.mediacodec.mime"; /* e.g. audi static const char *kCodecMode = "android.media.mediacodec.mode"; /* audio, video */ static const char *kCodecModeVideo = "video"; /* values returned for kCodecMode */ static const char *kCodecModeAudio = "audio"; static const char *kCodecModeImage = "image"; static const char *kCodecModeUnknown = "unknown"; static const char *kCodecEncoder = "android.media.mediacodec.encoder"; /* 0,1 */ static const char *kCodecSecure = "android.media.mediacodec.secure"; /* 0, 1 */ static const char *kCodecWidth = "android.media.mediacodec.width"; /* 0..n */ Loading Loading @@ -656,6 +658,24 @@ void CodecCallback::onFirstTunnelFrameReady() { notify->post(); } static MediaResourceSubType toMediaResourceSubType(MediaCodec::Domain domain) { switch (domain) { case MediaCodec::DOMAIN_VIDEO: return MediaResourceSubType::kVideoCodec; case MediaCodec::DOMAIN_AUDIO: return MediaResourceSubType::kAudioCodec; case MediaCodec::DOMAIN_IMAGE: return MediaResourceSubType::kImageCodec; default: return MediaResourceSubType::kUnspecifiedSubType; } } static const char * toCodecMode(MediaCodec::Domain domain) { switch (domain) { case MediaCodec::DOMAIN_VIDEO: return kCodecModeVideo; case MediaCodec::DOMAIN_AUDIO: return kCodecModeAudio; case MediaCodec::DOMAIN_IMAGE: return kCodecModeImage; default: return kCodecModeUnknown; } } } // namespace //////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -751,9 +771,9 @@ MediaCodec::MediaCodec( mFlags(0), mStickyError(OK), mSoftRenderer(NULL), mIsVideo(false), mVideoWidth(0), mVideoHeight(0), mDomain(DOMAIN_UNKNOWN), mWidth(0), mHeight(0), mRotationDegrees(0), mHDRMetadataFlags(0), mDequeueInputTimeoutGeneration(0), Loading Loading @@ -1165,7 +1185,7 @@ void MediaCodec::statsBufferSent(int64_t presentationUs, const sp<MediaCodecBuff }); } if (mIsVideo && (mFlags & kFlagIsEncoder)) { if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) { mBytesInput += buffer->size(); mFramesInput++; } Loading Loading @@ -1194,7 +1214,7 @@ void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodec CHECK_NE(mState, UNINITIALIZED); if (mIsVideo && (mFlags & kFlagIsEncoder)) { if (mDomain == DOMAIN_VIDEO && (mFlags & kFlagIsEncoder)) { int32_t flags = 0; (void) buffer->meta()->findInt32("flags", &flags); Loading Loading @@ -1402,7 +1422,13 @@ status_t MediaCodec::init(const AString &name) { mCodecInfo->getSupportedMediaTypes(&mediaTypes); for (size_t i = 0; i < mediaTypes.size(); ++i) { if (mediaTypes[i].startsWith("video/")) { mIsVideo = true; mDomain = DOMAIN_VIDEO; break; } else if (mediaTypes[i].startsWith("audio/")) { mDomain = DOMAIN_AUDIO; break; } else if (mediaTypes[i].startsWith("image/")) { mDomain = DOMAIN_IMAGE; break; } } Loading @@ -1415,7 +1441,7 @@ status_t MediaCodec::init(const AString &name) { return NAME_NOT_FOUND; } if (mIsVideo) { if (mDomain == DOMAIN_VIDEO) { // video codec needs dedicated looper if (mCodecLooper == NULL) { mCodecLooper = new ALooper; Loading Loading @@ -1448,17 +1474,16 @@ status_t MediaCodec::init(const AString &name) { if (mMetricsHandle != 0) { mediametrics_setCString(mMetricsHandle, kCodecCodec, name.c_str()); mediametrics_setCString(mMetricsHandle, kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio); mediametrics_setCString(mMetricsHandle, kCodecMode, toCodecMode(mDomain)); } if (mIsVideo) { if (mDomain == DOMAIN_VIDEO) { mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this)); } status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo)); resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain))); for (int i = 0; i <= kMaxRetry; ++i) { if (i > 0) { // Don't try to reclaim resource for the first time. Loading Loading @@ -1539,16 +1564,16 @@ status_t MediaCodec::configure( mediametrics_setCString(mMetricsHandle, kCodecLogSessionId, mLogSessionId.c_str()); } if (mIsVideo) { format->findInt32("width", &mVideoWidth); format->findInt32("height", &mVideoHeight); if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { format->findInt32("width", &mWidth); format->findInt32("height", &mHeight); if (!format->findInt32("rotation-degrees", &mRotationDegrees)) { mRotationDegrees = 0; } if (mMetricsHandle != 0) { mediametrics_setInt32(mMetricsHandle, kCodecWidth, mVideoWidth); mediametrics_setInt32(mMetricsHandle, kCodecHeight, mVideoHeight); mediametrics_setInt32(mMetricsHandle, kCodecWidth, mWidth); mediametrics_setInt32(mMetricsHandle, kCodecHeight, mHeight); mediametrics_setInt32(mMetricsHandle, kCodecRotation, mRotationDegrees); int32_t maxWidth = 0; if (format->findInt32("max-width", &maxWidth)) { Loading @@ -1562,6 +1587,7 @@ status_t MediaCodec::configure( if (format->findInt32("color-format", &colorFormat)) { mediametrics_setInt32(mMetricsHandle, kCodecColorFormat, colorFormat); } if (mDomain == DOMAIN_VIDEO) { float frameRate = -1.0; if (format->findFloat("frame-rate", &frameRate)) { mediametrics_setDouble(mMetricsHandle, kCodecFrameRate, frameRate); Loading @@ -1578,6 +1604,7 @@ status_t MediaCodec::configure( if (format->findInt32("priority", &priority)) { mediametrics_setInt32(mMetricsHandle, kCodecPriority, priority); } } int32_t colorStandard = -1; if (format->findInt32(KEY_COLOR_STANDARD, &colorStandard)) { mediametrics_setInt32(mMetricsHandle, kCodecConfigColorStandard, colorStandard); Loading @@ -1598,9 +1625,9 @@ status_t MediaCodec::configure( } // Prevent possible integer overflow in downstream code. if (mVideoWidth < 0 || mVideoHeight < 0 || (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) { ALOGE("Invalid size(s), width=%d, height=%d", mVideoWidth, mVideoHeight); if (mWidth < 0 || mHeight < 0 || (uint64_t)mWidth * mHeight > (uint64_t)INT32_MAX / 4) { ALOGE("Invalid size(s), width=%d, height=%d", mWidth, mHeight); return BAD_VALUE; } Loading Loading @@ -1633,7 +1660,7 @@ status_t MediaCodec::configure( } // push min/max QP to MediaMetrics after shaping if (mIsVideo && mMetricsHandle != 0) { if (mDomain == DOMAIN_VIDEO && mMetricsHandle != 0) { int32_t qpIMin = -1; if (format->findInt32("video-qp-i-min", &qpIMin)) { mediametrics_setInt32(mMetricsHandle, kCodecRequestedVideoQPIMin, qpIMin); Loading Loading @@ -1686,7 +1713,8 @@ status_t MediaCodec::configure( status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); Loading Loading @@ -2267,7 +2295,7 @@ status_t MediaCodec::createInputSurface( } uint64_t MediaCodec::getGraphicBufferSize() { if (!mIsVideo) { if (mDomain != DOMAIN_VIDEO && mDomain != DOMAIN_IMAGE) { return 0; } Loading @@ -2275,7 +2303,7 @@ uint64_t MediaCodec::getGraphicBufferSize() { size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]); for (size_t i = 0; i < portNum; ++i) { // TODO: this is just an estimation, we should get the real buffer size from ACodec. size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2; size += mPortBuffers[i].size() * mWidth * mHeight * 3 / 2; } return size; } Loading @@ -2287,7 +2315,8 @@ status_t MediaCodec::start() { status_t err; std::vector<MediaResourceParcel> resources; resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); resources.push_back(MediaResource::CodecResource(mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); // Don't know the buffer size at this point, but it's fine to use 1 because // the reclaimResource call doesn't consider the requester's buffer size for now. resources.push_back(MediaResource::GraphicMemoryResource(1)); Loading Loading @@ -3219,8 +3248,8 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { : MediaCodecInfo::Attributes(0); if (!(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) { // software codec is currently ignored. mResourceManagerProxy->addResource( MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo)); mResourceManagerProxy->addResource(MediaResource::CodecResource( mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain))); } postPendingRepliesAndDeferredMessages("kWhatComponentAllocated"); Loading Loading @@ -3386,7 +3415,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { } CHECK_EQ(mState, STARTING); if (mIsVideo) { if (mDomain == DOMAIN_VIDEO || mDomain == DOMAIN_IMAGE) { mResourceManagerProxy->addResource( MediaResource::GraphicMemoryResource(getGraphicBufferSize())); } Loading
media/libstagefright/include/media/stagefright/MediaCodec.h +10 −3 Original line number Diff line number Diff line Loading @@ -70,6 +70,13 @@ using hardware::cas::native::V1_0::IDescrambler; using aidl::android::media::MediaResourceParcel; struct MediaCodec : public AHandler { enum Domain { DOMAIN_UNKNOWN = 0, DOMAIN_VIDEO = 1, DOMAIN_AUDIO = 2, DOMAIN_IMAGE = 3 }; enum ConfigureFlags { CONFIGURE_FLAG_ENCODE = 1, CONFIGURE_FLAG_USE_BLOCK_MODEL = 2, Loading Loading @@ -438,10 +445,10 @@ private: sp<ResourceManagerServiceProxy> mResourceManagerProxy; bool mIsVideo; Domain mDomain; AString mLogSessionId; int32_t mVideoWidth; int32_t mVideoHeight; int32_t mWidth; int32_t mHeight; int32_t mRotationDegrees; int32_t mAllowFrameDroppingBySurface; Loading
services/mediaresourcemanager/test/ResourceObserverService_test.cpp +48 −28 Original line number Diff line number Diff line Loading @@ -116,6 +116,26 @@ private: const EventTracker::Event EventTracker::NoEvent; static MediaResource createSecureVideoCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, amount); } static MediaResource createNonSecureVideoCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kNonSecureCodec, MediaResource::SubType::kVideoCodec, amount); } static MediaResource createSecureAudioCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kAudioCodec, amount); } static MediaResource createNonSecureAudioCodecResource(int amount = 1) { return MediaResource(MediaResource::Type::kNonSecureCodec, MediaResource::SubType::kAudioCodec, amount); } // Operators for GTest macros. bool operator==(const EventTracker::Event& lhs, const EventTracker::Event& rhs) { return lhs.type == rhs.type && lhs.uid == rhs.uid && lhs.pid == rhs.pid && Loading Loading @@ -233,30 +253,30 @@ TEST_F(ResourceObserverServiceTest, testAddResourceBasic) { std::vector<MediaResourceParcel> resources; // Add secure video codec. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource()}; mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); // Add non-secure video codec. resources = {MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); // Add secure & non-secure video codecs. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Add additional audio codecs, should be ignored. resources.push_back(MediaResource::CodecResource(1 /*secure*/, 0 /*video*/)); resources.push_back(MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)); resources.push_back(createSecureAudioCodecResource()); resources.push_back(createNonSecureAudioCodecResource()); mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables2)); Loading @@ -276,9 +296,9 @@ TEST_F(ResourceObserverServiceTest, testAddResourceMultiple) { // Add multiple secure & non-secure video codecs. // Multiple entries of the same type should be merged, count should be propagated correctly. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 3 /*count*/)}; resources = {createSecureVideoCodecResource(), createSecureVideoCodecResource(), createNonSecureVideoCodecResource(3)}; observables1 = {{MediaObservableType::kVideoSecureCodec, 2}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 3}}; observables3 = {{MediaObservableType::kVideoSecureCodec, 2}, Loading @@ -300,7 +320,7 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { std::vector<MediaResourceParcel> resources; // Add secure video codec to client1. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource()}; mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading @@ -322,7 +342,7 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Add non-secure video codec to client2. resources = {MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); Loading @@ -344,24 +364,24 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceBasic) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Add secure & non-secure video codecs, plus audio codecs (that's ignored). resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 0 /*video*/), MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource(), createSecureAudioCodecResource(), createNonSecureAudioCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2)); EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Remove one audio codec, should have no event. resources = {MediaResource::CodecResource(1 /*secure*/, 0 /*video*/)}; resources = {createSecureAudioCodecResource()}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent); // Remove the other audio codec and the secure video codec, only secure video codec // removal should be reported. resources = {MediaResource::CodecResource(0 /*secure*/, 0 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/)}; resources = {createNonSecureAudioCodecResource(), createSecureVideoCodecResource()}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading @@ -386,10 +406,10 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceMultiple) { // Add multiple secure & non-secure video codecs, plus audio codecs (that's ignored). // (ResourceManager will merge these internally.) resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 4 /*count*/), MediaResource::CodecResource(1 /*secure*/, 0 /*video*/), MediaResource::CodecResource(0 /*secure*/, 0 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource(4), createSecureAudioCodecResource(), createNonSecureAudioCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); observables1 = {{MediaObservableType::kVideoSecureCodec, 1}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 4}}; Loading @@ -400,10 +420,10 @@ TEST_F(ResourceObserverServiceTest, testRemoveResourceMultiple) { EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3)); // Remove one audio codec, 2 secure video codecs and 2 non-secure video codecs. // 1 secure video codec removal and 2 non-secure video codec removals should be reported. resources = {MediaResource::CodecResource(0 /*secure*/, 0 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/, 2 /*count*/)}; resources = {createNonSecureAudioCodecResource(), createSecureVideoCodecResource(), createSecureVideoCodecResource(), createNonSecureVideoCodecResource(2)}; mService->removeResource(kTestPid2, getId(mTestClient3), resources); observables1 = {{MediaObservableType::kVideoSecureCodec, 1}}; observables2 = {{MediaObservableType::kVideoNonSecureCodec, 2}}; Loading Loading @@ -443,8 +463,8 @@ TEST_F(ResourceObserverServiceTest, testEventFilters) { std::vector<MediaResourceParcel> resources; // Add secure & non-secure video codecs. resources = {MediaResource::CodecResource(1 /*secure*/, 1 /*video*/), MediaResource::CodecResource(0 /*secure*/, 1 /*video*/)}; resources = {createSecureVideoCodecResource(), createNonSecureVideoCodecResource()}; mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources); EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1)); EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent); Loading