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
441d7f4e
authored
Nov 10, 2014
by
ojw28
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #130 from google/dev-l
Merge dev-l into dev, now L SDK is released.
parents
1653e816
5abb413f
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
178 additions
and
103 deletions
demo/build.gradle
demo/src/main/AndroidManifest.xml
demo/src/main/project.properties
library/build.gradle
library/src/main/AndroidManifest.xml
library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java
library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java
library/src/main/java/com/google/android/exoplayer/text/CaptionStyleCompat.java
library/src/main/project.properties
demo/build.gradle
View file @
441d7f4e
...
...
@@ -19,7 +19,7 @@ android {
defaultConfig
{
minSdkVersion
16
targetSdkVersion
19
targetSdkVersion
21
}
buildTypes
{
release
{
...
...
demo/src/main/AndroidManifest.xml
View file @
441d7f4e
...
...
@@ -25,7 +25,7 @@
<uses-permission
android:name=
"android.permission.ACCESS_WIFI_STATE"
/>
<uses-permission
android:name=
"android.permission.WRITE_EXTERNAL_STORAGE"
/>
<uses-sdk
android:minSdkVersion=
"16"
android:targetSdkVersion=
"
19
"
/>
<uses-sdk
android:minSdkVersion=
"16"
android:targetSdkVersion=
"
21
"
/>
<application
android:label=
"@string/application_name"
...
...
demo/src/main/project.properties
View file @
441d7f4e
...
...
@@ -8,6 +8,6 @@
# project structure.
# Project target.
target
=
android-
19
target
=
android-
21
android.library
=
false
android.library.reference.1
=
../../../library/src/main
library/build.gradle
View file @
441d7f4e
...
...
@@ -19,7 +19,7 @@ android {
defaultConfig
{
minSdkVersion
9
targetSdkVersion
19
targetSdkVersion
21
}
buildTypes
{
...
...
library/src/main/AndroidManifest.xml
View file @
441d7f4e
...
...
@@ -27,6 +27,6 @@
the library may be of use on older devices. However, please note that the core video playback
functionality provided by the library requires API level 16 or greater.
-->
<uses-sdk
android:minSdkVersion=
"9"
android:targetSdkVersion=
"
19
"
/>
<uses-sdk
android:minSdkVersion=
"9"
android:targetSdkVersion=
"
21
"
/>
</manifest>
library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java
View file @
441d7f4e
...
...
@@ -336,7 +336,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
AudioFormat
.
ENCODING_PCM_16BIT
,
bufferSize
,
AudioTrack
.
MODE_STREAM
,
audioSessionId
);
checkAudioTrackInitialized
();
}
audioTrack
.
setStereoVolume
(
volume
,
volume
);
setVolume
(
volume
);
if
(
getState
()
==
TrackRenderer
.
STATE_STARTED
)
{
audioTrackResumeSystemTimeUs
=
System
.
nanoTime
()
/
1000
;
audioTrack
.
play
();
...
...
@@ -519,7 +519,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
}
if
(
systemClockUs
-
lastTimestampSampleTimeUs
>=
MIN_TIMESTAMP_SAMPLE_INTERVAL_US
)
{
audioTimestampSet
=
audioTimestampCompat
.
initTimestamp
(
audioTrack
);
audioTimestampSet
=
audioTimestampCompat
.
update
(
audioTrack
);
if
(
audioTimestampSet
)
{
// Perform sanity checks on the timestamp.
long
audioTimestampUs
=
audioTimestampCompat
.
getNanoTime
()
/
1000
;
...
...
@@ -637,42 +637,52 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
}
}
// Copy {@code buffer} into {@code temporaryBuffer}.
// TODO: Bypass this copy step on versions of Android where [redacted] is implemented.
if
(
temporaryBuffer
==
null
||
temporaryBuffer
.
length
<
bufferInfo
.
size
)
{
temporaryBuffer
=
new
byte
[
bufferInfo
.
size
];
}
buffer
.
position
(
bufferInfo
.
offset
);
buffer
.
get
(
temporaryBuffer
,
0
,
bufferInfo
.
size
);
temporaryBufferOffset
=
0
;
temporaryBufferSize
=
bufferInfo
.
size
;
buffer
.
position
(
bufferInfo
.
offset
);
if
(
Util
.
SDK_INT
<
21
)
{
// Copy {@code buffer} into {@code temporaryBuffer}.
if
(
temporaryBuffer
==
null
||
temporaryBuffer
.
length
<
bufferInfo
.
size
)
{
temporaryBuffer
=
new
byte
[
bufferInfo
.
size
];
}
buffer
.
get
(
temporaryBuffer
,
0
,
bufferInfo
.
size
);
temporaryBufferOffset
=
0
;
}
}
if
(
audioTrack
==
null
)
{
initAudioTrack
();
}
// TODO: Don't bother doing this once [redacted] is fixed.
// Work out how many bytes we can write without the risk of blocking.
int
bytesPending
=
(
int
)
(
submittedBytes
-
getPlaybackHeadPosition
()
*
frameSize
);
int
bytesToWrite
=
bufferSize
-
bytesPending
;
if
(
bytesToWrite
>
0
)
{
bytesToWrite
=
Math
.
min
(
temporaryBufferSize
,
bytesToWrite
);
audioTrack
.
write
(
temporaryBuffer
,
temporaryBufferOffset
,
bytesToWrite
);
temporaryBufferOffset
+=
bytesToWrite
;
temporaryBufferSize
-=
bytesToWrite
;
submittedBytes
+=
bytesToWrite
;
if
(
temporaryBufferSize
==
0
)
{
codec
.
releaseOutputBuffer
(
bufferIndex
,
false
);
codecCounters
.
renderedOutputBufferCount
++;
return
true
;
int
bytesWritten
=
0
;
if
(
Util
.
SDK_INT
<
21
)
{
// Work out how many bytes we can write without the risk of blocking.
int
bytesPending
=
(
int
)
(
submittedBytes
-
getPlaybackHeadPosition
()
*
frameSize
);
int
bytesToWrite
=
bufferSize
-
bytesPending
;
if
(
bytesToWrite
>
0
)
{
bytesToWrite
=
Math
.
min
(
temporaryBufferSize
,
bytesToWrite
);
bytesWritten
=
audioTrack
.
write
(
temporaryBuffer
,
temporaryBufferOffset
,
bytesToWrite
);
temporaryBufferOffset
+=
bytesWritten
;
}
}
else
{
bytesWritten
=
writeNonBlockingV21
(
audioTrack
,
buffer
,
temporaryBufferSize
);
}
temporaryBufferSize
-=
bytesWritten
;
submittedBytes
+=
bytesWritten
;
if
(
temporaryBufferSize
==
0
)
{
codec
.
releaseOutputBuffer
(
bufferIndex
,
false
);
codecCounters
.
renderedOutputBufferCount
++;
return
true
;
}
return
false
;
}
@TargetApi
(
21
)
private
int
writeNonBlockingV21
(
AudioTrack
audioTrack
,
ByteBuffer
buffer
,
int
size
)
{
return
audioTrack
.
write
(
buffer
,
size
,
AudioTrack
.
WRITE_NON_BLOCKING
);
}
/**
* {@link AudioTrack#getPlaybackHeadPosition()} returns a value intended to be interpreted as
* an unsigned 32 bit integer, which also wraps around periodically. This method returns the
...
...
@@ -709,10 +719,24 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
private
void
setVolume
(
float
volume
)
{
this
.
volume
=
volume
;
if
(
audioTrack
!=
null
)
{
audioTrack
.
setStereoVolume
(
volume
,
volume
);
if
(
Util
.
SDK_INT
>=
21
)
{
setVolumeV21
(
audioTrack
,
volume
);
}
else
{
setVolumeV3
(
audioTrack
,
volume
);
}
}
}
@TargetApi
(
21
)
private
static
void
setVolumeV21
(
AudioTrack
audioTrack
,
float
volume
)
{
audioTrack
.
setVolume
(
volume
);
}
@SuppressWarnings
(
"deprecation"
)
private
static
void
setVolumeV3
(
AudioTrack
audioTrack
,
float
volume
)
{
audioTrack
.
setStereoVolume
(
volume
,
volume
);
}
private
void
notifyAudioTrackInitializationError
(
final
AudioTrackInitializationException
e
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
...
...
@@ -732,7 +756,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
/**
* Returns true if the audioTimestamp was retrieved from the audioTrack.
*/
boolean
initTimestamp
(
AudioTrack
audioTrack
);
boolean
update
(
AudioTrack
audioTrack
);
long
getNanoTime
();
...
...
@@ -746,7 +770,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
private
static
final
class
NoopAudioTimestampCompat
implements
AudioTimestampCompat
{
@Override
public
boolean
initTimestamp
(
AudioTrack
audioTrack
)
{
public
boolean
update
(
AudioTrack
audioTrack
)
{
return
false
;
}
...
...
@@ -778,7 +802,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer {
}
@Override
public
boolean
initTimestamp
(
AudioTrack
audioTrack
)
{
public
boolean
update
(
AudioTrack
audioTrack
)
{
return
audioTrack
.
getTimestamp
(
audioTimestamp
);
}
...
...
library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java
View file @
441d7f4e
...
...
@@ -18,6 +18,7 @@ package com.google.android.exoplayer;
import
com.google.android.exoplayer.drm.DrmSessionManager
;
import
com.google.android.exoplayer.util.MimeTypes
;
import
com.google.android.exoplayer.util.TraceUtil
;
import
com.google.android.exoplayer.util.Util
;
import
android.annotation.TargetApi
;
import
android.media.MediaCodec
;
...
...
@@ -93,7 +94,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
private
final
int
maxDroppedFrameCountToNotify
;
private
Surface
surface
;
private
boolean
d
rawnToSurface
;
private
boolean
reportedD
rawnToSurface
;
private
boolean
renderedFirstFrame
;
private
long
joiningDeadlineUs
;
private
long
droppedFrameAccumulationStartTimeMs
;
...
...
@@ -270,7 +271,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
@Override
protected
void
onStopped
()
{
joiningDeadlineUs
=
-
1
;
notifyAndReset
DroppedFrameCount
();
maybeNotify
DroppedFrameCount
();
super
.
onStopped
();
}
...
...
@@ -303,7 +304,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
return
;
}
this
.
surface
=
surface
;
this
.
d
rawnToSurface
=
false
;
this
.
reportedD
rawnToSurface
=
false
;
int
state
=
getState
();
if
(
state
==
TrackRenderer
.
STATE_ENABLED
||
state
==
TrackRenderer
.
STATE_STARTED
)
{
releaseCodec
();
...
...
@@ -370,24 +371,37 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
}
if
(!
renderedFirstFrame
)
{
renderOutputBuffer
(
codec
,
bufferIndex
);
renderOutputBuffer
Immediate
(
codec
,
bufferIndex
);
renderedFirstFrame
=
true
;
return
true
;
}
if
(
getState
()
==
TrackRenderer
.
STATE_STARTED
&&
earlyUs
<
30000
)
{
if
(
earlyUs
>
11000
)
{
// We're a little too early to render the frame. Sleep until the frame can be rendered.
// Note: The 11ms threshold was chosen fairly arbitrarily.
try
{
// Subtracting 10000 rather than 11000 ensures that the sleep time will be at least 1ms.
Thread
.
sleep
((
earlyUs
-
10000
)
/
1000
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
if
(
getState
()
!=
TrackRenderer
.
STATE_STARTED
)
{
return
false
;
}
if
(
Util
.
SDK_INT
>=
21
)
{
// Let the underlying framework time the release.
if
(
earlyUs
<
50000
)
{
renderOutputBufferTimedV21
(
codec
,
bufferIndex
,
System
.
nanoTime
()
+
(
earlyUs
*
1000L
));
return
true
;
}
}
else
{
// We need to time the release ourselves.
if
(
earlyUs
<
30000
)
{
if
(
earlyUs
>
11000
)
{
// We're a little too early to render the frame. Sleep until the frame can be rendered.
// Note: The 11ms threshold was chosen fairly arbitrarily.
try
{
// Subtracting 10000 rather than 11000 ensures the sleep time will be at least 1ms.
Thread
.
sleep
((
earlyUs
-
10000
)
/
1000
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
}
}
renderOutputBufferImmediate
(
codec
,
bufferIndex
);
return
true
;
}
renderOutputBuffer
(
codec
,
bufferIndex
);
return
true
;
}
// We're either not playing, or it's not time to render the frame yet.
...
...
@@ -408,65 +422,84 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
codecCounters
.
droppedOutputBufferCount
++;
droppedFrameCount
++;
if
(
droppedFrameCount
==
maxDroppedFrameCountToNotify
)
{
notifyAndReset
DroppedFrameCount
();
maybeNotify
DroppedFrameCount
();
}
}
private
void
renderOutputBuffer
(
MediaCodec
codec
,
int
bufferIndex
)
{
if
(
lastReportedWidth
!=
currentWidth
||
lastReportedHeight
!=
currentHeight
||
lastReportedPixelWidthHeightRatio
!=
currentPixelWidthHeightRatio
)
{
lastReportedWidth
=
currentWidth
;
lastReportedHeight
=
currentHeight
;
lastReportedPixelWidthHeightRatio
=
currentPixelWidthHeightRatio
;
notifyVideoSizeChanged
(
currentWidth
,
currentHeight
,
currentPixelWidthHeightRatio
);
}
TraceUtil
.
beginSection
(
"renderVideoBuffer"
);
private
void
renderOutputBufferImmediate
(
MediaCodec
codec
,
int
bufferIndex
)
{
maybeNotifyVideoSizeChanged
();
TraceUtil
.
beginSection
(
"renderVideoBufferImmediate"
);
codec
.
releaseOutputBuffer
(
bufferIndex
,
true
);
TraceUtil
.
endSection
();
codecCounters
.
renderedOutputBufferCount
++;
if
(!
drawnToSurface
)
{
drawnToSurface
=
true
;
notifyDrawnToSurface
(
surface
);
}
maybeNotifyDrawnToSurface
();
}
private
void
notifyVideoSizeChanged
(
final
int
width
,
final
int
height
,
final
float
pixelWidthHeightRatio
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onVideoSizeChanged
(
width
,
height
,
pixelWidthHeightRatio
);
}
});
@TargetApi
(
21
)
private
void
renderOutputBufferTimedV21
(
MediaCodec
codec
,
int
bufferIndex
,
long
nanoTime
)
{
maybeNotifyVideoSizeChanged
();
TraceUtil
.
beginSection
(
"releaseOutputBufferTimed"
);
codec
.
releaseOutputBuffer
(
bufferIndex
,
nanoTime
);
TraceUtil
.
endSection
();
codecCounters
.
renderedOutputBufferCount
++;
maybeNotifyDrawnToSurface
();
}
private
void
maybeNotifyVideoSizeChanged
()
{
if
(
eventHandler
==
null
||
eventListener
==
null
||
(
lastReportedWidth
==
currentWidth
&&
lastReportedHeight
==
currentHeight
&&
lastReportedPixelWidthHeightRatio
==
currentPixelWidthHeightRatio
))
{
return
;
}
// Make final copies to ensure the runnable reports the correct values.
final
int
currentWidth
=
this
.
currentWidth
;
final
int
currentHeight
=
this
.
currentHeight
;
final
float
currentPixelWidthHeightRatio
=
this
.
currentPixelWidthHeightRatio
;
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onVideoSizeChanged
(
currentWidth
,
currentHeight
,
currentPixelWidthHeightRatio
);
}
});
// Update the last reported values.
lastReportedWidth
=
currentWidth
;
lastReportedHeight
=
currentHeight
;
lastReportedPixelWidthHeightRatio
=
currentPixelWidthHeightRatio
;
}
private
void
notifyDrawnToSurface
(
final
Surface
surface
)
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onDrawnToSurface
(
surface
);
}
});
private
void
maybeNotifyDrawnToSurface
()
{
if
(
eventHandler
==
null
||
eventListener
==
null
||
reportedDrawnToSurface
)
{
return
;
}
// Make a final copy to ensure the runnable reports the correct surface.
final
Surface
surface
=
this
.
surface
;
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onDrawnToSurface
(
surface
);
}
});
// Record that we have reported that the surface has been drawn to.
reportedDrawnToSurface
=
true
;
}
private
void
notifyAndResetDroppedFrameCount
()
{
if
(
eventHandler
!=
null
&&
eventListener
!=
null
&&
droppedFrameCount
>
0
)
{
long
now
=
SystemClock
.
elapsedRealtime
();
final
int
countToNotify
=
droppedFrameCount
;
final
long
elapsedToNotify
=
now
-
droppedFrameAccumulationStartTimeMs
;
droppedFrameCount
=
0
;
droppedFrameAccumulationStartTimeMs
=
now
;
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onDroppedFrames
(
countToNotify
,
elapsedToNotify
);
}
});
private
void
maybeNotifyDroppedFrameCount
()
{
if
(
eventHandler
==
null
||
eventListener
==
null
||
droppedFrameCount
==
0
)
{
return
;
}
long
now
=
SystemClock
.
elapsedRealtime
();
// Make final copies to ensure the runnable reports the correct values.
final
int
countToNotify
=
droppedFrameCount
;
final
long
elapsedToNotify
=
now
-
droppedFrameAccumulationStartTimeMs
;
eventHandler
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
eventListener
.
onDroppedFrames
(
countToNotify
,
elapsedToNotify
);
}
});
// Reset the dropped frame tracking.
droppedFrameCount
=
0
;
droppedFrameAccumulationStartTimeMs
=
now
;
}
}
library/src/main/java/com/google/android/exoplayer/text/CaptionStyleCompat.java
View file @
441d7f4e
...
...
@@ -104,14 +104,19 @@ public final class CaptionStyleCompat {
/**
* Creates a {@link CaptionStyleCompat} equivalent to a provided {@link CaptionStyle}.
*
* @param
s
tyle A {@link CaptionStyle}.
* @param
captionS
tyle A {@link CaptionStyle}.
* @return The equivalent {@link CaptionStyleCompat}.
*/
@TargetApi
(
19
)
public
static
CaptionStyleCompat
createFromCaptionStyle
(
CaptionStyle
style
)
{
int
windowColor
=
Util
.
SDK_INT
>=
21
?
getWindowColorV21
(
style
)
:
Color
.
TRANSPARENT
;
return
new
CaptionStyleCompat
(
style
.
foregroundColor
,
style
.
backgroundColor
,
windowColor
,
style
.
edgeType
,
style
.
edgeColor
,
style
.
getTypeface
());
public
static
CaptionStyleCompat
createFromCaptionStyle
(
CaptioningManager
.
CaptionStyle
captionStyle
)
{
if
(
Util
.
SDK_INT
>=
21
)
{
return
createFromCaptionStyleV21
(
captionStyle
);
}
else
{
// Note - Any caller must be on at least API level 19 of greater (because CaptionStyle did
// not exist in earlier API levels).
return
createFromCaptionStyleV19
(
captionStyle
);
}
}
/**
...
...
@@ -132,11 +137,24 @@ public final class CaptionStyleCompat {
this
.
typeface
=
typeface
;
}
@SuppressWarnings
(
"unused"
)
@TargetApi
(
19
)
private
static
CaptionStyleCompat
createFromCaptionStyleV19
(
CaptioningManager
.
CaptionStyle
captionStyle
)
{
return
new
CaptionStyleCompat
(
captionStyle
.
foregroundColor
,
captionStyle
.
backgroundColor
,
Color
.
TRANSPARENT
,
captionStyle
.
edgeType
,
captionStyle
.
edgeColor
,
captionStyle
.
getTypeface
());
}
@TargetApi
(
21
)
private
static
int
getWindowColorV21
(
CaptioningManager
.
CaptionStyle
captionStyle
)
{
// TODO: Uncomment when building against API level 21.
return
Color
.
TRANSPARENT
;
//captionStyle.windowColor;
private
static
CaptionStyleCompat
createFromCaptionStyleV21
(
CaptioningManager
.
CaptionStyle
captionStyle
)
{
return
new
CaptionStyleCompat
(
captionStyle
.
hasForegroundColor
()
?
captionStyle
.
foregroundColor
:
DEFAULT
.
foregroundColor
,
captionStyle
.
hasBackgroundColor
()
?
captionStyle
.
backgroundColor
:
DEFAULT
.
backgroundColor
,
captionStyle
.
hasWindowColor
()
?
captionStyle
.
windowColor
:
DEFAULT
.
windowColor
,
captionStyle
.
hasEdgeType
()
?
captionStyle
.
edgeType
:
DEFAULT
.
edgeType
,
captionStyle
.
hasEdgeColor
()
?
captionStyle
.
edgeColor
:
DEFAULT
.
edgeColor
,
captionStyle
.
getTypeface
());
}
}
library/src/main/project.properties
View file @
441d7f4e
...
...
@@ -8,5 +8,5 @@
# project structure.
# Project target.
target
=
android-
19
target
=
android-
21
android.library
=
true
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