OSDN Git Service

mediarecorder: set level if setting default profile
authorLajos Molnar <lajos@google.com>
Thu, 2 Oct 2014 04:36:51 +0000 (21:36 -0700)
committerThe Android Automerger <android-build@google.com>
Fri, 3 Oct 2014 00:00:22 +0000 (17:00 -0700)
Bug: 17676461
Change-Id: If01ccd09935945d330de0842be95c3544951b6b9

include/media/stagefright/ACodec.h
media/libmediaplayerservice/StagefrightRecorder.cpp
media/libstagefright/ACodec.cpp

index df0dc58..28e5c56 100644 (file)
@@ -77,8 +77,14 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase {
     };
 
     static bool isFlexibleColorFormat(
-        const sp<IOMX> &omx, IOMX::node_id node,
-        uint32_t colorFormat, OMX_U32 *flexibleEquivalent);
+            const sp<IOMX> &omx, IOMX::node_id node,
+            uint32_t colorFormat, OMX_U32 *flexibleEquivalent);
+
+    // Returns 0 if configuration is not supported.  NOTE: this is treated by
+    // some OMX components as auto level, and by others as invalid level.
+    static int /* OMX_VIDEO_AVCLEVELTYPE */ getAVCLevelFor(
+            int width, int height, int rate, int bitrate,
+            OMX_VIDEO_AVCPROFILETYPE profile = OMX_VIDEO_AVCProfileBaseline);
 
 protected:
     virtual ~ACodec();
index b904aa8..17190fb 100644 (file)
@@ -30,6 +30,7 @@
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/ACodec.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/AACWriter.h>
@@ -1243,6 +1244,10 @@ void StagefrightRecorder::setDefaultProfileIfNecessary() {
         if (videoCodec == VIDEO_ENCODER_H264) {
             ALOGI("Force to use AVC baseline profile");
             setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
+            // set 0 for invalid levels - this will be rejected by the
+            // codec if it cannot handle it during configure
+            setParamVideoEncoderLevel(ACodec::getAVCLevelFor(
+                    videoFrameWidth, videoFrameHeight, videoFrameRate, videoBitRate));
         }
     }
 }
index d6fba98..b6ac2a0 100644 (file)
@@ -32,6 +32,7 @@
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
 
 #include <media/stagefright/BufferProducerWrapper.h>
 #include <media/stagefright/MediaCodecList.h>
@@ -2490,6 +2491,58 @@ status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
     return setupErrorCorrectionParameters();
 }
 
+// static
+int /* OMX_VIDEO_AVCLEVELTYPE */ ACodec::getAVCLevelFor(
+        int width, int height, int rate, int bitrate,
+        OMX_VIDEO_AVCPROFILETYPE profile) {
+    // convert bitrate to main/baseline profile kbps equivalent
+    switch (profile) {
+        case OMX_VIDEO_AVCProfileHigh10:
+            bitrate = divUp(bitrate, 3000); break;
+        case OMX_VIDEO_AVCProfileHigh:
+            bitrate = divUp(bitrate, 1250); break;
+        default:
+            bitrate = divUp(bitrate, 1000); break;
+    }
+
+    // convert size and rate to MBs
+    width = divUp(width, 16);
+    height = divUp(height, 16);
+    int mbs = width * height;
+    rate *= mbs;
+    int maxDimension = max(width, height);
+
+    static const int limits[][5] = {
+        /*   MBps     MB   dim  bitrate        level */
+        {    1485,    99,  28,     64, OMX_VIDEO_AVCLevel1  },
+        {    1485,    99,  28,    128, OMX_VIDEO_AVCLevel1b },
+        {    3000,   396,  56,    192, OMX_VIDEO_AVCLevel11 },
+        {    6000,   396,  56,    384, OMX_VIDEO_AVCLevel12 },
+        {   11880,   396,  56,    768, OMX_VIDEO_AVCLevel13 },
+        {   11880,   396,  56,   2000, OMX_VIDEO_AVCLevel2  },
+        {   19800,   792,  79,   4000, OMX_VIDEO_AVCLevel21 },
+        {   20250,  1620, 113,   4000, OMX_VIDEO_AVCLevel22 },
+        {   40500,  1620, 113,  10000, OMX_VIDEO_AVCLevel3  },
+        {  108000,  3600, 169,  14000, OMX_VIDEO_AVCLevel31 },
+        {  216000,  5120, 202,  20000, OMX_VIDEO_AVCLevel32 },
+        {  245760,  8192, 256,  20000, OMX_VIDEO_AVCLevel4  },
+        {  245760,  8192, 256,  50000, OMX_VIDEO_AVCLevel41 },
+        {  522240,  8704, 263,  50000, OMX_VIDEO_AVCLevel42 },
+        {  589824, 22080, 420, 135000, OMX_VIDEO_AVCLevel5  },
+        {  983040, 36864, 543, 240000, OMX_VIDEO_AVCLevel51 },
+        { 2073600, 36864, 543, 240000, OMX_VIDEO_AVCLevel52 },
+    };
+
+    for (size_t i = 0; i < ARRAY_SIZE(limits); i++) {
+        const int (&limit)[5] = limits[i];
+        if (rate <= limit[0] && mbs <= limit[1] && maxDimension <= limit[2]
+                && bitrate <= limit[3]) {
+            return limit[4];
+        }
+    }
+    return 0;
+}
+
 status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
     int32_t bitrate, iFrameInterval;
     if (!msg->findInt32("bitrate", &bitrate)