001package com.baidu.cloud.media.player; 002 003import android.os.Bundle; 004import android.text.TextUtils; 005 006import java.util.ArrayList; 007import java.util.Locale; 008 009@SuppressWarnings("SameParameterValue") 010public class BDCloudMediaMeta { 011 // media meta 012 public static final String IJKM_KEY_FORMAT = "format"; 013 public static final String IJKM_KEY_DURATION_US = "duration_us"; 014 public static final String IJKM_KEY_START_US = "start_us"; 015 public static final String IJKM_KEY_BITRATE = "bitrate"; 016 public static final String IJKM_KEY_VIDEO_STREAM = "video"; 017 public static final String IJKM_KEY_AUDIO_STREAM = "audio"; 018 019 // stream meta 020 public static final String IJKM_KEY_TYPE = "type"; 021 public static final String IJKM_VAL_TYPE__VIDEO = "video"; 022 public static final String IJKM_VAL_TYPE__AUDIO = "audio"; 023 public static final String IJKM_VAL_TYPE__TIMEDTEXT = "timedtext"; 024 public static final String IJKM_VAL_TYPE__UNKNOWN = "unknown"; 025 public static final String IJKM_KEY_LANGUAGE = "language"; 026 027 public static final String IJKM_KEY_CODEC_NAME = "codec_name"; 028 public static final String IJKM_KEY_CODEC_PROFILE = "codec_profile"; 029 public static final String IJKM_KEY_CODEC_LEVEL = "codec_level"; 030 public static final String IJKM_KEY_CODEC_LONG_NAME = "codec_long_name"; 031 public static final String IJKM_KEY_CODEC_PIXEL_FORMAT = "codec_pixel_format"; 032 public static final String IJKM_KEY_CODEC_PROFILE_ID = "codec_profile_id"; 033 034 // stream: video 035 public static final String IJKM_KEY_WIDTH = "width"; 036 public static final String IJKM_KEY_HEIGHT = "height"; 037 public static final String IJKM_KEY_FPS_NUM = "fps_num"; 038 public static final String IJKM_KEY_FPS_DEN = "fps_den"; 039 public static final String IJKM_KEY_TBR_NUM = "tbr_num"; 040 public static final String IJKM_KEY_TBR_DEN = "tbr_den"; 041 public static final String IJKM_KEY_SAR_NUM = "sar_num"; 042 public static final String IJKM_KEY_SAR_DEN = "sar_den"; 043 // stream: audio 044 public static final String IJKM_KEY_SAMPLE_RATE = "sample_rate"; 045 public static final String IJKM_KEY_CHANNEL_LAYOUT = "channel_layout"; 046 047 public static final String IJKM_KEY_STREAMS = "streams"; 048 049 public static final long AV_CH_FRONT_LEFT = 0x00000001; 050 public static final long AV_CH_FRONT_RIGHT = 0x00000002; 051 public static final long AV_CH_FRONT_CENTER = 0x00000004; 052 public static final long AV_CH_LOW_FREQUENCY = 0x00000008; 053 public static final long AV_CH_BACK_LEFT = 0x00000010; 054 public static final long AV_CH_BACK_RIGHT = 0x00000020; 055 public static final long AV_CH_FRONT_LEFT_OF_CENTER = 0x00000040; 056 public static final long AV_CH_FRONT_RIGHT_OF_CENTER = 0x00000080; 057 public static final long AV_CH_BACK_CENTER = 0x00000100; 058 public static final long AV_CH_SIDE_LEFT = 0x00000200; 059 public static final long AV_CH_SIDE_RIGHT = 0x00000400; 060 public static final long AV_CH_TOP_CENTER = 0x00000800; 061 public static final long AV_CH_TOP_FRONT_LEFT = 0x00001000; 062 public static final long AV_CH_TOP_FRONT_CENTER = 0x00002000; 063 public static final long AV_CH_TOP_FRONT_RIGHT = 0x00004000; 064 public static final long AV_CH_TOP_BACK_LEFT = 0x00008000; 065 public static final long AV_CH_TOP_BACK_CENTER = 0x00010000; 066 public static final long AV_CH_TOP_BACK_RIGHT = 0x00020000; 067 public static final long AV_CH_STEREO_LEFT = 0x20000000; 068 public static final long AV_CH_STEREO_RIGHT = 0x40000000; 069 public static final long AV_CH_WIDE_LEFT = 0x0000000080000000L; 070 public static final long AV_CH_WIDE_RIGHT = 0x0000000100000000L; 071 public static final long AV_CH_SURROUND_DIRECT_LEFT = 0x0000000200000000L; 072 public static final long AV_CH_SURROUND_DIRECT_RIGHT = 0x0000000400000000L; 073 public static final long AV_CH_LOW_FREQUENCY_2 = 0x0000000800000000L; 074 075 public static final long AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER); 076 public static final long AV_CH_LAYOUT_STEREO = (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT); 077 public static final long AV_CH_LAYOUT_2POINT1 = (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY); 078 public static final long AV_CH_LAYOUT_2_1 = (AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER); 079 public static final long AV_CH_LAYOUT_SURROUND = (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER); 080 public static final long AV_CH_LAYOUT_3POINT1 = (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY); 081 public static final long AV_CH_LAYOUT_4POINT0 = (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_CENTER); 082 public static final long AV_CH_LAYOUT_4POINT1 = (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY); 083 public static final long AV_CH_LAYOUT_2_2 = (AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); 084 public static final long AV_CH_LAYOUT_QUAD = (AV_CH_LAYOUT_STEREO | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 085 public static final long AV_CH_LAYOUT_5POINT0 = (AV_CH_LAYOUT_SURROUND | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); 086 public static final long AV_CH_LAYOUT_5POINT1 = (AV_CH_LAYOUT_5POINT0 | AV_CH_LOW_FREQUENCY); 087 public static final long AV_CH_LAYOUT_5POINT0_BACK = (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 088 public static final long AV_CH_LAYOUT_5POINT1_BACK = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_LOW_FREQUENCY); 089 public static final long AV_CH_LAYOUT_6POINT0 = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_CENTER); 090 public static final long AV_CH_LAYOUT_6POINT0_FRONT = (AV_CH_LAYOUT_2_2 | AV_CH_FRONT_LEFT_OF_CENTER 091 | AV_CH_FRONT_RIGHT_OF_CENTER); 092 public static final long AV_CH_LAYOUT_HEXAGONAL = (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_BACK_CENTER); 093 public static final long AV_CH_LAYOUT_6POINT1 = (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER); 094 public static final long AV_CH_LAYOUT_6POINT1_BACK = (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_BACK_CENTER); 095 public static final long AV_CH_LAYOUT_6POINT1_FRONT = (AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_LOW_FREQUENCY); 096 public static final long AV_CH_LAYOUT_7POINT0 = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 097 public static final long AV_CH_LAYOUT_7POINT0_FRONT = (AV_CH_LAYOUT_5POINT0 | AV_CH_FRONT_LEFT_OF_CENTER 098 | AV_CH_FRONT_RIGHT_OF_CENTER); 099 public static final long AV_CH_LAYOUT_7POINT1 = (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); 100 public static final long AV_CH_LAYOUT_7POINT1_WIDE = (AV_CH_LAYOUT_5POINT1 | AV_CH_FRONT_LEFT_OF_CENTER 101 | AV_CH_FRONT_RIGHT_OF_CENTER); 102 public static final long AV_CH_LAYOUT_7POINT1_WIDE_BACK = (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_FRONT_LEFT_OF_CENTER 103 | AV_CH_FRONT_RIGHT_OF_CENTER); 104 public static final long AV_CH_LAYOUT_OCTAGONAL = (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_LEFT | AV_CH_BACK_CENTER 105 | AV_CH_BACK_RIGHT); 106 public static final long AV_CH_LAYOUT_STEREO_DOWNMIX = (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT); 107 108 public static final int FF_PROFILE_H264_CONSTRAINED = (1 << 9); // 8+1; 109 // constraint_set1_flag 110 public static final int FF_PROFILE_H264_INTRA = (1 << 11); // 8+3; 111 // constraint_set3_flag 112 113 public static final int FF_PROFILE_H264_BASELINE = 66; 114 public static final int FF_PROFILE_H264_CONSTRAINED_BASELINE = (66 | FF_PROFILE_H264_CONSTRAINED); 115 public static final int FF_PROFILE_H264_MAIN = 77; 116 public static final int FF_PROFILE_H264_EXTENDED = 88; 117 public static final int FF_PROFILE_H264_HIGH = 100; 118 public static final int FF_PROFILE_H264_HIGH_10 = 110; 119 public static final int FF_PROFILE_H264_HIGH_10_INTRA = (110 | FF_PROFILE_H264_INTRA); 120 public static final int FF_PROFILE_H264_HIGH_422 = 122; 121 public static final int FF_PROFILE_H264_HIGH_422_INTRA = (122 | FF_PROFILE_H264_INTRA); 122 public static final int FF_PROFILE_H264_HIGH_444 = 144; 123 public static final int FF_PROFILE_H264_HIGH_444_PREDICTIVE = 244; 124 public static final int FF_PROFILE_H264_HIGH_444_INTRA = (244 | FF_PROFILE_H264_INTRA); 125 public static final int FF_PROFILE_H264_CAVLC_444 = 44; 126 127 public Bundle mMediaMeta; 128 129 public String mFormat; 130 public long mDurationUS; 131 public long mStartUS; 132 public long mBitrate; 133 134 public final ArrayList<BDCloudStreamMeta> mStreams = new ArrayList<BDCloudStreamMeta>(); 135 public BDCloudStreamMeta mVideoStream; 136 public BDCloudStreamMeta mAudioStream; 137 138 public String getString(String key) { 139 return mMediaMeta.getString(key); 140 } 141 142 public int getInt(String key) { 143 return getInt(key, 0); 144 } 145 146 public int getInt(String key, int defaultValue) { 147 String value = getString(key); 148 if (TextUtils.isEmpty(value)) { 149 return defaultValue; 150 } 151 152 try { 153 return Integer.parseInt(value); 154 } catch (NumberFormatException e) { 155 return defaultValue; 156 } 157 } 158 159 public long getLong(String key) { 160 return getLong(key, 0); 161 } 162 163 public long getLong(String key, long defaultValue) { 164 String value = getString(key); 165 if (TextUtils.isEmpty(value)) { 166 return defaultValue; 167 } 168 169 try { 170 return Long.parseLong(value); 171 } catch (NumberFormatException e) { 172 return defaultValue; 173 } 174 } 175 176 public ArrayList<Bundle> getParcelableArrayList(String key) { 177 return mMediaMeta.getParcelableArrayList(key); 178 } 179 180 public String getDurationInline() { 181 long duration = mDurationUS + 5000; 182 long secs = duration / 1000000; 183 long mins = secs / 60; 184 secs %= 60; 185 long hours = mins / 60; 186 mins %= 60; 187 return String.format(Locale.US, "%02d:%02d:%02d", hours, mins, secs); 188 } 189 190 public static BDCloudMediaMeta parse(Bundle mediaMeta) { 191 if (mediaMeta == null) { 192 return null; 193 } 194 195 BDCloudMediaMeta meta = new BDCloudMediaMeta(); 196 meta.mMediaMeta = mediaMeta; 197 198 meta.mFormat = meta.getString(IJKM_KEY_FORMAT); 199 meta.mDurationUS = meta.getLong(IJKM_KEY_DURATION_US); 200 meta.mStartUS = meta.getLong(IJKM_KEY_START_US); 201 meta.mBitrate = meta.getLong(IJKM_KEY_BITRATE); 202 203 int videoStreamIndex = meta.getInt(IJKM_KEY_VIDEO_STREAM, -1); 204 int audioStreamIndex = meta.getInt(IJKM_KEY_AUDIO_STREAM, -1); 205 206 ArrayList<Bundle> streams = meta.getParcelableArrayList(IJKM_KEY_STREAMS); 207 if (streams == null) { 208 return meta; 209 } 210 211 int index = -1; 212 for (Bundle streamBundle : streams) { 213 index++; 214 215 if (streamBundle == null) { 216 continue; 217 } 218 219 BDCloudStreamMeta streamMeta = new BDCloudStreamMeta(index); 220 streamMeta.mMeta = streamBundle; 221 streamMeta.mType = streamMeta.getString(IJKM_KEY_TYPE); 222 streamMeta.mLanguage = streamMeta.getString(IJKM_KEY_LANGUAGE); 223 if (TextUtils.isEmpty(streamMeta.mType)) { 224 continue; 225 } 226 227 streamMeta.mCodecName = streamMeta.getString(IJKM_KEY_CODEC_NAME); 228 streamMeta.mCodecProfile = streamMeta.getString(IJKM_KEY_CODEC_PROFILE); 229 streamMeta.mCodecLongName = streamMeta.getString(IJKM_KEY_CODEC_LONG_NAME); 230 streamMeta.mBitrate = streamMeta.getInt(IJKM_KEY_BITRATE); 231 232 if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__VIDEO)) { 233 streamMeta.mWidth = streamMeta.getInt(IJKM_KEY_WIDTH); 234 streamMeta.mHeight = streamMeta.getInt(IJKM_KEY_HEIGHT); 235 streamMeta.mFpsNum = streamMeta.getInt(IJKM_KEY_FPS_NUM); 236 streamMeta.mFpsDen = streamMeta.getInt(IJKM_KEY_FPS_DEN); 237 streamMeta.mTbrNum = streamMeta.getInt(IJKM_KEY_TBR_NUM); 238 streamMeta.mTbrDen = streamMeta.getInt(IJKM_KEY_TBR_DEN); 239 streamMeta.mSarNum = streamMeta.getInt(IJKM_KEY_SAR_NUM); 240 streamMeta.mSarDen = streamMeta.getInt(IJKM_KEY_SAR_DEN); 241 242 if (videoStreamIndex == index) { 243 meta.mVideoStream = streamMeta; 244 } 245 } else if (streamMeta.mType.equalsIgnoreCase(IJKM_VAL_TYPE__AUDIO)) { 246 streamMeta.mSampleRate = streamMeta.getInt(IJKM_KEY_SAMPLE_RATE); 247 streamMeta.mChannelLayout = streamMeta.getLong(IJKM_KEY_CHANNEL_LAYOUT); 248 249 if (audioStreamIndex == index) { 250 meta.mAudioStream = streamMeta; 251 } 252 } 253 meta.mStreams.add(streamMeta); 254 } 255 256 return meta; 257 } 258 259 public static class BDCloudStreamMeta { 260 public Bundle mMeta; 261 262 public final int mIndex; 263 public String mType; 264 public String mLanguage; 265 266 // common 267 public String mCodecName; 268 public String mCodecProfile; 269 public String mCodecLongName; 270 public long mBitrate; 271 272 // video 273 public int mWidth; 274 public int mHeight; 275 public int mFpsNum; 276 public int mFpsDen; 277 public int mTbrNum; 278 public int mTbrDen; 279 public int mSarNum; 280 public int mSarDen; 281 282 // audio 283 public int mSampleRate; 284 public long mChannelLayout; 285 286 public BDCloudStreamMeta(int index) { 287 mIndex = index; 288 } 289 290 public String getString(String key) { 291 return mMeta.getString(key); 292 } 293 294 public int getInt(String key) { 295 return getInt(key, 0); 296 } 297 298 public int getInt(String key, int defaultValue) { 299 String value = getString(key); 300 if (TextUtils.isEmpty(value)) { 301 return defaultValue; 302 } 303 304 try { 305 return Integer.parseInt(value); 306 } catch (NumberFormatException e) { 307 return defaultValue; 308 } 309 } 310 311 public long getLong(String key) { 312 return getLong(key, 0); 313 } 314 315 public long getLong(String key, long defaultValue) { 316 String value = getString(key); 317 if (TextUtils.isEmpty(value)) { 318 return defaultValue; 319 } 320 321 try { 322 return Long.parseLong(value); 323 } catch (NumberFormatException e) { 324 return defaultValue; 325 } 326 } 327 328 public String getCodecLongNameInline() { 329 if (!TextUtils.isEmpty(mCodecLongName)) { 330 return mCodecLongName; 331 } else if (!TextUtils.isEmpty(mCodecName)) { 332 return mCodecName; 333 } else { 334 return "N/A"; 335 } 336 } 337 338 public String getCodecShortNameInline() { 339 if (!TextUtils.isEmpty(mCodecName)) { 340 return mCodecName; 341 } else { 342 return "N/A"; 343 } 344 } 345 346 public String getResolutionInline() { 347 if (mWidth <= 0 || mHeight <= 0) { 348 return "N/A"; 349 } else if (mSarNum <= 0 || mSarDen <= 0) { 350 return String.format(Locale.US, "%d x %d", mWidth, mHeight); 351 } else { 352 return String.format(Locale.US, "%d x %d [SAR %d:%d]", mWidth, mHeight, mSarNum, mSarDen); 353 } 354 } 355 356 public String getFpsInline() { 357 if (mFpsNum <= 0 || mFpsDen <= 0) { 358 return "N/A"; 359 } else { 360 return String.valueOf(((float) (mFpsNum)) / mFpsDen); 361 } 362 } 363 364 public String getBitrateInline() { 365 if (mBitrate <= 0) { 366 return "N/A"; 367 } else if (mBitrate < 1000) { 368 return String.format(Locale.US, "%d bit/s", mBitrate); 369 } else { 370 return String.format(Locale.US, "%d kb/s", mBitrate / 1000); 371 } 372 } 373 374 public String getSampleRateInline() { 375 if (mSampleRate <= 0) { 376 return "N/A"; 377 } else { 378 return String.format(Locale.US, "%d Hz", mSampleRate); 379 } 380 } 381 382 public String getChannelLayoutInline() { 383 if (mChannelLayout <= 0) { 384 return "N/A"; 385 } else { 386 if (mChannelLayout == AV_CH_LAYOUT_MONO) { 387 return "mono"; 388 } else if (mChannelLayout == AV_CH_LAYOUT_STEREO) { 389 return "stereo"; 390 } else { 391 return String.format(Locale.US, "%x", mChannelLayout); 392 } 393 } 394 } 395 } 396}