xaVideoDecoderCapabilities.cpp revision 086a6f51a7b12880ed114962136972f89ed70da2
1/* 2 * Copyright (C) 2011 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#include <stdlib.h> 18#include <stdio.h> 19#include <string.h> 20#include <unistd.h> 21#include <sys/time.h> 22#include <fcntl.h> 23 24#include <OMXAL/OpenMAXAL.h> 25#include <OMXAL/OpenMAXAL_Android.h> // for VP8 definitions 26 27#define NUM_ENGINE_INTERFACES 1 28 29char unknown[50]; 30 31//----------------------------------------------------------------- 32/* Exits the application if an error is encountered */ 33#define ExitOnError(x) ExitOnErrorFunc(x,__LINE__) 34 35void ExitOnErrorFunc( XAresult result , int line) 36{ 37 if (XA_RESULT_SUCCESS != result) { 38 fprintf(stderr, "Error %u encountered at line %d, exiting\n", result, line); 39 exit(EXIT_FAILURE); 40 } 41} 42 43const char* videoCodecIdToString(XAuint32 decoderId) { 44 switch(decoderId) { 45 case XA_VIDEOCODEC_MPEG2: return "XA_VIDEOCODEC_MPEG2"; break; 46 case XA_VIDEOCODEC_H263: return "XA_VIDEOCODEC_H263"; break; 47 case XA_VIDEOCODEC_MPEG4: return "XA_VIDEOCODEC_MPEG4"; break; 48 case XA_VIDEOCODEC_AVC: return "XA_VIDEOCODEC_AVC"; break; 49 case XA_VIDEOCODEC_VC1: return "XA_VIDEOCODEC_VC1"; break; 50 case XA_ANDROID_VIDEOCODEC_VP8: return "XA_ANDROID_VIDEOCODEC_VP8"; break; 51 default: 52 sprintf(unknown, "Video codec %d unknown to OpenMAX AL", decoderId); 53 return unknown; 54 } 55} 56 57// Use a table of [integer, string] entries to map an integer to a string 58 59typedef struct { 60 XAuint32 id; 61 const char *string; 62} id_to_string_t; 63 64const char *id_to_string(XAuint32 id, const id_to_string_t *table, size_t numEntries) 65{ 66 size_t i; 67 for (i = 0; i < numEntries; ++i) { 68 if (id == table[i].id) { 69 return table[i].string; 70 } 71 } 72 return "Unknown"; 73} 74 75// Use a table of [integer, table] entries to map a pair of integers to a string 76 77typedef struct { 78 XAuint32 id1; 79 const id_to_string_t *id2_table; 80 size_t id2_numEntries; 81} id_pair_to_string_t; 82 83const char *id_pair_to_string(XAuint32 id1, XAuint32 id2, const id_pair_to_string_t *table, 84 size_t numEntries) 85{ 86 size_t i; 87 for (i = 0; i < numEntries; ++i) { 88 if (id1 == table[i].id1) { 89 return id_to_string(id2, table[i].id2_table, table[i].id2_numEntries); 90 } 91 } 92 return "Unknown"; 93} 94 95// Map a video codec and profile to string 96 97const char *videoProfileToString(XAuint32 codec, XAuint32 profile) { 98 // http://en.wikipedia.org/wiki/H.262/MPEG-2_Part_2 99 static const id_to_string_t MPEG2[] = { 100 {XA_VIDEOPROFILE_MPEG2_SIMPLE, "Simple"}, 101 {XA_VIDEOPROFILE_MPEG2_MAIN, "Main"}, 102 {XA_VIDEOPROFILE_MPEG2_422, "4:2:2"}, 103 {XA_VIDEOPROFILE_MPEG2_SNR, "SNR Scalable"}, 104 {XA_VIDEOPROFILE_MPEG2_SPATIAL, "Spatially Scalable"}, 105 {XA_VIDEOPROFILE_MPEG2_HIGH, "High"}, 106 }, H263[] = { 107 {XA_VIDEOPROFILE_H263_BASELINE, "baseline"}, 108 {XA_VIDEOPROFILE_H263_H320CODING, "H320 coding"}, 109 {XA_VIDEOPROFILE_H263_BACKWARDCOMPATIBLE, "backwards compatible"}, 110 {XA_VIDEOPROFILE_H263_ISWV2, "isw v2"}, 111 {XA_VIDEOPROFILE_H263_ISWV3, "isw v3"}, 112 {XA_VIDEOPROFILE_H263_HIGHCOMPRESSION, "high compression"}, 113 {XA_VIDEOPROFILE_H263_INTERNET, "internet"}, 114 {XA_VIDEOPROFILE_H263_INTERLACE, "interlace"}, 115 {XA_VIDEOPROFILE_H263_HIGHLATENCY, "high latency"}, 116 }, MPEG4[] = { 117 {XA_VIDEOPROFILE_MPEG4_SIMPLE, "simple"}, 118 {XA_VIDEOPROFILE_MPEG4_SIMPLESCALABLE, "simple scalable"}, 119 {XA_VIDEOPROFILE_MPEG4_CORE, "core"}, 120 {XA_VIDEOPROFILE_MPEG4_MAIN, "main"}, 121 {XA_VIDEOPROFILE_MPEG4_NBIT, "nbit"}, 122 {XA_VIDEOPROFILE_MPEG4_SCALABLETEXTURE, "scalable texture"}, 123 {XA_VIDEOPROFILE_MPEG4_SIMPLEFACE, "simple face"}, 124 {XA_VIDEOPROFILE_MPEG4_SIMPLEFBA, "simple fba"}, 125 {XA_VIDEOPROFILE_MPEG4_BASICANIMATED, "basic animated"}, 126 {XA_VIDEOPROFILE_MPEG4_HYBRID, "hybrid"}, 127 {XA_VIDEOPROFILE_MPEG4_ADVANCEDREALTIME, "advanced realtime"}, 128 {XA_VIDEOPROFILE_MPEG4_CORESCALABLE, "core scalable"}, 129 {XA_VIDEOPROFILE_MPEG4_ADVANCEDCODING, "advanced coding"}, 130 {XA_VIDEOPROFILE_MPEG4_ADVANCEDCORE, "advanced core"}, 131 {XA_VIDEOPROFILE_MPEG4_ADVANCEDSCALABLE, "advanced scalable"}, 132 // FIXME OpenMAX AL is out-of-date with respect to OpenMAX IL 133 {16, "advanced simple"}, 134 }, AVC[] = { 135 {XA_VIDEOPROFILE_AVC_BASELINE, "Baseline"}, 136 {XA_VIDEOPROFILE_AVC_MAIN, "Main"}, 137 {XA_VIDEOPROFILE_AVC_EXTENDED, "Extended"}, 138 {XA_VIDEOPROFILE_AVC_HIGH, "High"}, 139 {XA_VIDEOPROFILE_AVC_HIGH10, "High 10"}, 140 {XA_VIDEOPROFILE_AVC_HIGH422, "High 4:2:2"}, 141 {XA_VIDEOPROFILE_AVC_HIGH444, "High 4:4:4"}, 142 }, VC1[] = { 143 // FIXME sic should be XA_VIDEOPROFILE_* 144 {XA_VIDEOLEVEL_VC1_SIMPLE, "simple"}, 145 {XA_VIDEOLEVEL_VC1_MAIN, "main"}, 146 {XA_VIDEOLEVEL_VC1_ADVANCED, "advanced"}, 147 }; 148 static const id_pair_to_string_t table[] = { 149 {XA_VIDEOCODEC_MPEG2, MPEG2, sizeof(MPEG2) / sizeof(MPEG2[0])}, 150 {XA_VIDEOCODEC_H263, H263, sizeof(H263) / sizeof(H263[0])}, 151 {XA_VIDEOCODEC_MPEG4, MPEG4, sizeof(MPEG4) / sizeof(MPEG4[0])}, 152 {XA_VIDEOCODEC_AVC, AVC, sizeof(AVC) / sizeof(AVC[0])}, 153 {XA_VIDEOCODEC_VC1, VC1, sizeof(VC1) / sizeof(VC1[0])}, 154 }; 155 return id_pair_to_string(codec, profile, table, sizeof(table) / sizeof(table[0])); 156} 157 158// Map a video codec and level to string 159 160const char* videoLevelToString(XAuint32 codec, XAuint32 level) { 161 static const id_to_string_t MPEG2[] = { 162 {XA_VIDEOLEVEL_MPEG2_LL, "Low"}, 163 {XA_VIDEOLEVEL_MPEG2_ML, "Main"}, 164 {XA_VIDEOLEVEL_MPEG2_H14, "H-14"}, 165 {XA_VIDEOLEVEL_MPEG2_HL, "High"}, 166 }, H263[]= { 167 {XA_VIDEOLEVEL_H263_10, "10"}, 168 {XA_VIDEOLEVEL_H263_20, "20"}, 169 {XA_VIDEOLEVEL_H263_30, "30"}, 170 {XA_VIDEOLEVEL_H263_40, "40"}, 171 {XA_VIDEOLEVEL_H263_45, "45"}, 172 {XA_VIDEOLEVEL_H263_50, "50"}, 173 {XA_VIDEOLEVEL_H263_60, "60"}, 174 {XA_VIDEOLEVEL_H263_70, "70"}, 175 }, MPEG4[] = { 176 {XA_VIDEOLEVEL_MPEG4_0, "0"}, 177 {XA_VIDEOLEVEL_MPEG4_0b, "0b"}, 178 {XA_VIDEOLEVEL_MPEG4_1, "1"}, 179 {XA_VIDEOLEVEL_MPEG4_2, "2"}, 180 {XA_VIDEOLEVEL_MPEG4_3, "3"}, 181 {XA_VIDEOLEVEL_MPEG4_4, "4"}, 182 {XA_VIDEOLEVEL_MPEG4_4a, "4a"}, 183 // FIXME OpenMAX AL is out-of-date with respect to OpenMAX IL 184 {8, "5"}, 185 }, AVC[] = { 186 {XA_VIDEOLEVEL_AVC_1, "1"}, 187 {XA_VIDEOLEVEL_AVC_1B, "1B"}, 188 {XA_VIDEOLEVEL_AVC_11, "1.1"}, 189 {XA_VIDEOLEVEL_AVC_12, "1.2"}, 190 {XA_VIDEOLEVEL_AVC_13, "1.3"}, 191 {XA_VIDEOLEVEL_AVC_2, "2"}, 192 {XA_VIDEOLEVEL_AVC_21, "2.1"}, 193 {XA_VIDEOLEVEL_AVC_22, "2.2"}, 194 {XA_VIDEOLEVEL_AVC_3, "3"}, 195 {XA_VIDEOLEVEL_AVC_31, "3.1"}, 196 {XA_VIDEOLEVEL_AVC_32, "3.2"}, 197 {XA_VIDEOLEVEL_AVC_4, "4"}, 198 {XA_VIDEOLEVEL_AVC_41, "4.1"}, 199 {XA_VIDEOLEVEL_AVC_42, "4.2"}, 200 {XA_VIDEOLEVEL_AVC_5, "5"}, 201 {XA_VIDEOLEVEL_AVC_51, "5.1"}, 202 }, VC1[] = { 203 {XA_VIDEOLEVEL_VC1_LOW, "Low"}, 204 {XA_VIDEOLEVEL_VC1_MEDIUM, "Medium"}, 205 {XA_VIDEOLEVEL_VC1_HIGH, "High"}, 206 {XA_VIDEOLEVEL_VC1_L0, "L0"}, 207 {XA_VIDEOLEVEL_VC1_L1, "L1"}, 208 {XA_VIDEOLEVEL_VC1_L2, "L2"}, 209 {XA_VIDEOLEVEL_VC1_L3, "L3"}, 210 {XA_VIDEOLEVEL_VC1_L4, "L4"}, 211 }; 212 static const id_pair_to_string_t table[] = { 213 {XA_VIDEOCODEC_MPEG2, MPEG2, sizeof(MPEG2) / sizeof(MPEG2[0])}, 214 {XA_VIDEOCODEC_H263, H263, sizeof(H263) / sizeof(H263[0])}, 215 {XA_VIDEOCODEC_MPEG4, MPEG4, sizeof(MPEG4) / sizeof(MPEG4[0])}, 216 {XA_VIDEOCODEC_AVC, AVC, sizeof(AVC) / sizeof(AVC[0])}, 217 {XA_VIDEOCODEC_VC1, VC1, sizeof(VC1) / sizeof(VC1[0])}, 218 }; 219 return id_pair_to_string(codec, level, table, sizeof(table) / sizeof(table[0])); 220} 221 222//----------------------------------------------------------------- 223void TestVideoDecoderCapabilities() { 224 225 XAObjectItf xa; 226 XAresult res; 227 228 /* parameters for the OpenMAX AL engine creation */ 229 XAEngineOption EngineOption[] = { 230 {(XAuint32) XA_ENGINEOPTION_THREADSAFE, (XAuint32) XA_BOOLEAN_TRUE} 231 }; 232 XAInterfaceID itfIidArray[NUM_ENGINE_INTERFACES] = { XA_IID_VIDEODECODERCAPABILITIES }; 233 XAboolean itfRequired[NUM_ENGINE_INTERFACES] = { XA_BOOLEAN_TRUE }; 234 235 /* create OpenMAX AL engine */ 236 res = xaCreateEngine( &xa, 1, EngineOption, NUM_ENGINE_INTERFACES, itfIidArray, itfRequired); 237 ExitOnError(res); 238 239 /* realize the engine in synchronous mode. */ 240 res = (*xa)->Realize(xa, XA_BOOLEAN_FALSE); ExitOnError(res); 241 242 /* Get the video decoder capabilities interface which was explicitly requested */ 243 XAVideoDecoderCapabilitiesItf decItf; 244 res = (*xa)->GetInterface(xa, XA_IID_VIDEODECODERCAPABILITIES, (void*)&decItf); 245 ExitOnError(res); 246 247 /* Query the platform capabilities */ 248 XAuint32 numDecoders = 0; 249 XAuint32 *decoderIds = NULL; 250 251 /* -> Number of decoders */ 252 res = (*decItf)->GetVideoDecoders(decItf, &numDecoders, NULL); ExitOnError(res); 253 fprintf(stdout, "Found %d video decoders\n", numDecoders); 254 if (0 == numDecoders) { 255 fprintf(stderr, "0 video decoders is not an acceptable number, exiting\n"); 256 goto destroyRes; 257 } 258 259 /* -> Decoder list */ 260 decoderIds = (XAuint32 *) malloc(numDecoders * sizeof(XAuint32)); 261 res = (*decItf)->GetVideoDecoders(decItf, &numDecoders, decoderIds); ExitOnError(res); 262 fprintf(stdout, "Decoders:\n"); 263 for(XAuint32 i = 0 ; i < numDecoders ; i++) { 264 fprintf(stdout, "decoder %d is %s\n", i, videoCodecIdToString(decoderIds[i])); 265 } 266 267 /* -> Decoder capabilities */ 268 /* for each decoder */ 269 for(XAuint32 i = 0 ; i < numDecoders ; i++) { 270 XAuint32 nbCombinations = 0; 271 /* get the number of profile / level combinations */ 272 res = (*decItf)->GetVideoDecoderCapabilities(decItf, decoderIds[i], &nbCombinations, NULL); 273 ExitOnError(res); 274 fprintf(stdout, "decoder %s has %d profile/level combinations:\n\t", 275 videoCodecIdToString(decoderIds[i]), nbCombinations); 276 /* display the profile / level combinations */ 277 for(XAuint32 pl = 0 ; pl < nbCombinations ; pl++) { 278 XAVideoCodecDescriptor decDescriptor; 279 XAuint32 decoder = decoderIds[i]; 280 res = (*decItf)->GetVideoDecoderCapabilities(decItf, decoder, &pl, &decDescriptor); 281 ExitOnError(res); 282 XAuint32 profile = decDescriptor.profileSetting; 283 XAuint32 level = decDescriptor.levelSetting; 284 fprintf(stdout, "%u/%u ", profile, level); 285 ExitOnError(res); 286 printf("(%s/%s) ", videoProfileToString(decoder, profile), 287 videoLevelToString(decoder, level)); 288 } 289 fprintf(stdout, "\n"); 290 } 291 292destroyRes: 293 free(decoderIds); 294 295 /* shutdown OpenMAX AL */ 296 (*xa)->Destroy(xa); 297} 298 299 300//----------------------------------------------------------------- 301int main(int argc __unused, char* const argv[]) 302{ 303 XAresult result; 304 XAObjectItf sl; 305 306 fprintf(stdout, "OpenMAX AL test %s: exercises SLAudioDecoderCapabiltiesItf ", argv[0]); 307 fprintf(stdout, "and displays the list of supported video decoders, and for each, lists the "); 308 fprintf(stdout, "profile / levels combinations, that map to the constants defined in "); 309 fprintf(stdout, "\"XA_VIDEOPROFILE and XA_VIDEOLEVEL\" section of the specification\n\n"); 310 311 TestVideoDecoderCapabilities(); 312 313 return EXIT_SUCCESS; 314} 315