Enable the support for setting frame rate and
video frame size with system properties.

TODO: the system property retrieval code
      needs to be refactored in a later change

bug 1993400
diff --git a/android/author/authordriver.cpp b/android/author/authordriver.cpp
index 3b9f481..3bf6ae5 100644
--- a/android/author/authordriver.cpp
+++ b/android/author/authordriver.cpp
@@ -582,22 +582,8 @@
         return;
     }
 
-    // FIXME:
-    // Platform-specific and temporal workaround to prevent video size from being set too large
-    if (ac->width > ANDROID_MAX_ENCODED_FRAME_WIDTH) {
-        LOGW("Intended width(%d) exceeds the max allowed width(%d). Max width is used instead.", ac->width, ANDROID_MAX_ENCODED_FRAME_WIDTH);
-        mVideoWidth = ANDROID_MAX_ENCODED_FRAME_WIDTH;
-    } else {
-        mVideoWidth = ac->width;
-    }
-    if (ac->height > ANDROID_MAX_ENCODED_FRAME_HEIGHT) {
-        LOGW("Intended height(%d) exceeds the max allowed height(%d). Max height is used instead.", ac->height, ANDROID_MAX_ENCODED_FRAME_HEIGHT);
-        mVideoHeight = ANDROID_MAX_ENCODED_FRAME_HEIGHT;
-    } else {
-        mVideoHeight = ac->height;
-    }
-
-    ((AndroidCameraInput *)mVideoInputMIO)->SetFrameSize(mVideoWidth, mVideoHeight);
+    mVideoWidth = ac->width;
+    mVideoHeight = ac->height;
     FinishNonAsyncCommand(ac);
 }
 
@@ -609,16 +595,7 @@
         return;
     }
 
-    // FIXME:
-    // Platform-specific and temporal workaround to accept a reasonable frame rate range
-    if (ac->rate < ANDROID_MIN_FRAME_RATE_FPS) {
-    mVideoFrameRate = ANDROID_MIN_FRAME_RATE_FPS;
-    } else if (ac->rate > ANDROID_MAX_FRAME_RATE_FPS) {
-    mVideoFrameRate = ANDROID_MAX_FRAME_RATE_FPS;
-    } else {
     mVideoFrameRate = ac->rate;
-    }
-    ((AndroidCameraInput *)mVideoInputMIO)->SetFrameRate(mVideoFrameRate);
     FinishNonAsyncCommand(ac);
 }
 
@@ -928,6 +905,23 @@
 void AuthorDriver::handlePrepare(author_command *ac)
 {
     LOGV("handlePrepare");
+
+    // Set video encoding frame rate and video frame size if necessary
+    if (mVideoFrameRate == 0) {
+        mVideoFrameRate = DEFAULT_VIDEO_FRAME_RATE;
+    }
+    clipVideoFrameRate();
+    ((AndroidCameraInput *)mVideoInputMIO)->SetFrameRate(mVideoFrameRate);
+
+    if (mVideoWidth == 0) {
+        mVideoWidth = DEFAULT_VIDEO_WIDTH;
+    }
+    if (mVideoHeight == 0) {
+        mVideoHeight = DEFAULT_VIDEO_HEIGHT;
+    }
+    clipVideoFrameSize();
+    ((AndroidCameraInput *)mVideoInputMIO)->SetFrameSize(mVideoWidth, mVideoHeight);
+
     int error = 0;
     OSCL_TRY(error, mAuthor->Init(ac));
     OSCL_FIRST_CATCH_ANY(error, commandFailed(ac));
@@ -1165,13 +1159,13 @@
 {
     switch(encoder) {
         case VIDEO_ENCODER_MPEG_4_SP:
-            strncpy(name, "ro.media.enc.vid.m4v", len);
+            strncpy(name, "ro.media.enc.vid.m4v.", len);
             return true;
         case VIDEO_ENCODER_H264:
-            strncpy(name, "ro.media.enc.vid.h264", len);
+            strncpy(name, "ro.media.enc.vid.h264.", len);
             return true;
         case VIDEO_ENCODER_H263:
-            strncpy(name, "ro.media.enc.vid.h263", len);
+            strncpy(name, "ro.media.enc.vid.h263.", len);
             return true;
         default:
             LOGE("Failed to get system property key for video encoder(%d)", encoder);
@@ -1179,28 +1173,61 @@
     }
 }
 
-// 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)
+// Retrieves the advertised video property range from system properties for the given encoder.
+// If the encoder is not found, or the video property is not listed as a system property,
+// default hardcoded min and max values will be used.
+static void getSupportedPropertyRange(video_encoder encoder, const char* property, int64& min, int64& max)
 {
     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);
+        if ((strlen(videoEncoderName) + strlen(property) + 1) < PROPERTY_KEY_MAX) {  // Valid key length
+            strcat(videoEncoderName, property);
         } 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);
+    if (!propertyKeyExists || !getMinAndMaxValuesOfProperty(videoEncoderName, min, max)) {
+        if (strcmp(property, "bps") == 0) {
+            min = MIN_VIDEO_BITRATE_SETTING;
+            max = MAX_VIDEO_BITRATE_SETTING;
+        } else if (strcmp(property, "fps") == 0) {
+            min = ANDROID_MIN_FRAME_RATE_FPS;
+            max = ANDROID_MAX_FRAME_RATE_FPS;
+        } else if (strcmp(property, "width") == 0) {
+            min = ANDROID_MIN_ENCODED_FRAME_WIDTH;
+            max = ANDROID_MAX_ENCODED_FRAME_WIDTH;
+        } else if (strcmp(property, "height") == 0) {
+            min = ANDROID_MIN_ENCODED_FRAME_HEIGHT;
+            max = ANDROID_MAX_ENCODED_FRAME_HEIGHT;
+        } else {
+            LOGE("Unknown video property: %s", property);
+            min = max = 0;
+        }
+        LOGW("Use default video %s range [%lld %lld]", property, min, max);
     }
 }
 
