diff options
-rw-r--r-- | include/media/stagefright/MediaCodecList.h | 2 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 30 | ||||
-rw-r--r-- | media/libstagefright/MediaCodecList.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/MediaCodecListOverrides.cpp | 76 | ||||
-rw-r--r-- | media/libstagefright/omx/OMXNodeInstance.cpp | 10 |
5 files changed, 107 insertions, 13 deletions
diff --git a/include/media/stagefright/MediaCodecList.h b/include/media/stagefright/MediaCodecList.h index ce34338..df5e519 100644 --- a/include/media/stagefright/MediaCodecList.h +++ b/include/media/stagefright/MediaCodecList.h @@ -32,6 +32,8 @@ namespace android { +extern const char *kMaxEncoderInputBuffers; + struct AMessage; struct MediaCodecList : public BnMediaCodecList { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 46c154d..6f22e26 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -26,6 +26,7 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/MemoryDealer.h> +#include <gui/BufferQueue.h> #include <gui/Surface.h> #include <media/ICrypto.h> #include <media/IOMX.h> @@ -320,6 +321,27 @@ sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() { CHECK_EQ(client.connect(), (status_t)OK); sp<IOMX> omx = client.interface(); + const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance(); + if (mediaCodecList == NULL) { + ALOGE("Failed to obtain MediaCodecList!"); + return NULL; // if called from Java should raise IOException + } + + AString tmp; + sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings(); + if (globalSettings == NULL || !globalSettings->findString( + kMaxEncoderInputBuffers, &tmp)) { + ALOGE("Failed to get encoder input buffer count!"); + return NULL; + } + + int32_t bufferCount = strtol(tmp.c_str(), NULL, 10); + if (bufferCount <= 0 + || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) { + ALOGE("Encoder input buffer count is invalid!"); + return NULL; + } + sp<IGraphicBufferProducer> bufferProducer; sp<IGraphicBufferConsumer> bufferConsumer; @@ -331,6 +353,14 @@ sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() { return NULL; } + err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount); + + if (err != NO_ERROR) { + ALOGE("Unable to set BQ max acquired buffer count to %u: %d", + bufferCount, err); + return NULL; + } + return new PersistentSurface(bufferProducer, bufferConsumer); } diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp index d2352bc..6708828 100644 --- a/media/libstagefright/MediaCodecList.cpp +++ b/media/libstagefright/MediaCodecList.cpp @@ -42,6 +42,8 @@ namespace android { +const char *kMaxEncoderInputBuffers = "max-video-encoder-input-buffers"; + static Mutex sInitMutex; static MediaCodecList *gCodecList = NULL; diff --git a/media/libstagefright/MediaCodecListOverrides.cpp b/media/libstagefright/MediaCodecListOverrides.cpp index 0d95676..006454d 100644 --- a/media/libstagefright/MediaCodecListOverrides.cpp +++ b/media/libstagefright/MediaCodecListOverrides.cpp @@ -25,8 +25,10 @@ #include <media/IMediaCodecList.h> #include <media/MediaCodecInfo.h> #include <media/MediaResourcePolicy.h> +#include <media/openmax/OMX_IVCommon.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaCodec.h> +#include <media/stagefright/MediaCodecList.h> namespace android { @@ -86,6 +88,7 @@ static sp<AMessage> getMeasureFormat( int32_t bitrate = 0; getMeasureBitrate(caps, &bitrate); format->setInt32("bitrate", bitrate); + format->setInt32("encoder", 1); } if (mime.startsWith("video/")) { @@ -114,15 +117,67 @@ static sp<AMessage> getMeasureFormat( return format; } +static size_t doProfileEncoderInputBuffers( + AString name, AString mime, sp<MediaCodecInfo::Capabilities> caps) { + ALOGV("doProfileEncoderInputBuffers: name %s, mime %s", name.c_str(), mime.c_str()); + + sp<AMessage> format = getMeasureFormat(true /* isEncoder */, mime, caps); + if (format == NULL) { + return 0; + } + + format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque); + ALOGV("doProfileEncoderInputBuffers: format %s", format->debugString().c_str()); + + status_t err = OK; + sp<ALooper> looper = new ALooper; + looper->setName("MediaCodec_looper"); + looper->start( + false /* runOnCallingThread */, false /* canCallJava */, ANDROID_PRIORITY_AUDIO); + + sp<MediaCodec> codec = MediaCodec::CreateByComponentName(looper, name.c_str(), &err); + if (err != OK) { + ALOGE("Failed to create codec: %s", name.c_str()); + return 0; + } + + err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE); + if (err != OK) { + ALOGE("Failed to configure codec: %s with mime: %s", name.c_str(), mime.c_str()); + codec->release(); + return 0; + } + + sp<IGraphicBufferProducer> bufferProducer; + err = codec->createInputSurface(&bufferProducer); + if (err != OK) { + ALOGE("Failed to create surface: %s with mime: %s", name.c_str(), mime.c_str()); + codec->release(); + return 0; + } + + int minUndequeued = 0; + err = bufferProducer->query( + NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeued); + if (err != OK) { + ALOGE("Failed to query NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS"); + minUndequeued = 0; + } + + err = codec->release(); + if (err != OK) { + ALOGW("Failed to release codec: %s with mime: %s", name.c_str(), mime.c_str()); + } + + return minUndequeued; +} + static size_t doProfileCodecs( bool isEncoder, AString name, AString mime, sp<MediaCodecInfo::Capabilities> caps) { sp<AMessage> format = getMeasureFormat(isEncoder, mime, caps); if (format == NULL) { return 0; } - if (isEncoder) { - format->setInt32("encoder", 1); - } ALOGV("doProfileCodecs %s %s %s %s", name.c_str(), mime.c_str(), isEncoder ? "encoder" : "decoder", format->debugString().c_str()); @@ -144,7 +199,7 @@ static size_t doProfileCodecs( } const sp<Surface> nativeWindow; const sp<ICrypto> crypto; - uint32_t flags = 0; + uint32_t flags = isEncoder ? MediaCodec::CONFIGURE_FLAG_ENCODE : 0; ALOGV("doProfileCodecs configure"); err = codec->configure(format, nativeWindow, crypto, flags); if (err != OK) { @@ -211,6 +266,7 @@ void profileCodecs( bool forceToMeasure) { KeyedVector<AString, sp<MediaCodecInfo::Capabilities>> codecsNeedMeasure; AString supportMultipleSecureCodecs = "true"; + size_t maxEncoderInputBuffers = 0; for (size_t i = 0; i < infos.size(); ++i) { const sp<MediaCodecInfo> info = infos[i]; AString name = info->getCodecName(); @@ -251,9 +307,21 @@ void profileCodecs( supportMultipleSecureCodecs = "false"; } } + if (info->isEncoder() && mimes[i].startsWith("video/")) { + size_t encoderInputBuffers = + doProfileEncoderInputBuffers(name, mimes[i], caps); + if (encoderInputBuffers > maxEncoderInputBuffers) { + maxEncoderInputBuffers = encoderInputBuffers; + } + } } } } + if (maxEncoderInputBuffers > 0) { + char tmp[32]; + sprintf(tmp, "%zu", maxEncoderInputBuffers); + global_results->add(kMaxEncoderInputBuffers, tmp); + } global_results->add(kPolicySupportsMultipleSecureCodecs, supportMultipleSecureCodecs); } diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp index 91cee73..0540a82 100644 --- a/media/libstagefright/omx/OMXNodeInstance.cpp +++ b/media/libstagefright/omx/OMXNodeInstance.cpp @@ -868,17 +868,9 @@ status_t OMXNodeInstance::createPersistentInputSurface( consumer->setConsumerName(name); consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_VIDEO_ENCODER); - status_t err = consumer->setMaxAcquiredBufferCount( - BufferQueue::MAX_MAX_ACQUIRED_BUFFERS); - if (err != NO_ERROR) { - ALOGE("Unable to set BQ max acquired buffer count to %u: %d", - BufferQueue::MAX_MAX_ACQUIRED_BUFFERS, err); - return err; - } - sp<BufferQueue::ProxyConsumerListener> proxy = new BufferQueue::ProxyConsumerListener(NULL); - err = consumer->consumerConnect(proxy, false); + status_t err = consumer->consumerConnect(proxy, false); if (err != NO_ERROR) { ALOGE("Error connecting to BufferQueue: %s (%d)", strerror(-err), err); |