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
309d043c
authored
Aug 01, 2019
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Merge pull request #6239 from ittiam-systems:vorbis-picture-parse
PiperOrigin-RevId: 261087432
parent
e159e3ac
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
323 additions
and
32 deletions
RELEASENOTES.md
extensions/flac/proguard-rules.txt
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java
extensions/flac/src/main/jni/flac_jni.cc
extensions/flac/src/main/jni/flac_parser.cc
extensions/flac/src/main/jni/include/flac_parser.h
library/core/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java
library/core/src/main/java/com/google/android/exoplayer2/metadata/vorbis/VorbisComment.java → library/core/src/main/java/com/google/android/exoplayer2/metadata/flac/VorbisComment.java
library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java
library/core/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java
library/core/src/test/java/com/google/android/exoplayer2/metadata/vorbis/VorbisCommentTest.java → library/core/src/test/java/com/google/android/exoplayer2/metadata/flac/VorbisCommentTest.java
library/core/src/test/java/com/google/android/exoplayer2/util/FlacStreamMetadataTest.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
RELEASENOTES.md
View file @
309d043c
...
...
@@ -16,7 +16,7 @@
(
[
#6192
](
https://github.com/google/ExoPlayer/issues/6192
)
).
*
Ensure the
`SilenceMediaSource`
position is in range
(
[
#6229
](
https://github.com/google/ExoPlayer/issues/6229
)
).
*
Flac extension: Parse
`VORBIS_COMMENT`
metadata
*
Flac extension: Parse
`VORBIS_COMMENT`
and
`PICTURE`
metadata
(
[
#5527
](
https://github.com/google/ExoPlayer/issues/5527
)
).
### 2.10.3 ###
...
...
extensions/flac/proguard-rules.txt
View file @
309d043c
...
...
@@ -12,3 +12,6 @@
-keep class com.google.android.exoplayer2.util.FlacStreamMetadata {
*;
}
-keep class com.google.android.exoplayer2.metadata.flac.PictureFrame {
*;
}
extensions/flac/src/main/java/com/google/android/exoplayer2/ext/flac/FlacExtractor.java
View file @
309d043c
...
...
@@ -229,8 +229,8 @@ public final class FlacExtractor implements Extractor {
binarySearchSeeker
=
outputSeekMap
(
decoderJni
,
streamMetadata
,
input
.
getLength
(),
extractorOutput
);
Metadata
metadata
=
id3MetadataDisabled
?
null
:
id3Metadata
;
if
(
streamMetadata
.
vorbisComments
!=
null
)
{
metadata
=
streamMetadata
.
vorbisComments
.
copyWithAppendedEntriesFrom
(
metadata
);
if
(
streamMetadata
.
metadata
!=
null
)
{
metadata
=
streamMetadata
.
metadata
.
copyWithAppendedEntriesFrom
(
metadata
);
}
outputFormat
(
streamMetadata
,
metadata
,
trackOutput
);
outputBuffer
.
reset
(
streamMetadata
.
maxDecodedFrameSize
());
...
...
extensions/flac/src/main/jni/flac_jni.cc
View file @
309d043c
...
...
@@ -102,10 +102,10 @@ DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
jmethodID
arrayListConstructor
=
env
->
GetMethodID
(
arrayListClass
,
"<init>"
,
"()V"
);
jobject
commentList
=
env
->
NewObject
(
arrayListClass
,
arrayListConstructor
);
jmethodID
arrayListAddMethod
=
env
->
GetMethodID
(
arrayListClass
,
"add"
,
"(Ljava/lang/Object;)Z"
);
if
(
context
->
parser
->
isVorbisCommentsValid
())
{
jmethodID
arrayListAddMethod
=
env
->
GetMethodID
(
arrayListClass
,
"add"
,
"(Ljava/lang/Object;)Z"
);
if
(
context
->
parser
->
areVorbisCommentsValid
())
{
std
::
vector
<
std
::
string
>
vorbisComments
=
context
->
parser
->
getVorbisComments
();
for
(
std
::
vector
<
std
::
string
>::
const_iterator
vorbisComment
=
...
...
@@ -117,21 +117,49 @@ DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
}
}
jobject
pictureFrames
=
env
->
NewObject
(
arrayListClass
,
arrayListConstructor
);
bool
picturesValid
=
context
->
parser
->
arePicturesValid
();
if
(
picturesValid
)
{
std
::
vector
<
FlacPicture
>
pictures
=
context
->
parser
->
getPictures
();
jclass
pictureFrameClass
=
env
->
FindClass
(
"com/google/android/exoplayer2/metadata/flac/PictureFrame"
);
jmethodID
pictureFrameConstructor
=
env
->
GetMethodID
(
pictureFrameClass
,
"<init>"
,
"(ILjava/lang/String;Ljava/lang/String;IIII[B)V"
);
for
(
std
::
vector
<
FlacPicture
>::
const_iterator
picture
=
pictures
.
begin
();
picture
!=
pictures
.
end
();
++
picture
)
{
jstring
mimeType
=
env
->
NewStringUTF
(
picture
->
mimeType
.
c_str
());
jstring
description
=
env
->
NewStringUTF
(
picture
->
description
.
c_str
());
jbyteArray
pictureData
=
env
->
NewByteArray
(
picture
->
data
.
size
());
env
->
SetByteArrayRegion
(
pictureData
,
0
,
picture
->
data
.
size
(),
(
signed
char
*
)
&
picture
->
data
[
0
]);
jobject
pictureFrame
=
env
->
NewObject
(
pictureFrameClass
,
pictureFrameConstructor
,
picture
->
type
,
mimeType
,
description
,
picture
->
width
,
picture
->
height
,
picture
->
depth
,
picture
->
colors
,
pictureData
);
env
->
CallBooleanMethod
(
pictureFrames
,
arrayListAddMethod
,
pictureFrame
);
env
->
DeleteLocalRef
(
mimeType
);
env
->
DeleteLocalRef
(
description
);
env
->
DeleteLocalRef
(
pictureData
);
}
}
const
FLAC__StreamMetadata_StreamInfo
&
streamInfo
=
context
->
parser
->
getStreamInfo
();
jclass
flacStreamMetadataClass
=
env
->
FindClass
(
"com/google/android/exoplayer2/util/"
"FlacStreamMetadata"
);
jmethodID
flacStreamMetadataConstructor
=
env
->
GetMethodID
(
flacStreamMetadataClass
,
"<init>"
,
"(IIIIIIIJLjava/util/List;)V"
);
jmethodID
flacStreamMetadataConstructor
=
env
->
GetMethodID
(
flacStreamMetadataClass
,
"<init>"
,
"(IIIIIIIJLjava/util/List;Ljava/util/List;)V"
);
return
env
->
NewObject
(
flacStreamMetadataClass
,
flacStreamMetadataConstructor
,
streamInfo
.
min_blocksize
,
streamInfo
.
max_blocksize
,
streamInfo
.
min_framesize
,
streamInfo
.
max_framesize
,
streamInfo
.
sample_rate
,
streamInfo
.
channels
,
streamInfo
.
bits_per_sample
,
streamInfo
.
total_samples
,
commentList
);
commentList
,
pictureFrames
);
}
DECODER_FUNC
(
jint
,
flacDecodeToBuffer
,
jlong
jContext
,
jobject
jOutputBuffer
)
{
...
...
extensions/flac/src/main/jni/flac_parser.cc
View file @
309d043c
...
...
@@ -191,6 +191,24 @@ void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) {
ALOGE
(
"FLACParser::metadataCallback unexpected VORBISCOMMENT"
);
}
break
;
case
FLAC__METADATA_TYPE_PICTURE
:
{
const
FLAC__StreamMetadata_Picture
*
parsedPicture
=
&
metadata
->
data
.
picture
;
FlacPicture
picture
;
picture
.
mimeType
.
assign
(
std
::
string
(
parsedPicture
->
mime_type
));
picture
.
description
.
assign
(
std
::
string
((
char
*
)
parsedPicture
->
description
));
picture
.
data
.
assign
(
parsedPicture
->
data
,
parsedPicture
->
data
+
parsedPicture
->
data_length
);
picture
.
width
=
parsedPicture
->
width
;
picture
.
height
=
parsedPicture
->
height
;
picture
.
depth
=
parsedPicture
->
depth
;
picture
.
colors
=
parsedPicture
->
colors
;
picture
.
type
=
parsedPicture
->
type
;
mPictures
.
push_back
(
picture
);
mPicturesValid
=
true
;
break
;
}
default
:
ALOGE
(
"FLACParser::metadataCallback unexpected type %u"
,
metadata
->
type
);
break
;
...
...
@@ -253,6 +271,7 @@ FLACParser::FLACParser(DataSource *source)
mEOF
(
false
),
mStreamInfoValid
(
false
),
mVorbisCommentsValid
(
false
),
mPicturesValid
(
false
),
mWriteRequested
(
false
),
mWriteCompleted
(
false
),
mWriteBuffer
(
NULL
),
...
...
@@ -288,6 +307,8 @@ bool FLACParser::init() {
FLAC__METADATA_TYPE_SEEKTABLE
);
FLAC__stream_decoder_set_metadata_respond
(
mDecoder
,
FLAC__METADATA_TYPE_VORBIS_COMMENT
);
FLAC__stream_decoder_set_metadata_respond
(
mDecoder
,
FLAC__METADATA_TYPE_PICTURE
);
FLAC__StreamDecoderInitStatus
initStatus
;
initStatus
=
FLAC__stream_decoder_init_stream
(
mDecoder
,
read_callback
,
seek_callback
,
tell_callback
,
length_callback
,
...
...
extensions/flac/src/main/jni/include/flac_parser.h
View file @
309d043c
...
...
@@ -30,6 +30,17 @@
typedef
int
status_t
;
struct
FlacPicture
{
int
type
;
std
::
string
mimeType
;
std
::
string
description
;
FLAC__uint32
width
;
FLAC__uint32
height
;
FLAC__uint32
depth
;
FLAC__uint32
colors
;
std
::
vector
<
char
>
data
;
};
class
FLACParser
{
public
:
FLACParser
(
DataSource
*
source
);
...
...
@@ -48,10 +59,14 @@ class FLACParser {
return
mStreamInfo
;
}
bool
isVorbisCommentsValid
()
{
return
mVorbisCommentsValid
;
}
bool
areVorbisCommentsValid
()
const
{
return
mVorbisCommentsValid
;
}
std
::
vector
<
std
::
string
>
getVorbisComments
()
{
return
mVorbisComments
;
}
bool
arePicturesValid
()
const
{
return
mPicturesValid
;
}
const
std
::
vector
<
FlacPicture
>
&
getPictures
()
const
{
return
mPictures
;
}
int64_t
getLastFrameTimestamp
()
const
{
return
(
1000000LL
*
mWriteHeader
.
number
.
sample_number
)
/
getSampleRate
();
}
...
...
@@ -80,7 +95,9 @@ class FLACParser {
if
(
newPosition
==
0
)
{
mStreamInfoValid
=
false
;
mVorbisCommentsValid
=
false
;
mPicturesValid
=
false
;
mVorbisComments
.
clear
();
mPictures
.
clear
();
FLAC__stream_decoder_reset
(
mDecoder
);
}
else
{
FLAC__stream_decoder_flush
(
mDecoder
);
...
...
@@ -130,6 +147,10 @@ class FLACParser {
std
::
vector
<
std
::
string
>
mVorbisComments
;
bool
mVorbisCommentsValid
;
// cached when the PICTURE metadata is parsed by libFLAC
std
::
vector
<
FlacPicture
>
mPictures
;
bool
mPicturesValid
;
// cached when a decoded PCM block is "written" by libFLAC parser
bool
mWriteRequested
;
bool
mWriteCompleted
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/metadata/flac/PictureFrame.java
0 → 100644
View file @
309d043c
/*
* Copyright (C) 2019 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
.
flac
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
java.util.Arrays
;
/** A picture parsed from a FLAC file. */
public
final
class
PictureFrame
implements
Metadata
.
Entry
{
/** The type of the picture. */
public
final
int
pictureType
;
/** The mime type of the picture. */
public
final
String
mimeType
;
/** A description of the picture. */
public
final
String
description
;
/** The width of the picture in pixels. */
public
final
int
width
;
/** The height of the picture in pixels. */
public
final
int
height
;
/** The color depth of the picture in bits-per-pixel. */
public
final
int
depth
;
/** For indexed-color pictures (e.g. GIF), the number of colors used. 0 otherwise. */
public
final
int
colors
;
/** The encoded picture data. */
public
final
byte
[]
pictureData
;
public
PictureFrame
(
int
pictureType
,
String
mimeType
,
String
description
,
int
width
,
int
height
,
int
depth
,
int
colors
,
byte
[]
pictureData
)
{
this
.
pictureType
=
pictureType
;
this
.
mimeType
=
mimeType
;
this
.
description
=
description
;
this
.
width
=
width
;
this
.
height
=
height
;
this
.
depth
=
depth
;
this
.
colors
=
colors
;
this
.
pictureData
=
pictureData
;
}
/* package */
PictureFrame
(
Parcel
in
)
{
this
.
pictureType
=
in
.
readInt
();
this
.
mimeType
=
castNonNull
(
in
.
readString
());
this
.
description
=
castNonNull
(
in
.
readString
());
this
.
width
=
in
.
readInt
();
this
.
height
=
in
.
readInt
();
this
.
depth
=
in
.
readInt
();
this
.
colors
=
in
.
readInt
();
this
.
pictureData
=
castNonNull
(
in
.
createByteArray
());
}
@Override
public
String
toString
()
{
return
"Picture: mimeType="
+
mimeType
+
", description="
+
description
;
}
@Override
public
boolean
equals
(
@Nullable
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
getClass
()
!=
obj
.
getClass
())
{
return
false
;
}
PictureFrame
other
=
(
PictureFrame
)
obj
;
return
(
pictureType
==
other
.
pictureType
)
&&
mimeType
.
equals
(
other
.
mimeType
)
&&
description
.
equals
(
other
.
description
)
&&
(
width
==
other
.
width
)
&&
(
height
==
other
.
height
)
&&
(
depth
==
other
.
depth
)
&&
(
colors
==
other
.
colors
)
&&
Arrays
.
equals
(
pictureData
,
other
.
pictureData
);
}
@Override
public
int
hashCode
()
{
int
result
=
17
;
result
=
31
*
result
+
pictureType
;
result
=
31
*
result
+
mimeType
.
hashCode
();
result
=
31
*
result
+
description
.
hashCode
();
result
=
31
*
result
+
width
;
result
=
31
*
result
+
height
;
result
=
31
*
result
+
depth
;
result
=
31
*
result
+
colors
;
result
=
31
*
result
+
Arrays
.
hashCode
(
pictureData
);
return
result
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeInt
(
pictureType
);
dest
.
writeString
(
mimeType
);
dest
.
writeString
(
description
);
dest
.
writeInt
(
width
);
dest
.
writeInt
(
height
);
dest
.
writeInt
(
depth
);
dest
.
writeInt
(
colors
);
dest
.
writeByteArray
(
pictureData
);
}
@Override
public
int
describeContents
()
{
return
0
;
}
public
static
final
Parcelable
.
Creator
<
PictureFrame
>
CREATOR
=
new
Parcelable
.
Creator
<
PictureFrame
>()
{
@Override
public
PictureFrame
createFromParcel
(
Parcel
in
)
{
return
new
PictureFrame
(
in
);
}
@Override
public
PictureFrame
[]
newArray
(
int
size
)
{
return
new
PictureFrame
[
size
];
}
};
}
library/core/src/main/java/com/google/android/exoplayer2/metadata/
vorbis
/VorbisComment.java
→
library/core/src/main/java/com/google/android/exoplayer2/metadata/
flac
/VorbisComment.java
View file @
309d043c
...
...
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
metadata
.
vorbis
;
package
com
.
google
.
android
.
exoplayer2
.
metadata
.
flac
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/util/FlacStreamMetadata.java
View file @
309d043c
...
...
@@ -18,7 +18,8 @@ package com.google.android.exoplayer2.util;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.vorbis.VorbisComment
;
import
com.google.android.exoplayer2.metadata.flac.PictureFrame
;
import
com.google.android.exoplayer2.metadata.flac.VorbisComment
;
import
java.util.ArrayList
;
import
java.util.List
;
...
...
@@ -35,7 +36,7 @@ public final class FlacStreamMetadata {
public
final
int
channels
;
public
final
int
bitsPerSample
;
public
final
long
totalSamples
;
@Nullable
public
final
Metadata
vorbisComments
;
@Nullable
public
final
Metadata
metadata
;
private
static
final
String
SEPARATOR
=
"="
;
...
...
@@ -58,7 +59,7 @@ public final class FlacStreamMetadata {
this
.
channels
=
scratch
.
readBits
(
3
)
+
1
;
this
.
bitsPerSample
=
scratch
.
readBits
(
5
)
+
1
;
this
.
totalSamples
=
((
scratch
.
readBits
(
4
)
&
0xF
L
)
<<
32
)
|
(
scratch
.
readBits
(
32
)
&
0xFFFFFFFF
L
);
this
.
vorbisComments
=
null
;
this
.
metadata
=
null
;
}
/**
...
...
@@ -71,10 +72,13 @@ public final class FlacStreamMetadata {
* @param bitsPerSample Number of bits per sample of the FLAC stream.
* @param totalSamples Total samples of the FLAC stream.
* @param vorbisComments Vorbis comments. Each entry must be in key=value form.
* @param pictureFrames Picture frames.
* @see <a href="https://xiph.org/flac/format.html#metadata_block_streaminfo">FLAC format
* METADATA_BLOCK_STREAMINFO</a>
* @see <a href="https://xiph.org/flac/format.html#metadata_block_vorbis_comment">FLAC format
* METADATA_BLOCK_VORBIS_COMMENT</a>
* @see <a href="https://xiph.org/flac/format.html#metadata_block_picture">FLAC format
* METADATA_BLOCK_PICTURE</a>
*/
public
FlacStreamMetadata
(
int
minBlockSize
,
...
...
@@ -85,7 +89,8 @@ public final class FlacStreamMetadata {
int
channels
,
int
bitsPerSample
,
long
totalSamples
,
List
<
String
>
vorbisComments
)
{
List
<
String
>
vorbisComments
,
List
<
PictureFrame
>
pictureFrames
)
{
this
.
minBlockSize
=
minBlockSize
;
this
.
maxBlockSize
=
maxBlockSize
;
this
.
minFrameSize
=
minFrameSize
;
...
...
@@ -94,7 +99,7 @@ public final class FlacStreamMetadata {
this
.
channels
=
channels
;
this
.
bitsPerSample
=
bitsPerSample
;
this
.
totalSamples
=
totalSamples
;
this
.
vorbisComments
=
parseVorbisComments
(
vorbisComment
s
);
this
.
metadata
=
buildMetadata
(
vorbisComments
,
pictureFrame
s
);
}
/** Returns the maximum size for a decoded frame from the FLAC stream. */
...
...
@@ -138,22 +143,25 @@ public final class FlacStreamMetadata {
}
@Nullable
private
static
Metadata
parseVorbisComments
(
@Nullable
List
<
String
>
vorbisComments
)
{
if
(
vorbisComments
==
null
||
vorbisComments
.
isEmpty
())
{
private
static
Metadata
buildMetadata
(
List
<
String
>
vorbisComments
,
List
<
PictureFrame
>
pictureFrames
)
{
if
(
vorbisComments
.
isEmpty
()
&&
pictureFrames
.
isEmpty
())
{
return
null
;
}
ArrayList
<
VorbisComment
>
commentFrames
=
new
ArrayList
<>();
for
(
String
vorbisComment
:
vorbisComments
)
{
ArrayList
<
Metadata
.
Entry
>
metadataEntries
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
vorbisComments
.
size
();
i
++)
{
String
vorbisComment
=
vorbisComments
.
get
(
i
);
String
[]
keyAndValue
=
Util
.
splitAtFirst
(
vorbisComment
,
SEPARATOR
);
if
(
keyAndValue
.
length
!=
2
)
{
Log
.
w
(
TAG
,
"Failed to parse vorbis comment: "
+
vorbisComment
);
}
else
{
VorbisComment
commentFrame
=
new
VorbisComment
(
keyAndValue
[
0
],
keyAndValue
[
1
]);
commentFrames
.
add
(
commentFrame
);
VorbisComment
entry
=
new
VorbisComment
(
keyAndValue
[
0
],
keyAndValue
[
1
]);
metadataEntries
.
add
(
entry
);
}
}
metadataEntries
.
addAll
(
pictureFrames
);
return
commentFrames
.
isEmpty
()
?
null
:
new
Metadata
(
commentFram
es
);
return
metadataEntries
.
isEmpty
()
?
null
:
new
Metadata
(
metadataEntri
es
);
}
}
library/core/src/test/java/com/google/android/exoplayer2/metadata/flac/PictureFrameTest.java
0 → 100644
View file @
309d043c
/*
* Copyright (C) 2019 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
.
flac
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
android.os.Parcel
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
/** Test for {@link PictureFrame}. */
@RunWith
(
AndroidJUnit4
.
class
)
public
final
class
PictureFrameTest
{
@Test
public
void
testParcelable
()
{
PictureFrame
pictureFrameToParcel
=
new
PictureFrame
(
0
,
""
,
""
,
0
,
0
,
0
,
0
,
new
byte
[
0
]);
Parcel
parcel
=
Parcel
.
obtain
();
pictureFrameToParcel
.
writeToParcel
(
parcel
,
0
);
parcel
.
setDataPosition
(
0
);
PictureFrame
pictureFrameFromParcel
=
PictureFrame
.
CREATOR
.
createFromParcel
(
parcel
);
assertThat
(
pictureFrameFromParcel
).
isEqualTo
(
pictureFrameToParcel
);
parcel
.
recycle
();
}
}
library/core/src/test/java/com/google/android/exoplayer2/metadata/
vorbis
/VorbisCommentTest.java
→
library/core/src/test/java/com/google/android/exoplayer2/metadata/
flac
/VorbisCommentTest.java
View file @
309d043c
...
...
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
metadata
.
vorbis
;
package
com
.
google
.
android
.
exoplayer2
.
metadata
.
flac
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
...
...
library/core/src/test/java/com/google/android/exoplayer2/util/FlacStreamMetadataTest.java
View file @
309d043c
...
...
@@ -19,7 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.
vorbis
.VorbisComment
;
import
com.google.android.exoplayer2.metadata.
flac
.VorbisComment
;
import
java.util.ArrayList
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -34,7 +34,8 @@ public final class FlacStreamMetadataTest {
commentsList
.
add
(
"Title=Song"
);
commentsList
.
add
(
"Artist=Singer"
);
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
).
vorbisComments
;
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
,
new
ArrayList
<>()).
metadata
;
assertThat
(
metadata
.
length
()).
isEqualTo
(
2
);
VorbisComment
commentFrame
=
(
VorbisComment
)
metadata
.
get
(
0
);
...
...
@@ -49,7 +50,8 @@ public final class FlacStreamMetadataTest {
public
void
parseEmptyVorbisComments
()
{
ArrayList
<
String
>
commentsList
=
new
ArrayList
<>();
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
).
vorbisComments
;
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
,
new
ArrayList
<>()).
metadata
;
assertThat
(
metadata
).
isNull
();
}
...
...
@@ -59,7 +61,8 @@ public final class FlacStreamMetadataTest {
ArrayList
<
String
>
commentsList
=
new
ArrayList
<>();
commentsList
.
add
(
"Title=So=ng"
);
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
).
vorbisComments
;
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
,
new
ArrayList
<>()).
metadata
;
assertThat
(
metadata
.
length
()).
isEqualTo
(
1
);
VorbisComment
commentFrame
=
(
VorbisComment
)
metadata
.
get
(
0
);
...
...
@@ -73,7 +76,8 @@ public final class FlacStreamMetadataTest {
commentsList
.
add
(
"TitleSong"
);
commentsList
.
add
(
"Artist=Singer"
);
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
).
vorbisComments
;
Metadata
metadata
=
new
FlacStreamMetadata
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
commentsList
,
new
ArrayList
<>()).
metadata
;
assertThat
(
metadata
.
length
()).
isEqualTo
(
1
);
VorbisComment
commentFrame
=
(
VorbisComment
)
metadata
.
get
(
0
);
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
View file @
309d043c
...
...
@@ -50,6 +50,7 @@ import com.google.android.exoplayer2.PlaybackPreparer;
import
com.google.android.exoplayer2.Player
;
import
com.google.android.exoplayer2.Player.DiscontinuityReason
;
import
com.google.android.exoplayer2.metadata.Metadata
;
import
com.google.android.exoplayer2.metadata.flac.PictureFrame
;
import
com.google.android.exoplayer2.metadata.id3.ApicFrame
;
import
com.google.android.exoplayer2.source.TrackGroupArray
;
import
com.google.android.exoplayer2.source.ads.AdsLoader
;
...
...
@@ -304,6 +305,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
private
boolean
controllerHideOnTouch
;
private
int
textureViewRotation
;
private
boolean
isTouching
;
private
static
final
int
PICTURE_TYPE_FRONT_COVER
=
3
;
private
static
final
int
PICTURE_TYPE_NOT_SET
=
-
1
;
public
PlayerView
(
Context
context
)
{
this
(
context
,
null
);
...
...
@@ -1246,15 +1249,32 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
}
private
boolean
setArtworkFromMetadata
(
Metadata
metadata
)
{
boolean
isArtworkSet
=
false
;
int
currentPictureType
=
PICTURE_TYPE_NOT_SET
;
for
(
int
i
=
0
;
i
<
metadata
.
length
();
i
++)
{
Metadata
.
Entry
metadataEntry
=
metadata
.
get
(
i
);
int
pictureType
;
byte
[]
bitmapData
;
if
(
metadataEntry
instanceof
ApicFrame
)
{
byte
[]
bitmapData
=
((
ApicFrame
)
metadataEntry
).
pictureData
;
bitmapData
=
((
ApicFrame
)
metadataEntry
).
pictureData
;
pictureType
=
((
ApicFrame
)
metadataEntry
).
pictureType
;
}
else
if
(
metadataEntry
instanceof
PictureFrame
)
{
bitmapData
=
((
PictureFrame
)
metadataEntry
).
pictureData
;
pictureType
=
((
PictureFrame
)
metadataEntry
).
pictureType
;
}
else
{
continue
;
}
// Prefer the first front cover picture. If there aren't any, prefer the first picture.
if
(
currentPictureType
==
PICTURE_TYPE_NOT_SET
||
pictureType
==
PICTURE_TYPE_FRONT_COVER
)
{
Bitmap
bitmap
=
BitmapFactory
.
decodeByteArray
(
bitmapData
,
0
,
bitmapData
.
length
);
return
setDrawableArtwork
(
new
BitmapDrawable
(
getResources
(),
bitmap
));
isArtworkSet
=
setDrawableArtwork
(
new
BitmapDrawable
(
getResources
(),
bitmap
));
currentPictureType
=
pictureType
;
if
(
currentPictureType
==
PICTURE_TYPE_FRONT_COVER
)
{
break
;
}
}
}
return
false
;
return
isArtworkSet
;
}
private
boolean
setDrawableArtwork
(
@Nullable
Drawable
drawable
)
{
...
...
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