summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/VideoFormats.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/wifi-display/VideoFormats.cpp')
-rw-r--r--media/libstagefright/wifi-display/VideoFormats.cpp370
1 files changed, 370 insertions, 0 deletions
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
new file mode 100644
index 0000000..9ad8c3c
--- /dev/null
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "VideoFormats"
+#include <utils/Log.h>
+
+#include "VideoFormats.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+VideoFormats::VideoFormats() {
+ for (size_t i = 0; i < kNumResolutionTypes; ++i) {
+ mResolutionEnabled[i] = 0;
+ }
+
+ setNativeResolution(RESOLUTION_CEA, 0); // default to 640x480 p60
+}
+
+void VideoFormats::setNativeResolution(ResolutionType type, size_t index) {
+ CHECK_LT(type, kNumResolutionTypes);
+ CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));
+
+ mNativeType = type;
+ mNativeIndex = index;
+
+ setResolutionEnabled(type, index);
+}
+
+void VideoFormats::getNativeResolution(
+ ResolutionType *type, size_t *index) const {
+ *type = mNativeType;
+ *index = mNativeIndex;
+}
+
+void VideoFormats::disableAll() {
+ for (size_t i = 0; i < kNumResolutionTypes; ++i) {
+ mResolutionEnabled[i] = 0;
+ }
+}
+
+void VideoFormats::enableAll() {
+ for (size_t i = 0; i < kNumResolutionTypes; ++i) {
+ mResolutionEnabled[i] = 0xffffffff;
+ }
+}
+
+void VideoFormats::setResolutionEnabled(
+ ResolutionType type, size_t index, bool enabled) {
+ CHECK_LT(type, kNumResolutionTypes);
+ CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));
+
+ if (enabled) {
+ mResolutionEnabled[type] |= (1ul << index);
+ } else {
+ mResolutionEnabled[type] &= ~(1ul << index);
+ }
+}
+
+bool VideoFormats::isResolutionEnabled(
+ ResolutionType type, size_t index) const {
+ CHECK_LT(type, kNumResolutionTypes);
+ CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL));
+
+ return mResolutionEnabled[type] & (1ul << index);
+}
+
+// static
+bool VideoFormats::GetConfiguration(
+ ResolutionType type,
+ size_t index,
+ size_t *width, size_t *height, size_t *framesPerSecond,
+ bool *interlaced) {
+ CHECK_LT(type, kNumResolutionTypes);
+
+ if (index >= 32) {
+ return false;
+ }
+
+ static const struct config_t {
+ size_t width, height, framesPerSecond;
+ bool interlaced;
+ } kConfigs[kNumResolutionTypes][32] = {
+ {
+ // CEA Resolutions
+ { 640, 480, 60, false },
+ { 720, 480, 60, false },
+ { 720, 480, 60, true },
+ { 720, 576, 50, false },
+ { 720, 576, 50, true },
+ { 1280, 720, 30, false },
+ { 1280, 720, 60, false },
+ { 1920, 1080, 30, false },
+ { 1920, 1080, 60, false },
+ { 1920, 1080, 60, true },
+ { 1280, 720, 25, false },
+ { 1280, 720, 50, false },
+ { 1920, 1080, 25, false },
+ { 1920, 1080, 50, false },
+ { 1920, 1080, 50, true },
+ { 1280, 720, 24, false },
+ { 1920, 1080, 24, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ },
+ {
+ // VESA Resolutions
+ { 800, 600, 30, false },
+ { 800, 600, 60, false },
+ { 1024, 768, 30, false },
+ { 1024, 768, 60, false },
+ { 1152, 864, 30, false },
+ { 1152, 864, 60, false },
+ { 1280, 768, 30, false },
+ { 1280, 768, 60, false },
+ { 1280, 800, 30, false },
+ { 1280, 800, 60, false },
+ { 1360, 768, 30, false },
+ { 1360, 768, 60, false },
+ { 1366, 768, 30, false },
+ { 1366, 768, 60, false },
+ { 1280, 1024, 30, false },
+ { 1280, 1024, 60, false },
+ { 1400, 1050, 30, false },
+ { 1400, 1050, 60, false },
+ { 1440, 900, 30, false },
+ { 1440, 900, 60, false },
+ { 1600, 900, 30, false },
+ { 1600, 900, 60, false },
+ { 1600, 1200, 30, false },
+ { 1600, 1200, 60, false },
+ { 1680, 1024, 30, false },
+ { 1680, 1024, 60, false },
+ { 1680, 1050, 30, false },
+ { 1680, 1050, 60, false },
+ { 1920, 1200, 30, false },
+ { 1920, 1200, 60, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ },
+ {
+ // HH Resolutions
+ { 800, 480, 30, false },
+ { 800, 480, 60, false },
+ { 854, 480, 30, false },
+ { 854, 480, 60, false },
+ { 864, 480, 30, false },
+ { 864, 480, 60, false },
+ { 640, 360, 30, false },
+ { 640, 360, 60, false },
+ { 960, 540, 30, false },
+ { 960, 540, 60, false },
+ { 848, 480, 30, false },
+ { 848, 480, 60, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ { 0, 0, 0, false },
+ }
+ };
+
+ const config_t *config = &kConfigs[type][index];
+
+ if (config->width == 0) {
+ return false;
+ }
+
+ if (width) {
+ *width = config->width;
+ }
+
+ if (height) {
+ *height = config->height;
+ }
+
+ if (framesPerSecond) {
+ *framesPerSecond = config->framesPerSecond;
+ }
+
+ if (interlaced) {
+ *interlaced = config->interlaced;
+ }
+
+ return true;
+}
+
+bool VideoFormats::parseFormatSpec(const char *spec) {
+ CHECK_EQ(kNumResolutionTypes, 3);
+
+ unsigned native, dummy;
+
+ if (sscanf(
+ spec,
+ "%02x %02x %02x %02x %08X %08X %08X",
+ &native,
+ &dummy,
+ &dummy,
+ &dummy,
+ &mResolutionEnabled[0],
+ &mResolutionEnabled[1],
+ &mResolutionEnabled[2]) != 7) {
+ return false;
+ }
+
+ mNativeIndex = native >> 3;
+ mNativeType = (ResolutionType)(native & 7);
+
+ if (mNativeType >= kNumResolutionTypes) {
+ return false;
+ }
+
+ return GetConfiguration(mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
+}
+
+AString VideoFormats::getFormatSpec() const {
+ CHECK_EQ(kNumResolutionTypes, 3);
+
+ // wfd_video_formats:
+ // 1 byte "native"
+ // 1 byte "preferred-display-mode-supported" 0 or 1
+ // one or more avc codec structures
+ // 1 byte profile
+ // 1 byte level
+ // 4 byte CEA mask
+ // 4 byte VESA mask
+ // 4 byte HH mask
+ // 1 byte latency
+ // 2 byte min-slice-slice
+ // 2 byte slice-enc-params
+ // 1 byte framerate-control-support
+ // max-hres (none or 2 byte)
+ // max-vres (none or 2 byte)
+
+ return StringPrintf(
+ "%02x 00 02 02 %08x %08x %08x 00 0000 0000 00 none none",
+ (mNativeIndex << 3) | mNativeType,
+ mResolutionEnabled[0],
+ mResolutionEnabled[1],
+ mResolutionEnabled[2]);
+}
+
+// static
+bool VideoFormats::PickBestFormat(
+ const VideoFormats &sinkSupported,
+ const VideoFormats &sourceSupported,
+ ResolutionType *chosenType,
+ size_t *chosenIndex) {
+ ResolutionType nativeType;
+ size_t nativeIndex;
+ sinkSupported.getNativeResolution(&nativeType, &nativeIndex);
+ if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) {
+ if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) {
+ ALOGI("Choosing sink's native resolution");
+ *chosenType = nativeType;
+ *chosenIndex = nativeIndex;
+ return true;
+ }
+ } else {
+ ALOGW("Sink advertised native resolution that it doesn't "
+ "actually support... ignoring");
+ }
+
+ sourceSupported.getNativeResolution(&nativeType, &nativeIndex);
+ if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) {
+ if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) {
+ ALOGI("Choosing source's native resolution");
+ *chosenType = nativeType;
+ *chosenIndex = nativeIndex;
+ return true;
+ }
+ } else {
+ ALOGW("Source advertised native resolution that it doesn't "
+ "actually support... ignoring");
+ }
+
+ bool first = true;
+ uint32_t bestScore = 0;
+ size_t bestType = 0;
+ size_t bestIndex = 0;
+ for (size_t i = 0; i < kNumResolutionTypes; ++i) {
+ for (size_t j = 0; j < 32; ++j) {
+ size_t width, height, framesPerSecond;
+ bool interlaced;
+ if (!GetConfiguration(
+ (ResolutionType)i,
+ j,
+ &width, &height, &framesPerSecond, &interlaced)) {
+ break;
+ }
+
+ if (!sinkSupported.isResolutionEnabled((ResolutionType)i, j)
+ || !sourceSupported.isResolutionEnabled(
+ (ResolutionType)i, j)) {
+ continue;
+ }
+
+ ALOGV("type %u, index %u, %u x %u %c%u supported",
+ i, j, width, height, interlaced ? 'i' : 'p', framesPerSecond);
+
+ uint32_t score = width * height * framesPerSecond;
+ if (!interlaced) {
+ score *= 2;
+ }
+
+ if (first || score > bestScore) {
+ bestScore = score;
+ bestType = i;
+ bestIndex = j;
+
+ first = false;
+ }
+ }
+ }
+
+ if (first) {
+ return false;
+ }
+
+ *chosenType = (ResolutionType)bestType;
+ *chosenIndex = bestIndex;
+
+ return true;
+}
+
+} // namespace android
+