1 /*
2  * Copyright (C) 2016 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 com.google.android.exoplayer2.metadata;
17 
18 import android.os.Parcel;
19 import android.os.Parcelable;
20 import androidx.annotation.Nullable;
21 import com.google.android.exoplayer2.Format;
22 import com.google.android.exoplayer2.util.Util;
23 import java.util.Arrays;
24 import java.util.List;
25 
26 /**
27  * A collection of metadata entries.
28  */
29 public final class Metadata implements Parcelable {
30 
31   /** A metadata entry. */
32   public interface Entry extends Parcelable {
33 
34     /**
35      * Returns the {@link Format} that can be used to decode the wrapped metadata in {@link
36      * #getWrappedMetadataBytes()}, or null if this Entry doesn't contain wrapped metadata.
37      */
38     @Nullable
getWrappedMetadataFormat()39     default Format getWrappedMetadataFormat() {
40       return null;
41     }
42 
43     /**
44      * Returns the bytes of the wrapped metadata in this Entry, or null if it doesn't contain
45      * wrapped metadata.
46      */
47     @Nullable
getWrappedMetadataBytes()48     default byte[] getWrappedMetadataBytes() {
49       return null;
50     }
51   }
52 
53   private final Entry[] entries;
54 
55   /**
56    * @param entries The metadata entries.
57    */
Metadata(Entry... entries)58   public Metadata(Entry... entries) {
59     this.entries = entries;
60   }
61 
62   /**
63    * @param entries The metadata entries.
64    */
Metadata(List<? extends Entry> entries)65   public Metadata(List<? extends Entry> entries) {
66     this.entries = new Entry[entries.size()];
67     entries.toArray(this.entries);
68   }
69 
Metadata(Parcel in)70   /* package */ Metadata(Parcel in) {
71     entries = new Metadata.Entry[in.readInt()];
72     for (int i = 0; i < entries.length; i++) {
73       entries[i] = in.readParcelable(Entry.class.getClassLoader());
74     }
75   }
76 
77   /**
78    * Returns the number of metadata entries.
79    */
length()80   public int length() {
81     return entries.length;
82   }
83 
84   /**
85    * Returns the entry at the specified index.
86    *
87    * @param index The index of the entry.
88    * @return The entry at the specified index.
89    */
get(int index)90   public Metadata.Entry get(int index) {
91     return entries[index];
92   }
93 
94   /**
95    * Returns a copy of this metadata with the entries of the specified metadata appended. Returns
96    * this instance if {@code other} is null.
97    *
98    * @param other The metadata that holds the entries to append. If null, this methods returns this
99    *     instance.
100    * @return The metadata instance with the appended entries.
101    */
copyWithAppendedEntriesFrom(@ullable Metadata other)102   public Metadata copyWithAppendedEntriesFrom(@Nullable Metadata other) {
103     if (other == null) {
104       return this;
105     }
106     return copyWithAppendedEntries(other.entries);
107   }
108 
109   /**
110    * Returns a copy of this metadata with the specified entries appended.
111    *
112    * @param entriesToAppend The entries to append.
113    * @return The metadata instance with the appended entries.
114    */
copyWithAppendedEntries(Entry... entriesToAppend)115   public Metadata copyWithAppendedEntries(Entry... entriesToAppend) {
116     if (entriesToAppend.length == 0) {
117       return this;
118     }
119     return new Metadata(Util.nullSafeArrayConcatenation(entries, entriesToAppend));
120   }
121 
122   @Override
equals(@ullable Object obj)123   public boolean equals(@Nullable Object obj) {
124     if (this == obj) {
125       return true;
126     }
127     if (obj == null || getClass() != obj.getClass()) {
128       return false;
129     }
130     Metadata other = (Metadata) obj;
131     return Arrays.equals(entries, other.entries);
132   }
133 
134   @Override
hashCode()135   public int hashCode() {
136     return Arrays.hashCode(entries);
137   }
138 
139   @Override
toString()140   public String toString() {
141     return "entries=" + Arrays.toString(entries);
142   }
143 
144   // Parcelable implementation.
145 
146   @Override
describeContents()147   public int describeContents() {
148     return 0;
149   }
150 
151   @Override
writeToParcel(Parcel dest, int flags)152   public void writeToParcel(Parcel dest, int flags) {
153     dest.writeInt(entries.length);
154     for (Entry entry : entries) {
155       dest.writeParcelable(entry, 0);
156     }
157   }
158 
159   public static final Parcelable.Creator<Metadata> CREATOR =
160       new Parcelable.Creator<Metadata>() {
161         @Override
162         public Metadata createFromParcel(Parcel in) {
163           return new Metadata(in);
164         }
165 
166         @Override
167         public Metadata[] newArray(int size) {
168           return new Metadata[size];
169         }
170       };
171 }
172