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
f4c10dc5
authored
Dec 17, 2015
by
andrewlewis
Committed by
Oliver Woodman
Dec 17, 2015
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Don't hold a lock while rendering in VpxRenderer.
parent
b9607321
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
70 additions
and
51 deletions
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxDecoderWrapper.java
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxOutputBuffer.java
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxOutputBufferRenderer.java
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxRenderer.java
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java
View file @
f4c10dc5
...
...
@@ -106,7 +106,6 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
private
VpxDecoderWrapper
decoder
;
private
VpxInputBuffer
inputBuffer
;
private
VpxOutputBuffer
outputBuffer
;
private
VpxOutputBuffer
renderedOutputBuffer
;
private
Bitmap
bitmap
;
private
boolean
drawnToSurface
;
...
...
@@ -181,13 +180,7 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
return
;
}
sourceIsReady
=
continueBufferingSource
(
positionUs
);
try
{
checkForDiscontinuity
(
positionUs
);
}
catch
(
VpxDecoderException
e
)
{
notifyDecoderError
(
e
);
throw
new
ExoPlaybackException
(
e
);
}
// Try and read a format if we don't have one already.
if
(
format
==
null
&&
!
readFormat
(
positionUs
))
{
...
...
@@ -226,7 +219,7 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
if
(
outputBuffer
.
flags
==
VpxDecoderWrapper
.
FLAG_END_OF_STREAM
)
{
outputStreamEnded
=
true
;
releaseOutputBuffer
(
outputBuffer
);
decoder
.
releaseOutputBuffer
(
outputBuffer
);
outputBuffer
=
null
;
return
;
}
...
...
@@ -241,7 +234,7 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
if
(
droppedFrameCount
==
maxDroppedFrameCountToNotify
)
{
notifyAndResetDroppedFrameCount
();
}
releaseOutputBuffer
(
outputBuffer
);
decoder
.
releaseOutputBuffer
(
outputBuffer
);
outputBuffer
=
null
;
return
;
}
...
...
@@ -270,7 +263,7 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
renderBuffer
();
}
private
void
renderBuffer
()
throws
VpxDecoderException
{
private
void
renderBuffer
()
{
codecCounters
.
renderedOutputBufferCount
++;
notifyIfVideoSizeChanged
(
outputBuffer
);
if
(
outputBuffer
.
mode
==
VpxDecoder
.
OUTPUT_MODE_RGB
&&
surface
!=
null
)
{
...
...
@@ -279,22 +272,16 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
drawnToSurface
=
true
;
notifyDrawnToSurface
(
surface
);
}
outputBuffer
.
release
();
}
else
if
(
outputBuffer
.
mode
==
VpxDecoder
.
OUTPUT_MODE_YUV
&&
outputBufferRenderer
!=
null
)
{
// The renderer will release the buffer.
outputBufferRenderer
.
setOutputBuffer
(
outputBuffer
);
}
else
{
outputBuffer
.
release
();
}
// Release the output buffer we rendered during the previous cycle, now that we delivered a new
// buffer.
releaseOutputBuffer
(
renderedOutputBuffer
);
renderedOutputBuffer
=
outputBuffer
;
outputBuffer
=
null
;
}
private
void
releaseOutputBuffer
(
VpxOutputBuffer
buffer
)
throws
VpxDecoderException
{
if
(
buffer
!=
null
)
{
decoder
.
releaseOutputBuffer
(
buffer
);
}
}
private
void
renderRgbFrame
(
VpxOutputBuffer
outputBuffer
,
boolean
scale
)
{
if
(
bitmap
==
null
||
bitmap
.
getWidth
()
!=
outputBuffer
.
width
||
bitmap
.
getHeight
()
!=
outputBuffer
.
height
)
{
...
...
@@ -350,7 +337,7 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
return
true
;
}
private
void
checkForDiscontinuity
(
long
positionUs
)
throws
VpxDecoderException
{
private
void
checkForDiscontinuity
(
long
positionUs
)
{
if
(
decoder
==
null
)
{
return
;
}
...
...
@@ -360,12 +347,12 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
}
}
private
void
flushDecoder
()
throws
VpxDecoderException
{
private
void
flushDecoder
()
{
inputBuffer
=
null
;
VpxOutputBuffer
bufferToRelease
=
outputBuffer
;
// Set this to null now because releaseOutputBuffer could throw an exception.
if
(
outputBuffer
!=
null
)
{
decoder
.
releaseOutputBuffer
(
outputBuffer
);
outputBuffer
=
null
;
releaseOutputBuffer
(
bufferToRelease
);
}
decoder
.
flush
();
}
...
...
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxDecoderWrapper.java
View file @
f4c10dc5
...
...
@@ -24,14 +24,15 @@ import java.util.LinkedList;
/**
* Wraps {@link VpxDecoder}, exposing a higher level decoder interface.
*/
/* package */
class
VpxDecoderWrapper
extends
Thread
{
/* package */
final
class
VpxDecoderWrapper
extends
Thread
{
public
static
final
int
FLAG_END_OF_STREAM
=
1
;
private
static
final
int
INPUT_BUFFER_SIZE
=
768
*
1024
;
// Value based on cs/SoftVpx.cpp.
/**
* The total number of output buffers. {@link LibvpxVideoTrackRenderer} may hold on to 2 buffers
* at a time so this value should be high enough considering LibvpxVideoTrackRenderer requirement.
* The number of input buffers and the number of output buffers. The track renderer may limit the
* minimum possible value due to requiring multiple output buffers to be dequeued at a time for it
* to make progress.
*/
private
static
final
int
NUM_BUFFERS
=
16
;
...
...
@@ -66,7 +67,7 @@ import java.util.LinkedList;
availableOutputBufferCount
=
NUM_BUFFERS
;
for
(
int
i
=
0
;
i
<
NUM_BUFFERS
;
i
++)
{
availableInputBuffers
[
i
]
=
new
VpxInputBuffer
();
availableOutputBuffers
[
i
]
=
new
VpxOutputBuffer
();
availableOutputBuffers
[
i
]
=
new
VpxOutputBuffer
(
this
);
}
}
...
...
@@ -105,19 +106,22 @@ import java.util.LinkedList;
if
(
queuedOutputBuffers
.
isEmpty
())
{
return
null
;
}
VpxOutputBuffer
outputBuffer
=
queuedOutputBuffers
.
removeFirst
();
return
outputBuffer
;
return
queuedOutputBuffers
.
removeFirst
();
}
}
public
void
releaseOutputBuffer
(
VpxOutputBuffer
outputBuffer
)
throws
VpxDecoderException
{
public
void
releaseOutputBuffer
(
VpxOutputBuffer
outputBuffer
)
{
synchronized
(
lock
)
{
maybeThrowDecoderError
();
availableOutputBuffers
[
availableOutputBufferCount
++]
=
outputBuffer
;
maybeNotifyDecodeLoop
();
}
}
/**
* Flushes input/output buffers that have not been dequeued yet and returns ownership of any
* dequeued input buffer to the decoder. Flushes any pending output currently in the decoder. The
* caller is still responsible for releasing any dequeued output buffers.
*/
public
void
flush
()
{
synchronized
(
lock
)
{
flushDecodedOutputBuffer
=
true
;
...
...
@@ -159,7 +163,7 @@ import java.util.LinkedList;
* Should only be called whilst synchronized on the lock object.
*/
private
void
maybeNotifyDecodeLoop
()
{
if
(
!
queuedInputBuffers
.
isEmpty
()
&&
availableOutputBufferCount
>
0
)
{
if
(
canDecodeBuffer
()
)
{
lock
.
notify
();
}
}
...
...
@@ -192,7 +196,7 @@ import java.util.LinkedList;
// Wait until we have an input buffer to decode, and an output buffer to decode into.
synchronized
(
lock
)
{
while
(!
released
&&
(
queuedInputBuffers
.
isEmpty
()
||
availableOutputBufferCount
==
0
))
{
while
(!
released
&&
!
canDecodeBuffer
(
))
{
lock
.
wait
();
}
if
(
released
)
{
...
...
@@ -238,6 +242,10 @@ import java.util.LinkedList;
return
true
;
}
private
boolean
canDecodeBuffer
()
{
return
!
queuedInputBuffers
.
isEmpty
()
&&
availableOutputBufferCount
>
0
;
}
/* package */
static
final
class
VpxInputBuffer
{
public
final
SampleHolder
sampleHolder
;
...
...
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxOutputBuffer.java
View file @
f4c10dc5
...
...
@@ -26,6 +26,12 @@ public final class VpxOutputBuffer {
public
static
final
int
COLORSPACE_BT601
=
1
;
public
static
final
int
COLORSPACE_BT709
=
2
;
private
final
VpxDecoderWrapper
decoder
;
/* package */
VpxOutputBuffer
(
VpxDecoderWrapper
decoder
)
{
this
.
decoder
=
decoder
;
}
/**
* RGB buffer for RGB mode.
*/
...
...
@@ -43,10 +49,16 @@ public final class VpxOutputBuffer {
public
int
colorspace
;
/**
* This method is called from C++ through JNI after decoding is done. It will resize the
* buffer based on the given dimensions.
* Releases the buffer back to the decoder, allowing it to be reused.
*/
public
void
release
()
{
decoder
.
releaseOutputBuffer
(
this
);
}
/**
* Resizes the buffer based on the given dimensions. Called via JNI after decoding completes.
*/
public
void
initForRgbFrame
(
int
width
,
int
height
)
{
/* package */
void
initForRgbFrame
(
int
width
,
int
height
)
{
this
.
width
=
width
;
this
.
height
=
height
;
int
minimumRgbSize
=
width
*
height
*
2
;
...
...
@@ -59,10 +71,10 @@ public final class VpxOutputBuffer {
}
/**
* This method is called from C++ through JNI after decoding is done. It will resize the
* buffer based on the given stride.
* Resizes the buffer based on the given stride. Called via JNI after decoding completes.
*/
public
void
initForYuvFrame
(
int
width
,
int
height
,
int
yStride
,
int
uvStride
,
int
colorspace
)
{
/* package */
void
initForYuvFrame
(
int
width
,
int
height
,
int
yStride
,
int
uvStride
,
int
colorspace
)
{
this
.
width
=
width
;
this
.
height
=
height
;
this
.
colorspace
=
colorspace
;
...
...
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxOutputBufferRenderer.java
View file @
f4c10dc5
...
...
@@ -21,7 +21,7 @@ package com.google.android.exoplayer.ext.vp9;
public
interface
VpxOutputBufferRenderer
{
/**
* Sets the output buffer to be rendered.
* Sets the output buffer to be rendered.
The renderer is responsible for releasing the buffer.
*/
void
setOutputBuffer
(
VpxOutputBuffer
outputBuffer
);
...
...
extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/VpxRenderer.java
View file @
f4c10dc5
...
...
@@ -21,6 +21,7 @@ import android.opengl.GLSurfaceView;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.nio.FloatBuffer
;
import
java.util.concurrent.atomic.AtomicReference
;
import
javax.microedition.khronos.egl.EGLConfig
;
import
javax.microedition.khronos.opengles.GL10
;
...
...
@@ -72,18 +73,21 @@ import javax.microedition.khronos.opengles.GL10;
1.0f
,
1.0f
,
1.0f
,
-
1.0f
);
private
final
int
[]
yuvTextures
=
new
int
[
3
];
private
final
AtomicReference
<
VpxOutputBuffer
>
pendingOutputBufferReference
;
private
int
program
;
private
int
texLocation
;
private
int
colorMatrixLocation
;
private
FloatBuffer
textureCoords
;
private
VpxOutputBuffer
outputBuffer
;
private
int
previousWidth
;
private
int
previousStride
;
private
VpxOutputBuffer
renderedOutputBuffer
;
// Accessed only from the GL thread.
public
VpxRenderer
()
{
previousWidth
=
-
1
;
previousStride
=
-
1
;
pendingOutputBufferReference
=
new
AtomicReference
<>();
}
/**
...
...
@@ -92,8 +96,12 @@ import javax.microedition.khronos.opengles.GL10;
*
* @param outputBuffer OutputBuffer containing the YUV Frame to be rendered
*/
public
synchronized
void
setFrame
(
VpxOutputBuffer
outputBuffer
)
{
this
.
outputBuffer
=
outputBuffer
;
public
void
setFrame
(
VpxOutputBuffer
outputBuffer
)
{
VpxOutputBuffer
oldPendingOutputBuffer
=
pendingOutputBufferReference
.
getAndSet
(
outputBuffer
);
if
(
oldPendingOutputBuffer
!=
null
)
{
// The old pending output buffer will never be used for rendering, so release it now.
oldPendingOutputBuffer
.
release
();
}
}
@Override
...
...
@@ -134,13 +142,18 @@ import javax.microedition.khronos.opengles.GL10;
@Override
public
void
onDrawFrame
(
GL10
unused
)
{
synchronized
(
this
)
{
VpxOutputBuffer
outputBuffer
=
this
.
outputBuffer
;
if
(
outputBuffer
==
null
)
{
// Nothing to render yet.
VpxOutputBuffer
pendingOutputBuffer
=
pendingOutputBufferReference
.
getAndSet
(
null
);
if
(
pendingOutputBuffer
==
null
&&
renderedOutputBuffer
==
null
)
{
// There is no output buffer to render at the moment.
return
;
}
if
(
pendingOutputBuffer
!=
null
)
{
if
(
renderedOutputBuffer
!=
null
)
{
renderedOutputBuffer
.
release
();
}
renderedOutputBuffer
=
pendingOutputBuffer
;
}
VpxOutputBuffer
outputBuffer
=
renderedOutputBuffer
;
// Set color matrix. Assume BT709 if the color space is unknown.
float
[]
colorConversion
=
outputBuffer
.
colorspace
==
VpxOutputBuffer
.
COLORSPACE_BT601
?
kColorConversion601
:
kColorConversion709
;
...
...
@@ -168,7 +181,6 @@ import javax.microedition.khronos.opengles.GL10;
previousWidth
=
outputBuffer
.
width
;
previousStride
=
outputBuffer
.
yuvStrides
[
0
];
}
}
GLES20
.
glClear
(
GLES20
.
GL_COLOR_BUFFER_BIT
);
GLES20
.
glDrawArrays
(
GLES20
.
GL_TRIANGLE_STRIP
,
0
,
4
);
checkNoGLES2Error
();
...
...
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