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
7e639974
authored
Dec 16, 2022
by
tofunmi
Committed by
Tianyi Feng
Dec 21, 2022
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add TransformerTestBuilderFactory to make transformer testable by apps
PiperOrigin-RevId: 495821660
parent
6376f5f7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
428 additions
and
243 deletions
libraries/test_utils/build.gradle
libraries/transformer/src/test/java/androidx/media3/transformer/TestMuxer.java → libraries/test_utils/src/main/java/androidx/media3/test/utils/TestMuxer.java
libraries/test_utils/src/main/java/androidx/media3/test/utils/TestTransformerBuilderFactory.java
libraries/test_utils_robolectric/build.gradle
libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java
libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java
libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java
libraries/test_utils/build.gradle
View file @
7e639974
...
@@ -26,6 +26,7 @@ dependencies {
...
@@ -26,6 +26,7 @@ dependencies {
implementation
'androidx.annotation:annotation:'
+
androidxAnnotationVersion
implementation
'androidx.annotation:annotation:'
+
androidxAnnotationVersion
implementation
'com.squareup.okhttp3:mockwebserver:'
+
okhttpVersion
implementation
'com.squareup.okhttp3:mockwebserver:'
+
okhttpVersion
implementation
project
(
modulePrefix
+
'lib-exoplayer'
)
implementation
project
(
modulePrefix
+
'lib-exoplayer'
)
implementation
project
(
modulePrefix
+
':lib-transformer'
)
testImplementation
'org.robolectric:robolectric:'
+
robolectricVersion
testImplementation
'org.robolectric:robolectric:'
+
robolectricVersion
}
}
...
...
libraries/t
ransformer/src/test/java/androidx/media3/transformer
/TestMuxer.java
→
libraries/t
est_utils/src/main/java/androidx/media3/test/utils
/TestMuxer.java
View file @
7e639974
...
@@ -13,11 +13,11 @@
...
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* See the License for the specific language governing permissions and
* limitations under the License.
* limitations under the License.
*/
*/
package
androidx
.
media3
.
t
ransformer
;
package
androidx
.
media3
.
t
est
.
utils
;
import
androidx.media3.common.Format
;
import
androidx.media3.common.Format
;
import
androidx.media3.
test.utils.DumpableFormat
;
import
androidx.media3.
common.util.UnstableApi
;
import
androidx.media3.t
est.utils.Dump
er
;
import
androidx.media3.t
ransformer.Mux
er
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
...
@@ -28,6 +28,7 @@ import java.util.List;
...
@@ -28,6 +28,7 @@ import java.util.List;
* testing purposes) and delegates the actual muxing operations to another {@link Muxer} created
* testing purposes) and delegates the actual muxing operations to another {@link Muxer} created
* using the factory provided.
* using the factory provided.
*/
*/
@UnstableApi
public
final
class
TestMuxer
implements
Muxer
,
Dumper
.
Dumpable
{
public
final
class
TestMuxer
implements
Muxer
,
Dumper
.
Dumpable
{
private
final
Muxer
muxer
;
private
final
Muxer
muxer
;
...
...
libraries/test_utils/src/main/java/androidx/media3/test/utils/TestTransformerBuilderFactory.java
0 → 100644
View file @
7e639974
/*
* Copyright 2022 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
androidx
.
media3
.
test
.
utils
;
import
static
androidx
.
media3
.
common
.
util
.
Assertions
.
checkStateNotNull
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.os.ParcelFileDescriptor
;
import
androidx.media3.common.C
;
import
androidx.media3.common.util.Clock
;
import
androidx.media3.common.util.UnstableApi
;
import
androidx.media3.transformer.DefaultEncoderFactory
;
import
androidx.media3.transformer.DefaultMuxer
;
import
androidx.media3.transformer.Muxer
;
import
androidx.media3.transformer.Transformer
;
import
com.google.common.collect.ImmutableList
;
import
com.google.errorprone.annotations.CanIgnoreReturnValue
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/**
* Creates a {@link Transformer.Builder} setting up some of the common resources needed for testing
* {@link Transformer}.
*/
@UnstableApi
public
final
class
TestTransformerBuilderFactory
{
private
final
Context
context
;
private
static
@MonotonicNonNull
TestMuxer
testMuxer
;
private
long
maxDelayBetweenSamplesMs
;
/** Creates a new instance */
public
TestTransformerBuilderFactory
(
Context
context
)
{
this
.
context
=
context
;
maxDelayBetweenSamplesMs
=
DefaultMuxer
.
Factory
.
DEFAULT_MAX_DELAY_BETWEEN_SAMPLES_MS
;
}
/**
* Sets the muxer's {@linkplain Muxer#getMaxDelayBetweenSamplesMs() max delay} between samples.
*/
@CanIgnoreReturnValue
public
TestTransformerBuilderFactory
setMaxDelayBetweenSamplesMs
(
long
maxDelayBetweenSamplesMs
)
{
this
.
maxDelayBetweenSamplesMs
=
maxDelayBetweenSamplesMs
;
return
this
;
}
/** Returns a {@link Transformer.Builder} using the provided values or their defaults. */
@SuppressLint
(
"VisibleForTests"
)
// Suppresses warning on setting the clock outside of a test file
public
Transformer
.
Builder
create
(
boolean
enableFallback
)
{
Clock
clock
=
new
FakeClock
(
/* isAutoAdvancing= */
true
);
Muxer
.
Factory
defaultMuxerFactory
=
new
DefaultMuxer
.
Factory
(
maxDelayBetweenSamplesMs
);
return
new
Transformer
.
Builder
(
context
)
.
setClock
(
clock
)
.
setMuxerFactory
(
new
TestMuxerFactory
(
defaultMuxerFactory
))
.
setEncoderFactory
(
new
DefaultEncoderFactory
.
Builder
(
context
).
setEnableFallback
(
enableFallback
).
build
());
}
/**
* Returns the test muxer used in the {@link Transformer.Builder}.
*
* <p>This method should only be called after the transformation is completed.
*/
public
TestMuxer
getTestMuxer
()
{
return
checkStateNotNull
(
testMuxer
);
}
private
static
final
class
TestMuxerFactory
implements
Muxer
.
Factory
{
private
final
Muxer
.
Factory
defaultMuxerFactory
;
public
TestMuxerFactory
(
Muxer
.
Factory
defaultMuxerFactory
)
{
this
.
defaultMuxerFactory
=
defaultMuxerFactory
;
}
@Override
public
Muxer
create
(
String
path
)
throws
Muxer
.
MuxerException
{
testMuxer
=
new
TestMuxer
(
path
,
defaultMuxerFactory
);
return
testMuxer
;
}
@Override
public
Muxer
create
(
ParcelFileDescriptor
parcelFileDescriptor
)
throws
Muxer
.
MuxerException
{
testMuxer
=
new
TestMuxer
(
"FD:"
+
parcelFileDescriptor
.
getFd
(),
defaultMuxerFactory
);
return
testMuxer
;
}
@Override
public
ImmutableList
<
String
>
getSupportedSampleMimeTypes
(
@C
.
TrackType
int
trackType
)
{
return
defaultMuxerFactory
.
getSupportedSampleMimeTypes
(
trackType
);
}
}
}
libraries/test_utils_robolectric/build.gradle
View file @
7e639974
...
@@ -20,6 +20,7 @@ dependencies {
...
@@ -20,6 +20,7 @@ dependencies {
implementation
'androidx.annotation:annotation:'
+
androidxAnnotationVersion
implementation
'androidx.annotation:annotation:'
+
androidxAnnotationVersion
implementation
'org.robolectric:robolectric:'
+
robolectricVersion
implementation
'org.robolectric:robolectric:'
+
robolectricVersion
implementation
project
(
modulePrefix
+
'lib-exoplayer'
)
implementation
project
(
modulePrefix
+
'lib-exoplayer'
)
implementation
project
(
modulePrefix
+
':lib-transformer'
)
implementation
project
(
modulePrefix
+
'test-utils'
)
implementation
project
(
modulePrefix
+
'test-utils'
)
}
}
...
...
libraries/test_utils_robolectric/src/main/java/androidx/media3/test/utils/robolectric/ShadowMediaCodecConfig.java
View file @
7e639974
...
@@ -16,10 +16,15 @@
...
@@ -16,10 +16,15 @@
package
androidx
.
media3
.
test
.
utils
.
robolectric
;
package
androidx
.
media3
.
test
.
utils
.
robolectric
;
import
android.media.MediaCodecInfo
;
import
android.media.MediaCodecInfo
;
import
android.media.MediaCrypto
;
import
android.media.MediaFormat
;
import
android.media.MediaFormat
;
import
android.view.Surface
;
import
androidx.annotation.Nullable
;
import
androidx.media3.common.MimeTypes
;
import
androidx.media3.common.MimeTypes
;
import
androidx.media3.common.util.UnstableApi
;
import
androidx.media3.common.util.UnstableApi
;
import
androidx.media3.common.util.Util
;
import
androidx.media3.exoplayer.mediacodec.MediaCodecUtil
;
import
androidx.media3.exoplayer.mediacodec.MediaCodecUtil
;
import
androidx.media3.transformer.EncoderUtil
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.primitives.Ints
;
import
com.google.common.primitives.Ints
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
...
@@ -30,105 +35,247 @@ import org.robolectric.shadows.ShadowMediaCodec;
...
@@ -30,105 +35,247 @@ import org.robolectric.shadows.ShadowMediaCodec;
import
org.robolectric.shadows.ShadowMediaCodecList
;
import
org.robolectric.shadows.ShadowMediaCodecList
;
/**
/**
* A JUnit @Rule to configure
Roboelectric's {@link ShadowMediaCodec}
.
* A JUnit @Rule to configure
{@link ShadowMediaCodec} for transcoding or decoding
.
*
*
* <p>Registers
a {@link org.robolectric.shadows.ShadowMediaCodec.CodecConfig} for each audio/video
* <p>Registers
{@link org.robolectric.shadows.ShadowMediaCodec.CodecConfig} instances for ExoPlayer
*
MIME type known by ExoPlayer
.
*
and Transformer tests
.
*/
*/
@UnstableApi
@UnstableApi
public
final
class
ShadowMediaCodecConfig
extends
ExternalResource
{
public
final
class
ShadowMediaCodecConfig
extends
ExternalResource
{
private
static
final
String
EXOTEST_VIDEO_AVC
=
"exotest.video.avc"
;
private
static
final
String
EXOTEST_VIDEO_MPEG2
=
"exotest.video.mpeg2"
;
private
static
final
String
EXOTEST_VIDEO_VP9
=
"exotest.video.vp9"
;
private
static
final
String
EXOTEST_AUDIO_AAC
=
"exotest.audio.aac"
;
private
static
final
String
EXOTEST_AUDIO_AC3
=
"exotest.audio.ac3"
;
private
static
final
String
EXOTEST_AUDIO_AC4
=
"exotest.audio.ac4"
;
private
static
final
String
EXOTEST_AUDIO_E_AC3
=
"exotest.audio.eac3"
;
private
static
final
String
EXOTEST_AUDIO_E_AC3_JOC
=
"exotest.audio.eac3joc"
;
private
static
final
String
EXOTEST_AUDIO_FLAC
=
"exotest.audio.flac"
;
private
static
final
String
EXOTEST_AUDIO_MPEG
=
"exotest.audio.mpeg"
;
private
static
final
String
EXOTEST_AUDIO_MPEG_L2
=
"exotest.audio.mpegl2"
;
private
static
final
String
EXOTEST_AUDIO_OPUS
=
"exotest.audio.opus"
;
private
static
final
String
EXOTEST_AUDIO_VORBIS
=
"exotest.audio.vorbis"
;
private
static
final
String
EXOTEST_AUDIO_RAW
=
"exotest.audio.raw"
;
private
final
boolean
forTranscoding
;
private
ShadowMediaCodecConfig
(
boolean
forTranscoding
)
{
this
.
forTranscoding
=
forTranscoding
;
}
/** Creates an instance that configures {@link ShadowMediaCodec} for Transformer transcoding. */
public
static
ShadowMediaCodecConfig
forTranscoding
()
{
return
new
ShadowMediaCodecConfig
(
/* forTranscoding= */
true
);
}
/** Creates an instance that configures {@link ShadowMediaCodec} for Exoplayer decoding. */
public
static
ShadowMediaCodecConfig
forAllSupportedMimeTypes
()
{
public
static
ShadowMediaCodecConfig
forAllSupportedMimeTypes
()
{
return
new
ShadowMediaCodecConfig
();
return
new
ShadowMediaCodecConfig
(
/* forTranscoding= */
false
);
}
}
@Override
@Override
protected
void
before
()
throws
Throwable
{
protected
void
before
()
throws
Throwable
{
if
(
forTranscoding
)
{
addTranscodingCodecs
();
}
else
{
addDecodingCodecs
();
}
}
private
void
addTranscodingCodecs
()
{
ShadowMediaCodec
.
CodecConfig
codecConfig
=
new
ShadowMediaCodec
.
CodecConfig
(
/* inputBufferSize= */
10_000
,
/* outputBufferSize= */
10_000
,
/* codec= */
(
in
,
out
)
->
out
.
put
(
in
));
addTransformerCodec
(
MimeTypes
.
AUDIO_AAC
,
codecConfig
,
/* isDecoder= */
true
);
addTransformerCodec
(
MimeTypes
.
AUDIO_AC3
,
codecConfig
,
/* isDecoder= */
true
);
addTransformerCodec
(
MimeTypes
.
AUDIO_AMR_NB
,
codecConfig
,
/* isDecoder= */
true
);
addTransformerCodec
(
MimeTypes
.
AUDIO_AAC
,
codecConfig
,
/* isDecoder= */
false
);
ShadowMediaCodec
.
CodecConfig
throwingCodecConfig
=
new
ShadowMediaCodec
.
CodecConfig
(
/* inputBufferSize= */
10_000
,
/* outputBufferSize= */
10_000
,
new
ShadowMediaCodec
.
CodecConfig
.
Codec
()
{
@Override
public
void
process
(
ByteBuffer
in
,
ByteBuffer
out
)
{
out
.
put
(
in
);
}
@Override
public
void
onConfigured
(
MediaFormat
format
,
@Nullable
Surface
surface
,
@Nullable
MediaCrypto
crypto
,
int
flags
)
{
throw
new
IllegalArgumentException
(
"Format unsupported"
);
}
});
addTransformerCodec
(
MimeTypes
.
AUDIO_AMR_WB
,
throwingCodecConfig
,
/* isDecoder= */
true
);
addTransformerCodec
(
MimeTypes
.
AUDIO_AMR_NB
,
throwingCodecConfig
,
/* isDecoder= */
false
);
}
private
void
addDecodingCodecs
()
{
// Video codecs
// Video codecs
MediaCodecInfo
.
CodecProfileLevel
avcProfileLevel
=
MediaCodecInfo
.
CodecProfileLevel
avcProfileLevel
=
createProfileLevel
(
createProfileLevel
(
MediaCodecInfo
.
CodecProfileLevel
.
AVCProfileHigh
,
MediaCodecInfo
.
CodecProfileLevel
.
AVCProfileHigh
,
MediaCodecInfo
.
CodecProfileLevel
.
AVCLevel62
);
MediaCodecInfo
.
CodecProfileLevel
.
AVCLevel62
);
configure
Codec
(
addExoplayer
Codec
(
/* codecName= */
"exotest.video.avc"
,
EXOTEST_VIDEO_AVC
,
MimeTypes
.
VIDEO_H264
,
MimeTypes
.
VIDEO_H264
,
generateDecodingCodecConfig
(
MimeTypes
.
VIDEO_H264
),
ImmutableList
.
of
(
avcProfileLevel
),
ImmutableList
.
of
(
avcProfileLevel
),
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
MediaCodecInfo
.
CodecProfileLevel
mpeg2ProfileLevel
=
MediaCodecInfo
.
CodecProfileLevel
mpeg2ProfileLevel
=
createProfileLevel
(
createProfileLevel
(
MediaCodecInfo
.
CodecProfileLevel
.
MPEG2ProfileMain
,
MediaCodecInfo
.
CodecProfileLevel
.
MPEG2ProfileMain
,
MediaCodecInfo
.
CodecProfileLevel
.
MPEG2LevelML
);
MediaCodecInfo
.
CodecProfileLevel
.
MPEG2LevelML
);
configure
Codec
(
addExoplayer
Codec
(
/* codecName= */
"exotest.video.mpeg2"
,
EXOTEST_VIDEO_MPEG2
,
MimeTypes
.
VIDEO_MPEG2
,
MimeTypes
.
VIDEO_MPEG2
,
generateDecodingCodecConfig
(
MimeTypes
.
VIDEO_MPEG2
),
ImmutableList
.
of
(
mpeg2ProfileLevel
),
ImmutableList
.
of
(
mpeg2ProfileLevel
),
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
configure
Codec
(
addExoplayer
Codec
(
/* codecName= */
"exotest.video.vp9"
,
EXOTEST_VIDEO_VP9
,
MimeTypes
.
VIDEO_VP9
,
MimeTypes
.
VIDEO_VP9
,
generateDecodingCodecConfig
(
MimeTypes
.
VIDEO_VP9
),
ImmutableList
.
of
(),
ImmutableList
.
of
(),
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
ImmutableList
.
of
(
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatYUV420Flexible
));
// Audio codecs
// Audio codecs
configureCodec
(
"exotest.audio.aac"
,
MimeTypes
.
AUDIO_AAC
);
addExoplayerCodec
(
configureCodec
(
"exotest.audio.ac3"
,
MimeTypes
.
AUDIO_AC3
);
EXOTEST_AUDIO_AAC
,
MimeTypes
.
AUDIO_AAC
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_AAC
));
configureCodec
(
"exotest.audio.ac4"
,
MimeTypes
.
AUDIO_AC4
);
addExoplayerCodec
(
configureCodec
(
"exotest.audio.eac3"
,
MimeTypes
.
AUDIO_E_AC3
);
EXOTEST_AUDIO_AC3
,
MimeTypes
.
AUDIO_AC3
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_AC3
));
configureCodec
(
"exotest.audio.eac3joc"
,
MimeTypes
.
AUDIO_E_AC3_JOC
);
addExoplayerCodec
(
configureCodec
(
"exotest.audio.flac"
,
MimeTypes
.
AUDIO_FLAC
);
EXOTEST_AUDIO_AC4
,
MimeTypes
.
AUDIO_AC4
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_AC4
));
configureCodec
(
"exotest.audio.mpeg"
,
MimeTypes
.
AUDIO_MPEG
);
addExoplayerCodec
(
configureCodec
(
"exotest.audio.mpegl2"
,
MimeTypes
.
AUDIO_MPEG_L2
);
EXOTEST_AUDIO_E_AC3
,
configureCodec
(
"exotest.audio.opus"
,
MimeTypes
.
AUDIO_OPUS
);
MimeTypes
.
AUDIO_E_AC3
,
configureCodec
(
"exotest.audio.vorbis"
,
MimeTypes
.
AUDIO_VORBIS
);
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_E_AC3
));
addExoplayerCodec
(
EXOTEST_AUDIO_E_AC3_JOC
,
MimeTypes
.
AUDIO_E_AC3_JOC
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_E_AC3_JOC
));
addExoplayerCodec
(
EXOTEST_AUDIO_FLAC
,
MimeTypes
.
AUDIO_FLAC
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_FLAC
));
addExoplayerCodec
(
EXOTEST_AUDIO_MPEG
,
MimeTypes
.
AUDIO_MPEG
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_MPEG
));
addExoplayerCodec
(
EXOTEST_AUDIO_MPEG_L2
,
MimeTypes
.
AUDIO_MPEG_L2
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_MPEG_L2
));
addExoplayerCodec
(
EXOTEST_AUDIO_OPUS
,
MimeTypes
.
AUDIO_OPUS
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_OPUS
));
addExoplayerCodec
(
EXOTEST_AUDIO_VORBIS
,
MimeTypes
.
AUDIO_VORBIS
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_VORBIS
));
// Raw audio should use a bypass mode and never need this codec. However, to easily assert
// Raw audio should use a bypass mode and never need this codec. However, to easily assert
// failures of the bypass mode we want to detect when the raw audio is decoded by this class and
// failures of the bypass mode we want to detect when the raw audio is decoded by this class and
// thus we need a codec to output samples.
// thus we need a codec to output samples.
configureCodec
(
"exotest.audio.raw"
,
MimeTypes
.
AUDIO_RAW
);
addExoplayerCodec
(
EXOTEST_AUDIO_RAW
,
MimeTypes
.
AUDIO_RAW
,
generateDecodingCodecConfig
(
MimeTypes
.
AUDIO_RAW
));
}
}
@Override
@Override
protected
void
after
()
{
protected
void
after
()
{
if
(!
forTranscoding
)
{
MediaCodecUtil
.
clearDecoderInfoCache
();
MediaCodecUtil
.
clearDecoderInfoCache
();
}
else
{
EncoderUtil
.
clearCachedEncoders
();
}
ShadowMediaCodecList
.
reset
();
ShadowMediaCodecList
.
reset
();
ShadowMediaCodec
.
clearCodecs
();
ShadowMediaCodec
.
clearCodecs
();
}
}
private
void
configureCodec
(
String
codecName
,
String
mimeType
)
{
private
ShadowMediaCodec
.
CodecConfig
generateDecodingCodecConfig
(
String
mimeType
)
{
configureCodec
(
// TODO: Update ShadowMediaCodec to consider the MediaFormat.KEY_MAX_INPUT_SIZE value passed
// to configure() so we don't have to specify large buffers here.
CodecImpl
codec
=
new
CodecImpl
(
mimeType
);
return
new
ShadowMediaCodec
.
CodecConfig
(
/* inputBufferSize= */
100_000
,
/* outputBufferSize= */
100_000
,
codec
);
}
private
void
addTransformerCodec
(
String
mimeType
,
ShadowMediaCodec
.
CodecConfig
codecConfig
,
boolean
isDecoder
)
{
String
codecName
=
Util
.
formatInvariant
(
isDecoder
?
"transformertest.%s.decoder"
:
"transformertest.%s.encoder"
,
mimeType
.
replace
(
'/'
,
'.'
));
addCodec
(
codecName
,
mimeType
,
codecConfig
,
/* profileLevels= */
ImmutableList
.
of
(),
/* colorFormats= */
ImmutableList
.
of
(),
isDecoder
);
}
private
void
addExoplayerCodec
(
String
codecName
,
String
mimeType
,
ShadowMediaCodec
.
CodecConfig
codecConfig
)
{
addExoplayerCodec
(
codecName
,
codecName
,
mimeType
,
mimeType
,
codecConfig
,
/* profileLevels= */
ImmutableList
.
of
(),
/* profileLevels= */
ImmutableList
.
of
(),
/* colorFormats= */
ImmutableList
.
of
());
/* colorFormats= */
ImmutableList
.
of
());
}
}
private
void
configure
Codec
(
private
void
addExoplayer
Codec
(
String
codecName
,
String
codecName
,
String
mimeType
,
String
mimeType
,
ShadowMediaCodec
.
CodecConfig
codecConfig
,
List
<
MediaCodecInfo
.
CodecProfileLevel
>
profileLevels
,
List
<
MediaCodecInfo
.
CodecProfileLevel
>
profileLevels
,
List
<
Integer
>
colorFormats
)
{
List
<
Integer
>
colorFormats
)
{
addCodec
(
codecName
,
mimeType
,
codecConfig
,
profileLevels
,
colorFormats
,
/* isDecoder= */
true
);
}
private
void
addCodec
(
String
codecName
,
String
mimeType
,
ShadowMediaCodec
.
CodecConfig
codecConfig
,
List
<
MediaCodecInfo
.
CodecProfileLevel
>
profileLevels
,
List
<
Integer
>
colorFormats
,
boolean
isDecoder
)
{
MediaFormat
mediaFormat
=
new
MediaFormat
();
MediaFormat
mediaFormat
=
new
MediaFormat
();
mediaFormat
.
setString
(
MediaFormat
.
KEY_MIME
,
mimeType
);
mediaFormat
.
setString
(
MediaFormat
.
KEY_MIME
,
mimeType
);
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
capabilities
=
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
capabilities
=
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
.
newBuilder
().
setMediaFormat
(
mediaFormat
);
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
.
newBuilder
()
.
setMediaFormat
(
mediaFormat
)
.
setIsEncoder
(!
isDecoder
);
if
(!
profileLevels
.
isEmpty
())
{
if
(!
profileLevels
.
isEmpty
())
{
capabilities
.
setProfileLevels
(
profileLevels
.
toArray
(
new
MediaCodecInfo
.
CodecProfileLevel
[
0
]));
capabilities
.
setProfileLevels
(
profileLevels
.
toArray
(
new
MediaCodecInfo
.
CodecProfileLevel
[
0
]));
}
}
if
(!
colorFormats
.
isEmpty
())
{
if
(!
colorFormats
.
isEmpty
())
{
capabilities
.
setColorFormats
(
Ints
.
toArray
(
colorFormats
));
capabilities
.
setColorFormats
(
Ints
.
toArray
(
colorFormats
));
}
}
ShadowMediaCodecList
.
addCodec
(
ShadowMediaCodecList
.
addCodec
(
MediaCodecInfoBuilder
.
newBuilder
()
MediaCodecInfoBuilder
.
newBuilder
()
.
setName
(
codecName
)
.
setName
(
codecName
)
.
setIsEncoder
(!
isDecoder
)
.
setCapabilities
(
capabilities
.
build
())
.
setCapabilities
(
capabilities
.
build
())
.
build
());
.
build
());
// TODO: Update ShadowMediaCodec to consider the MediaFormat.KEY_MAX_INPUT_SIZE value passed
// to configure() so we don't have to specify large buffers here.
if
(
isDecoder
)
{
CodecImpl
codec
=
new
CodecImpl
(
mimeType
);
ShadowMediaCodec
.
addDecoder
(
codecName
,
codecConfig
);
ShadowMediaCodec
.
addDecoder
(
}
else
{
codecName
,
ShadowMediaCodec
.
addEncoder
(
codecName
,
codecConfig
);
new
ShadowMediaCodec
.
CodecConfig
(
}
/* inputBufferSize= */
100_000
,
/* outputBufferSize= */
100_000
,
codec
));
}
}
private
static
MediaCodecInfo
.
CodecProfileLevel
createProfileLevel
(
int
profile
,
int
level
)
{
private
static
MediaCodecInfo
.
CodecProfileLevel
createProfileLevel
(
int
profile
,
int
level
)
{
...
...
libraries/transformer/src/main/java/androidx/media3/transformer/Transformer.java
View file @
7e639974
...
@@ -430,7 +430,7 @@ public final class Transformer {
...
@@ -430,7 +430,7 @@ public final class Transformer {
*/
*/
@CanIgnoreReturnValue
@CanIgnoreReturnValue
@VisibleForTesting
@VisibleForTesting
/* package */
Builder
setClock
(
Clock
clock
)
{
public
Builder
setClock
(
Clock
clock
)
{
this
.
clock
=
clock
;
this
.
clock
=
clock
;
this
.
listeners
=
listeners
.
copy
(
looper
,
clock
,
(
listener
,
flags
)
->
{});
this
.
listeners
=
listeners
.
copy
(
looper
,
clock
,
(
listener
,
flags
)
->
{});
return
this
;
return
this
;
...
...
libraries/transformer/src/test/java/androidx/media3/transformer/TransformerEndToEndTest.java
View file @
7e639974
...
@@ -29,15 +29,11 @@ import static org.mockito.Mockito.never;
...
@@ -29,15 +29,11 @@ import static org.mockito.Mockito.never;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
android.content.Context
;
import
android.content.Context
;
import
android.media.MediaCrypto
;
import
android.media.MediaFormat
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.Handler
;
import
android.os.HandlerThread
;
import
android.os.HandlerThread
;
import
android.os.Looper
;
import
android.os.Looper
;
import
android.os.Message
;
import
android.os.Message
;
import
android.os.ParcelFileDescriptor
;
import
android.view.Surface
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
androidx.media3.common.C
;
import
androidx.media3.common.C
;
import
androidx.media3.common.MediaItem
;
import
androidx.media3.common.MediaItem
;
...
@@ -53,14 +49,13 @@ import androidx.media3.extractor.ExtractorOutput;
...
@@ -53,14 +49,13 @@ import androidx.media3.extractor.ExtractorOutput;
import
androidx.media3.extractor.ExtractorsFactory
;
import
androidx.media3.extractor.ExtractorsFactory
;
import
androidx.media3.extractor.PositionHolder
;
import
androidx.media3.extractor.PositionHolder
;
import
androidx.media3.test.utils.DumpFileAsserts
;
import
androidx.media3.test.utils.DumpFileAsserts
;
import
androidx.media3.test.utils.FakeClock
;
import
androidx.media3.test.utils.TestTransformerBuilderFactory
;
import
androidx.media3.test.utils.robolectric.ShadowMediaCodecConfig
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.Iterables
;
import
com.google.common.collect.Iterables
;
import
com.google.common.primitives.Ints
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.file.Files
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.Paths
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
...
@@ -74,16 +69,17 @@ import java.util.concurrent.atomic.AtomicReference;
...
@@ -74,16 +69,17 @@ import java.util.concurrent.atomic.AtomicReference;
import
org.checkerframework.checker.nullness.compatqual.NullableType
;
import
org.checkerframework.checker.nullness.compatqual.NullableType
;
import
org.junit.After
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runner.RunWith
;
import
org.robolectric.shadows.MediaCodecInfoBuilder
;
import
org.robolectric.shadows.ShadowMediaCodec
;
import
org.robolectric.shadows.ShadowMediaCodecList
;
/** End-to-end test for {@link Transformer}. */
/** End-to-end test for {@link Transformer}. */
@RunWith
(
AndroidJUnit4
.
class
)
@RunWith
(
AndroidJUnit4
.
class
)
public
final
class
TransformerEndToEndTest
{
public
final
class
TransformerEndToEndTest
{
@Rule
public
final
ShadowMediaCodecConfig
mediaCodecConfig
=
ShadowMediaCodecConfig
.
forTranscoding
();
private
static
final
String
ASSET_URI_PREFIX
=
"asset:///media/"
;
private
static
final
String
ASSET_URI_PREFIX
=
"asset:///media/"
;
private
static
final
String
FILE_VIDEO_ONLY
=
"mp4/sample_18byte_nclx_colr.mp4"
;
private
static
final
String
FILE_VIDEO_ONLY
=
"mp4/sample_18byte_nclx_colr.mp4"
;
private
static
final
String
FILE_AUDIO_VIDEO
=
"mp4/sample.mp4"
;
private
static
final
String
FILE_AUDIO_VIDEO
=
"mp4/sample.mp4"
;
...
@@ -100,39 +96,39 @@ public final class TransformerEndToEndTest {
...
@@ -100,39 +96,39 @@ public final class TransformerEndToEndTest {
private
Context
context
;
private
Context
context
;
private
String
outputPath
;
private
String
outputPath
;
private
TestMuxer
testMuxer
;
private
FakeClock
clock
;
private
ProgressHolder
progressHolder
;
private
ProgressHolder
progressHolder
;
private
TestTransformerBuilderFactory
testTransformerBuilderFactory
;
@Before
@Before
public
void
setUp
()
throws
Exception
{
public
void
setUp
()
throws
Exception
{
context
=
ApplicationProvider
.
getApplicationContext
();
context
=
ApplicationProvider
.
getApplicationContext
();
outputPath
=
Util
.
createTempFile
(
context
,
"TransformerTest"
).
getPath
();
outputPath
=
Util
.
createTempFile
(
context
,
"TransformerTest"
).
getPath
();
clock
=
new
FakeClock
(
/* isAutoAdvancing= */
true
);
progressHolder
=
new
ProgressHolder
();
progressHolder
=
new
ProgressHolder
();
createEncodersAndDecoders
(
);
testTransformerBuilderFactory
=
new
TestTransformerBuilderFactory
(
context
);
}
}
@After
@After
public
void
tearDown
()
throws
Exception
{
public
void
tearDown
()
throws
Exception
{
Files
.
delete
(
Paths
.
get
(
outputPath
));
Files
.
delete
(
Paths
.
get
(
outputPath
));
removeEncodersAndDecoders
();
}
}
@Test
@Test
public
void
startTransformation_videoOnlyPassthrough_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_videoOnlyPassthrough_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_VIDEO_ONLY
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_VIDEO_ONLY
));
}
}
@Test
@Test
public
void
startTransformation_audioOnlyPassthrough_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_audioOnlyPassthrough_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
);
...
@@ -140,13 +136,16 @@ public final class TransformerEndToEndTest {
...
@@ -140,13 +136,16 @@ public final class TransformerEndToEndTest {
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
));
}
}
@Test
@Test
public
void
startTransformation_audioOnlyTranscoding_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_audioOnlyTranscoding_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setTransformationRequest
(
.
setTransformationRequest
(
new
TransformationRequest
.
Builder
()
new
TransformationRequest
.
Builder
()
.
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
)
// supported by encoder and muxer
.
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
)
// supported by encoder and muxer
...
@@ -158,24 +157,29 @@ public final class TransformerEndToEndTest {
...
@@ -158,24 +157,29 @@ public final class TransformerEndToEndTest {
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
+
".aac"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_ENCODER
+
".aac"
));
}
}
@Test
@Test
public
void
startTransformation_audioAndVideo_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_audioAndVideo_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
));
}
}
@Test
@Test
public
void
startTransformation_audioAndVideo_withClippingStartAtKeyFrame_completesSuccessfully
()
public
void
startTransformation_audioAndVideo_withClippingStartAtKeyFrame_completesSuccessfully
()
throws
Exception
{
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
mediaItem
=
new
MediaItem
.
Builder
()
new
MediaItem
.
Builder
()
.
setUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S
)
.
setUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S
)
...
@@ -192,14 +196,15 @@ public final class TransformerEndToEndTest {
...
@@ -192,14 +196,15 @@ public final class TransformerEndToEndTest {
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
context
,
test
Muxer
,
test
TransformerBuilderFactory
.
getTestMuxer
()
,
getDumpFileName
(
FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S
+
".clipped"
));
getDumpFileName
(
FILE_AUDIO_VIDEO_INCREASING_TIMESTAMPS_15S
+
".clipped"
));
}
}
@Test
@Test
public
void
startTransformation_withSubtitles_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_withSubtitles_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setTransformationRequest
(
.
setTransformationRequest
(
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
())
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
())
.
build
();
.
build
();
...
@@ -208,13 +213,17 @@ public final class TransformerEndToEndTest {
...
@@ -208,13 +213,17 @@ public final class TransformerEndToEndTest {
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_WITH_SUBTITLES
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_WITH_SUBTITLES
));
}
}
@Test
@Test
public
void
startTransformation_successiveTransformations_completesSuccessfully
()
public
void
startTransformation_successiveTransformations_completesSuccessfully
()
throws
Exception
{
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
// Transform first media item.
// Transform first media item.
...
@@ -226,12 +235,14 @@ public final class TransformerEndToEndTest {
...
@@ -226,12 +235,14 @@ public final class TransformerEndToEndTest {
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
));
}
}
@Test
@Test
public
void
startTransformation_concurrentTransformations_throwsError
()
throws
Exception
{
public
void
startTransformation_concurrentTransformations_throwsError
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
...
@@ -243,33 +254,44 @@ public final class TransformerEndToEndTest {
...
@@ -243,33 +254,44 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
startTransformation_removeAudio_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_removeAudio_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
setRemoveAudio
(
true
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setRemoveAudio
(
true
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".noaudio"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".noaudio"
));
}
}
@Test
@Test
public
void
startTransformation_removeVideo_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_removeVideo_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
setRemoveVideo
(
true
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setRemoveVideo
(
true
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".novideo"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".novideo"
));
}
}
@Test
@Test
public
void
startTransformation_silentAudio_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_silentAudio_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
experimentalSetForceSilentAudio
(
true
)
.
experimentalSetForceSilentAudio
(
true
)
.
build
();
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
...
@@ -278,7 +300,9 @@ public final class TransformerEndToEndTest {
...
@@ -278,7 +300,9 @@ public final class TransformerEndToEndTest {
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".silentaudio"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".silentaudio"
));
}
}
@Test
@Test
...
@@ -286,7 +310,8 @@ public final class TransformerEndToEndTest {
...
@@ -286,7 +310,8 @@ public final class TransformerEndToEndTest {
SonicAudioProcessor
sonicAudioProcessor
=
new
SonicAudioProcessor
();
SonicAudioProcessor
sonicAudioProcessor
=
new
SonicAudioProcessor
();
sonicAudioProcessor
.
setOutputSampleRateHz
(
48000
);
sonicAudioProcessor
.
setOutputSampleRateHz
(
48000
);
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setAudioProcessors
(
ImmutableList
.
of
(
sonicAudioProcessor
))
.
setAudioProcessors
(
ImmutableList
.
of
(
sonicAudioProcessor
))
.
build
();
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
...
@@ -295,7 +320,9 @@ public final class TransformerEndToEndTest {
...
@@ -295,7 +320,9 @@ public final class TransformerEndToEndTest {
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".48000hz"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
+
".48000hz"
));
}
}
@Test
@Test
...
@@ -304,7 +331,8 @@ public final class TransformerEndToEndTest {
...
@@ -304,7 +331,8 @@ public final class TransformerEndToEndTest {
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener3
)
.
addListener
(
mockListener3
)
...
@@ -325,7 +353,8 @@ public final class TransformerEndToEndTest {
...
@@ -325,7 +353,8 @@ public final class TransformerEndToEndTest {
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener3
)
.
addListener
(
mockListener3
)
...
@@ -352,7 +381,8 @@ public final class TransformerEndToEndTest {
...
@@ -352,7 +381,8 @@ public final class TransformerEndToEndTest {
TransformationRequest
fallbackTransformationRequest
=
TransformationRequest
fallbackTransformationRequest
=
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
true
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
true
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener3
)
.
addListener
(
mockListener3
)
...
@@ -377,7 +407,8 @@ public final class TransformerEndToEndTest {
...
@@ -377,7 +407,8 @@ public final class TransformerEndToEndTest {
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener2
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
.
Listener
mockListener3
=
mock
(
Transformer
.
Listener
.
class
);
Transformer
transformer1
=
Transformer
transformer1
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener1
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener2
)
.
addListener
(
mockListener3
)
.
addListener
(
mockListener3
)
...
@@ -396,7 +427,8 @@ public final class TransformerEndToEndTest {
...
@@ -396,7 +427,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
startTransformation_flattenForSlowMotion_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_flattenForSlowMotion_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setTransformationRequest
(
.
setTransformationRequest
(
new
TransformationRequest
.
Builder
().
setFlattenForSlowMotion
(
true
).
build
())
new
TransformationRequest
.
Builder
().
setFlattenForSlowMotion
(
true
).
build
())
.
build
();
.
build
();
...
@@ -405,7 +437,10 @@ public final class TransformerEndToEndTest {
...
@@ -405,7 +437,10 @@ public final class TransformerEndToEndTest {
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_WITH_SEF_SLOW_MOTION
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_WITH_SEF_SLOW_MOTION
));
}
}
@Test
@Test
...
@@ -420,7 +455,10 @@ public final class TransformerEndToEndTest {
...
@@ -420,7 +455,10 @@ public final class TransformerEndToEndTest {
}
}
};
};
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
addListener
(
listener
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
addListener
(
listener
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
...
@@ -436,7 +474,8 @@ public final class TransformerEndToEndTest {
...
@@ -436,7 +474,8 @@ public final class TransformerEndToEndTest {
public
void
startTransformation_withAudioEncoderFormatUnsupported_completesWithError
()
public
void
startTransformation_withAudioEncoderFormatUnsupported_completesWithError
()
throws
Exception
{
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setTransformationRequest
(
.
setTransformationRequest
(
new
TransformationRequest
.
Builder
()
new
TransformationRequest
.
Builder
()
.
setAudioMimeType
(
.
setAudioMimeType
(
...
@@ -457,7 +496,8 @@ public final class TransformerEndToEndTest {
...
@@ -457,7 +496,8 @@ public final class TransformerEndToEndTest {
public
void
startTransformation_withAudioDecoderFormatUnsupported_completesWithError
()
public
void
startTransformation_withAudioDecoderFormatUnsupported_completesWithError
()
throws
Exception
{
throws
Exception
{
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
setTransformationRequest
(
.
setTransformationRequest
(
new
TransformationRequest
.
Builder
()
new
TransformationRequest
.
Builder
()
.
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
)
// supported by encoder and muxer
.
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
)
// supported by encoder and muxer
...
@@ -475,7 +515,8 @@ public final class TransformerEndToEndTest {
...
@@ -475,7 +515,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
startTransformation_withIoError_completesWithError
()
throws
Exception
{
public
void
startTransformation_withIoError_completesWithError
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
"asset:///non-existing-path.mp4"
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
"asset:///non-existing-path.mp4"
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
...
@@ -495,14 +536,19 @@ public final class TransformerEndToEndTest {
...
@@ -495,14 +536,19 @@ public final class TransformerEndToEndTest {
TransformationRequest
fallbackTransformationRequest
=
TransformationRequest
fallbackTransformationRequest
=
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
addListener
(
mockListener
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
)
.
addListener
(
mockListener
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_MUXER
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_MUXER
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_MUXER
+
".fallback"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_MUXER
+
".fallback"
));
verify
(
mockListener
)
verify
(
mockListener
)
.
onFallbackApplied
(
mediaItem
,
originalTransformationRequest
,
fallbackTransformationRequest
);
.
onFallbackApplied
(
mediaItem
,
originalTransformationRequest
,
fallbackTransformationRequest
);
}
}
...
@@ -516,14 +562,19 @@ public final class TransformerEndToEndTest {
...
@@ -516,14 +562,19 @@ public final class TransformerEndToEndTest {
TransformationRequest
fallbackTransformationRequest
=
TransformationRequest
fallbackTransformationRequest
=
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
new
TransformationRequest
.
Builder
().
setAudioMimeType
(
MimeTypes
.
AUDIO_AAC
).
build
();
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
true
).
addListener
(
mockListener
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
true
)
.
addListener
(
mockListener
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_MUXER
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_UNSUPPORTED_BY_MUXER
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_MUXER
+
".fallback"
));
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_UNSUPPORTED_BY_MUXER
+
".fallback"
));
verify
(
mockListener
)
verify
(
mockListener
)
.
onFallbackApplied
(
mediaItem
,
originalTransformationRequest
,
fallbackTransformationRequest
);
.
onFallbackApplied
(
mediaItem
,
originalTransformationRequest
,
fallbackTransformationRequest
);
}
}
...
@@ -533,11 +584,11 @@ public final class TransformerEndToEndTest {
...
@@ -533,11 +584,11 @@ public final class TransformerEndToEndTest {
MediaSource
.
Factory
mediaSourceFactory
=
MediaSource
.
Factory
mediaSourceFactory
=
new
DefaultMediaSourceFactory
(
new
DefaultMediaSourceFactory
(
context
,
new
SlowExtractorsFactory
(
/* delayBetweenReadsMs= */
10
));
context
,
new
SlowExtractorsFactory
(
/* delayBetweenReadsMs= */
10
));
Muxer
.
Factory
muxerFactory
=
new
TestMuxerFactory
(
/* maxDelayBetweenSamplesMs= */
1
);
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
)
testTransformerBuilderFactory
.
setMaxDelayBetweenSamplesMs
(
1
)
.
create
(
/* enableFallback= */
false
)
.
setMediaSourceFactory
(
mediaSourceFactory
)
.
setMediaSourceFactory
(
mediaSourceFactory
)
.
setMuxerFactory
(
muxerFactory
)
.
build
();
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
...
@@ -551,20 +602,24 @@ public final class TransformerEndToEndTest {
...
@@ -551,20 +602,24 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
startTransformation_withUnsetMaxDelayBetweenSamples_completesSuccessfully
()
public
void
startTransformation_withUnsetMaxDelayBetweenSamples_completesSuccessfully
()
throws
Exception
{
throws
Exception
{
Muxer
.
Factory
muxerFactory
=
new
TestMuxerFactory
(
/* maxDelayBetweenSamplesMs= */
C
.
TIME_UNSET
);
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
setMuxerFactory
(
muxerFactory
).
build
();
testTransformerBuilderFactory
.
setMaxDelayBetweenSamplesMs
(
C
.
TIME_UNSET
)
.
create
(
/* enableFallback= */
false
)
.
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
));
}
}
@Test
@Test
public
void
startTransformation_afterCancellation_completesSuccessfully
()
throws
Exception
{
public
void
startTransformation_afterCancellation_completesSuccessfully
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
...
@@ -575,7 +630,8 @@ public final class TransformerEndToEndTest {
...
@@ -575,7 +630,8 @@ public final class TransformerEndToEndTest {
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
TransformerTestRunner
.
runUntilCompleted
(
transformer
);
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
));
}
}
@Test
@Test
...
@@ -584,7 +640,7 @@ public final class TransformerEndToEndTest {
...
@@ -584,7 +640,7 @@ public final class TransformerEndToEndTest {
anotherThread
.
start
();
anotherThread
.
start
();
Looper
looper
=
anotherThread
.
getLooper
();
Looper
looper
=
anotherThread
.
getLooper
();
Transformer
transformer
=
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
setLooper
(
looper
).
build
();
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
setLooper
(
looper
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
AtomicReference
<
Exception
>
exception
=
new
AtomicReference
<>();
AtomicReference
<
Exception
>
exception
=
new
AtomicReference
<>();
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
...
@@ -604,12 +660,14 @@ public final class TransformerEndToEndTest {
...
@@ -604,12 +660,14 @@ public final class TransformerEndToEndTest {
countDownLatch
.
await
();
countDownLatch
.
await
();
assertThat
(
exception
.
get
()).
isNull
();
assertThat
(
exception
.
get
()).
isNull
();
DumpFileAsserts
.
assertOutput
(
context
,
testMuxer
,
getDumpFileName
(
FILE_AUDIO_VIDEO
));
DumpFileAsserts
.
assertOutput
(
context
,
testTransformerBuilderFactory
.
getTestMuxer
(),
getDumpFileName
(
FILE_AUDIO_VIDEO
));
}
}
@Test
@Test
public
void
startTransformation_fromWrongThread_throwsError
()
throws
Exception
{
public
void
startTransformation_fromWrongThread_throwsError
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_AUDIO_VIDEO
);
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
...
@@ -634,7 +692,8 @@ public final class TransformerEndToEndTest {
...
@@ -634,7 +692,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
getProgress_knownDuration_returnsConsistentStates
()
throws
Exception
{
public
void
getProgress_knownDuration_returnsConsistentStates
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
AtomicInteger
previousProgressState
=
AtomicInteger
previousProgressState
=
new
AtomicInteger
(
PROGRESS_STATE_WAITING_FOR_AVAILABILITY
);
new
AtomicInteger
(
PROGRESS_STATE_WAITING_FOR_AVAILABILITY
);
...
@@ -680,7 +739,8 @@ public final class TransformerEndToEndTest {
...
@@ -680,7 +739,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
getProgress_knownDuration_givesIncreasingPercentages
()
throws
Exception
{
public
void
getProgress_knownDuration_givesIncreasingPercentages
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
List
<
Integer
>
progresses
=
new
ArrayList
<>();
List
<
Integer
>
progresses
=
new
ArrayList
<>();
Handler
progressHandler
=
Handler
progressHandler
=
...
@@ -715,7 +775,8 @@ public final class TransformerEndToEndTest {
...
@@ -715,7 +775,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
getProgress_noCurrentTransformation_returnsNoTransformation
()
throws
Exception
{
public
void
getProgress_noCurrentTransformation_returnsNoTransformation
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
@Transformer
.
ProgressState
int
stateBeforeTransform
=
transformer
.
getProgress
(
progressHolder
);
@Transformer
.
ProgressState
int
stateBeforeTransform
=
transformer
.
getProgress
(
progressHolder
);
...
@@ -729,7 +790,8 @@ public final class TransformerEndToEndTest {
...
@@ -729,7 +790,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
getProgress_unknownDuration_returnsConsistentStates
()
throws
Exception
{
public
void
getProgress_unknownDuration_returnsConsistentStates
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_UNKNOWN_DURATION
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_UNKNOWN_DURATION
);
AtomicInteger
previousProgressState
=
AtomicInteger
previousProgressState
=
new
AtomicInteger
(
PROGRESS_STATE_WAITING_FOR_AVAILABILITY
);
new
AtomicInteger
(
PROGRESS_STATE_WAITING_FOR_AVAILABILITY
);
...
@@ -772,7 +834,8 @@ public final class TransformerEndToEndTest {
...
@@ -772,7 +834,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
getProgress_fromWrongThread_throwsError
()
throws
Exception
{
public
void
getProgress_fromWrongThread_throwsError
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
...
@@ -796,7 +859,8 @@ public final class TransformerEndToEndTest {
...
@@ -796,7 +859,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
cancel_afterCompletion_doesNotThrow
()
throws
Exception
{
public
void
cancel_afterCompletion_doesNotThrow
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
ASSET_URI_PREFIX
+
FILE_VIDEO_ONLY
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
transformer
.
startTransformation
(
mediaItem
,
outputPath
);
...
@@ -806,7 +870,8 @@ public final class TransformerEndToEndTest {
...
@@ -806,7 +870,8 @@ public final class TransformerEndToEndTest {
@Test
@Test
public
void
cancel_fromWrongThread_throwsError
()
throws
Exception
{
public
void
cancel_fromWrongThread_throwsError
()
throws
Exception
{
Transformer
transformer
=
createTransformerBuilder
(
/* enableFallback= */
false
).
build
();
Transformer
transformer
=
testTransformerBuilderFactory
.
create
(
/* enableFallback= */
false
).
build
();
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
HandlerThread
anotherThread
=
new
HandlerThread
(
"AnotherThread"
);
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
AtomicReference
<
IllegalStateException
>
illegalStateException
=
new
AtomicReference
<>();
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
CountDownLatch
countDownLatch
=
new
CountDownLatch
(
1
);
...
@@ -828,147 +893,10 @@ public final class TransformerEndToEndTest {
...
@@ -828,147 +893,10 @@ public final class TransformerEndToEndTest {
assertThat
(
illegalStateException
.
get
()).
isNotNull
();
assertThat
(
illegalStateException
.
get
()).
isNotNull
();
}
}
private
Transformer
.
Builder
createTransformerBuilder
(
boolean
enableFallback
)
{
return
new
Transformer
.
Builder
(
context
)
.
setClock
(
clock
)
.
setMuxerFactory
(
new
TestMuxerFactory
())
.
setEncoderFactory
(
new
DefaultEncoderFactory
.
Builder
(
context
).
setEnableFallback
(
enableFallback
).
build
());
}
private
static
void
createEncodersAndDecoders
()
{
ShadowMediaCodec
.
CodecConfig
codecConfig
=
new
ShadowMediaCodec
.
CodecConfig
(
/* inputBufferSize= */
10_000
,
/* outputBufferSize= */
10_000
,
/* codec= */
(
in
,
out
)
->
out
.
put
(
in
));
addCodec
(
MimeTypes
.
AUDIO_AAC
,
codecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
true
);
addCodec
(
MimeTypes
.
AUDIO_AC3
,
codecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
true
);
addCodec
(
MimeTypes
.
AUDIO_AMR_NB
,
codecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
true
);
addCodec
(
MimeTypes
.
AUDIO_AAC
,
codecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
false
);
ShadowMediaCodec
.
CodecConfig
throwingCodecConfig
=
new
ShadowMediaCodec
.
CodecConfig
(
/* inputBufferSize= */
10_000
,
/* outputBufferSize= */
10_000
,
new
ShadowMediaCodec
.
CodecConfig
.
Codec
()
{
@Override
public
void
process
(
ByteBuffer
in
,
ByteBuffer
out
)
{
out
.
put
(
in
);
}
@Override
public
void
onConfigured
(
MediaFormat
format
,
@Nullable
Surface
surface
,
@Nullable
MediaCrypto
crypto
,
int
flags
)
{
throw
new
IllegalArgumentException
(
"Format unsupported"
);
}
});
addCodec
(
MimeTypes
.
AUDIO_AMR_WB
,
throwingCodecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
true
);
addCodec
(
MimeTypes
.
AUDIO_AMR_NB
,
throwingCodecConfig
,
/* colorFormats= */
ImmutableList
.
of
(),
/* isDecoder= */
false
);
}
private
static
void
addCodec
(
String
mimeType
,
ShadowMediaCodec
.
CodecConfig
codecConfig
,
List
<
Integer
>
colorFormats
,
boolean
isDecoder
)
{
String
codecName
=
Util
.
formatInvariant
(
isDecoder
?
"exo.%s.decoder"
:
"exo.%s.encoder"
,
mimeType
.
replace
(
'/'
,
'-'
));
if
(
isDecoder
)
{
ShadowMediaCodec
.
addDecoder
(
codecName
,
codecConfig
);
}
else
{
ShadowMediaCodec
.
addEncoder
(
codecName
,
codecConfig
);
}
MediaFormat
mediaFormat
=
new
MediaFormat
();
mediaFormat
.
setString
(
MediaFormat
.
KEY_MIME
,
mimeType
);
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
codecCapabilities
=
MediaCodecInfoBuilder
.
CodecCapabilitiesBuilder
.
newBuilder
()
.
setMediaFormat
(
mediaFormat
)
.
setIsEncoder
(!
isDecoder
);
if
(!
colorFormats
.
isEmpty
())
{
codecCapabilities
.
setColorFormats
(
Ints
.
toArray
(
colorFormats
));
}
ShadowMediaCodecList
.
addCodec
(
MediaCodecInfoBuilder
.
newBuilder
()
.
setName
(
codecName
)
.
setIsEncoder
(!
isDecoder
)
.
setCapabilities
(
codecCapabilities
.
build
())
.
build
());
}
private
static
void
removeEncodersAndDecoders
()
{
ShadowMediaCodec
.
clearCodecs
();
ShadowMediaCodecList
.
reset
();
EncoderUtil
.
clearCachedEncoders
();
}
private
static
String
getDumpFileName
(
String
originalFileName
)
{
private
static
String
getDumpFileName
(
String
originalFileName
)
{
return
DUMP_FILE_OUTPUT_DIRECTORY
+
'/'
+
originalFileName
+
'.'
+
DUMP_FILE_EXTENSION
;
return
DUMP_FILE_OUTPUT_DIRECTORY
+
'/'
+
originalFileName
+
'.'
+
DUMP_FILE_EXTENSION
;
}
}
private
final
class
TestMuxerFactory
implements
Muxer
.
Factory
{
private
final
Muxer
.
Factory
defaultMuxerFactory
;
public
TestMuxerFactory
()
{
defaultMuxerFactory
=
new
DefaultMuxer
.
Factory
();
}
public
TestMuxerFactory
(
long
maxDelayBetweenSamplesMs
)
{
defaultMuxerFactory
=
new
DefaultMuxer
.
Factory
(
maxDelayBetweenSamplesMs
);
}
@Override
public
Muxer
create
(
String
path
)
throws
Muxer
.
MuxerException
{
testMuxer
=
new
TestMuxer
(
path
,
defaultMuxerFactory
);
return
testMuxer
;
}
@Override
public
Muxer
create
(
ParcelFileDescriptor
parcelFileDescriptor
)
throws
Muxer
.
MuxerException
{
testMuxer
=
new
TestMuxer
(
"FD:"
+
parcelFileDescriptor
.
getFd
(),
defaultMuxerFactory
);
return
testMuxer
;
}
@Override
public
ImmutableList
<
String
>
getSupportedSampleMimeTypes
(
@C
.
TrackType
int
trackType
)
{
return
defaultMuxerFactory
.
getSupportedSampleMimeTypes
(
trackType
);
}
}
private
static
final
class
SlowExtractorsFactory
implements
ExtractorsFactory
{
private
static
final
class
SlowExtractorsFactory
implements
ExtractorsFactory
{
private
final
long
delayBetweenReadsMs
;
private
final
long
delayBetweenReadsMs
;
...
...
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