1 /* 2 * Copyright (C) 2024 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 package android.media.metrics; 17 18 import static com.android.media.editing.flags.Flags.FLAG_ADD_MEDIA_METRICS_EDITING; 19 20 import android.annotation.FlaggedApi; 21 import android.annotation.FloatRange; 22 import android.annotation.IntDef; 23 import android.annotation.IntRange; 24 import android.annotation.LongDef; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.SuppressLint; 28 import android.hardware.DataSpace; 29 import android.media.MediaCodec; 30 import android.os.Parcel; 31 import android.os.Parcelable; 32 import android.util.Size; 33 34 import java.lang.annotation.Retention; 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.Objects; 38 39 /** Represents information about a piece of media (for example, an audio or video file). */ 40 @FlaggedApi(FLAG_ADD_MEDIA_METRICS_EDITING) 41 public final class MediaItemInfo implements Parcelable { 42 43 /** @hide */ 44 @IntDef( 45 prefix = {"SOURCE_TYPE_"}, 46 value = { 47 SOURCE_TYPE_UNSPECIFIED, 48 SOURCE_TYPE_GALLERY, 49 SOURCE_TYPE_CAMERA, 50 SOURCE_TYPE_EDITING_SESSION, 51 SOURCE_TYPE_LOCAL_FILE, 52 SOURCE_TYPE_REMOTE_FILE, 53 SOURCE_TYPE_REMOTE_LIVE_STREAM, 54 SOURCE_TYPE_GENERATED, 55 }) 56 @Retention(java.lang.annotation.RetentionPolicy.SOURCE) 57 public @interface SourceType {} 58 59 /** The media item's source is not known. */ 60 public static final int SOURCE_TYPE_UNSPECIFIED = 0; 61 62 /** The media item came from the device gallery. */ 63 public static final int SOURCE_TYPE_GALLERY = 1; 64 65 /** The media item came directly from camera capture. */ 66 public static final int SOURCE_TYPE_CAMERA = 2; 67 68 /** The media item was output by a previous editing session. */ 69 public static final int SOURCE_TYPE_EDITING_SESSION = 3; 70 71 /** The media item is stored on the local device's file system. */ 72 public static final int SOURCE_TYPE_LOCAL_FILE = 4; 73 74 /** The media item is a remote file (for example, it's loaded from an HTTP server). */ 75 public static final int SOURCE_TYPE_REMOTE_FILE = 5; 76 77 /** The media item is a remotely-served live stream. */ 78 public static final int SOURCE_TYPE_REMOTE_LIVE_STREAM = 6; 79 80 /** The media item was generated by another system. */ 81 public static final int SOURCE_TYPE_GENERATED = 7; 82 83 /** @hide */ 84 @LongDef( 85 prefix = {"DATA_TYPE_"}, 86 flag = true, 87 value = { 88 DATA_TYPE_IMAGE, 89 DATA_TYPE_VIDEO, 90 DATA_TYPE_AUDIO, 91 DATA_TYPE_METADATA, 92 DATA_TYPE_DEPTH, 93 DATA_TYPE_GAIN_MAP, 94 DATA_TYPE_HIGH_FRAME_RATE, 95 DATA_TYPE_SPEED_SETTING_CUE_POINTS, 96 DATA_TYPE_GAPLESS, 97 DATA_TYPE_SPATIAL_AUDIO, 98 DATA_TYPE_HIGH_DYNAMIC_RANGE_VIDEO, 99 }) 100 @Retention(java.lang.annotation.RetentionPolicy.SOURCE) 101 public @interface DataType {} 102 103 /** The media item includes image data. */ 104 public static final long DATA_TYPE_IMAGE = 1L; 105 106 /** The media item includes video data. */ 107 public static final long DATA_TYPE_VIDEO = 1L << 1; 108 109 /** The media item includes audio data. */ 110 public static final long DATA_TYPE_AUDIO = 1L << 2; 111 112 /** 113 * The media item includes static media container metadata (for example, capture frame rate or 114 * location information). 115 */ 116 public static final long DATA_TYPE_METADATA = 1L << 3; 117 118 /** The media item includes depth (z-distance) information. */ 119 public static final long DATA_TYPE_DEPTH = 1L << 4; 120 121 /** The media item includes gain map information (for example, an Ultra HDR gain map). */ 122 public static final long DATA_TYPE_GAIN_MAP = 1L << 5; 123 124 /** The media item includes high frame rate video data. */ 125 public static final long DATA_TYPE_HIGH_FRAME_RATE = 1L << 6; 126 127 /** 128 * The media item includes time-dependent speed information (for example, slow motion cue 129 * points). 130 */ 131 public static final long DATA_TYPE_SPEED_SETTING_CUE_POINTS = 1L << 7; 132 133 /** The media item includes gapless audio metadata. */ 134 public static final long DATA_TYPE_GAPLESS = 1L << 8; 135 136 /** The media item includes spatial audio data. */ 137 public static final long DATA_TYPE_SPATIAL_AUDIO = 1L << 9; 138 139 /** The media item includes high dynamic range (HDR) video. */ 140 public static final long DATA_TYPE_HIGH_DYNAMIC_RANGE_VIDEO = 1L << 10; 141 142 /** Special value for numerical fields where the value was not specified. */ 143 public static final int VALUE_UNSPECIFIED = -1; 144 145 private final @SourceType int mSourceType; 146 private final @DataType long mDataTypes; 147 private final long mDurationMillis; 148 private final long mClipDurationMillis; 149 @Nullable private final String mContainerMimeType; 150 private final List<String> mSampleMimeTypes; 151 private final List<String> mCodecNames; 152 private final int mAudioSampleRateHz; 153 private final int mAudioChannelCount; 154 private final long mAudioSampleCount; 155 private final Size mVideoSize; 156 private final int mVideoDataSpace; 157 private final float mVideoFrameRate; 158 private final long mVideoSampleCount; 159 MediaItemInfo( @ourceType int sourceType, @DataType long dataTypes, long durationMillis, long clipDurationMillis, @Nullable String containerMimeType, List<String> sampleMimeTypes, List<String> codecNames, int audioSampleRateHz, int audioChannelCount, long audioSampleCount, Size videoSize, int videoDataSpace, float videoFrameRate, long videoSampleCount)160 private MediaItemInfo( 161 @SourceType int sourceType, 162 @DataType long dataTypes, 163 long durationMillis, 164 long clipDurationMillis, 165 @Nullable String containerMimeType, 166 List<String> sampleMimeTypes, 167 List<String> codecNames, 168 int audioSampleRateHz, 169 int audioChannelCount, 170 long audioSampleCount, 171 Size videoSize, 172 int videoDataSpace, 173 float videoFrameRate, 174 long videoSampleCount) { 175 mSourceType = sourceType; 176 mDataTypes = dataTypes; 177 mDurationMillis = durationMillis; 178 mClipDurationMillis = clipDurationMillis; 179 mContainerMimeType = containerMimeType; 180 mSampleMimeTypes = sampleMimeTypes; 181 mCodecNames = codecNames; 182 mAudioSampleRateHz = audioSampleRateHz; 183 mAudioChannelCount = audioChannelCount; 184 mAudioSampleCount = audioSampleCount; 185 mVideoSize = videoSize; 186 mVideoDataSpace = videoDataSpace; 187 mVideoFrameRate = videoFrameRate; 188 mVideoSampleCount = videoSampleCount; 189 } 190 191 /** 192 * Returns where the media item came from, or {@link #SOURCE_TYPE_UNSPECIFIED} if not specified. 193 */ getSourceType()194 public @SourceType int getSourceType() { 195 return mSourceType; 196 } 197 198 /** Returns the data types that are present in the media item. */ getDataTypes()199 public @DataType long getDataTypes() { 200 return mDataTypes; 201 } 202 203 /** 204 * Returns the duration of the media item, in milliseconds, or {@link #VALUE_UNSPECIFIED} if not 205 * specified. 206 */ getDurationMillis()207 public long getDurationMillis() { 208 return mDurationMillis; 209 } 210 211 /** 212 * Returns the duration of the clip taken from the media item, in milliseconds, or {@link 213 * #VALUE_UNSPECIFIED} if not specified. 214 */ getClipDurationMillis()215 public long getClipDurationMillis() { 216 return mClipDurationMillis; 217 } 218 219 /** Returns the MIME type of the media container, or {@code null} if unspecified. */ 220 @Nullable getContainerMimeType()221 public String getContainerMimeType() { 222 return mContainerMimeType; 223 } 224 225 /** 226 * Returns the MIME types of samples stored in the media container, or an empty list if not 227 * known. 228 */ 229 @NonNull getSampleMimeTypes()230 public List<String> getSampleMimeTypes() { 231 return new ArrayList<>(mSampleMimeTypes); 232 } 233 234 /** 235 * Returns the {@linkplain MediaCodec#getName() media codec names} for codecs that were used as 236 * part of encoding/decoding this media item, or an empty list if not known or not applicable. 237 */ 238 @NonNull getCodecNames()239 public List<String> getCodecNames() { 240 return new ArrayList<>(mCodecNames); 241 } 242 243 /** 244 * Returns the sample rate of audio, in Hertz, or {@link #VALUE_UNSPECIFIED} if not specified. 245 */ getAudioSampleRateHz()246 public int getAudioSampleRateHz() { 247 return mAudioSampleRateHz; 248 } 249 250 /** Returns the number of audio channels, or {@link #VALUE_UNSPECIFIED} if not specified. */ getAudioChannelCount()251 public int getAudioChannelCount() { 252 return mAudioChannelCount; 253 } 254 255 /** 256 * Returns the number of audio frames in the item, after clipping (if applicable), or {@link 257 * #VALUE_UNSPECIFIED} if not specified. 258 */ getAudioSampleCount()259 public long getAudioSampleCount() { 260 return mAudioSampleCount; 261 } 262 263 /** 264 * Returns the video size, in pixels, or a {@link Size} with width and height set to {@link 265 * #VALUE_UNSPECIFIED} if not specified. 266 */ 267 @NonNull getVideoSize()268 public Size getVideoSize() { 269 return mVideoSize; 270 } 271 272 /** Returns the {@linkplain DataSpace data space} for video, as a packed integer. */ 273 @SuppressLint("MethodNameUnits") // Packed integer for an android.hardware.DataSpace. getVideoDataSpace()274 public int getVideoDataSpace() { 275 return mVideoDataSpace; 276 } 277 278 /** 279 * Returns the average video frame rate, in frames per second, or {@link #VALUE_UNSPECIFIED} if 280 * not specified. 281 */ getVideoFrameRate()282 public float getVideoFrameRate() { 283 return mVideoFrameRate; 284 } 285 286 /** 287 * Returns the number of video frames, aftrer clipping (if applicable), or {@link 288 * #VALUE_UNSPECIFIED} if not specified. 289 */ getVideoSampleCount()290 public long getVideoSampleCount() { 291 return mVideoSampleCount; 292 } 293 294 /** Builder for {@link MediaItemInfo}. */ 295 @FlaggedApi(FLAG_ADD_MEDIA_METRICS_EDITING) 296 public static final class Builder { 297 298 private @SourceType int mSourceType; 299 private @DataType long mDataTypes; 300 private long mDurationMillis; 301 private long mClipDurationMillis; 302 @Nullable private String mContainerMimeType; 303 private final ArrayList<String> mSampleMimeTypes; 304 private final ArrayList<String> mCodecNames; 305 private int mAudioSampleRateHz; 306 private int mAudioChannelCount; 307 private long mAudioSampleCount; 308 @Nullable private Size mVideoSize; 309 private int mVideoDataSpace; 310 private float mVideoFrameRate; 311 private long mVideoSampleCount; 312 313 /** Creates a new builder. */ Builder()314 public Builder() { 315 mSourceType = SOURCE_TYPE_UNSPECIFIED; 316 mDurationMillis = VALUE_UNSPECIFIED; 317 mClipDurationMillis = VALUE_UNSPECIFIED; 318 mSampleMimeTypes = new ArrayList<>(); 319 mCodecNames = new ArrayList<>(); 320 mAudioSampleRateHz = VALUE_UNSPECIFIED; 321 mAudioChannelCount = VALUE_UNSPECIFIED; 322 mAudioSampleCount = VALUE_UNSPECIFIED; 323 mVideoSize = new Size(VALUE_UNSPECIFIED, VALUE_UNSPECIFIED); 324 mVideoFrameRate = VALUE_UNSPECIFIED; 325 mVideoSampleCount = VALUE_UNSPECIFIED; 326 } 327 328 /** Sets where the media item came from. */ setSourceType(@ourceType int sourceType)329 public @NonNull Builder setSourceType(@SourceType int sourceType) { 330 mSourceType = sourceType; 331 return this; 332 } 333 334 /** Adds an additional data type represented as part of the media item. */ addDataType(@ataType long dataType)335 public @NonNull Builder addDataType(@DataType long dataType) { 336 mDataTypes |= dataType; 337 return this; 338 } 339 340 /** Sets the duration of the media item, in milliseconds. */ setDurationMillis(long durationMillis)341 public @NonNull Builder setDurationMillis(long durationMillis) { 342 mDurationMillis = durationMillis; 343 return this; 344 } 345 346 /** Sets the duration of the clip taken from the media item, in milliseconds. */ setClipDurationMillis(long clipDurationMillis)347 public @NonNull Builder setClipDurationMillis(long clipDurationMillis) { 348 mClipDurationMillis = clipDurationMillis; 349 return this; 350 } 351 352 /** Sets the MIME type of the media container. */ setContainerMimeType(@onNull String containerMimeType)353 public @NonNull Builder setContainerMimeType(@NonNull String containerMimeType) { 354 mContainerMimeType = Objects.requireNonNull(containerMimeType); 355 return this; 356 } 357 358 /** Adds a sample MIME type stored in the media container. */ addSampleMimeType(@onNull String mimeType)359 public @NonNull Builder addSampleMimeType(@NonNull String mimeType) { 360 mSampleMimeTypes.add(Objects.requireNonNull(mimeType)); 361 return this; 362 } 363 364 /** 365 * Adds an {@linkplain MediaCodec#getName() media codec name} that was used as part of 366 * decoding/encoding this media item. 367 */ addCodecName(@onNull String codecName)368 public @NonNull Builder addCodecName(@NonNull String codecName) { 369 mCodecNames.add(Objects.requireNonNull(codecName)); 370 return this; 371 } 372 373 /** Sets the sample rate of audio, in Hertz. */ setAudioSampleRateHz(@ntRangefrom = 0) int audioSampleRateHz)374 public @NonNull Builder setAudioSampleRateHz(@IntRange(from = 0) int audioSampleRateHz) { 375 mAudioSampleRateHz = audioSampleRateHz; 376 return this; 377 } 378 379 /** Sets the number of audio channels. */ setAudioChannelCount(@ntRangefrom = 0) int audioChannelCount)380 public @NonNull Builder setAudioChannelCount(@IntRange(from = 0) int audioChannelCount) { 381 mAudioChannelCount = audioChannelCount; 382 return this; 383 } 384 385 /** Sets the number of audio frames in the item, after clipping (if applicable). */ setAudioSampleCount(@ntRangefrom = 0) long audioSampleCount)386 public @NonNull Builder setAudioSampleCount(@IntRange(from = 0) long audioSampleCount) { 387 mAudioSampleCount = audioSampleCount; 388 return this; 389 } 390 391 /** Sets the video size, in pixels. */ setVideoSize(@onNull Size videoSize)392 public @NonNull Builder setVideoSize(@NonNull Size videoSize) { 393 mVideoSize = Objects.requireNonNull(videoSize); 394 return this; 395 } 396 397 /** 398 * Sets the {@link DataSpace} of video frames. 399 * 400 * @param videoDataSpace The data space, returned by {@link DataSpace#pack(int, int, int)}. 401 */ setVideoDataSpace(int videoDataSpace)402 public @NonNull Builder setVideoDataSpace(int videoDataSpace) { 403 mVideoDataSpace = videoDataSpace; 404 return this; 405 } 406 407 /** Sets the average video frame rate, in frames per second. */ setVideoFrameRate(@loatRangefrom = 0) float videoFrameRate)408 public @NonNull Builder setVideoFrameRate(@FloatRange(from = 0) float videoFrameRate) { 409 mVideoFrameRate = videoFrameRate; 410 return this; 411 } 412 413 /** Sets the number of video frames, after clipping (if applicable). */ setVideoSampleCount(@ntRangefrom = 0) long videoSampleCount)414 public @NonNull Builder setVideoSampleCount(@IntRange(from = 0) long videoSampleCount) { 415 mVideoSampleCount = videoSampleCount; 416 return this; 417 } 418 419 /** Builds an instance. */ 420 @NonNull build()421 public MediaItemInfo build() { 422 return new MediaItemInfo( 423 mSourceType, 424 mDataTypes, 425 mDurationMillis, 426 mClipDurationMillis, 427 mContainerMimeType, 428 mSampleMimeTypes, 429 mCodecNames, 430 mAudioSampleRateHz, 431 mAudioChannelCount, 432 mAudioSampleCount, 433 mVideoSize, 434 mVideoDataSpace, 435 mVideoFrameRate, 436 mVideoSampleCount); 437 } 438 } 439 440 @Override 441 @NonNull toString()442 public String toString() { 443 return "MediaItemInfo { " 444 + "sourceType = " 445 + mSourceType 446 + ", " 447 + "dataTypes = " 448 + mDataTypes 449 + ", " 450 + "durationMillis = " 451 + mDurationMillis 452 + ", " 453 + "clipDurationMillis = " 454 + mClipDurationMillis 455 + ", " 456 + "containerMimeType = " 457 + mContainerMimeType 458 + ", " 459 + "sampleMimeTypes = " 460 + mSampleMimeTypes 461 + ", " 462 + "codecNames = " 463 + mCodecNames 464 + ", " 465 + "audioSampleRateHz = " 466 + mAudioSampleRateHz 467 + ", " 468 + "audioChannelCount = " 469 + mAudioChannelCount 470 + ", " 471 + "audioSampleCount = " 472 + mAudioSampleCount 473 + ", " 474 + "videoSize = " 475 + mVideoSize 476 + ", " 477 + "videoDataSpace = " 478 + mVideoDataSpace 479 + ", " 480 + "videoFrameRate = " 481 + mVideoFrameRate 482 + ", " 483 + "videoSampleCount = " 484 + mVideoSampleCount 485 + " }"; 486 } 487 488 @Override equals(@ullable Object o)489 public boolean equals(@Nullable Object o) { 490 if (this == o) return true; 491 if (o == null || getClass() != o.getClass()) return false; 492 MediaItemInfo that = (MediaItemInfo) o; 493 return mSourceType == that.mSourceType 494 && mDataTypes == that.mDataTypes 495 && mDurationMillis == that.mDurationMillis 496 && mClipDurationMillis == that.mClipDurationMillis 497 && Objects.equals(mContainerMimeType, that.mContainerMimeType) 498 && mSampleMimeTypes.equals(that.mSampleMimeTypes) 499 && mCodecNames.equals(that.mCodecNames) 500 && mAudioSampleRateHz == that.mAudioSampleRateHz 501 && mAudioChannelCount == that.mAudioChannelCount 502 && mAudioSampleCount == that.mAudioSampleCount 503 && Objects.equals(mVideoSize, that.mVideoSize) 504 && Objects.equals(mVideoDataSpace, that.mVideoDataSpace) 505 && mVideoFrameRate == that.mVideoFrameRate 506 && mVideoSampleCount == that.mVideoSampleCount; 507 } 508 509 @Override hashCode()510 public int hashCode() { 511 return Objects.hash(mSourceType, mDataTypes); 512 } 513 514 @Override writeToParcel(@onNull Parcel dest, int flags)515 public void writeToParcel(@NonNull Parcel dest, int flags) { 516 dest.writeInt(mSourceType); 517 dest.writeLong(mDataTypes); 518 dest.writeLong(mDurationMillis); 519 dest.writeLong(mClipDurationMillis); 520 dest.writeString(mContainerMimeType); 521 dest.writeStringList(mSampleMimeTypes); 522 dest.writeStringList(mCodecNames); 523 dest.writeInt(mAudioSampleRateHz); 524 dest.writeInt(mAudioChannelCount); 525 dest.writeLong(mAudioSampleCount); 526 dest.writeInt(mVideoSize.getWidth()); 527 dest.writeInt(mVideoSize.getHeight()); 528 dest.writeInt(mVideoDataSpace); 529 dest.writeFloat(mVideoFrameRate); 530 dest.writeLong(mVideoSampleCount); 531 } 532 533 @Override describeContents()534 public int describeContents() { 535 return 0; 536 } 537 MediaItemInfo(@onNull Parcel in)538 private MediaItemInfo(@NonNull Parcel in) { 539 mSourceType = in.readInt(); 540 mDataTypes = in.readLong(); 541 mDurationMillis = in.readLong(); 542 mClipDurationMillis = in.readLong(); 543 mContainerMimeType = in.readString(); 544 mSampleMimeTypes = new ArrayList<>(); 545 in.readStringList(mSampleMimeTypes); 546 mCodecNames = new ArrayList<>(); 547 in.readStringList(mCodecNames); 548 mAudioSampleRateHz = in.readInt(); 549 mAudioChannelCount = in.readInt(); 550 mAudioSampleCount = in.readLong(); 551 int videoSizeWidth = in.readInt(); 552 int videoSizeHeight = in.readInt(); 553 mVideoSize = new Size(videoSizeWidth, videoSizeHeight); 554 mVideoDataSpace = in.readInt(); 555 mVideoFrameRate = in.readFloat(); 556 mVideoSampleCount = in.readLong(); 557 } 558 559 public static final @NonNull Creator<MediaItemInfo> CREATOR = 560 new Creator<>() { 561 @Override 562 public MediaItemInfo[] newArray(int size) { 563 return new MediaItemInfo[size]; 564 } 565 566 @Override 567 public MediaItemInfo createFromParcel(@NonNull Parcel in) { 568 return new MediaItemInfo(in); 569 } 570 }; 571 } 572