From ccecc29f64a537a8136642761e6357ff240e835d Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Wed, 1 Oct 2014 21:36:51 -0700 Subject: [PATCH] mediarecorder: set level if setting default profile Bug: 17676461 Change-Id: If01ccd09935945d330de0842be95c3544951b6b9 --- include/media/stagefright/ACodec.h | 10 +++- .../libmediaplayerservice/StagefrightRecorder.cpp | 5 ++ media/libstagefright/ACodec.cpp | 53 ++++++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index df0dc58dae..28e5c569e1 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -77,8 +77,14 @@ struct ACodec : public AHierarchicalStateMachine, public CodecBase { }; static bool isFlexibleColorFormat( - const sp &omx, IOMX::node_id node, - uint32_t colorFormat, OMX_U32 *flexibleEquivalent); + const sp &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(); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index b904aa81a2..17190fba38 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -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)); } } } diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index d6fba9809a..b6ac2a02e4 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -2490,6 +2491,58 @@ status_t ACodec::setupH263EncoderParameters(const sp &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 &msg) { int32_t bitrate, iFrameInterval; if (!msg->findInt32("bitrate", &bitrate) -- 2.11.0