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
a3b721e6
authored
May 28, 2020
by
bachinger
Committed by
Oliver Woodman
May 29, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Make SsMediaSource add the media item to the timeline
PiperOrigin-RevId: 313573424
parent
a37374d5
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
208 additions
and
24 deletions
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java
library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java
library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java
View file @
a3b721e6
...
...
@@ -15,6 +15,8 @@
*/
package
com
.
google
.
android
.
exoplayer2
.
source
.
smoothstreaming
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Assertions
.
checkNotNull
;
import
android.net.Uri
;
import
android.os.Handler
;
import
android.os.SystemClock
;
...
...
@@ -54,6 +56,7 @@ import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import
com.google.android.exoplayer2.upstream.ParsingLoadable
;
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.io.IOException
;
import
java.util.ArrayList
;
...
...
@@ -104,7 +107,7 @@ public final class SsMediaSource extends BaseMediaSource
public
Factory
(
SsChunkSource
.
Factory
chunkSourceFactory
,
@Nullable
DataSource
.
Factory
manifestDataSourceFactory
)
{
this
.
chunkSourceFactory
=
Assertions
.
checkNotNull
(
chunkSourceFactory
);
this
.
chunkSourceFactory
=
checkNotNull
(
chunkSourceFactory
);
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
drmSessionManager
=
DrmSessionManager
.
getDummyDrmSessionManager
();
loadErrorHandlingPolicy
=
new
DefaultLoadErrorHandlingPolicy
();
...
...
@@ -237,21 +240,47 @@ public final class SsMediaSource extends BaseMediaSource
* @throws IllegalArgumentException If {@link SsManifest#isLive} is true.
*/
public
SsMediaSource
createMediaSource
(
SsManifest
manifest
)
{
return
createMediaSource
(
manifest
,
MediaItem
.
fromUri
(
Uri
.
EMPTY
));
}
/**
* Returns a new {@link SsMediaSource} using the current parameters and the specified sideloaded
* manifest.
*
* @param manifest The manifest. {@link SsManifest#isLive} must be false.
* @param mediaItem The {@link MediaItem} to be included in the timeline.
* @return The new {@link SsMediaSource}.
* @throws IllegalArgumentException If {@link SsManifest#isLive} is true.
*/
public
SsMediaSource
createMediaSource
(
SsManifest
manifest
,
MediaItem
mediaItem
)
{
Assertions
.
checkArgument
(!
manifest
.
isLive
);
List
<
StreamKey
>
streamKeys
=
mediaItem
.
playbackProperties
!=
null
&&
!
mediaItem
.
playbackProperties
.
streamKeys
.
isEmpty
()
?
mediaItem
.
playbackProperties
.
streamKeys
:
this
.
streamKeys
;
if
(!
streamKeys
.
isEmpty
())
{
manifest
=
manifest
.
copy
(
streamKeys
);
}
boolean
hasUri
=
mediaItem
.
playbackProperties
!=
null
;
boolean
hasTag
=
hasUri
&&
mediaItem
.
playbackProperties
.
tag
!=
null
;
mediaItem
=
mediaItem
.
buildUpon
()
.
setMimeType
(
MimeTypes
.
APPLICATION_SS
)
.
setUri
(
hasUri
?
mediaItem
.
playbackProperties
.
uri
:
Uri
.
EMPTY
)
.
setTag
(
hasTag
?
mediaItem
.
playbackProperties
.
tag
:
tag
)
.
setStreamKeys
(
streamKeys
)
.
build
();
return
new
SsMediaSource
(
mediaItem
,
manifest
,
/* manifestUri= */
null
,
/* manifestDataSourceFactory= */
null
,
/* manifestParser= */
null
,
chunkSourceFactory
,
compositeSequenceableLoaderFactory
,
drmSessionManager
,
loadErrorHandlingPolicy
,
livePresentationDelayMs
,
tag
);
livePresentationDelayMs
);
}
/**
...
...
@@ -274,6 +303,7 @@ public final class SsMediaSource extends BaseMediaSource
* @deprecated Use {@link #createMediaSource(Uri)} and {@link #addEventListener(Handler,
* MediaSourceEventListener)} instead.
*/
@SuppressWarnings
(
"deprecation"
)
@Deprecated
public
SsMediaSource
createMediaSource
(
Uri
manifestUri
,
...
...
@@ -295,7 +325,7 @@ public final class SsMediaSource extends BaseMediaSource
*/
@Override
public
SsMediaSource
createMediaSource
(
MediaItem
mediaItem
)
{
Assertions
.
checkNotNull
(
mediaItem
.
playbackProperties
);
checkNotNull
(
mediaItem
.
playbackProperties
);
@Nullable
ParsingLoadable
.
Parser
<?
extends
SsManifest
>
manifestParser
=
this
.
manifestParser
;
if
(
manifestParser
==
null
)
{
manifestParser
=
new
SsManifestParser
();
...
...
@@ -307,17 +337,27 @@ public final class SsMediaSource extends BaseMediaSource
if
(!
streamKeys
.
isEmpty
())
{
manifestParser
=
new
FilteringManifestParser
<>(
manifestParser
,
streamKeys
);
}
boolean
needsTag
=
mediaItem
.
playbackProperties
.
tag
==
null
&&
tag
!=
null
;
boolean
needsStreamKeys
=
mediaItem
.
playbackProperties
.
streamKeys
.
isEmpty
()
&&
!
streamKeys
.
isEmpty
();
if
(
needsTag
&&
needsStreamKeys
)
{
mediaItem
=
mediaItem
.
buildUpon
().
setTag
(
tag
).
setStreamKeys
(
streamKeys
).
build
();
}
else
if
(
needsTag
)
{
mediaItem
=
mediaItem
.
buildUpon
().
setTag
(
tag
).
build
();
}
else
if
(
needsStreamKeys
)
{
mediaItem
=
mediaItem
.
buildUpon
().
setStreamKeys
(
streamKeys
).
build
();
}
return
new
SsMediaSource
(
mediaItem
,
/* manifest= */
null
,
mediaItem
.
playbackProperties
.
uri
,
manifestDataSourceFactory
,
manifestParser
,
chunkSourceFactory
,
compositeSequenceableLoaderFactory
,
drmSessionManager
,
loadErrorHandlingPolicy
,
livePresentationDelayMs
,
mediaItem
.
playbackProperties
.
tag
!=
null
?
mediaItem
.
playbackProperties
.
tag
:
tag
);
livePresentationDelayMs
);
}
@Override
...
...
@@ -343,6 +383,8 @@ public final class SsMediaSource extends BaseMediaSource
private
final
boolean
sideloadedManifest
;
private
final
Uri
manifestUri
;
private
final
MediaItem
.
PlaybackProperties
playbackProperties
;
private
final
MediaItem
mediaItem
;
private
final
DataSource
.
Factory
manifestDataSourceFactory
;
private
final
SsChunkSource
.
Factory
chunkSourceFactory
;
private
final
CompositeSequenceableLoaderFactory
compositeSequenceableLoaderFactory
;
...
...
@@ -352,7 +394,6 @@ public final class SsMediaSource extends BaseMediaSource
private
final
EventDispatcher
manifestEventDispatcher
;
private
final
ParsingLoadable
.
Parser
<?
extends
SsManifest
>
manifestParser
;
private
final
ArrayList
<
SsMediaPeriod
>
mediaPeriods
;
@Nullable
private
final
Object
tag
;
private
DataSource
manifestDataSource
;
private
Loader
manifestLoader
;
...
...
@@ -406,16 +447,15 @@ public final class SsMediaSource extends BaseMediaSource
@Nullable
Handler
eventHandler
,
@Nullable
MediaSourceEventListener
eventListener
)
{
this
(
new
MediaItem
.
Builder
().
setUri
(
Uri
.
EMPTY
).
setMimeType
(
MimeTypes
.
APPLICATION_SS
).
build
(),
manifest
,
/* manifestUri= */
null
,
/* manifestDataSourceFactory= */
null
,
/* manifestParser= */
null
,
chunkSourceFactory
,
new
DefaultCompositeSequenceableLoaderFactory
(),
DrmSessionManager
.
getDummyDrmSessionManager
(),
new
DefaultLoadErrorHandlingPolicy
(
minLoadableRetryCount
),
DEFAULT_LIVE_PRESENTATION_DELAY_MS
,
/* tag= */
null
);
DEFAULT_LIVE_PRESENTATION_DELAY_MS
);
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
addEventListener
(
eventHandler
,
eventListener
);
}
...
...
@@ -507,35 +547,38 @@ public final class SsMediaSource extends BaseMediaSource
@Nullable
Handler
eventHandler
,
@Nullable
MediaSourceEventListener
eventListener
)
{
this
(
new
MediaItem
.
Builder
().
setUri
(
manifestUri
).
setMimeType
(
MimeTypes
.
APPLICATION_SS
).
build
(),
/* manifest= */
null
,
manifestUri
,
manifestDataSourceFactory
,
manifestParser
,
chunkSourceFactory
,
new
DefaultCompositeSequenceableLoaderFactory
(),
DrmSessionManager
.
getDummyDrmSessionManager
(),
new
DefaultLoadErrorHandlingPolicy
(
minLoadableRetryCount
),
livePresentationDelayMs
,
/* tag= */
null
);
livePresentationDelayMs
);
if
(
eventHandler
!=
null
&&
eventListener
!=
null
)
{
addEventListener
(
eventHandler
,
eventListener
);
}
}
private
SsMediaSource
(
MediaItem
mediaItem
,
@Nullable
SsManifest
manifest
,
@Nullable
Uri
manifestUri
,
@Nullable
DataSource
.
Factory
manifestDataSourceFactory
,
@Nullable
ParsingLoadable
.
Parser
<?
extends
SsManifest
>
manifestParser
,
SsChunkSource
.
Factory
chunkSourceFactory
,
CompositeSequenceableLoaderFactory
compositeSequenceableLoaderFactory
,
DrmSessionManager
drmSessionManager
,
LoadErrorHandlingPolicy
loadErrorHandlingPolicy
,
long
livePresentationDelayMs
,
@Nullable
Object
tag
)
{
long
livePresentationDelayMs
)
{
Assertions
.
checkState
(
manifest
==
null
||
!
manifest
.
isLive
);
this
.
mediaItem
=
mediaItem
;
playbackProperties
=
checkNotNull
(
mediaItem
.
playbackProperties
);
this
.
manifest
=
manifest
;
this
.
manifestUri
=
manifestUri
==
null
?
null
:
SsUtil
.
fixManifestUri
(
manifestUri
);
this
.
manifestUri
=
playbackProperties
.
uri
.
equals
(
Uri
.
EMPTY
)
?
null
:
SsUtil
.
fixManifestUri
(
playbackProperties
.
uri
);
this
.
manifestDataSourceFactory
=
manifestDataSourceFactory
;
this
.
manifestParser
=
manifestParser
;
this
.
chunkSourceFactory
=
chunkSourceFactory
;
...
...
@@ -544,7 +587,6 @@ public final class SsMediaSource extends BaseMediaSource
this
.
loadErrorHandlingPolicy
=
loadErrorHandlingPolicy
;
this
.
livePresentationDelayMs
=
livePresentationDelayMs
;
this
.
manifestEventDispatcher
=
createEventDispatcher
(
/* mediaPeriodId= */
null
);
this
.
tag
=
tag
;
sideloadedManifest
=
manifest
!=
null
;
mediaPeriods
=
new
ArrayList
<>();
}
...
...
@@ -554,7 +596,12 @@ public final class SsMediaSource extends BaseMediaSource
@Override
@Nullable
public
Object
getTag
()
{
return
tag
;
return
playbackProperties
.
tag
;
}
// TODO(bachinger): add @Override annotation once the method is defined by MediaSource.
public
MediaItem
getMediaItem
()
{
return
mediaItem
;
}
@Override
...
...
@@ -721,7 +768,7 @@ public final class SsMediaSource extends BaseMediaSource
/* isDynamic= */
manifest
.
isLive
,
/* isLive= */
manifest
.
isLive
,
manifest
,
tag
);
mediaItem
);
}
else
if
(
manifest
.
isLive
)
{
if
(
manifest
.
dvrWindowLengthUs
!=
C
.
TIME_UNSET
&&
manifest
.
dvrWindowLengthUs
>
0
)
{
startTimeUs
=
Math
.
max
(
startTimeUs
,
endTimeUs
-
manifest
.
dvrWindowLengthUs
);
...
...
@@ -744,7 +791,7 @@ public final class SsMediaSource extends BaseMediaSource
/* isDynamic= */
true
,
/* isLive= */
true
,
manifest
,
tag
);
mediaItem
);
}
else
{
long
durationUs
=
manifest
.
durationUs
!=
C
.
TIME_UNSET
?
manifest
.
durationUs
:
endTimeUs
-
startTimeUs
;
...
...
@@ -758,7 +805,7 @@ public final class SsMediaSource extends BaseMediaSource
/* isDynamic= */
false
,
/* isLive= */
false
,
manifest
,
tag
);
mediaItem
);
}
refreshSourceInfo
(
timeline
);
}
...
...
library/smoothstreaming/src/test/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSourceTest.java
0 → 100644
View file @
a3b721e6
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com
.
google
.
android
.
exoplayer2
.
source
.
smoothstreaming
;
import
static
com
.
google
.
android
.
exoplayer2
.
util
.
Util
.
castNonNull
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
androidx.annotation.Nullable
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.MediaItem
;
import
com.google.android.exoplayer2.offline.StreamKey
;
import
com.google.android.exoplayer2.upstream.FileDataSource
;
import
java.util.Collections
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
/** Unit tests for {@link SsMediaSource}. */
@RunWith
(
AndroidJUnit4
.
class
)
public
class
SsMediaSourceTest
{
// Tests backwards compatibility
@SuppressWarnings
(
"deprecation"
)
@Test
public
void
factorySetTag_nullMediaItemTag_setsMediaItemTag
()
{
Object
tag
=
new
Object
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
"http://www.google.com"
);
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
()).
setTag
(
tag
);
MediaItem
ssMediaItem
=
factory
.
createMediaSource
(
mediaItem
).
getMediaItem
();
assertThat
(
ssMediaItem
.
playbackProperties
).
isNotNull
();
assertThat
(
ssMediaItem
.
playbackProperties
.
uri
)
.
isEqualTo
(
castNonNull
(
mediaItem
.
playbackProperties
).
uri
);
assertThat
(
ssMediaItem
.
playbackProperties
.
tag
).
isEqualTo
(
tag
);
}
// Tests backwards compatibility
@SuppressWarnings
(
"deprecation"
)
@Test
public
void
factorySetTag_nonNullMediaItemTag_doesNotOverrideMediaItemTag
()
{
Object
factoryTag
=
new
Object
();
Object
mediaItemTag
=
new
Object
();
MediaItem
mediaItem
=
new
MediaItem
.
Builder
().
setUri
(
"http://www.google.com"
).
setTag
(
mediaItemTag
).
build
();
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
()).
setTag
(
factoryTag
);
MediaItem
ssMediaItem
=
factory
.
createMediaSource
(
mediaItem
).
getMediaItem
();
assertThat
(
ssMediaItem
.
playbackProperties
).
isNotNull
();
assertThat
(
ssMediaItem
.
playbackProperties
.
uri
)
.
isEqualTo
(
castNonNull
(
mediaItem
.
playbackProperties
).
uri
);
assertThat
(
ssMediaItem
.
playbackProperties
.
tag
).
isEqualTo
(
mediaItemTag
);
}
// Tests backwards compatibility
@SuppressWarnings
(
"deprecation"
)
@Test
public
void
factorySetTag_setsDeprecatedMediaSourceTag
()
{
Object
tag
=
new
Object
();
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
"http://www.google.com"
);
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
()).
setTag
(
tag
);
@Nullable
Object
mediaSourceTag
=
factory
.
createMediaSource
(
mediaItem
).
getTag
();
assertThat
(
mediaSourceTag
).
isEqualTo
(
tag
);
}
// Tests backwards compatibility
@Test
public
void
factoryCreateMediaSource_setsDeprecatedMediaSourceTag
()
{
Object
tag
=
new
Object
();
MediaItem
mediaItem
=
new
MediaItem
.
Builder
().
setUri
(
"http://www.google.com"
).
setTag
(
tag
).
build
();
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
());
@Nullable
Object
mediaSourceTag
=
factory
.
createMediaSource
(
mediaItem
).
getTag
();
assertThat
(
mediaSourceTag
).
isEqualTo
(
tag
);
}
// Tests backwards compatibility
@SuppressWarnings
(
"deprecation"
)
@Test
public
void
factorySetStreamKeys_emptyMediaItemStreamKeys_setsMediaItemStreamKeys
()
{
MediaItem
mediaItem
=
MediaItem
.
fromUri
(
"http://www.google.com"
);
StreamKey
streamKey
=
new
StreamKey
(
/* groupIndex= */
0
,
/* trackIndex= */
1
);
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
())
.
setStreamKeys
(
Collections
.
singletonList
(
streamKey
));
MediaItem
ssMediaItem
=
factory
.
createMediaSource
(
mediaItem
).
getMediaItem
();
assertThat
(
ssMediaItem
.
playbackProperties
).
isNotNull
();
assertThat
(
ssMediaItem
.
playbackProperties
.
uri
)
.
isEqualTo
(
castNonNull
(
mediaItem
.
playbackProperties
).
uri
);
assertThat
(
ssMediaItem
.
playbackProperties
.
streamKeys
).
containsExactly
(
streamKey
);
}
// Tests backwards compatibility
@SuppressWarnings
(
"deprecation"
)
@Test
public
void
factorySetStreamKeys_withMediaItemStreamKeys_doesNotOverrideMediaItemStreamKeys
()
{
StreamKey
mediaItemStreamKey
=
new
StreamKey
(
/* groupIndex= */
0
,
/* trackIndex= */
1
);
MediaItem
mediaItem
=
new
MediaItem
.
Builder
()
.
setUri
(
"http://www.google.com"
)
.
setStreamKeys
(
Collections
.
singletonList
(
mediaItemStreamKey
))
.
build
();
SsMediaSource
.
Factory
factory
=
new
SsMediaSource
.
Factory
(
new
FileDataSource
.
Factory
())
.
setStreamKeys
(
Collections
.
singletonList
(
new
StreamKey
(
/* groupIndex= */
1
,
/* trackIndex= */
0
)));
MediaItem
ssMediaItem
=
factory
.
createMediaSource
(
mediaItem
).
getMediaItem
();
assertThat
(
ssMediaItem
.
playbackProperties
).
isNotNull
();
assertThat
(
ssMediaItem
.
playbackProperties
.
uri
)
.
isEqualTo
(
castNonNull
(
mediaItem
.
playbackProperties
).
uri
);
assertThat
(
ssMediaItem
.
playbackProperties
.
streamKeys
).
containsExactly
(
mediaItemStreamKey
);
}
}
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