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
bfeec25b
authored
May 17, 2019
by
andrewlewis
Committed by
Oliver Woodman
May 20, 2019
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add SilenceMediaSource
Issue: #5735 PiperOrigin-RevId: 248745617
parent
128ded5b
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
247 additions
and
2 deletions
RELEASENOTES.md
library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java
RELEASENOTES.md
View file @
bfeec25b
...
@@ -8,8 +8,11 @@
...
@@ -8,8 +8,11 @@
even if they are listed lower in the
`MediaCodecList`
.
even if they are listed lower in the
`MediaCodecList`
.
*
CEA-608: Handle XDS and TEXT modes
*
CEA-608: Handle XDS and TEXT modes
(
[
5807
](
https://github.com/google/ExoPlayer/pull/5807
)
).
(
[
5807
](
https://github.com/google/ExoPlayer/pull/5807
)
).
*
Audio: fix an issue where not all audio was played out when the configuration
*
Audio:
for the underlying track was changing (e.g., at some period transitions).
*
Fix an issue where not all audio was played out when the configuration
for the underlying track was changing (e.g., at some period transitions).
*
Add
`SilenceMediaSource`
that can be used to play silence of a given
duration (
[
#5735
](
https://github.com/google/ExoPlayer/issues/5735
)
).
*
UI: Change playback controls toggle from touch down to touch up events
*
UI: Change playback controls toggle from touch down to touch up events
(
[
#5784
](
https://github.com/google/ExoPlayer/issues/5784
)
).
(
[
#5784
](
https://github.com/google/ExoPlayer/issues/5784
)
).
*
Add a workaround for broken raw audio decoding on Oppo R9
*
Add a workaround for broken raw audio decoding on Oppo R9
...
...
library/core/src/main/java/com/google/android/exoplayer2/source/SilenceMediaSource.java
0 → 100644
View file @
bfeec25b
/*
* Copyright (C) 2019 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
.
source
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.Format
;
import
com.google.android.exoplayer2.FormatHolder
;
import
com.google.android.exoplayer2.SeekParameters
;
import
com.google.android.exoplayer2.decoder.DecoderInputBuffer
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.upstream.TransferListener
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.MimeTypes
;
import
com.google.android.exoplayer2.util.Util
;
import
java.util.ArrayList
;
import
org.checkerframework.checker.nullness.compatqual.NullableType
;
/** Media source with a single period consisting of silent raw audio of a given duration. */
public
final
class
SilenceMediaSource
extends
BaseMediaSource
{
private
static
final
int
SAMPLE_RATE_HZ
=
44100
;
@C
.
PcmEncoding
private
static
final
int
ENCODING
=
C
.
ENCODING_PCM_16BIT
;
private
static
final
int
CHANNEL_COUNT
=
2
;
private
static
final
Format
FORMAT
=
Format
.
createAudioSampleFormat
(
/* id=*/
null
,
MimeTypes
.
AUDIO_RAW
,
/* codecs= */
null
,
/* bitrate= */
Format
.
NO_VALUE
,
/* maxInputSize= */
Format
.
NO_VALUE
,
CHANNEL_COUNT
,
SAMPLE_RATE_HZ
,
ENCODING
,
/* initializationData= */
null
,
/* drmInitData= */
null
,
/* selectionFlags= */
0
,
/* language= */
null
);
private
static
final
byte
[]
SILENCE_SAMPLE
=
new
byte
[
Util
.
getPcmFrameSize
(
ENCODING
,
CHANNEL_COUNT
)
*
1024
];
private
final
long
durationUs
;
/**
* Creates a new media source providing silent audio of the given duration.
*
* @param durationUs The duration of silent audio to output, in microseconds.
*/
public
SilenceMediaSource
(
long
durationUs
)
{
Assertions
.
checkArgument
(
durationUs
>=
0
);
this
.
durationUs
=
durationUs
;
}
@Override
public
void
prepareSourceInternal
(
@Nullable
TransferListener
mediaTransferListener
)
{
refreshSourceInfo
(
new
SinglePeriodTimeline
(
durationUs
,
/* isSeekable= */
true
,
/* isDynamic= */
false
),
/* manifest= */
null
);
}
@Override
public
void
maybeThrowSourceInfoRefreshError
()
{}
@Override
public
MediaPeriod
createPeriod
(
MediaPeriodId
id
,
Allocator
allocator
,
long
startPositionUs
)
{
return
new
SilenceMediaPeriod
(
durationUs
);
}
@Override
public
void
releasePeriod
(
MediaPeriod
mediaPeriod
)
{}
@Override
public
void
releaseSourceInternal
()
{}
private
static
final
class
SilenceMediaPeriod
implements
MediaPeriod
{
private
static
final
TrackGroupArray
TRACKS
=
new
TrackGroupArray
(
new
TrackGroup
(
FORMAT
));
private
final
long
durationUs
;
private
final
ArrayList
<
SampleStream
>
sampleStreams
;
public
SilenceMediaPeriod
(
long
durationUs
)
{
this
.
durationUs
=
durationUs
;
sampleStreams
=
new
ArrayList
<>();
}
@Override
public
void
prepare
(
Callback
callback
,
long
positionUs
)
{
callback
.
onPrepared
(
/* mediaPeriod= */
this
);
}
@Override
public
void
maybeThrowPrepareError
()
{}
@Override
public
TrackGroupArray
getTrackGroups
()
{
return
TRACKS
;
}
@Override
public
long
selectTracks
(
@NullableType
TrackSelection
[]
selections
,
boolean
[]
mayRetainStreamFlags
,
@NullableType
SampleStream
[]
streams
,
boolean
[]
streamResetFlags
,
long
positionUs
)
{
for
(
int
i
=
0
;
i
<
selections
.
length
;
i
++)
{
if
(
streams
[
i
]
!=
null
&&
(
selections
[
i
]
==
null
||
!
mayRetainStreamFlags
[
i
]))
{
sampleStreams
.
remove
(
streams
[
i
]);
streams
[
i
]
=
null
;
}
if
(
streams
[
i
]
==
null
&&
selections
[
i
]
!=
null
)
{
SilenceSampleStream
stream
=
new
SilenceSampleStream
(
durationUs
);
stream
.
seekTo
(
positionUs
);
sampleStreams
.
add
(
stream
);
streams
[
i
]
=
stream
;
streamResetFlags
[
i
]
=
true
;
}
}
return
positionUs
;
}
@Override
public
void
discardBuffer
(
long
positionUs
,
boolean
toKeyframe
)
{}
@Override
public
long
readDiscontinuity
()
{
return
C
.
TIME_UNSET
;
}
@Override
public
long
seekToUs
(
long
positionUs
)
{
for
(
int
i
=
0
;
i
<
sampleStreams
.
size
();
i
++)
{
((
SilenceSampleStream
)
sampleStreams
.
get
(
i
)).
seekTo
(
positionUs
);
}
return
positionUs
;
}
@Override
public
long
getAdjustedSeekPositionUs
(
long
positionUs
,
SeekParameters
seekParameters
)
{
return
positionUs
;
}
@Override
public
long
getBufferedPositionUs
()
{
return
C
.
TIME_END_OF_SOURCE
;
}
@Override
public
long
getNextLoadPositionUs
()
{
return
C
.
TIME_END_OF_SOURCE
;
}
@Override
public
boolean
continueLoading
(
long
positionUs
)
{
return
false
;
}
@Override
public
void
reevaluateBuffer
(
long
positionUs
)
{}
}
private
static
final
class
SilenceSampleStream
implements
SampleStream
{
private
final
long
durationBytes
;
private
boolean
sentFormat
;
private
long
positionBytes
;
public
SilenceSampleStream
(
long
durationUs
)
{
durationBytes
=
getAudioByteCount
(
durationUs
);
seekTo
(
0
);
}
public
void
seekTo
(
long
positionUs
)
{
positionBytes
=
getAudioByteCount
(
positionUs
);
}
@Override
public
boolean
isReady
()
{
return
true
;
}
@Override
public
void
maybeThrowError
()
{}
@Override
public
int
readData
(
FormatHolder
formatHolder
,
DecoderInputBuffer
buffer
,
boolean
formatRequired
)
{
if
(!
sentFormat
||
formatRequired
)
{
formatHolder
.
format
=
FORMAT
;
sentFormat
=
true
;
return
C
.
RESULT_FORMAT_READ
;
}
long
bytesRemaining
=
durationBytes
-
positionBytes
;
if
(
bytesRemaining
==
0
)
{
buffer
.
addFlag
(
C
.
BUFFER_FLAG_END_OF_STREAM
);
return
C
.
RESULT_BUFFER_READ
;
}
int
bytesToWrite
=
(
int
)
Math
.
min
(
SILENCE_SAMPLE
.
length
,
bytesRemaining
);
buffer
.
ensureSpaceForWrite
(
bytesToWrite
);
buffer
.
addFlag
(
C
.
BUFFER_FLAG_KEY_FRAME
);
buffer
.
data
.
put
(
SILENCE_SAMPLE
,
/* offset= */
0
,
bytesToWrite
);
buffer
.
timeUs
=
getAudioPositionUs
(
positionBytes
);
positionBytes
+=
bytesToWrite
;
return
C
.
RESULT_BUFFER_READ
;
}
@Override
public
int
skipData
(
long
positionUs
)
{
long
oldPositionBytes
=
positionBytes
;
seekTo
(
positionUs
);
return
(
int
)
((
positionBytes
-
oldPositionBytes
)
/
SILENCE_SAMPLE
.
length
);
}
}
private
static
long
getAudioByteCount
(
long
durationUs
)
{
long
audioSampleCount
=
durationUs
*
SAMPLE_RATE_HZ
/
C
.
MICROS_PER_SECOND
;
return
Util
.
getPcmFrameSize
(
ENCODING
,
CHANNEL_COUNT
)
*
audioSampleCount
;
}
private
static
long
getAudioPositionUs
(
long
bytes
)
{
long
audioSampleCount
=
bytes
/
Util
.
getPcmFrameSize
(
ENCODING
,
CHANNEL_COUNT
);
return
audioSampleCount
*
C
.
MICROS_PER_SECOND
/
SAMPLE_RATE_HZ
;
}
}
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