VideoFormats.cpp revision 0182f9acca6f873ee127898e408cf75cc316c3ea
1/* 2 * Copyright 2013, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "VideoFormats" 19#include <utils/Log.h> 20 21#include "VideoFormats.h" 22 23#include <media/stagefright/foundation/ADebug.h> 24 25namespace android { 26 27VideoFormats::VideoFormats() { 28 for (size_t i = 0; i < kNumResolutionTypes; ++i) { 29 mResolutionEnabled[i] = 0; 30 } 31 32 setNativeResolution(RESOLUTION_CEA, 0); // default to 640x480 p60 33} 34 35void VideoFormats::setNativeResolution(ResolutionType type, size_t index) { 36 CHECK_LT(type, kNumResolutionTypes); 37 CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL)); 38 39 mNativeType = type; 40 mNativeIndex = index; 41 42 setResolutionEnabled(type, index); 43} 44 45void VideoFormats::getNativeResolution( 46 ResolutionType *type, size_t *index) const { 47 *type = mNativeType; 48 *index = mNativeIndex; 49} 50 51void VideoFormats::disableAll() { 52 for (size_t i = 0; i < kNumResolutionTypes; ++i) { 53 mResolutionEnabled[i] = 0; 54 } 55} 56 57void VideoFormats::enableAll() { 58 for (size_t i = 0; i < kNumResolutionTypes; ++i) { 59 mResolutionEnabled[i] = 0xffffffff; 60 } 61} 62 63void VideoFormats::setResolutionEnabled( 64 ResolutionType type, size_t index, bool enabled) { 65 CHECK_LT(type, kNumResolutionTypes); 66 CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL)); 67 68 if (enabled) { 69 mResolutionEnabled[type] |= (1ul << index); 70 } else { 71 mResolutionEnabled[type] &= ~(1ul << index); 72 } 73} 74 75bool VideoFormats::isResolutionEnabled( 76 ResolutionType type, size_t index) const { 77 CHECK_LT(type, kNumResolutionTypes); 78 CHECK(GetConfiguration(type, index, NULL, NULL, NULL, NULL)); 79 80 return mResolutionEnabled[type] & (1ul << index); 81} 82 83// static 84bool VideoFormats::GetConfiguration( 85 ResolutionType type, 86 size_t index, 87 size_t *width, size_t *height, size_t *framesPerSecond, 88 bool *interlaced) { 89 CHECK_LT(type, kNumResolutionTypes); 90 91 if (index >= 32) { 92 return false; 93 } 94 95 static const struct config_t { 96 size_t width, height, framesPerSecond; 97 bool interlaced; 98 } kConfigs[kNumResolutionTypes][32] = { 99 { 100 // CEA Resolutions 101 { 640, 480, 60, false }, 102 { 720, 480, 60, false }, 103 { 720, 480, 60, true }, 104 { 720, 576, 50, false }, 105 { 720, 576, 50, true }, 106 { 1280, 720, 30, false }, 107 { 1280, 720, 60, false }, 108 { 1920, 1080, 30, false }, 109 { 1920, 1080, 60, false }, 110 { 1920, 1080, 60, true }, 111 { 1280, 720, 25, false }, 112 { 1280, 720, 50, false }, 113 { 1920, 1080, 25, false }, 114 { 1920, 1080, 50, false }, 115 { 1920, 1080, 50, true }, 116 { 1280, 720, 24, false }, 117 { 1920, 1080, 24, false }, 118 { 0, 0, 0, false }, 119 { 0, 0, 0, false }, 120 { 0, 0, 0, false }, 121 { 0, 0, 0, false }, 122 { 0, 0, 0, false }, 123 { 0, 0, 0, false }, 124 { 0, 0, 0, false }, 125 { 0, 0, 0, false }, 126 { 0, 0, 0, false }, 127 { 0, 0, 0, false }, 128 { 0, 0, 0, false }, 129 { 0, 0, 0, false }, 130 { 0, 0, 0, false }, 131 { 0, 0, 0, false }, 132 { 0, 0, 0, false }, 133 }, 134 { 135 // VESA Resolutions 136 { 800, 600, 30, false }, 137 { 800, 600, 60, false }, 138 { 1024, 768, 30, false }, 139 { 1024, 768, 60, false }, 140 { 1152, 864, 30, false }, 141 { 1152, 864, 60, false }, 142 { 1280, 768, 30, false }, 143 { 1280, 768, 60, false }, 144 { 1280, 800, 30, false }, 145 { 1280, 800, 60, false }, 146 { 1360, 768, 30, false }, 147 { 1360, 768, 60, false }, 148 { 1366, 768, 30, false }, 149 { 1366, 768, 60, false }, 150 { 1280, 1024, 30, false }, 151 { 1280, 1024, 60, false }, 152 { 1400, 1050, 30, false }, 153 { 1400, 1050, 60, false }, 154 { 1440, 900, 30, false }, 155 { 1440, 900, 60, false }, 156 { 1600, 900, 30, false }, 157 { 1600, 900, 60, false }, 158 { 1600, 1200, 30, false }, 159 { 1600, 1200, 60, false }, 160 { 1680, 1024, 30, false }, 161 { 1680, 1024, 60, false }, 162 { 1680, 1050, 30, false }, 163 { 1680, 1050, 60, false }, 164 { 1920, 1200, 30, false }, 165 { 1920, 1200, 60, false }, 166 { 0, 0, 0, false }, 167 { 0, 0, 0, false }, 168 }, 169 { 170 // HH Resolutions 171 { 800, 480, 30, false }, 172 { 800, 480, 60, false }, 173 { 854, 480, 30, false }, 174 { 854, 480, 60, false }, 175 { 864, 480, 30, false }, 176 { 864, 480, 60, false }, 177 { 640, 360, 30, false }, 178 { 640, 360, 60, false }, 179 { 960, 540, 30, false }, 180 { 960, 540, 60, false }, 181 { 848, 480, 30, false }, 182 { 848, 480, 60, false }, 183 { 0, 0, 0, false }, 184 { 0, 0, 0, false }, 185 { 0, 0, 0, false }, 186 { 0, 0, 0, false }, 187 { 0, 0, 0, false }, 188 { 0, 0, 0, false }, 189 { 0, 0, 0, false }, 190 { 0, 0, 0, false }, 191 { 0, 0, 0, false }, 192 { 0, 0, 0, false }, 193 { 0, 0, 0, false }, 194 { 0, 0, 0, false }, 195 { 0, 0, 0, false }, 196 { 0, 0, 0, false }, 197 { 0, 0, 0, false }, 198 { 0, 0, 0, false }, 199 { 0, 0, 0, false }, 200 { 0, 0, 0, false }, 201 { 0, 0, 0, false }, 202 { 0, 0, 0, false }, 203 } 204 }; 205 206 const config_t *config = &kConfigs[type][index]; 207 208 if (config->width == 0) { 209 return false; 210 } 211 212 if (width) { 213 *width = config->width; 214 } 215 216 if (height) { 217 *height = config->height; 218 } 219 220 if (framesPerSecond) { 221 *framesPerSecond = config->framesPerSecond; 222 } 223 224 if (interlaced) { 225 *interlaced = config->interlaced; 226 } 227 228 return true; 229} 230 231bool VideoFormats::parseFormatSpec(const char *spec) { 232 CHECK_EQ(kNumResolutionTypes, 3); 233 234 unsigned native, dummy; 235 236 if (sscanf( 237 spec, 238 "%02x %02x %02x %02x %08X %08X %08X", 239 &native, 240 &dummy, 241 &dummy, 242 &dummy, 243 &mResolutionEnabled[0], 244 &mResolutionEnabled[1], 245 &mResolutionEnabled[2]) != 7) { 246 return false; 247 } 248 249 mNativeIndex = native >> 3; 250 mNativeType = (ResolutionType)(native & 7); 251 252 bool success; 253 if (mNativeType >= kNumResolutionTypes) { 254 success = false; 255 } else { 256 success = GetConfiguration( 257 mNativeType, mNativeIndex, NULL, NULL, NULL, NULL); 258 } 259 260 if (!success) { 261 ALOGW("sink advertised an illegal native resolution, fortunately " 262 "this value is ignored for the time being..."); 263 } 264 265 return true; 266} 267 268AString VideoFormats::getFormatSpec(bool forM4Message) const { 269 CHECK_EQ(kNumResolutionTypes, 3); 270 271 // wfd_video_formats: 272 // 1 byte "native" 273 // 1 byte "preferred-display-mode-supported" 0 or 1 274 // one or more avc codec structures 275 // 1 byte profile 276 // 1 byte level 277 // 4 byte CEA mask 278 // 4 byte VESA mask 279 // 4 byte HH mask 280 // 1 byte latency 281 // 2 byte min-slice-slice 282 // 2 byte slice-enc-params 283 // 1 byte framerate-control-support 284 // max-hres (none or 2 byte) 285 // max-vres (none or 2 byte) 286 287 return StringPrintf( 288 "%02x 00 02 02 %08x %08x %08x 00 0000 0000 00 none none", 289 forM4Message ? 0x00 : ((mNativeIndex << 3) | mNativeType), 290 mResolutionEnabled[0], 291 mResolutionEnabled[1], 292 mResolutionEnabled[2]); 293} 294 295// static 296bool VideoFormats::PickBestFormat( 297 const VideoFormats &sinkSupported, 298 const VideoFormats &sourceSupported, 299 ResolutionType *chosenType, 300 size_t *chosenIndex) { 301#if 0 302 // Support for the native format is a great idea, the spec includes 303 // these features, but nobody supports it and the tests don't validate it. 304 305 ResolutionType nativeType; 306 size_t nativeIndex; 307 sinkSupported.getNativeResolution(&nativeType, &nativeIndex); 308 if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) { 309 if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) { 310 ALOGI("Choosing sink's native resolution"); 311 *chosenType = nativeType; 312 *chosenIndex = nativeIndex; 313 return true; 314 } 315 } else { 316 ALOGW("Sink advertised native resolution that it doesn't " 317 "actually support... ignoring"); 318 } 319 320 sourceSupported.getNativeResolution(&nativeType, &nativeIndex); 321 if (sourceSupported.isResolutionEnabled(nativeType, nativeIndex)) { 322 if (sinkSupported.isResolutionEnabled(nativeType, nativeIndex)) { 323 ALOGI("Choosing source's native resolution"); 324 *chosenType = nativeType; 325 *chosenIndex = nativeIndex; 326 return true; 327 } 328 } else { 329 ALOGW("Source advertised native resolution that it doesn't " 330 "actually support... ignoring"); 331 } 332#endif 333 334 bool first = true; 335 uint32_t bestScore = 0; 336 size_t bestType = 0; 337 size_t bestIndex = 0; 338 for (size_t i = 0; i < kNumResolutionTypes; ++i) { 339 for (size_t j = 0; j < 32; ++j) { 340 size_t width, height, framesPerSecond; 341 bool interlaced; 342 if (!GetConfiguration( 343 (ResolutionType)i, 344 j, 345 &width, &height, &framesPerSecond, &interlaced)) { 346 break; 347 } 348 349 if (!sinkSupported.isResolutionEnabled((ResolutionType)i, j) 350 || !sourceSupported.isResolutionEnabled( 351 (ResolutionType)i, j)) { 352 continue; 353 } 354 355 ALOGV("type %u, index %u, %u x %u %c%u supported", 356 i, j, width, height, interlaced ? 'i' : 'p', framesPerSecond); 357 358 uint32_t score = width * height * framesPerSecond; 359 if (!interlaced) { 360 score *= 2; 361 } 362 363 if (first || score > bestScore) { 364 bestScore = score; 365 bestType = i; 366 bestIndex = j; 367 368 first = false; 369 } 370 } 371 } 372 373 if (first) { 374 return false; 375 } 376 377 *chosenType = (ResolutionType)bestType; 378 *chosenIndex = bestIndex; 379 380 return true; 381} 382 383} // namespace android 384 385