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