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
e65110e1
authored
Dec 14, 2016
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Remove ClippingMediaSource from release
parent
42c7ea42
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
0 additions
and
432 deletions
library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java
library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java
library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaPeriod.java
deleted
100644 → 0
View file @
42c7ea42
/*
* Copyright (C) 2016 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
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.FormatHolder
;
import
com.google.android.exoplayer2.decoder.DecoderInputBuffer
;
import
com.google.android.exoplayer2.trackselection.TrackSelection
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
/**
* Wraps a {@link MediaPeriod} and clips its {@link SampleStream}s to provide a subsequence of their
* samples.
*/
/* package */
final
class
ClippingMediaPeriod
implements
MediaPeriod
,
MediaPeriod
.
Callback
{
public
final
MediaPeriod
mediaPeriod
;
private
final
ClippingMediaSource
mediaSource
;
private
MediaPeriod
.
Callback
callback
;
private
long
startUs
;
private
long
endUs
;
private
ClippingSampleStream
[]
sampleStreams
;
private
boolean
pendingInitialDiscontinuity
;
/**
* Creates a new clipping media period that provides a clipped view of the specified
* {@link MediaPeriod}'s sample streams.
*
* @param mediaPeriod The media period to clip.
* @param mediaSource The {@link ClippingMediaSource} to which this period belongs.
*/
public
ClippingMediaPeriod
(
MediaPeriod
mediaPeriod
,
ClippingMediaSource
mediaSource
)
{
this
.
mediaPeriod
=
mediaPeriod
;
this
.
mediaSource
=
mediaSource
;
startUs
=
C
.
TIME_UNSET
;
endUs
=
C
.
TIME_UNSET
;
sampleStreams
=
new
ClippingSampleStream
[
0
];
}
@Override
public
void
prepare
(
MediaPeriod
.
Callback
callback
)
{
this
.
callback
=
callback
;
mediaPeriod
.
prepare
(
this
);
}
@Override
public
void
maybeThrowPrepareError
()
throws
IOException
{
mediaPeriod
.
maybeThrowPrepareError
();
}
@Override
public
TrackGroupArray
getTrackGroups
()
{
return
mediaPeriod
.
getTrackGroups
();
}
@Override
public
long
selectTracks
(
TrackSelection
[]
selections
,
boolean
[]
mayRetainStreamFlags
,
SampleStream
[]
streams
,
boolean
[]
streamResetFlags
,
long
positionUs
)
{
sampleStreams
=
new
ClippingSampleStream
[
streams
.
length
];
SampleStream
[]
internalStreams
=
new
SampleStream
[
streams
.
length
];
for
(
int
i
=
0
;
i
<
streams
.
length
;
i
++)
{
sampleStreams
[
i
]
=
(
ClippingSampleStream
)
streams
[
i
];
internalStreams
[
i
]
=
sampleStreams
[
i
]
!=
null
?
sampleStreams
[
i
].
stream
:
null
;
}
long
enablePositionUs
=
mediaPeriod
.
selectTracks
(
selections
,
mayRetainStreamFlags
,
internalStreams
,
streamResetFlags
,
positionUs
+
startUs
);
Assertions
.
checkState
(
enablePositionUs
==
positionUs
+
startUs
||
(
enablePositionUs
>=
startUs
&&
enablePositionUs
<=
endUs
));
for
(
int
i
=
0
;
i
<
streams
.
length
;
i
++)
{
if
(
internalStreams
[
i
]
==
null
)
{
sampleStreams
[
i
]
=
null
;
}
else
if
(
streams
[
i
]
==
null
||
sampleStreams
[
i
].
stream
!=
internalStreams
[
i
])
{
sampleStreams
[
i
]
=
new
ClippingSampleStream
(
this
,
internalStreams
[
i
],
startUs
,
endUs
,
pendingInitialDiscontinuity
);
}
streams
[
i
]
=
sampleStreams
[
i
];
}
return
enablePositionUs
-
startUs
;
}
@Override
public
long
readDiscontinuity
()
{
if
(
pendingInitialDiscontinuity
)
{
for
(
ClippingSampleStream
sampleStream
:
sampleStreams
)
{
if
(
sampleStream
!=
null
)
{
sampleStream
.
clearPendingDiscontinuity
();
}
}
pendingInitialDiscontinuity
=
false
;
// Always read an initial discontinuity, using mediaPeriod's discontinuity if set.
long
discontinuityUs
=
readDiscontinuity
();
return
discontinuityUs
!=
C
.
TIME_UNSET
?
discontinuityUs
:
0
;
}
long
discontinuityUs
=
mediaPeriod
.
readDiscontinuity
();
if
(
discontinuityUs
==
C
.
TIME_UNSET
)
{
return
C
.
TIME_UNSET
;
}
Assertions
.
checkState
(
discontinuityUs
>=
startUs
&&
discontinuityUs
<=
endUs
);
return
discontinuityUs
-
startUs
;
}
@Override
public
long
getBufferedPositionUs
()
{
long
bufferedPositionUs
=
mediaPeriod
.
getBufferedPositionUs
();
if
(
bufferedPositionUs
==
C
.
TIME_END_OF_SOURCE
||
bufferedPositionUs
>=
endUs
)
{
return
C
.
TIME_END_OF_SOURCE
;
}
return
Math
.
max
(
0
,
bufferedPositionUs
-
startUs
);
}
@Override
public
long
seekToUs
(
long
positionUs
)
{
for
(
ClippingSampleStream
sampleStream
:
sampleStreams
)
{
if
(
sampleStream
!=
null
)
{
sampleStream
.
clearSentEos
();
}
}
long
seekUs
=
mediaPeriod
.
seekToUs
(
positionUs
+
startUs
);
Assertions
.
checkState
(
seekUs
==
positionUs
+
startUs
||
(
seekUs
>=
startUs
&&
seekUs
<=
endUs
));
return
seekUs
-
startUs
;
}
@Override
public
long
getNextLoadPositionUs
()
{
long
nextLoadPositionUs
=
mediaPeriod
.
getNextLoadPositionUs
();
if
(
nextLoadPositionUs
==
C
.
TIME_END_OF_SOURCE
||
nextLoadPositionUs
>=
endUs
)
{
return
C
.
TIME_END_OF_SOURCE
;
}
return
nextLoadPositionUs
-
startUs
;
}
@Override
public
boolean
continueLoading
(
long
positionUs
)
{
return
mediaPeriod
.
continueLoading
(
positionUs
+
startUs
);
}
// MediaPeriod.Callback implementation.
@Override
public
void
onPrepared
(
MediaPeriod
mediaPeriod
)
{
startUs
=
mediaSource
.
getStartUs
();
endUs
=
mediaSource
.
getEndUs
();
Assertions
.
checkState
(
startUs
!=
C
.
TIME_UNSET
&&
endUs
!=
C
.
TIME_UNSET
);
// If the clipping start position is non-zero, the clipping sample streams will adjust
// timestamps on buffers they read from the unclipped sample streams. These adjusted buffer
// timestamps can be negative, because sample streams provide buffers starting at a key-frame,
// which may be before the clipping start point. When the renderer reads a buffer with a
// negative timestamp, its offset timestamp can jump backwards compared to the last timestamp
// read in the previous period. Renderer implementations may not allow this, so we signal a
// discontinuity which resets the renderers before they read the clipping sample stream.
pendingInitialDiscontinuity
=
startUs
!=
0
;
callback
.
onPrepared
(
this
);
}
@Override
public
void
onContinueLoadingRequested
(
MediaPeriod
source
)
{
callback
.
onContinueLoadingRequested
(
this
);
}
/**
* Wraps a {@link SampleStream} and clips its samples.
*/
private
static
final
class
ClippingSampleStream
implements
SampleStream
{
private
final
MediaPeriod
mediaPeriod
;
private
final
SampleStream
stream
;
private
final
long
startUs
;
private
final
long
endUs
;
private
boolean
pendingDiscontinuity
;
private
boolean
sentEos
;
public
ClippingSampleStream
(
MediaPeriod
mediaPeriod
,
SampleStream
stream
,
long
startUs
,
long
endUs
,
boolean
pendingDiscontinuity
)
{
this
.
mediaPeriod
=
mediaPeriod
;
this
.
stream
=
stream
;
this
.
startUs
=
startUs
;
this
.
endUs
=
endUs
;
this
.
pendingDiscontinuity
=
pendingDiscontinuity
;
}
public
void
clearPendingDiscontinuity
()
{
pendingDiscontinuity
=
false
;
}
public
void
clearSentEos
()
{
sentEos
=
false
;
}
@Override
public
boolean
isReady
()
{
return
stream
.
isReady
();
}
@Override
public
void
maybeThrowError
()
throws
IOException
{
stream
.
maybeThrowError
();
}
@Override
public
int
readData
(
FormatHolder
formatHolder
,
DecoderInputBuffer
buffer
)
{
if
(
pendingDiscontinuity
)
{
return
C
.
RESULT_NOTHING_READ
;
}
if
(
sentEos
)
{
buffer
.
setFlags
(
C
.
BUFFER_FLAG_END_OF_STREAM
);
return
C
.
RESULT_BUFFER_READ
;
}
int
result
=
stream
.
readData
(
formatHolder
,
buffer
);
// TODO: Clear gapless playback metadata if a format was read (if applicable).
if
((
result
==
C
.
RESULT_BUFFER_READ
&&
buffer
.
timeUs
>=
endUs
)
||
(
result
==
C
.
RESULT_NOTHING_READ
&&
mediaPeriod
.
getBufferedPositionUs
()
==
C
.
TIME_END_OF_SOURCE
))
{
buffer
.
clear
();
buffer
.
setFlags
(
C
.
BUFFER_FLAG_END_OF_STREAM
);
sentEos
=
true
;
return
C
.
RESULT_BUFFER_READ
;
}
if
(
result
==
C
.
RESULT_BUFFER_READ
)
{
buffer
.
timeUs
-=
startUs
;
}
return
result
;
}
@Override
public
void
skipToKeyframeBefore
(
long
timeUs
)
{
stream
.
skipToKeyframeBefore
(
startUs
+
timeUs
);
}
}
}
library/src/main/java/com/google/android/exoplayer2/source/ClippingMediaSource.java
deleted
100644 → 0
View file @
42c7ea42
/*
* Copyright (C) 2016 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
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.ExoPlayer
;
import
com.google.android.exoplayer2.Timeline
;
import
com.google.android.exoplayer2.upstream.Allocator
;
import
com.google.android.exoplayer2.util.Assertions
;
import
java.io.IOException
;
/**
* {@link MediaSource} that wraps a source and clips its timeline based on specified start/end
* positions. The wrapped source may only have a single period/window and it must not be dynamic
* (live). The specified start position must correspond to a synchronization sample in the period.
*/
public
final
class
ClippingMediaSource
implements
MediaSource
,
MediaSource
.
Listener
{
private
final
MediaSource
mediaSource
;
private
final
long
startUs
;
private
final
long
endUs
;
private
MediaSource
.
Listener
sourceListener
;
private
ClippingTimeline
clippingTimeline
;
/**
* Creates a new clipping source that wraps the specified source.
*
* @param mediaSource The single-period, non-dynamic source to wrap.
* @param startPositionUs The start position within {@code mediaSource}'s timeline at which to
* start providing samples, in microseconds.
* @param endPositionUs The end position within {@code mediaSource}'s timeline at which to stop
* providing samples, in microseconds. Specify {@link C#TIME_END_OF_SOURCE} to provide samples
* from the specified start point up to the end of the source.
*/
public
ClippingMediaSource
(
MediaSource
mediaSource
,
long
startPositionUs
,
long
endPositionUs
)
{
Assertions
.
checkArgument
(
startPositionUs
>=
0
);
this
.
mediaSource
=
Assertions
.
checkNotNull
(
mediaSource
);
startUs
=
startPositionUs
;
endUs
=
endPositionUs
;
}
/**
* Returns the start position of the clipping source's timeline in microseconds.
*/
/* package */
long
getStartUs
()
{
return
clippingTimeline
.
startUs
;
}
/**
* Returns the end position of the clipping source's timeline in microseconds.
*/
/* package */
long
getEndUs
()
{
return
clippingTimeline
.
endUs
;
}
@Override
public
void
prepareSource
(
ExoPlayer
player
,
boolean
isTopLevelSource
,
Listener
listener
)
{
this
.
sourceListener
=
listener
;
mediaSource
.
prepareSource
(
player
,
false
,
this
);
}
@Override
public
void
maybeThrowSourceInfoRefreshError
()
throws
IOException
{
mediaSource
.
maybeThrowSourceInfoRefreshError
();
}
@Override
public
MediaPeriod
createPeriod
(
int
index
,
Allocator
allocator
,
long
positionUs
)
{
return
new
ClippingMediaPeriod
(
mediaSource
.
createPeriod
(
index
,
allocator
,
startUs
+
positionUs
),
this
);
}
@Override
public
void
releasePeriod
(
MediaPeriod
mediaPeriod
)
{
mediaSource
.
releasePeriod
(((
ClippingMediaPeriod
)
mediaPeriod
).
mediaPeriod
);
}
@Override
public
void
releaseSource
()
{
mediaSource
.
releaseSource
();
}
// MediaSource.Listener implementation.
@Override
public
void
onSourceInfoRefreshed
(
Timeline
timeline
,
Object
manifest
)
{
clippingTimeline
=
new
ClippingTimeline
(
timeline
,
startUs
,
endUs
);
sourceListener
.
onSourceInfoRefreshed
(
clippingTimeline
,
manifest
);
}
/**
* Provides a clipped view of a specified timeline.
*/
private
static
final
class
ClippingTimeline
extends
Timeline
{
private
final
Timeline
timeline
;
private
final
long
startUs
;
private
final
long
endUs
;
/**
* Creates a new timeline that wraps the specified timeline.
*
* @param timeline The timeline to clip.
* @param startUs The number of microseconds to clip from the start of {@code timeline}.
* @param endUs The end position in microseconds for the clipped timeline relative to the start
* of {@code timeline}, or {@link C#TIME_END_OF_SOURCE} to clip no samples from the end.
*/
public
ClippingTimeline
(
Timeline
timeline
,
long
startUs
,
long
endUs
)
{
Assertions
.
checkArgument
(
timeline
.
getWindowCount
()
==
1
);
Assertions
.
checkArgument
(
timeline
.
getPeriodCount
()
==
1
);
Window
window
=
timeline
.
getWindow
(
0
,
new
Window
(),
false
);
Assertions
.
checkArgument
(!
window
.
isDynamic
);
long
resolvedEndUs
=
endUs
==
C
.
TIME_END_OF_SOURCE
?
window
.
durationUs
:
endUs
;
if
(
window
.
durationUs
!=
C
.
TIME_UNSET
)
{
Assertions
.
checkArgument
(
startUs
==
0
||
window
.
isSeekable
);
Assertions
.
checkArgument
(
resolvedEndUs
<=
window
.
durationUs
);
Assertions
.
checkArgument
(
startUs
<=
resolvedEndUs
);
}
Period
period
=
timeline
.
getPeriod
(
0
,
new
Period
());
Assertions
.
checkArgument
(
period
.
getPositionInWindowUs
()
==
0
);
this
.
timeline
=
timeline
;
this
.
startUs
=
startUs
;
this
.
endUs
=
resolvedEndUs
;
}
@Override
public
int
getWindowCount
()
{
return
1
;
}
@Override
public
Window
getWindow
(
int
windowIndex
,
Window
window
,
boolean
setIds
,
long
defaultPositionProjectionUs
)
{
window
=
timeline
.
getWindow
(
0
,
window
,
setIds
,
defaultPositionProjectionUs
);
window
.
durationUs
=
endUs
!=
C
.
TIME_UNSET
?
endUs
-
startUs
:
C
.
TIME_UNSET
;
if
(
window
.
defaultPositionUs
!=
C
.
TIME_UNSET
)
{
window
.
defaultPositionUs
=
Math
.
max
(
window
.
defaultPositionUs
,
startUs
);
window
.
defaultPositionUs
=
endUs
==
C
.
TIME_UNSET
?
window
.
defaultPositionUs
:
Math
.
min
(
window
.
defaultPositionUs
,
endUs
);
window
.
defaultPositionUs
-=
startUs
;
}
long
startMs
=
C
.
usToMs
(
startUs
);
if
(
window
.
presentationStartTimeMs
!=
C
.
TIME_UNSET
)
{
window
.
presentationStartTimeMs
+=
startMs
;
}
if
(
window
.
windowStartTimeMs
!=
C
.
TIME_UNSET
)
{
window
.
windowStartTimeMs
+=
startMs
;
}
return
window
;
}
@Override
public
int
getPeriodCount
()
{
return
1
;
}
@Override
public
Period
getPeriod
(
int
periodIndex
,
Period
period
,
boolean
setIds
)
{
period
=
timeline
.
getPeriod
(
0
,
period
,
setIds
);
period
.
durationUs
=
endUs
!=
C
.
TIME_UNSET
?
endUs
-
startUs
:
C
.
TIME_UNSET
;
return
period
;
}
@Override
public
int
getIndexOfPeriod
(
Object
uid
)
{
return
timeline
.
getIndexOfPeriod
(
uid
);
}
}
}
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