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
6a544da2
authored
Nov 18, 2014
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Use new MediaCodecList APIs on L.
parent
685e1d1f
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
173 additions
and
43 deletions
library/src/main/java/com/google/android/exoplayer/DecoderInfo.java
library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java
library/src/main/java/com/google/android/exoplayer/MediaCodecUtil.java
library/src/main/java/com/google/android/exoplayer/DecoderInfo.java
View file @
6a544da2
...
@@ -29,7 +29,7 @@ public final class DecoderInfo {
...
@@ -29,7 +29,7 @@ public final class DecoderInfo {
public
final
String
name
;
public
final
String
name
;
/**
/**
* Whether the decoder
is adaptive
.
* Whether the decoder
supports seamless resolution switches
.
*
*
* @see android.media.MediaCodecInfo.CodecCapabilities#isFeatureSupported(String)
* @see android.media.MediaCodecInfo.CodecCapabilities#isFeatureSupported(String)
* @see android.media.MediaCodecInfo.CodecCapabilities#FEATURE_AdaptivePlayback
* @see android.media.MediaCodecInfo.CodecCapabilities#FEATURE_AdaptivePlayback
...
...
library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java
View file @
6a544da2
...
@@ -280,11 +280,9 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
...
@@ -280,11 +280,9 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
}
}
}
}
DecoderInfo
selectedDecoderInfo
=
MediaCodecUtil
.
getDecoderInfo
(
mimeType
);
DecoderInfo
selectedDecoderInfo
=
MediaCodecUtil
.
getDecoderInfo
(
mimeType
,
requiresSecureDecoder
);
String
selectedDecoderName
=
selectedDecoderInfo
.
name
;
String
selectedDecoderName
=
selectedDecoderInfo
.
name
;
if
(
requiresSecureDecoder
)
{
selectedDecoderName
=
getSecureDecoderName
(
selectedDecoderName
);
}
codecIsAdaptive
=
selectedDecoderInfo
.
adaptive
;
codecIsAdaptive
=
selectedDecoderInfo
.
adaptive
;
try
{
try
{
codec
=
MediaCodec
.
createByCodecName
(
selectedDecoderName
);
codec
=
MediaCodec
.
createByCodecName
(
selectedDecoderName
);
...
@@ -765,13 +763,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
...
@@ -765,13 +763,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer {
MediaCodec
codec
,
ByteBuffer
buffer
,
MediaCodec
.
BufferInfo
bufferInfo
,
int
bufferIndex
,
MediaCodec
codec
,
ByteBuffer
buffer
,
MediaCodec
.
BufferInfo
bufferInfo
,
int
bufferIndex
,
boolean
shouldSkip
)
throws
ExoPlaybackException
;
boolean
shouldSkip
)
throws
ExoPlaybackException
;
/**
* Returns the name of the secure variant of a given decoder.
*/
private
static
String
getSecureDecoderName
(
String
rawDecoderName
)
{
return
rawDecoderName
+
".secure"
;
}
private
void
notifyDecoderInitializationError
(
final
DecoderInitializationException
e
)
{
private
void
notifyDecoderInitializationError
(
final
DecoderInitializationException
e
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
eventHandler
.
post
(
new
Runnable
()
{
...
...
library/src/main/java/com/google/android/exoplayer/MediaCodecUtil.java
View file @
6a544da2
...
@@ -23,6 +23,7 @@ import android.media.MediaCodecInfo;
...
@@ -23,6 +23,7 @@ import android.media.MediaCodecInfo;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecCapabilities
;
import
android.media.MediaCodecInfo.CodecProfileLevel
;
import
android.media.MediaCodecInfo.CodecProfileLevel
;
import
android.media.MediaCodecList
;
import
android.media.MediaCodecList
;
import
android.text.TextUtils
;
import
android.util.Pair
;
import
android.util.Pair
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -33,60 +34,79 @@ import java.util.HashMap;
...
@@ -33,60 +34,79 @@ import java.util.HashMap;
@TargetApi
(
16
)
@TargetApi
(
16
)
public
class
MediaCodecUtil
{
public
class
MediaCodecUtil
{
private
static
final
HashMap
<
String
,
Pair
<
MediaCodecInfo
,
CodecCapabilities
>>
codecs
=
private
static
final
HashMap
<
CodecKey
,
Pair
<
String
,
CodecCapabilities
>>
codecs
=
new
HashMap
<
String
,
Pair
<
MediaCodecInfo
,
CodecCapabilities
>>();
new
HashMap
<
CodecKey
,
Pair
<
String
,
CodecCapabilities
>>();
/**
/**
* Get information about the decoder that will be used for a given mime type. If no decoder
* Get information about the decoder that will be used for a given mime type.
* exists for the mime type then null is returned.
*
*
* @param mimeType The mime type.
* @param mimeType The mime type.
* @param secure Whether the decoder is required to support secure decryption. Always pass false
* unless secure decryption really is required.
* @return Information about the decoder that will be used, or null if no decoder exists.
* @return Information about the decoder that will be used, or null if no decoder exists.
*/
*/
public
static
DecoderInfo
getDecoderInfo
(
String
mimeType
)
{
public
static
DecoderInfo
getDecoderInfo
(
String
mimeType
,
boolean
secure
)
{
Pair
<
MediaCodecInfo
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
mimeTyp
e
);
Pair
<
String
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
mimeType
,
secur
e
);
if
(
info
==
null
)
{
if
(
info
==
null
)
{
return
null
;
return
null
;
}
}
return
new
DecoderInfo
(
info
.
first
.
getName
()
,
isAdaptive
(
info
.
second
));
return
new
DecoderInfo
(
info
.
first
,
isAdaptive
(
info
.
second
));
}
}
/**
/**
* Optional call to warm the codec cache. Call from any appropriate
* Optional call to warm the codec cache for a given mime type.
* place to hide latency.
* <p>
* Calling this method may speed up subsequent calls to {@link #getDecoderInfo(String, boolean)}.
*
* @param mimeType The mime type.
* @param secure Whether the decoder is required to support secure decryption. Always pass false
* unless secure decryption really is required.
*/
*/
public
static
synchronized
void
warmCodecs
(
String
[]
mimeTypes
)
{
public
static
synchronized
void
warmCodec
(
String
mimeType
,
boolean
secure
)
{
for
(
int
i
=
0
;
i
<
mimeTypes
.
length
;
i
++)
{
getMediaCodecInfo
(
mimeType
,
secure
);
getMediaCodecInfo
(
mimeTypes
[
i
]);
}
}
}
/**
/**
* Returns the best decoder and its capabilities for the given mimeType. If there's no decoder
* Returns the name of the best decoder and its capabilities for the given mimeType.
* returns null.
*
* TODO: We need to use the new object based MediaCodecList API.
*/
*/
@SuppressWarnings
(
"deprecation"
)
private
static
synchronized
Pair
<
String
,
CodecCapabilities
>
getMediaCodecInfo
(
private
static
synchronized
Pair
<
MediaCodecInfo
,
CodecCapabilities
>
getMediaCodecInfo
(
String
mimeType
,
boolean
secure
)
{
String
mimeType
)
{
CodecKey
key
=
new
CodecKey
(
mimeType
,
secure
);
Pair
<
MediaCodecInfo
,
CodecCapabilities
>
result
=
codecs
.
get
(
mimeType
);
if
(
codecs
.
containsKey
(
key
))
{
if
(
result
!=
null
)
{
return
codecs
.
get
(
key
);
return
result
;
}
}
int
numberOfCodecs
=
MediaCodecList
.
getCodecCount
();
MediaCodecListCompat
mediaCodecList
=
Util
.
SDK_INT
>=
21
?
new
MediaCodecListCompatV21
(
secure
)
:
new
MediaCodecListCompatV16
();
int
numberOfCodecs
=
mediaCodecList
.
getCodecCount
();
boolean
secureDecodersExplicit
=
mediaCodecList
.
secureDecodersExplicit
();
// Note: MediaCodecList is sorted by the framework such that the best decoders come first.
// Note: MediaCodecList is sorted by the framework such that the best decoders come first.
for
(
int
i
=
0
;
i
<
numberOfCodecs
;
i
++)
{
for
(
int
i
=
0
;
i
<
numberOfCodecs
;
i
++)
{
MediaCodecInfo
info
=
M
ediaCodecList
.
getCodecInfoAt
(
i
);
MediaCodecInfo
info
=
m
ediaCodecList
.
getCodecInfoAt
(
i
);
String
codecName
=
info
.
getName
();
String
codecName
=
info
.
getName
();
if
(!
info
.
isEncoder
()
&&
codecName
.
startsWith
(
"OMX."
)
&&
!
codecName
.
endsWith
(
".secure"
))
{
if
(!
info
.
isEncoder
()
&&
codecName
.
startsWith
(
"OMX."
)
&&
(
secureDecodersExplicit
||
!
codecName
.
endsWith
(
".secure"
)))
{
String
[]
supportedTypes
=
info
.
getSupportedTypes
();
String
[]
supportedTypes
=
info
.
getSupportedTypes
();
for
(
int
j
=
0
;
j
<
supportedTypes
.
length
;
j
++)
{
for
(
int
j
=
0
;
j
<
supportedTypes
.
length
;
j
++)
{
String
supportedType
=
supportedTypes
[
j
];
String
supportedType
=
supportedTypes
[
j
];
if
(
supportedType
.
equalsIgnoreCase
(
mimeType
))
{
if
(
supportedType
.
equalsIgnoreCase
(
mimeType
))
{
result
=
Pair
.
create
(
info
,
info
.
getCapabilitiesForType
(
supportedType
));
CodecCapabilities
capabilities
=
info
.
getCapabilitiesForType
(
supportedType
);
codecs
.
put
(
mimeType
,
result
);
if
(!
secureDecodersExplicit
)
{
return
result
;
// Cache variants for secure and insecure playback. Note that the secure decoder is
// inferred, and may not actually exist.
codecs
.
put
(
key
.
secure
?
new
CodecKey
(
mimeType
,
false
)
:
key
,
Pair
.
create
(
codecName
,
capabilities
));
codecs
.
put
(
key
.
secure
?
key
:
new
CodecKey
(
mimeType
,
true
),
Pair
.
create
(
codecName
+
".secure"
,
capabilities
));
}
else
{
// We can only cache this variant. The other should be listed explicitly.
boolean
codecSecure
=
mediaCodecList
.
isSecurePlaybackSupported
(
info
.
getCapabilitiesForType
(
supportedType
));
codecs
.
put
(
key
.
secure
==
codecSecure
?
key
:
new
CodecKey
(
mimeType
,
codecSecure
),
Pair
.
create
(
codecName
,
capabilities
));
}
if
(
codecs
.
containsKey
(
key
))
{
return
codecs
.
get
(
key
);
}
}
}
}
}
}
}
...
@@ -113,7 +133,7 @@ public class MediaCodecUtil {
...
@@ -113,7 +133,7 @@ public class MediaCodecUtil {
* @return Whether the specified profile is supported at the specified level.
* @return Whether the specified profile is supported at the specified level.
*/
*/
public
static
boolean
isH264ProfileSupported
(
int
profile
,
int
level
)
{
public
static
boolean
isH264ProfileSupported
(
int
profile
,
int
level
)
{
Pair
<
MediaCodecInfo
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
MimeTypes
.
VIDEO_H264
);
Pair
<
String
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
MimeTypes
.
VIDEO_H264
,
false
);
if
(
info
==
null
)
{
if
(
info
==
null
)
{
return
false
;
return
false
;
}
}
...
@@ -133,7 +153,7 @@ public class MediaCodecUtil {
...
@@ -133,7 +153,7 @@ public class MediaCodecUtil {
* @return the maximum frame size for an H264 stream that can be decoded on the device.
* @return the maximum frame size for an H264 stream that can be decoded on the device.
*/
*/
public
static
int
maxH264DecodableFrameSize
()
{
public
static
int
maxH264DecodableFrameSize
()
{
Pair
<
MediaCodecInfo
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
MimeTypes
.
VIDEO_H264
);
Pair
<
String
,
CodecCapabilities
>
info
=
getMediaCodecInfo
(
MimeTypes
.
VIDEO_H264
,
false
);
if
(
info
==
null
)
{
if
(
info
==
null
)
{
return
0
;
return
0
;
}
}
...
@@ -177,4 +197,123 @@ public class MediaCodecUtil {
...
@@ -177,4 +197,123 @@ public class MediaCodecUtil {
}
}
}
}
private
interface
MediaCodecListCompat
{
/**
* The number of codecs in the list.
*/
public
int
getCodecCount
();
/**
* The info at the specified index in the list.
*
* @param index The index.
*/
public
MediaCodecInfo
getCodecInfoAt
(
int
index
);
/**
* @return Returns whether secure decoders are explicitly listed, if present.
*/
public
boolean
secureDecodersExplicit
();
/**
* Whether secure playback is supported for the given {@link CodecCapabilities}, which should
* have been obtained from a {@link MediaCodecInfo} obtained from this list.
* <p>
* May only be called if {@link #secureDecodersExplicit()} returns true.
*/
public
boolean
isSecurePlaybackSupported
(
CodecCapabilities
capabilities
);
}
@TargetApi
(
21
)
private
static
final
class
MediaCodecListCompatV21
implements
MediaCodecListCompat
{
private
final
MediaCodecInfo
[]
mediaCodecInfos
;
public
MediaCodecListCompatV21
(
boolean
includeSecure
)
{
int
codecKind
=
includeSecure
?
MediaCodecList
.
ALL_CODECS
:
MediaCodecList
.
REGULAR_CODECS
;
mediaCodecInfos
=
new
MediaCodecList
(
codecKind
).
getCodecInfos
();
}
@Override
public
int
getCodecCount
()
{
return
mediaCodecInfos
.
length
;
}
@Override
public
MediaCodecInfo
getCodecInfoAt
(
int
index
)
{
return
mediaCodecInfos
[
index
];
}
@Override
public
boolean
secureDecodersExplicit
()
{
return
true
;
}
@Override
public
boolean
isSecurePlaybackSupported
(
CodecCapabilities
capabilities
)
{
return
capabilities
.
isFeatureSupported
(
CodecCapabilities
.
FEATURE_SecurePlayback
);
}
}
@SuppressWarnings
(
"deprecation"
)
private
static
final
class
MediaCodecListCompatV16
implements
MediaCodecListCompat
{
@Override
public
int
getCodecCount
()
{
return
MediaCodecList
.
getCodecCount
();
}
@Override
public
MediaCodecInfo
getCodecInfoAt
(
int
index
)
{
return
MediaCodecList
.
getCodecInfoAt
(
index
);
}
@Override
public
boolean
secureDecodersExplicit
()
{
return
false
;
}
@Override
public
boolean
isSecurePlaybackSupported
(
CodecCapabilities
capabilities
)
{
throw
new
UnsupportedOperationException
();
}
}
private
static
final
class
CodecKey
{
public
final
String
mimeType
;
public
final
boolean
secure
;
public
CodecKey
(
String
mimeType
,
boolean
secure
)
{
this
.
mimeType
=
mimeType
;
this
.
secure
=
secure
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
mimeType
==
null
)
?
0
:
mimeType
.
hashCode
());
result
=
prime
*
result
+
(
secure
?
1231
:
1237
);
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
{
return
true
;
}
if
(
obj
==
null
||
obj
.
getClass
()
!=
CodecKey
.
class
)
{
return
false
;
}
CodecKey
other
=
(
CodecKey
)
obj
;
return
TextUtils
.
equals
(
mimeType
,
other
.
mimeType
)
&&
secure
==
other
.
secure
;
}
}
}
}
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