Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
31602af3
authored
Jan 17, 2017
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge branch 'dev-v2' of
git://github.com/geekygecko/ExoPlayer
into geekygecko-dev-v2
parents
7f967f30
f6ecaddc
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
434 additions
and
2 deletions
library/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapFrame.java
library/src/main/java/com/google/android/exoplayer2/metadata/id3/CtocFrame.java
library/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java
library/src/main/java/com/google/android/exoplayer2/metadata/id3/WxxxFrame.java
library/src/main/java/com/google/android/exoplayer2/metadata/id3/ChapFrame.java
0 → 100644
View file @
31602af3
/*
* 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
com.google.android.exoplayer2.util.Util
;
/**
* Chapter information "CHAP" ID3 frame.
*/
public
final
class
ChapFrame
extends
Id3Frame
{
public
static
final
String
ID
=
"CHAP"
;
public
final
String
chapterId
;
public
final
int
startTime
;
public
final
int
endTime
;
public
final
int
startOffset
;
public
final
int
endOffset
;
public
final
String
title
;
public
final
String
url
;
public
final
ApicFrame
image
;
public
ChapFrame
(
String
chapterId
,
int
startTime
,
int
endTime
,
int
startOffset
,
int
endOffset
,
String
title
,
String
url
,
ApicFrame
image
)
{
super
(
ID
);
this
.
chapterId
=
chapterId
;
this
.
startTime
=
startTime
;
this
.
endTime
=
endTime
;
this
.
startOffset
=
startOffset
;
this
.
endOffset
=
endOffset
;
this
.
title
=
title
;
this
.
url
=
url
;
this
.
image
=
image
;
}
/* package */
ChapFrame
(
Parcel
in
)
{
super
(
ID
);
this
.
chapterId
=
in
.
readString
();
this
.
startTime
=
in
.
readInt
();
this
.
endTime
=
in
.
readInt
();
this
.
startOffset
=
in
.
readInt
();
this
.
endOffset
=
in
.
readInt
();
this
.
title
=
in
.
readString
();
this
.
url
=
in
.
readString
();
this
.
image
=
in
.
readParcelable
(
ApicFrame
.
class
.
getClassLoader
());
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
ChapFrame
other
=
(
ChapFrame
)
obj
;
return
startTime
==
other
.
startTime
&&
endTime
==
other
.
endTime
&&
startOffset
==
other
.
startOffset
&&
endOffset
==
other
.
endOffset
&&
Util
.
areEqual
(
chapterId
,
other
.
chapterId
)
&&
Util
.
areEqual
(
title
,
other
.
title
)
&&
Util
.
areEqual
(
url
,
other
.
url
)
&&
Util
.
areEqual
(
image
,
other
.
image
);
}
@Override
public
int
hashCode
()
{
int
result
=
17
;
result
=
31
*
result
+
(
chapterId
!=
null
?
chapterId
.
hashCode
()
:
0
);
result
=
31
*
result
+
startTime
;
result
=
31
*
result
+
endTime
;
result
=
31
*
result
+
startOffset
;
result
=
31
*
result
+
endOffset
;
result
=
31
*
result
+
(
title
!=
null
?
title
.
hashCode
()
:
0
);
result
=
31
*
result
+
(
url
!=
null
?
url
.
hashCode
()
:
0
);
result
=
31
*
result
+
(
image
!=
null
?
image
.
hashCode
()
:
0
);
return
result
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeString
(
chapterId
);
dest
.
writeInt
(
startTime
);
dest
.
writeInt
(
endTime
);
dest
.
writeInt
(
startOffset
);
dest
.
writeInt
(
endOffset
);
dest
.
writeString
(
title
);
dest
.
writeString
(
url
);
dest
.
writeString
(
title
);
dest
.
writeParcelable
(
image
,
flags
);
}
@Override
public
int
describeContents
()
{
return
0
;
}
public
static
final
Creator
<
ChapFrame
>
CREATOR
=
new
Creator
<
ChapFrame
>()
{
@Override
public
ChapFrame
createFromParcel
(
Parcel
in
)
{
return
new
ChapFrame
(
in
);
}
@Override
public
ChapFrame
[]
newArray
(
int
size
)
{
return
new
ChapFrame
[
size
];
}
};
}
library/src/main/java/com/google/android/exoplayer2/metadata/id3/CtocFrame.java
0 → 100644
View file @
31602af3
/*
* 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
com.google.android.exoplayer2.util.Util
;
import
java.util.Arrays
;
/**
* Chapter table of contents information "CTOC" ID3 frame.
*/
public
final
class
CtocFrame
extends
Id3Frame
{
public
static
final
String
ID
=
"CTOC"
;
public
final
String
elementId
;
public
final
boolean
isRoot
;
public
final
boolean
isOrdered
;
public
final
String
[]
children
;
public
final
String
title
;
public
CtocFrame
(
String
elementId
,
boolean
isRoot
,
boolean
isOrdered
,
String
[]
children
,
String
title
)
{
super
(
ID
);
this
.
elementId
=
elementId
;
this
.
isRoot
=
isRoot
;
this
.
isOrdered
=
isOrdered
;
this
.
children
=
children
;
this
.
title
=
title
;
}
/* package */
CtocFrame
(
Parcel
in
)
{
super
(
ID
);
this
.
elementId
=
in
.
readString
();
this
.
isRoot
=
in
.
readByte
()
!=
0
;
this
.
isOrdered
=
in
.
readByte
()
!=
0
;
this
.
children
=
in
.
createStringArray
();
this
.
title
=
in
.
readString
();
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
CtocFrame
other
=
(
CtocFrame
)
obj
;
return
isRoot
==
other
.
isRoot
&&
isOrdered
==
other
.
isOrdered
&&
Util
.
areEqual
(
elementId
,
other
.
elementId
)
&&
Util
.
areEqual
(
title
,
other
.
title
)
&&
Arrays
.
equals
(
children
,
other
.
children
);
}
@Override
public
int
hashCode
()
{
int
result
=
17
;
result
=
31
*
result
+
(
elementId
!=
null
?
elementId
.
hashCode
()
:
0
);
result
=
31
*
result
+
(
isRoot
?
1
:
0
);
result
=
31
*
result
+
(
isOrdered
?
1
:
0
);
result
=
31
*
result
+
Arrays
.
hashCode
(
children
);
result
=
31
*
result
+
(
title
!=
null
?
title
.
hashCode
()
:
0
);
return
result
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeString
(
elementId
);
dest
.
writeByte
((
byte
)(
isRoot
?
1
:
0
));
dest
.
writeByte
((
byte
)(
isOrdered
?
1
:
0
));
dest
.
writeStringArray
(
children
);
dest
.
writeString
(
title
);
}
public
static
final
Creator
<
CtocFrame
>
CREATOR
=
new
Creator
<
CtocFrame
>()
{
@Override
public
CtocFrame
createFromParcel
(
Parcel
in
)
{
return
new
CtocFrame
(
in
);
}
@Override
public
CtocFrame
[]
newArray
(
int
size
)
{
return
new
CtocFrame
[
size
];
}
};
}
library/src/main/java/com/google/android/exoplayer2/metadata/id3/Id3Decoder.java
View file @
31602af3
...
@@ -98,7 +98,7 @@ public final class Id3Decoder implements MetadataDecoder {
...
@@ -98,7 +98,7 @@ public final class Id3Decoder implements MetadataDecoder {
int
frameHeaderSize
=
id3Header
.
majorVersion
==
2
?
6
:
10
;
int
frameHeaderSize
=
id3Header
.
majorVersion
==
2
?
6
:
10
;
while
(
id3Data
.
bytesLeft
()
>=
frameHeaderSize
)
{
while
(
id3Data
.
bytesLeft
()
>=
frameHeaderSize
)
{
Id3Frame
frame
=
decodeFrame
(
id3Header
.
majorVersion
,
id3Data
,
unsignedIntFrameSizeHack
);
Id3Frame
frame
=
decodeFrame
(
id3Header
.
majorVersion
,
id3Data
,
unsignedIntFrameSizeHack
,
frameHeaderSize
);
if
(
frame
!=
null
)
{
if
(
frame
!=
null
)
{
id3Frames
.
add
(
frame
);
id3Frames
.
add
(
frame
);
}
}
...
@@ -204,7 +204,7 @@ public final class Id3Decoder implements MetadataDecoder {
...
@@ -204,7 +204,7 @@ public final class Id3Decoder implements MetadataDecoder {
}
}
private
static
Id3Frame
decodeFrame
(
int
majorVersion
,
ParsableByteArray
id3Data
,
private
static
Id3Frame
decodeFrame
(
int
majorVersion
,
ParsableByteArray
id3Data
,
boolean
unsignedIntFrameSizeHack
)
{
boolean
unsignedIntFrameSizeHack
,
int
frameHeaderSize
)
{
int
frameId0
=
id3Data
.
readUnsignedByte
();
int
frameId0
=
id3Data
.
readUnsignedByte
();
int
frameId1
=
id3Data
.
readUnsignedByte
();
int
frameId1
=
id3Data
.
readUnsignedByte
();
int
frameId2
=
id3Data
.
readUnsignedByte
();
int
frameId2
=
id3Data
.
readUnsignedByte
();
...
@@ -296,6 +296,15 @@ public final class Id3Decoder implements MetadataDecoder {
...
@@ -296,6 +296,15 @@ public final class Id3Decoder implements MetadataDecoder {
}
else
if
(
frameId0
==
'C'
&&
frameId1
==
'O'
&&
frameId2
==
'M'
}
else
if
(
frameId0
==
'C'
&&
frameId1
==
'O'
&&
frameId2
==
'M'
&&
(
frameId3
==
'M'
||
majorVersion
==
2
))
{
&&
(
frameId3
==
'M'
||
majorVersion
==
2
))
{
frame
=
decodeCommentFrame
(
id3Data
,
frameSize
);
frame
=
decodeCommentFrame
(
id3Data
,
frameSize
);
}
else
if
(
majorVersion
==
2
?
(
frameId0
==
'W'
&&
frameId1
==
'X'
&&
frameId2
==
'X'
)
:
(
frameId0
==
'W'
&&
frameId1
==
'X'
&&
frameId2
==
'X'
&&
frameId3
==
'X'
))
{
frame
=
decodeWxxxFrame
(
id3Data
,
frameSize
);
}
else
if
(
frameId0
==
'C'
&&
frameId1
==
'H'
&&
frameId2
==
'A'
&&
frameId3
==
'P'
)
{
frame
=
decodeChapFrame
(
id3Data
,
frameSize
,
majorVersion
,
unsignedIntFrameSizeHack
,
frameHeaderSize
);
}
else
if
(
frameId0
==
'C'
&&
frameId1
==
'T'
&&
frameId2
==
'O'
&&
frameId3
==
'C'
)
{
frame
=
decodeCtocFrame
(
id3Data
,
frameSize
,
majorVersion
,
unsignedIntFrameSizeHack
,
frameHeaderSize
);
}
else
{
}
else
{
String
id
=
majorVersion
==
2
String
id
=
majorVersion
==
2
?
String
.
format
(
Locale
.
US
,
"%c%c%c"
,
frameId0
,
frameId1
,
frameId2
)
?
String
.
format
(
Locale
.
US
,
"%c%c%c"
,
frameId0
,
frameId1
,
frameId2
)
...
@@ -458,6 +467,115 @@ public final class Id3Decoder implements MetadataDecoder {
...
@@ -458,6 +467,115 @@ public final class Id3Decoder implements MetadataDecoder {
return
new
TextInformationFrame
(
id
,
description
);
return
new
TextInformationFrame
(
id
,
description
);
}
}
private
static
WxxxFrame
decodeWxxxFrame
(
ParsableByteArray
id3Data
,
int
frameSize
)
throws
UnsupportedEncodingException
{
int
encoding
=
id3Data
.
readUnsignedByte
();
String
charset
=
getCharsetName
(
encoding
);
byte
[]
data
=
new
byte
[
frameSize
-
1
];
id3Data
.
readBytes
(
data
,
0
,
frameSize
-
1
);
int
descriptionEndIndex
=
indexOfEos
(
data
,
0
,
encoding
);
String
description
=
new
String
(
data
,
0
,
descriptionEndIndex
,
charset
);
String
url
;
int
urlStartIndex
=
descriptionEndIndex
+
delimiterLength
(
encoding
);
if
(
urlStartIndex
<
data
.
length
)
{
int
urlEndIndex
=
indexOfEos
(
data
,
urlStartIndex
,
encoding
);
url
=
new
String
(
data
,
urlStartIndex
,
urlEndIndex
-
urlStartIndex
,
charset
);
}
else
{
url
=
""
;
}
return
new
WxxxFrame
(
description
,
url
);
}
private
static
ChapFrame
decodeChapFrame
(
ParsableByteArray
id3Data
,
int
frameSize
,
int
majorVersion
,
boolean
unsignedIntFrameSizeHack
,
int
frameHeaderSize
)
throws
UnsupportedEncodingException
{
byte
[]
frameBytes
=
new
byte
[
frameSize
];
id3Data
.
readBytes
(
frameBytes
,
0
,
frameSize
-
1
);
ParsableByteArray
chapterData
=
new
ParsableByteArray
(
frameBytes
);
int
chapterIdEndIndex
=
indexOfZeroByte
(
frameBytes
,
0
)
+
1
;
String
chapterId
=
chapterData
.
readNullTerminatedString
(
chapterIdEndIndex
);
chapterData
.
setPosition
(
chapterIdEndIndex
);
int
startTime
=
chapterData
.
readInt
();
int
endTime
=
chapterData
.
readInt
();
int
startOffset
=
chapterData
.
readInt
();
int
endOffset
=
chapterData
.
readInt
();
String
title
=
null
;
String
url
=
null
;
ApicFrame
image
=
null
;
while
(
chapterData
.
bytesLeft
()
>=
frameHeaderSize
)
{
Id3Frame
frame
=
decodeFrame
(
majorVersion
,
chapterData
,
unsignedIntFrameSizeHack
,
frameHeaderSize
);
if
(
frame
==
null
)
{
continue
;
}
if
(
frame
instanceof
TextInformationFrame
)
{
TextInformationFrame
textFrame
=
(
TextInformationFrame
)
frame
;
if
(
"TIT2"
.
equals
(
textFrame
.
id
))
{
title
=
textFrame
.
description
;
}
}
else
if
(
frame
instanceof
WxxxFrame
)
{
WxxxFrame
linkFrame
=
(
WxxxFrame
)
frame
;
url
=
linkFrame
.
url
;
}
else
if
(
frame
instanceof
ApicFrame
)
{
image
=
(
ApicFrame
)
frame
;
}
}
return
new
ChapFrame
(
chapterId
,
startTime
,
endTime
,
startOffset
,
endOffset
,
title
,
url
,
image
);
}
private
static
CtocFrame
decodeCtocFrame
(
ParsableByteArray
id3Data
,
int
frameSize
,
int
majorVersion
,
boolean
unsignedIntFrameSizeHack
,
int
frameHeaderSize
)
throws
UnsupportedEncodingException
{
byte
[]
frameBytes
=
new
byte
[
frameSize
];
id3Data
.
readBytes
(
frameBytes
,
0
,
frameSize
-
1
);
ParsableByteArray
tocData
=
new
ParsableByteArray
(
frameBytes
);
int
idEndIndex
=
indexOfZeroByte
(
frameBytes
,
0
)
+
1
;
String
id
=
tocData
.
readNullTerminatedString
(
idEndIndex
);
tocData
.
setPosition
(
idEndIndex
);
int
flags
=
tocData
.
readUnsignedByte
();
boolean
isRoot
=
(
flags
&
0x0002
)
!=
0
;
boolean
isOrdered
=
(
flags
&
0x0001
)
!=
0
;
int
entryCount
=
tocData
.
readUnsignedByte
();
String
[]
children
=
new
String
[
entryCount
];
for
(
int
i
=
0
;
i
<
entryCount
;
i
++)
{
int
startIndex
=
tocData
.
getPosition
();
int
endIndex
=
indexOfZeroByte
(
frameBytes
,
startIndex
)
+
1
;
int
stringLength
=
endIndex
-
startIndex
;
String
childId
=
tocData
.
readNullTerminatedString
(
stringLength
);
children
[
i
]
=
childId
;
}
String
title
=
null
;
while
(
tocData
.
bytesLeft
()
>=
frameHeaderSize
)
{
Id3Frame
frame
=
decodeFrame
(
majorVersion
,
tocData
,
unsignedIntFrameSizeHack
,
frameHeaderSize
);
if
(
frame
instanceof
TextInformationFrame
)
{
TextInformationFrame
textFrame
=
(
TextInformationFrame
)
frame
;
if
(
"TIT2"
.
equals
(
textFrame
.
id
))
{
title
=
textFrame
.
description
;
}
}
}
return
new
CtocFrame
(
id
,
isRoot
,
isOrdered
,
children
,
title
);
}
private
static
BinaryFrame
decodeBinaryFrame
(
ParsableByteArray
id3Data
,
int
frameSize
,
private
static
BinaryFrame
decodeBinaryFrame
(
ParsableByteArray
id3Data
,
int
frameSize
,
String
id
)
{
String
id
)
{
byte
[]
frame
=
new
byte
[
frameSize
];
byte
[]
frame
=
new
byte
[
frameSize
];
...
...
library/src/main/java/com/google/android/exoplayer2/metadata/id3/WxxxFrame.java
0 → 100644
View file @
31602af3
/*
* 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
android.os.Parcelable
;
import
com.google.android.exoplayer2.util.Util
;
/**
* Url Frame "WXX" ID3 frame.
*/
public
final
class
WxxxFrame
extends
Id3Frame
{
public
static
final
String
ID
=
"WXXX"
;
public
final
String
description
;
public
final
String
url
;
public
WxxxFrame
(
String
description
,
String
url
)
{
super
(
ID
);
this
.
description
=
description
;
this
.
url
=
url
;
}
/* package */
WxxxFrame
(
Parcel
in
)
{
super
(
ID
);
description
=
in
.
readString
();
url
=
in
.
readString
();
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
WxxxFrame
other
=
(
WxxxFrame
)
obj
;
return
Util
.
areEqual
(
description
,
other
.
description
)
&&
Util
.
areEqual
(
url
,
other
.
url
);
}
@Override
public
int
hashCode
()
{
int
result
=
17
;
result
=
31
*
result
+
(
description
!=
null
?
description
.
hashCode
()
:
0
);
result
=
31
*
result
+
(
url
!=
null
?
url
.
hashCode
()
:
0
);
return
result
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeString
(
description
);
dest
.
writeString
(
url
);
}
public
static
final
Parcelable
.
Creator
<
WxxxFrame
>
CREATOR
=
new
Parcelable
.
Creator
<
WxxxFrame
>()
{
@Override
public
WxxxFrame
createFromParcel
(
Parcel
in
)
{
return
new
WxxxFrame
(
in
);
}
@Override
public
WxxxFrame
[]
newArray
(
int
size
)
{
return
new
WxxxFrame
[
size
];
}
};
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment