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