Commit 5aff31c0 by Oliver Woodman

Further improve ID3 parsing

parent 31602af3
...@@ -35,7 +35,6 @@ import com.google.android.exoplayer2.metadata.id3.GeobFrame; ...@@ -35,7 +35,6 @@ import com.google.android.exoplayer2.metadata.id3.GeobFrame;
import com.google.android.exoplayer2.metadata.id3.Id3Frame; import com.google.android.exoplayer2.metadata.id3.Id3Frame;
import com.google.android.exoplayer2.metadata.id3.PrivFrame; import com.google.android.exoplayer2.metadata.id3.PrivFrame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.metadata.id3.TxxxFrame;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
...@@ -359,10 +358,10 @@ import java.util.Locale; ...@@ -359,10 +358,10 @@ import java.util.Locale;
private void printMetadata(Metadata metadata, String prefix) { private void printMetadata(Metadata metadata, String prefix) {
for (int i = 0; i < metadata.length(); i++) { for (int i = 0; i < metadata.length(); i++) {
Metadata.Entry entry = metadata.get(i); Metadata.Entry entry = metadata.get(i);
if (entry instanceof TxxxFrame) { if (entry instanceof TextInformationFrame) {
TxxxFrame txxxFrame = (TxxxFrame) entry; TextInformationFrame textInformationFrame = (TextInformationFrame) entry;
Log.d(TAG, prefix + String.format("%s: description=%s, value=%s", txxxFrame.id, Log.d(TAG, prefix + String.format("%s: value=%s", textInformationFrame.id,
txxxFrame.description, txxxFrame.value)); textInformationFrame.value));
} else if (entry instanceof PrivFrame) { } else if (entry instanceof PrivFrame) {
PrivFrame privFrame = (PrivFrame) entry; PrivFrame privFrame = (PrivFrame) entry;
Log.d(TAG, prefix + String.format("%s: owner=%s", privFrame.id, privFrame.owner)); Log.d(TAG, prefix + String.format("%s: owner=%s", privFrame.id, privFrame.owner));
...@@ -374,10 +373,6 @@ import java.util.Locale; ...@@ -374,10 +373,6 @@ import java.util.Locale;
ApicFrame apicFrame = (ApicFrame) entry; ApicFrame apicFrame = (ApicFrame) entry;
Log.d(TAG, prefix + String.format("%s: mimeType=%s, description=%s", Log.d(TAG, prefix + String.format("%s: mimeType=%s, description=%s",
apicFrame.id, apicFrame.mimeType, apicFrame.description)); apicFrame.id, apicFrame.mimeType, apicFrame.description));
} else if (entry instanceof TextInformationFrame) {
TextInformationFrame textInformationFrame = (TextInformationFrame) entry;
Log.d(TAG, prefix + String.format("%s: description=%s", textInformationFrame.id,
textInformationFrame.description));
} else if (entry instanceof CommentFrame) { } else if (entry instanceof CommentFrame) {
CommentFrame commentFrame = (CommentFrame) entry; CommentFrame commentFrame = (CommentFrame) entry;
Log.d(TAG, prefix + String.format("%s: language=%s description=%s", commentFrame.id, Log.d(TAG, prefix + String.format("%s: language=%s description=%s", commentFrame.id,
......
...@@ -59,8 +59,8 @@ public final class FormatTest extends TestCase { ...@@ -59,8 +59,8 @@ public final class FormatTest extends TestCase {
DrmInitData drmInitData = new DrmInitData(DRM_DATA_1, DRM_DATA_2); DrmInitData drmInitData = new DrmInitData(DRM_DATA_1, DRM_DATA_2);
byte[] projectionData = new byte[] {1, 2, 3}; byte[] projectionData = new byte[] {1, 2, 3};
Metadata metadata = new Metadata( Metadata metadata = new Metadata(
new TextInformationFrame("id1", "description1"), new TextInformationFrame("id1", "description1", "value1"),
new TextInformationFrame("id2", "description2")); new TextInformationFrame("id2", "description2", "value2"));
Format formatToParcel = new Format("id", MimeTypes.VIDEO_MP4, MimeTypes.VIDEO_H264, null, Format formatToParcel = new Format("id", MimeTypes.VIDEO_MP4, MimeTypes.VIDEO_H264, null,
1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, 6, 44100, 1024, 2048, 1920, 1080, 24, 90, 2, projectionData, C.STEREO_MODE_TOP_BOTTOM, 6, 44100,
......
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.metadata.id3;
import android.os.Parcel;
import junit.framework.TestCase;
/**
* Test for {@link ChapterFrame}.
*/
public final class ChapterFrameTest extends TestCase {
public void testParcelable() {
Id3Frame[] subFrames = new Id3Frame[] {
new TextInformationFrame("TIT2", null, "title"),
new UrlLinkFrame("WXXX", "description", "url")
};
ChapterFrame chapterFrameToParcel = new ChapterFrame("id", 0, 1, 2, 3, subFrames);
Parcel parcel = Parcel.obtain();
chapterFrameToParcel.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
ChapterFrame chapterFrameFromParcel = ChapterFrame.CREATOR.createFromParcel(parcel);
assertEquals(chapterFrameToParcel, chapterFrameFromParcel);
parcel.recycle();
}
}
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.metadata.id3;
import android.os.Parcel;
import junit.framework.TestCase;
/**
* Test for {@link ChapterTOCFrame}.
*/
public final class ChapterTOCFrameTest extends TestCase {
public void testParcelable() {
String[] children = new String[] {"child0", "child1"};
Id3Frame[] subFrames = new Id3Frame[] {
new TextInformationFrame("TIT2", null, "title"),
new UrlLinkFrame("WXXX", "description", "url")
};
ChapterTOCFrame chapterTOCFrameToParcel = new ChapterTOCFrame("id", false, true, children,
subFrames);
Parcel parcel = Parcel.obtain();
chapterTOCFrameToParcel.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
ChapterTOCFrame chapterTOCFrameFromParcel = ChapterTOCFrame.CREATOR.createFromParcel(parcel);
assertEquals(chapterTOCFrameToParcel, chapterTOCFrameFromParcel);
parcel.recycle();
}
}
...@@ -32,9 +32,10 @@ public final class Id3DecoderTest extends TestCase { ...@@ -32,9 +32,10 @@ public final class Id3DecoderTest extends TestCase {
Id3Decoder decoder = new Id3Decoder(); Id3Decoder decoder = new Id3Decoder();
Metadata metadata = decoder.decode(rawId3, rawId3.length); Metadata metadata = decoder.decode(rawId3, rawId3.length);
assertEquals(1, metadata.length()); assertEquals(1, metadata.length());
TxxxFrame txxxFrame = (TxxxFrame) metadata.get(0); TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0);
assertEquals("", txxxFrame.description); assertEquals("TXXX", textInformationFrame.id);
assertEquals("mdialog_VINDICO1527664_start", txxxFrame.value); assertEquals("", textInformationFrame.description);
assertEquals("mdialog_VINDICO1527664_start", textInformationFrame.value);
} }
public void testDecodeApicFrame() throws MetadataDecoderException { public void testDecodeApicFrame() throws MetadataDecoderException {
...@@ -60,7 +61,8 @@ public final class Id3DecoderTest extends TestCase { ...@@ -60,7 +61,8 @@ public final class Id3DecoderTest extends TestCase {
assertEquals(1, metadata.length()); assertEquals(1, metadata.length());
TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0); TextInformationFrame textInformationFrame = (TextInformationFrame) metadata.get(0);
assertEquals("TIT2", textInformationFrame.id); assertEquals("TIT2", textInformationFrame.id);
assertEquals("Hello World", textInformationFrame.description); assertNull(textInformationFrame.description);
assertEquals("Hello World", textInformationFrame.value);
} }
public void testDecodePrivFrame() throws MetadataDecoderException { public void testDecodePrivFrame() throws MetadataDecoderException {
......
...@@ -188,7 +188,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -188,7 +188,7 @@ import com.google.android.exoplayer2.util.Util;
if (atomType == Atom.TYPE_data) { if (atomType == Atom.TYPE_data) {
data.skipBytes(8); // version (1), flags (3), empty (4) data.skipBytes(8); // version (1), flags (3), empty (4)
String value = data.readNullTerminatedString(atomSize - 16); String value = data.readNullTerminatedString(atomSize - 16);
return new TextInformationFrame(id, value); return new TextInformationFrame(id, null, value);
} }
Log.w(TAG, "Failed to parse text attribute: " + Atom.getAtomTypeString(type)); Log.w(TAG, "Failed to parse text attribute: " + Atom.getAtomTypeString(type));
return null; return null;
...@@ -213,7 +213,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -213,7 +213,7 @@ import com.google.android.exoplayer2.util.Util;
value = Math.min(1, value); value = Math.min(1, value);
} }
if (value >= 0) { if (value >= 0) {
return isTextInformationFrame ? new TextInformationFrame(id, Integer.toString(value)) return isTextInformationFrame ? new TextInformationFrame(id, null, Integer.toString(value))
: new CommentFrame(LANGUAGE_UNDEFINED, id, Integer.toString(value)); : new CommentFrame(LANGUAGE_UNDEFINED, id, Integer.toString(value));
} }
Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type)); Log.w(TAG, "Failed to parse uint8 attribute: " + Atom.getAtomTypeString(type));
...@@ -228,12 +228,12 @@ import com.google.android.exoplayer2.util.Util; ...@@ -228,12 +228,12 @@ import com.google.android.exoplayer2.util.Util;
data.skipBytes(10); // version (1), flags (3), empty (4), empty (2) data.skipBytes(10); // version (1), flags (3), empty (4), empty (2)
int index = data.readUnsignedShort(); int index = data.readUnsignedShort();
if (index > 0) { if (index > 0) {
String description = "" + index; String value = "" + index;
int count = data.readUnsignedShort(); int count = data.readUnsignedShort();
if (count > 0) { if (count > 0) {
description += "/" + count; value += "/" + count;
} }
return new TextInformationFrame(attributeName, description); return new TextInformationFrame(attributeName, null, value);
} }
} }
Log.w(TAG, "Failed to parse index/count attribute: " + Atom.getAtomTypeString(type)); Log.w(TAG, "Failed to parse index/count attribute: " + Atom.getAtomTypeString(type));
...@@ -245,7 +245,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -245,7 +245,7 @@ import com.google.android.exoplayer2.util.Util;
String genreString = (0 < genreCode && genreCode <= STANDARD_GENRES.length) String genreString = (0 < genreCode && genreCode <= STANDARD_GENRES.length)
? STANDARD_GENRES[genreCode - 1] : null; ? STANDARD_GENRES[genreCode - 1] : null;
if (genreString != null) { if (genreString != null) {
return new TextInformationFrame("TCON", genreString); return new TextInformationFrame("TCON", null, genreString);
} }
Log.w(TAG, "Failed to parse standard genre code"); Log.w(TAG, "Failed to parse standard genre code");
return null; return null;
......
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
package com.google.android.exoplayer2.metadata.id3; package com.google.android.exoplayer2.metadata.id3;
import android.os.Parcel; import android.os.Parcel;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
/** /**
* Chapter information "CHAP" ID3 frame. * Chapter information ID3 frame.
*/ */
public final class ChapFrame extends Id3Frame { public final class ChapterFrame extends Id3Frame {
public static final String ID = "CHAP"; public static final String ID = "CHAP";
...@@ -31,33 +31,31 @@ public final class ChapFrame extends Id3Frame { ...@@ -31,33 +31,31 @@ public final class ChapFrame extends Id3Frame {
public final int endTime; public final int endTime;
public final int startOffset; public final int startOffset;
public final int endOffset; public final int endOffset;
public final String title; private final Id3Frame[] subFrames;
public final String url;
public final ApicFrame image;
public ChapFrame(String chapterId, int startTime, int endTime, int startOffset, int endOffset, public ChapterFrame(String chapterId, int startTime, int endTime, int startOffset, int endOffset,
String title, String url, ApicFrame image) { Id3Frame[] subFrames) {
super(ID); super(ID);
this.chapterId = chapterId; this.chapterId = chapterId;
this.startTime = startTime; this.startTime = startTime;
this.endTime = endTime; this.endTime = endTime;
this.startOffset = startOffset; this.startOffset = startOffset;
this.endOffset = endOffset; this.endOffset = endOffset;
this.title = title; this.subFrames = subFrames;
this.url = url;
this.image = image;
} }
/* package */ ChapFrame(Parcel in) { /* package */ ChapterFrame(Parcel in) {
super(ID); super(ID);
this.chapterId = in.readString(); this.chapterId = in.readString();
this.startTime = in.readInt(); this.startTime = in.readInt();
this.endTime = in.readInt(); this.endTime = in.readInt();
this.startOffset = in.readInt(); this.startOffset = in.readInt();
this.endOffset = in.readInt(); this.endOffset = in.readInt();
this.title = in.readString(); int subFrameCount = in.readInt();
this.url = in.readString(); subFrames = new Id3Frame[subFrameCount];
this.image = in.readParcelable(ApicFrame.class.getClassLoader()); for (int i = 0; i < subFrameCount; i++) {
subFrames[i] = in.readParcelable(Id3Frame.class.getClassLoader());
}
} }
@Override @Override
...@@ -68,28 +66,23 @@ public final class ChapFrame extends Id3Frame { ...@@ -68,28 +66,23 @@ public final class ChapFrame extends Id3Frame {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
ChapFrame other = (ChapFrame) obj; ChapterFrame other = (ChapterFrame) obj;
return startTime == other.startTime return startTime == other.startTime
&& endTime == other.endTime && endTime == other.endTime
&& startOffset == other.startOffset && startOffset == other.startOffset
&& endOffset == other.endOffset && endOffset == other.endOffset
&& Util.areEqual(chapterId, other.chapterId) && Util.areEqual(chapterId, other.chapterId)
&& Util.areEqual(title, other.title) && Arrays.equals(subFrames, other.subFrames);
&& Util.areEqual(url, other.url)
&& Util.areEqual(image, other.image);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = 17; int result = 17;
result = 31 * result + (chapterId != null ? chapterId.hashCode() : 0);
result = 31 * result + startTime; result = 31 * result + startTime;
result = 31 * result + endTime; result = 31 * result + endTime;
result = 31 * result + startOffset; result = 31 * result + startOffset;
result = 31 * result + endOffset; result = 31 * result + endOffset;
result = 31 * result + (title != null ? title.hashCode() : 0); result = 31 * result + (chapterId != null ? chapterId.hashCode() : 0);
result = 31 * result + (url != null ? url.hashCode() : 0);
result = 31 * result + (image != null ? image.hashCode() : 0);
return result; return result;
} }
...@@ -100,10 +93,10 @@ public final class ChapFrame extends Id3Frame { ...@@ -100,10 +93,10 @@ public final class ChapFrame extends Id3Frame {
dest.writeInt(endTime); dest.writeInt(endTime);
dest.writeInt(startOffset); dest.writeInt(startOffset);
dest.writeInt(endOffset); dest.writeInt(endOffset);
dest.writeString(title); dest.writeInt(subFrames.length);
dest.writeString(url); for (int i = 0; i < subFrames.length; i++) {
dest.writeString(title); dest.writeParcelable(subFrames[i], 0);
dest.writeParcelable(image, flags); }
} }
@Override @Override
...@@ -111,15 +104,18 @@ public final class ChapFrame extends Id3Frame { ...@@ -111,15 +104,18 @@ public final class ChapFrame extends Id3Frame {
return 0; return 0;
} }
public static final Creator<ChapFrame> CREATOR = new Creator<ChapFrame>() { public static final Creator<ChapterFrame> CREATOR = new Creator<ChapterFrame>() {
@Override @Override
public ChapFrame createFromParcel(Parcel in) { public ChapterFrame createFromParcel(Parcel in) {
return new ChapFrame(in); return new ChapterFrame(in);
} }
@Override @Override
public ChapFrame[] newArray(int size) { public ChapterFrame[] newArray(int size) {
return new ChapFrame[size]; return new ChapterFrame[size];
} }
}; };
} }
...@@ -22,9 +22,9 @@ import com.google.android.exoplayer2.util.Util; ...@@ -22,9 +22,9 @@ import com.google.android.exoplayer2.util.Util;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Chapter table of contents information "CTOC" ID3 frame. * Chapter table of contents ID3 frame.
*/ */
public final class CtocFrame extends Id3Frame { public final class ChapterTOCFrame extends Id3Frame {
public static final String ID = "CTOC"; public static final String ID = "CTOC";
...@@ -32,24 +32,29 @@ public final class CtocFrame extends Id3Frame { ...@@ -32,24 +32,29 @@ public final class CtocFrame extends Id3Frame {
public final boolean isRoot; public final boolean isRoot;
public final boolean isOrdered; public final boolean isOrdered;
public final String[] children; public final String[] children;
public final String title; public final Id3Frame[] subFrames;
public CtocFrame(String elementId, boolean isRoot, boolean isOrdered, String[] children, String title) { public ChapterTOCFrame(String elementId, boolean isRoot, boolean isOrdered, String[] children,
Id3Frame[] subFrames) {
super(ID); super(ID);
this.elementId = elementId; this.elementId = elementId;
this.isRoot = isRoot; this.isRoot = isRoot;
this.isOrdered = isOrdered; this.isOrdered = isOrdered;
this.children = children; this.children = children;
this.title = title; this.subFrames = subFrames;
} }
/* package */ CtocFrame(Parcel in) { /* package */ ChapterTOCFrame(Parcel in) {
super(ID); super(ID);
this.elementId = in.readString(); this.elementId = in.readString();
this.isRoot = in.readByte() != 0; this.isRoot = in.readByte() != 0;
this.isOrdered = in.readByte() != 0; this.isOrdered = in.readByte() != 0;
this.children = in.createStringArray(); this.children = in.createStringArray();
this.title = in.readString(); int subFrameCount = in.readInt();
subFrames = new Id3Frame[subFrameCount];
for (int i = 0; i < subFrameCount; i++) {
subFrames[i] = in.readParcelable(Id3Frame.class.getClassLoader());
}
} }
@Override @Override
...@@ -60,43 +65,47 @@ public final class CtocFrame extends Id3Frame { ...@@ -60,43 +65,47 @@ public final class CtocFrame extends Id3Frame {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
CtocFrame other = (CtocFrame) obj; ChapterTOCFrame other = (ChapterTOCFrame) obj;
return isRoot == other.isRoot return isRoot == other.isRoot
&& isOrdered == other.isOrdered && isOrdered == other.isOrdered
&& Util.areEqual(elementId, other.elementId) && Util.areEqual(elementId, other.elementId)
&& Util.areEqual(title, other.title) && Arrays.equals(children, other.children)
&& Arrays.equals(children, other.children); && Arrays.equals(subFrames, other.subFrames);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = 17; int result = 17;
result = 31 * result + (elementId != null ? elementId.hashCode() : 0);
result = 31 * result + (isRoot ? 1 : 0); result = 31 * result + (isRoot ? 1 : 0);
result = 31 * result + (isOrdered ? 1 : 0); result = 31 * result + (isOrdered ? 1 : 0);
result = 31 * result + Arrays.hashCode(children); result = 31 * result + (elementId != null ? elementId.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
return result; return result;
} }
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(elementId); dest.writeString(elementId);
dest.writeByte((byte)(isRoot ? 1 : 0)); dest.writeByte((byte) (isRoot ? 1 : 0));
dest.writeByte((byte)(isOrdered ? 1 : 0)); dest.writeByte((byte) (isOrdered ? 1 : 0));
dest.writeStringArray(children); dest.writeStringArray(children);
dest.writeString(title); dest.writeInt(subFrames.length);
for (int i = 0; i < subFrames.length; i++) {
dest.writeParcelable(subFrames[i], 0);
}
} }
public static final Creator<CtocFrame> CREATOR = new Creator<CtocFrame>() { public static final Creator<ChapterTOCFrame> CREATOR = new Creator<ChapterTOCFrame>() {
@Override @Override
public CtocFrame createFromParcel(Parcel in) { public ChapterTOCFrame createFromParcel(Parcel in) {
return new CtocFrame(in); return new ChapterTOCFrame(in);
} }
@Override @Override
public CtocFrame[] newArray(int size) { public ChapterTOCFrame[] newArray(int size) {
return new CtocFrame[size]; return new ChapterTOCFrame[size];
} }
}; };
} }
...@@ -25,15 +25,18 @@ import com.google.android.exoplayer2.util.Util; ...@@ -25,15 +25,18 @@ import com.google.android.exoplayer2.util.Util;
public final class TextInformationFrame extends Id3Frame { public final class TextInformationFrame extends Id3Frame {
public final String description; public final String description;
public final String value;
public TextInformationFrame(String id, String description) { public TextInformationFrame(String id, String description, String value) {
super(id); super(id);
this.description = description; this.description = description;
this.value = value;
} }
/* package */ TextInformationFrame(Parcel in) { /* package */ TextInformationFrame(Parcel in) {
super(in.readString()); super(in.readString());
description = in.readString(); description = in.readString();
value = in.readString();
} }
@Override @Override
...@@ -45,7 +48,8 @@ public final class TextInformationFrame extends Id3Frame { ...@@ -45,7 +48,8 @@ public final class TextInformationFrame extends Id3Frame {
return false; return false;
} }
TextInformationFrame other = (TextInformationFrame) obj; TextInformationFrame other = (TextInformationFrame) obj;
return id.equals(other.id) && Util.areEqual(description, other.description); return id.equals(other.id) && Util.areEqual(description, other.description)
&& Util.areEqual(value, other.value);
} }
@Override @Override
...@@ -53,6 +57,7 @@ public final class TextInformationFrame extends Id3Frame { ...@@ -53,6 +57,7 @@ public final class TextInformationFrame extends Id3Frame {
int result = 17; int result = 17;
result = 31 * result + id.hashCode(); result = 31 * result + id.hashCode();
result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
return result; return result;
} }
...@@ -60,6 +65,7 @@ public final class TextInformationFrame extends Id3Frame { ...@@ -60,6 +65,7 @@ public final class TextInformationFrame extends Id3Frame {
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id); dest.writeString(id);
dest.writeString(description); dest.writeString(description);
dest.writeString(value);
} }
public static final Parcelable.Creator<TextInformationFrame> CREATOR = public static final Parcelable.Creator<TextInformationFrame> CREATOR =
......
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.metadata.id3;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.android.exoplayer2.util.Util;
/**
* TXXX (User defined text information) ID3 frame.
*/
public final class TxxxFrame extends Id3Frame {
public static final String ID = "TXXX";
public final String description;
public final String value;
public TxxxFrame(String description, String value) {
super(ID);
this.description = description;
this.value = value;
}
/* package */ TxxxFrame(Parcel in) {
super(ID);
description = in.readString();
value = in.readString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TxxxFrame other = (TxxxFrame) obj;
return Util.areEqual(description, other.description) && Util.areEqual(value, other.value);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (value != null ? value.hashCode() : 0);
return result;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(description);
dest.writeString(value);
}
public static final Parcelable.Creator<TxxxFrame> CREATOR = new Parcelable.Creator<TxxxFrame>() {
@Override
public TxxxFrame createFromParcel(Parcel in) {
return new TxxxFrame(in);
}
@Override
public TxxxFrame[] newArray(int size) {
return new TxxxFrame[size];
}
};
}
...@@ -21,23 +21,21 @@ import android.os.Parcelable; ...@@ -21,23 +21,21 @@ import android.os.Parcelable;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
/** /**
* Url Frame "WXX" ID3 frame. * WXXX (User defined URL link) ID3 frame.
*/ */
public final class WxxxFrame extends Id3Frame { public final class UrlLinkFrame extends Id3Frame {
public static final String ID = "WXXX";
public final String description; public final String description;
public final String url; public final String url;
public WxxxFrame(String description, String url) { public UrlLinkFrame(String id, String description, String url) {
super(ID); super(id);
this.description = description; this.description = description;
this.url = url; this.url = url;
} }
/* package */ WxxxFrame(Parcel in) { /* package */ UrlLinkFrame(Parcel in) {
super(ID); super(in.readString());
description = in.readString(); description = in.readString();
url = in.readString(); url = in.readString();
} }
...@@ -50,14 +48,15 @@ public final class WxxxFrame extends Id3Frame { ...@@ -50,14 +48,15 @@ public final class WxxxFrame extends Id3Frame {
if (obj == null || getClass() != obj.getClass()) { if (obj == null || getClass() != obj.getClass()) {
return false; return false;
} }
WxxxFrame other = (WxxxFrame) obj; UrlLinkFrame other = (UrlLinkFrame) obj;
return Util.areEqual(description, other.description) return id.equals(other.id) && Util.areEqual(description, other.description)
&& Util.areEqual(url, other.url); && Util.areEqual(url, other.url);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = 17; int result = 17;
result = 31 * result + id.hashCode();
result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (url != null ? url.hashCode() : 0); result = 31 * result + (url != null ? url.hashCode() : 0);
return result; return result;
...@@ -65,23 +64,24 @@ public final class WxxxFrame extends Id3Frame { ...@@ -65,23 +64,24 @@ public final class WxxxFrame extends Id3Frame {
@Override @Override
public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(description); dest.writeString(description);
dest.writeString(url); dest.writeString(url);
} }
public static final Parcelable.Creator<WxxxFrame> CREATOR = public static final Parcelable.Creator<UrlLinkFrame> CREATOR =
new Parcelable.Creator<WxxxFrame>() { new Parcelable.Creator<UrlLinkFrame>() {
@Override @Override
public WxxxFrame createFromParcel(Parcel in) { public UrlLinkFrame createFromParcel(Parcel in) {
return new WxxxFrame(in); return new UrlLinkFrame(in);
} }
@Override @Override
public WxxxFrame[] newArray(int size) { public UrlLinkFrame[] newArray(int size) {
return new WxxxFrame[size]; return new UrlLinkFrame[size];
} }
}; };
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment