Enable the support of setting video bit rate
bug 1993400
diff --git a/android/author/authordriver.cpp b/android/author/authordriver.cpp
index 322ab8e..3b9f481 100644
--- a/android/author/authordriver.cpp
+++ b/android/author/authordriver.cpp
@@ -22,6 +22,7 @@
#include <media/thread_init.h>
#include <ui/ISurface.h>
#include <ui/ICamera.h>
+#include <cutils/properties.h> // for property_get
#include "authordriver.h"
#include "pv_omxcore.h"
#include <sys/prctl.h>
@@ -114,6 +115,7 @@
mSamplingRate(0),
mNumberOfChannels(0),
mAudio_bitrate_setting(0),
+ mVideo_bitrate_setting(0),
ifpOutput(NULL)
{
mSyncSem = new OsclSemaphore();
@@ -841,6 +843,11 @@
if (safe_strtoi64(value.string(), &audio_bitrate)) {
return setParamAudioEncodingBitrate(audio_bitrate);
}
+ } else if (key == "video-param-encoding-bitrate") {
+ int64_t video_bitrate;
+ if (safe_strtoi64(value.string(), &video_bitrate)) {
+ return setParamVideoEncodingBitrate(video_bitrate);
+ }
}
// Return error if the key wasnt found
@@ -848,6 +855,19 @@
return PVMFErrArgument;
}
+PVMFStatus AuthorDriver::setParamVideoEncodingBitrate(int64_t aVideoBitrate)
+{
+ if (aVideoBitrate <= 0)
+ {
+ LOGE("setParamVideoEncodingBitrate() invalid video bitrate (%lld). Set call ignored.", aVideoBitrate);
+ return PVMFErrArgument;
+ }
+
+ mVideo_bitrate_setting = aVideoBitrate;
+ LOGD("setParamVideoEncodingBitrate() %d", mVideo_bitrate_setting);
+ return PVMFSuccess;
+}
+
// Applies the requested parameters, completes either successfully or stops
// application of parameters upon encountering the first error, finishing the
// transaction with the failure result of that initial failure.
@@ -1097,6 +1117,106 @@
ed->mSyncSem->Signal();
}
+// Backward compatible hardcoded video bit rate setting
+// These bit rate settings are from the original work with
+// QCOM's hardware encoders. Originally, anything above
+// 420000 bps is not stable, and default low quality bit
+// rate it set to 192000 bps. For those devices with
+// media capabilities specified as system properties, these
+// bit rate settings will not be used.
+static int setVideoBitrateHeuristically(int videoWidth)
+{
+ int bitrate_setting = 192000;
+ if (videoWidth >= 480) {
+ bitrate_setting = 420000;
+ } else if (videoWidth >= 352) {
+ bitrate_setting = 360000;
+ } else if (videoWidth >= 320) {
+ bitrate_setting = 320000;
+ }
+ return bitrate_setting;
+}
+
+
+// Returns true on success
+static bool getMinAndMaxValuesOfProperty(const char*propertyKey, int64& minValue, int64& maxValue)
+{
+ char value[PROPERTY_VALUE_MAX];
+ int rc = property_get(propertyKey, value, 0);
+ LOGV("property_get(): rc = %d, value=%s", rc, value);
+ if (rc > 0) {
+ char* b = strchr(value, ',');
+ if (b == 0) { // A pair of values separated by ","?
+ return false;
+ } else {
+ String8 key(value, b - value);
+ if (!safe_strtoi64(key.string(), &minValue) || !safe_strtoi64(b + 1, &maxValue)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+// Maps the given encoder to a system property key
+// Returns true on success
+static bool getPropertyKeyForVideoEncoder(video_encoder encoder, char* name, size_t len)
+{
+ switch(encoder) {
+ case VIDEO_ENCODER_MPEG_4_SP:
+ strncpy(name, "ro.media.enc.vid.m4v", len);
+ return true;
+ case VIDEO_ENCODER_H264:
+ strncpy(name, "ro.media.enc.vid.h264", len);
+ return true;
+ case VIDEO_ENCODER_H263:
+ strncpy(name, "ro.media.enc.vid.h263", len);
+ return true;
+ default:
+ LOGE("Failed to get system property key for video encoder(%d)", encoder);
+ return false;
+ }
+}
+
+// Retrieves the advertised video bit rate range from system properties for the given encoder.
+// If the encoder is not found, or the bit rate range is not listed as a system property,
+// default hardcoded min and max bit rate will be used.
+static void getSupportedVideoBitRateRange(video_encoder encoder, int64& minBitRateBps, int64& maxBitRateBps)
+{
+ char videoEncoderName[PROPERTY_KEY_MAX];
+ bool propertyKeyExists = getPropertyKeyForVideoEncoder(encoder, videoEncoderName, PROPERTY_KEY_MAX - 1);
+ if (propertyKeyExists) {
+ const char* bps = ".bps"; // Specify the specific property for the given video encoder
+ if ((strlen(videoEncoderName) + strlen(bps) + 1) < PROPERTY_KEY_MAX) { // Valid key length
+ strcat(videoEncoderName, bps);
+ } else {
+ propertyKeyExists = false;
+ }
+ }
+ if (!propertyKeyExists || !getMinAndMaxValuesOfProperty(videoEncoderName, minBitRateBps, maxBitRateBps)) {
+ minBitRateBps = MIN_VIDEO_BITRATE_SETTING;
+ maxBitRateBps = MAX_VIDEO_BITRATE_SETTING;
+ LOGW("Use default video bit rate range [%lld %lld]", minBitRateBps, maxBitRateBps);
+ }
+}
+
+// Clips the intented video encoding rate so that it is
+// within the advertised support range. Logs a warning if
+// the intended bit rate is out of the range.
+void AuthorDriver::clipVideoBitrate()
+{
+ int64 minBitrate, maxBitrate;
+ getSupportedVideoBitRateRange(mVideoEncoder, minBitrate, maxBitrate);
+ if (mVideo_bitrate_setting < minBitrate) {
+ LOGW("Intended video encoding bit rate (%d bps) is too small and will be set to (%lld bps)", mVideo_bitrate_setting, minBitrate);
+ mVideo_bitrate_setting = minBitrate;
+ } else if (mVideo_bitrate_setting > maxBitrate) {
+ LOGW("Intended video encoding bit rate (%d bps) is too large and will be set to (%lld bps)", mVideo_bitrate_setting, maxBitrate);
+ mVideo_bitrate_setting = maxBitrate;
+ }
+}
+
void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse)
{
author_command *ac = (author_command *)aResponse.GetContext();
@@ -1118,19 +1238,14 @@
case VIDEO_ENCODER_H264: {
PVMp4H263EncExtensionInterface *config = OSCL_STATIC_CAST(PVMp4H263EncExtensionInterface*,
mVideoEncoderConfig);
- // TODO:
- // fix the hardcoded bit rate settings.
if (config) {
- int bitrate_setting = 192000;
- if (mVideoWidth >= 480) {
- bitrate_setting = 420000; // unstable
- } else if (mVideoWidth >= 352) {
- bitrate_setting = 360000;
- } else if (mVideoWidth >= 320) {
- bitrate_setting = 320000;
+ if (mVideo_bitrate_setting == 0) {
+ mVideo_bitrate_setting = setVideoBitrateHeuristically(mVideoWidth);
+ LOGW("Video encoding bit rate is set to %d bps", mVideo_bitrate_setting);
}
+ clipVideoBitrate();
config->SetNumLayers(1);
- config->SetOutputBitRate(0, bitrate_setting);
+ config->SetOutputBitRate(0, mVideo_bitrate_setting);
config->SetOutputFrameSize(0, mVideoWidth, mVideoHeight);
config->SetOutputFrameRate(0, mVideoFrameRate);
config->SetIFrameInterval(ANDROID_DEFAULT_I_FRAME_INTERVAL);
diff --git a/android/author/authordriver.h b/android/author/authordriver.h
index 22f4f6a..2337b75 100644
--- a/android/author/authordriver.h
+++ b/android/author/authordriver.h
@@ -73,6 +73,8 @@
#define ANDROID_MIN_FRAME_RATE_FPS 5
#define ANDROID_MAX_FRAME_RATE_FPS 20
+static const int32 MIN_VIDEO_BITRATE_SETTING = 192000;
+static const int32 MAX_VIDEO_BITRATE_SETTING = 420000;
static const int32 MAX_AUDIO_BITRATE_SETTING = 320000; // Max bitrate??
static const int32 MIN_AUDIO_BITRATE_SETTING = 1; // Min bitrate??
static const int32 DEFAULT_AUDIO_BITRATE_SETTING = 64000; // Default for all the other audio
@@ -315,6 +317,13 @@
PVMFStatus setParameter(const String8 &key, const String8 &value);
+ // Has no effect if called after video encoder is set
+ PVMFStatus setParamVideoEncodingBitrate(int64_t aVideoBitrate);
+
+ // Clips the intended video encoding bit rate so that it is within the
+ // supported range.
+ void clipVideoBitrate();
+
// Used to map the incoming bitrate to the closest AMR bitrate
bool MapAMRBitrate(int32 aAudioBitrate, PVMF_GSMAMR_Rate &anAMRBitrate);
@@ -355,6 +364,7 @@
int32 mSamplingRate;
int32 mNumberOfChannels;
int32 mAudio_bitrate_setting;
+ int32 mVideo_bitrate_setting;
FILE* ifpOutput;
};