+static void getSupportedVideoBitRateRange(video_encoder encoder, int64& minBitRateBps, int64& maxBitRateBps)
+{
+    getSupportedPropertyRange(encoder, "bps", minBitRateBps, maxBitRateBps);
+}
+
+static void getSupportedVideoFrameRateRange(video_encoder encoder, int64& minFrameRateFps, int64& maxFrameRateFps)
+{
+    getSupportedPropertyRange(encoder, "fps", minFrameRateFps, maxFrameRateFps);
+}
+
+static void getSupportedVideoFrameWidthRange(video_encoder encoder, int64& minWidth, int64& maxWidth)
+{
+    getSupportedPropertyRange(encoder, "width", minWidth, maxWidth);
+}
+
+static void getSupportedVideoFrameHeightRange(video_encoder encoder, int64& minHeight, int64& maxHeight)
+{
+    getSupportedPropertyRange(encoder, "height", minHeight, maxHeight);
+}
+
 // 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.
@@ -1217,6 +1244,51 @@
     }
 }
 
+void AuthorDriver::clipVideoFrameRate()
+{
+    int64 minFrameRate, maxFrameRate;
+    getSupportedVideoFrameRateRange(mVideoEncoder, minFrameRate, maxFrameRate);
+    if (mVideoFrameRate < minFrameRate) {
+        LOGW("Intended video encoding frame rate (%d fps) is too small and will be set to (%lld fps)", mVideoFrameRate, minFrameRate);
+        mVideoFrameRate = minFrameRate;
+    } else if (mVideoFrameRate > maxFrameRate) {
+        LOGW("Intended video encoding frame rate (%d fps) is too large and will be set to (%lld fps)", mVideoFrameRate, maxFrameRate);
+        mVideoFrameRate = maxFrameRate;
+    }
+}
+
+void AuthorDriver::clipVideoFrameWidth()
+{
+    int64 minFrameWidth, maxFrameWidth;
+    getSupportedVideoFrameWidthRange(mVideoEncoder, minFrameWidth, maxFrameWidth);
+    if (mVideoWidth < minFrameWidth) {
+        LOGW("Intended video encoding frame width (%d) is too small and will be set to (%lld)", mVideoWidth, minFrameWidth);
+        mVideoWidth = minFrameWidth;
+    } else if (mVideoWidth > maxFrameWidth) {
+        LOGW("Intended video encoding frame width (%d) is too large and will be set to (%lld)", mVideoWidth, maxFrameWidth);
+        mVideoWidth = maxFrameWidth;
+    }
+}
+
+void AuthorDriver::clipVideoFrameHeight()
+{
+    int64 minFrameHeight, maxFrameHeight;
+    getSupportedVideoFrameHeightRange(mVideoEncoder, minFrameHeight, maxFrameHeight);
+    if (mVideoHeight < minFrameHeight) {
+        LOGW("Intended video encoding frame height (%d) is too small and will be set to (%lld)", mVideoHeight, minFrameHeight);
+        mVideoHeight = minFrameHeight;
+    } else if (mVideoHeight > maxFrameHeight) {
+        LOGW("Intended video encoding frame height (%d) is too large and will be set to (%lld)", mVideoHeight, maxFrameHeight);
+        mVideoHeight = maxFrameHeight;
+    }
+}
+
+void AuthorDriver::clipVideoFrameSize()
+{
+    clipVideoFrameWidth();
+    clipVideoFrameHeight();
+}
+
 void AuthorDriver::CommandCompleted(const PVCmdResponse& aResponse)
 {
     author_command *ac = (author_command *)aResponse.GetContext();
diff --git a/android/author/authordriver.h b/android/author/authordriver.h
index 2337b75..d8c0dee 100644
--- a/android/author/authordriver.h
+++ b/android/author/authordriver.h
@@ -67,12 +67,19 @@
 // FIXME:
 // Platform-specic and temporal workaround to prevent video size
 // from being set too large
+
 #define ANDROID_MAX_ENCODED_FRAME_WIDTH            352
 #define ANDROID_MAX_ENCODED_FRAME_HEIGHT           288
+#define ANDROID_MIN_ENCODED_FRAME_WIDTH            176
+#define ANDROID_MIN_ENCODED_FRAME_HEIGHT           144
 
 #define ANDROID_MIN_FRAME_RATE_FPS                 5
 #define ANDROID_MAX_FRAME_RATE_FPS                 20
 
+static const int32 DEFAULT_VIDEO_FRAME_RATE  = 20;
+static const int32 DEFAULT_VIDEO_WIDTH       = 176;
+static const int32 DEFAULT_VIDEO_HEIGHT      = 144;
+
 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??
@@ -320,9 +327,13 @@
     // 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.
+    // Clips the intended video encoding bit rate, frame rate, frame size
+    // (width and height) so that it is within the supported range.
     void clipVideoBitrate();
+    void clipVideoFrameRate();
+    void clipVideoFrameSize();
+    void clipVideoFrameWidth();
+    void clipVideoFrameHeight();
 
     // Used to map the incoming bitrate to the closest AMR bitrate
     bool MapAMRBitrate(int32 aAudioBitrate, PVMF_GSMAMR_Rate &anAMRBitrate);