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
003b3c4e
authored
Feb 26, 2020
by
tonihei
Committed by
kim-vde
Feb 27, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Move MediaCodecVideoRendererTest to right package.
PiperOrigin-RevId: 297354294
parent
52825a27
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
0 additions
and
459 deletions
library/core/src/test/java/com/google/android/exoplayer2/mediacodec/MediaCodecVideoRendererTest.java
library/core/src/test/resources/com/google/android/exoplayer2/mediacodec/robolectric.properties
library/core/src/test/java/com/google/android/exoplayer2/mediacodec/MediaCodecVideoRendererTest.java
deleted
100644 → 0
View file @
52825a27
/*
* Copyright (C) 2020 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
.
mediacodec
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyLong
;
import
static
org
.
mockito
.
ArgumentMatchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
inOrder
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
android.graphics.SurfaceTexture
;
import
android.media.MediaCodec
;
import
android.media.MediaFormat
;
import
android.os.Handler
;
import
android.os.SystemClock
;
import
android.view.Surface
;
import
androidx.annotation.Nullable
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlaybackException
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.Renderer
;
import
com.google.android.exoplayer2.RendererCapabilities
;
import
com.google.android.exoplayer2.RendererConfiguration
;
import
com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException
;
import
com.google.android.exoplayer2.testutil.FakeSampleStream
;
import
com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem
;
import
com.google.android.exoplayer2.util.ClosedSource
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.video.MediaCodecVideoRenderer
;
import
com.google.android.exoplayer2.video.VideoFrameMetadataListener
;
import
com.google.android.exoplayer2.video.VideoRendererEventListener
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.junit.Before
;
import
org.junit.Ignore
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.InOrder
;
import
org.mockito.Mock
;
import
org.mockito.junit.MockitoJUnit
;
import
org.mockito.junit.MockitoRule
;
/** Unit test for {@link MediaCodecVideoRenderer}. */
@ClosedSource
(
reason
=
"See b/147731297."
)
@RunWith
(
AndroidJUnit4
.
class
)
public
class
MediaCodecVideoRendererTest
{
@Rule
public
final
MockitoRule
mockito
=
MockitoJUnit
.
rule
();
private
static
final
Format
BASIC_MP4_1080
=
Format
.
createVideoSampleFormat
(
/* id= */
null
,
/* sampleMimeType= */
MimeTypes
.
VIDEO_MP4
,
/* codecs= */
null
,
/* bitrate= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
/* width= */
1920
,
/* height= */
1080
,
/* frameRate= */
Format
.
NO_VALUE
,
/* initializationData= */
null
,
/* rotationDegrees= */
0
,
/* pixelWidthHeightRatio= */
1
f
,
/* drmInitData= */
null
);
private
MediaCodecVideoRenderer
mediaCodecVideoRenderer
;
@Mock
private
VideoRendererEventListener
eventListener
;
@Before
public
void
setUp
()
throws
Exception
{
MediaCodecSelector
mediaCodecSelector
=
new
MediaCodecSelector
()
{
@Override
public
List
<
MediaCodecInfo
>
getDecoderInfos
(
String
mimeType
,
boolean
requiresSecureDecoder
,
boolean
requiresTunnelingDecoder
)
{
return
Collections
.
singletonList
(
MediaCodecInfo
.
newInstance
(
/* name= */
"name"
,
/* mimeType= */
mimeType
,
/* codecMimeType= */
mimeType
,
/* capabilities= */
null
,
/* hardwareAccelerated= */
false
,
/* softwareOnly= */
true
,
/* vendor= */
false
,
/* forceDisableAdaptive= */
false
,
/* forceSecure= */
false
));
}
@Override
@Nullable
public
MediaCodecInfo
getPassthroughDecoderInfo
()
throws
DecoderQueryException
{
throw
new
UnsupportedOperationException
();
}
};
mediaCodecVideoRenderer
=
new
MediaCodecVideoRenderer
(
ApplicationProvider
.
getApplicationContext
(),
mediaCodecSelector
,
/* allowedJoiningTimeMs= */
0
,
/* eventHandler= */
new
Handler
(),
/* eventListener= */
eventListener
,
/* maxDroppedFramesToNotify= */
-
1
)
{
@Override
@Capabilities
protected
int
supportsFormat
(
MediaCodecSelector
mediaCodecSelector
,
Format
format
)
throws
DecoderQueryException
{
return
RendererCapabilities
.
create
(
FORMAT_HANDLED
);
}
};
mediaCodecVideoRenderer
.
handleMessage
(
Renderer
.
MSG_SET_SURFACE
,
new
Surface
(
new
SurfaceTexture
(
/* texName= */
0
)));
}
@Test
public
void
render_sendsVideoSizeChangeWithCurrentFormatValues
()
throws
Exception
{
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
0
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
),
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
setCurrentStreamFinal
();
mediaCodecVideoRenderer
.
start
();
int
positionUs
=
0
;
do
{
mediaCodecVideoRenderer
.
render
(
positionUs
,
SystemClock
.
elapsedRealtime
()
*
1000
);
positionUs
+=
10
;
}
while
(!
mediaCodecVideoRenderer
.
isEnded
());
verify
(
eventListener
)
.
onVideoSizeChanged
(
BASIC_MP4_1080
.
width
,
BASIC_MP4_1080
.
height
,
BASIC_MP4_1080
.
rotationDegrees
,
BASIC_MP4_1080
.
pixelWidthHeightRatio
);
}
@Test
public
void
render_includingResetPosition_keepsOutputFormatInVideoFrameMetadataListener
()
throws
Exception
{
AtomicReference
<
Format
>
lastRenderedFrameFormat
=
new
AtomicReference
<>();
VideoFrameMetadataListener
frameMetadataListener
=
new
VideoFrameMetadataListener
()
{
@Override
public
void
onVideoFrameAboutToBeRendered
(
long
presentationTimeUs
,
long
releaseTimeNs
,
Format
format
,
@Nullable
MediaFormat
mediaFormat
)
{
lastRenderedFrameFormat
.
set
(
format
);
}
};
mediaCodecVideoRenderer
.
handleMessage
(
Renderer
.
MSG_SET_VIDEO_FRAME_METADATA_LISTENER
,
frameMetadataListener
);
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
));
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
start
();
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
mediaCodecVideoRenderer
.
resetPosition
(
0
);
mediaCodecVideoRenderer
.
setCurrentStreamFinal
();
fakeSampleStream
.
addFakeSampleStreamItem
(
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
));
fakeSampleStream
.
addFakeSampleStreamItem
(
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
int
positionUs
=
10
;
do
{
mediaCodecVideoRenderer
.
render
(
positionUs
,
SystemClock
.
elapsedRealtime
()
*
1000
);
positionUs
+=
10
;
}
while
(!
mediaCodecVideoRenderer
.
isEnded
());
assertThat
(
lastRenderedFrameFormat
.
get
()).
isEqualTo
(
BASIC_MP4_1080
);
}
@Test
public
void
enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart
()
throws
Exception
{
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
));
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
}
verify
(
eventListener
).
onRenderedFirstFrame
(
any
());
}
@Test
public
void
enable_withoutMayRenderStartOfStream_doesNotRenderFirstFrameBeforeStart
()
throws
Exception
{
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
));
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
false
,
/* offsetUs */
0
);
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
}
verify
(
eventListener
,
never
()).
onRenderedFirstFrame
(
any
());
}
@Test
public
void
enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart
()
throws
Exception
{
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
));
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
false
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
start
();
for
(
int
i
=
0
;
i
<
10
;
i
++)
{
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
0
,
SystemClock
.
elapsedRealtime
()
*
1000
);
}
verify
(
eventListener
).
onRenderedFirstFrame
(
any
());
}
@Test
public
void
replaceStream_whenStarted_rendersFirstFrameOfNewStream
()
throws
Exception
{
FakeSampleStream
fakeSampleStream1
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
FakeSampleStream
fakeSampleStream2
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream1
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
start
();
boolean
replacedStream
=
false
;
for
(
int
i
=
0
;
i
<
200
;
i
+=
10
)
{
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
i
*
10
,
SystemClock
.
elapsedRealtime
()
*
1000
);
if
(!
replacedStream
&&
mediaCodecVideoRenderer
.
hasReadStreamToEnd
())
{
mediaCodecVideoRenderer
.
replaceStream
(
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream2
,
/* offsetUs= */
100
);
replacedStream
=
true
;
}
}
verify
(
eventListener
,
times
(
2
)).
onRenderedFirstFrame
(
any
());
}
// TODO: Fix this by not rendering the first frame of a new stream unless started.
@Ignore
@Test
public
void
replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream
()
throws
Exception
{
FakeSampleStream
fakeSampleStream1
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
FakeSampleStream
fakeSampleStream2
=
new
FakeSampleStream
(
/* format= */
BASIC_MP4_1080
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
new
byte
[]
{
0
},
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream1
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
boolean
replacedStream
=
false
;
for
(
int
i
=
0
;
i
<
200
;
i
+=
10
)
{
mediaCodecVideoRenderer
.
render
(
/* positionUs= */
i
*
10
,
SystemClock
.
elapsedRealtime
()
*
1000
);
if
(!
replacedStream
&&
mediaCodecVideoRenderer
.
hasReadStreamToEnd
())
{
mediaCodecVideoRenderer
.
replaceStream
(
new
Format
[]
{
BASIC_MP4_1080
},
fakeSampleStream2
,
/* offsetUs= */
100
);
replacedStream
=
true
;
}
}
verify
(
eventListener
).
onRenderedFirstFrame
(
any
());
}
/**
* Tests that {@link VideoRendererEventListener#onVideoFrameProcessingOffset} is called for every
* output format change triggered from {@link MediaCodec}.
*
* <p>This test is needed to ensure that {@link MediaCodecRenderer#updateOutputFormatForTime}
* (which updates the value returned from {@link MediaCodecRenderer#getCurrentOutputFormat()} is
* called after {@link MediaCodecVideoRenderer} handles the {@link MediaCodec MediaCodec's }
* output format change.
*/
@Test
public
void
onVideoFrameProcessingOffset_isCalledAfterOutputFormatChanges
()
throws
ExoPlaybackException
{
Format
mp4Uhd
=
BASIC_MP4_1080
.
buildUpon
().
setWidth
(
3840
).
setHeight
(
2160
).
build
();
byte
[]
sampleData
=
new
byte
[
0
];
FakeSampleStream
fakeSampleStream
=
new
FakeSampleStream
(
/* format= */
mp4Uhd
,
/* eventDispatcher= */
null
,
/* firstSampleTimeUs= */
0
,
/* timeUsIncrement= */
50
,
new
FakeSampleStreamItem
(
mp4Uhd
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
BASIC_MP4_1080
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
mp4Uhd
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
new
FakeSampleStreamItem
(
BASIC_MP4_1080
),
new
FakeSampleStreamItem
(
sampleData
,
C
.
BUFFER_FLAG_KEY_FRAME
),
FakeSampleStreamItem
.
END_OF_STREAM_ITEM
);
mediaCodecVideoRenderer
.
enable
(
RendererConfiguration
.
DEFAULT
,
new
Format
[]
{
mp4Uhd
},
fakeSampleStream
,
/* positionUs= */
0
,
/* joining= */
false
,
/* mayRenderStartOfStream= */
true
,
/* offsetUs */
0
);
mediaCodecVideoRenderer
.
setCurrentStreamFinal
();
mediaCodecVideoRenderer
.
start
();
int
positionUs
=
10
;
do
{
mediaCodecVideoRenderer
.
render
(
positionUs
,
SystemClock
.
elapsedRealtime
()
*
1000
);
positionUs
+=
10
;
}
while
(!
mediaCodecVideoRenderer
.
isEnded
());
mediaCodecVideoRenderer
.
stop
();
InOrder
orderVerifier
=
inOrder
(
eventListener
);
orderVerifier
.
verify
(
eventListener
).
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
1
),
eq
(
mp4Uhd
));
orderVerifier
.
verify
(
eventListener
)
.
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
2
),
eq
(
BASIC_MP4_1080
));
orderVerifier
.
verify
(
eventListener
).
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
3
),
eq
(
mp4Uhd
));
orderVerifier
.
verify
(
eventListener
)
.
onVideoFrameProcessingOffset
(
anyLong
(),
eq
(
1
),
eq
(
BASIC_MP4_1080
));
orderVerifier
.
verifyNoMoreInteractions
();
}
}
library/core/src/test/resources/com/google/android/exoplayer2/mediacodec/robolectric.properties
deleted
100644 → 0
View file @
52825a27
#
# Copyright (C) 2020 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.
# This file needs removing once Robolectric release a version > 4.3.1.
# [Internal ref: b/147731297]
shadows
=
com.google.android.exoplayer2.mediacodec.ShadowMediaCodec
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