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
75242281
authored
Jul 05, 2017
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Clean up rtmp extension
parent
1279b7dc
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
184 additions
and
59 deletions
core_settings.gradle
extensions/rtmp/README.md
extensions/rtmp/build.gradle
extensions/rtmp/src/main/AndroidManifest.xml
extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java
extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java
core_settings.gradle
View file @
75242281
...
@@ -31,6 +31,7 @@ include modulePrefix + 'extension-ima'
...
@@ -31,6 +31,7 @@ include modulePrefix + 'extension-ima'
include
modulePrefix
+
'extension-okhttp'
include
modulePrefix
+
'extension-okhttp'
include
modulePrefix
+
'extension-opus'
include
modulePrefix
+
'extension-opus'
include
modulePrefix
+
'extension-vp9'
include
modulePrefix
+
'extension-vp9'
include
modulePrefix
+
'extension-rtmp'
project
(
modulePrefix
+
'library'
).
projectDir
=
new
File
(
rootDir
,
'library/all'
)
project
(
modulePrefix
+
'library'
).
projectDir
=
new
File
(
rootDir
,
'library/all'
)
project
(
modulePrefix
+
'library-core'
).
projectDir
=
new
File
(
rootDir
,
'library/core'
)
project
(
modulePrefix
+
'library-core'
).
projectDir
=
new
File
(
rootDir
,
'library/core'
)
...
@@ -46,6 +47,7 @@ project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensio
...
@@ -46,6 +47,7 @@ project(modulePrefix + 'extension-ima').projectDir = new File(rootDir, 'extensio
project
(
modulePrefix
+
'extension-okhttp'
).
projectDir
=
new
File
(
rootDir
,
'extensions/okhttp'
)
project
(
modulePrefix
+
'extension-okhttp'
).
projectDir
=
new
File
(
rootDir
,
'extensions/okhttp'
)
project
(
modulePrefix
+
'extension-opus'
).
projectDir
=
new
File
(
rootDir
,
'extensions/opus'
)
project
(
modulePrefix
+
'extension-opus'
).
projectDir
=
new
File
(
rootDir
,
'extensions/opus'
)
project
(
modulePrefix
+
'extension-vp9'
).
projectDir
=
new
File
(
rootDir
,
'extensions/vp9'
)
project
(
modulePrefix
+
'extension-vp9'
).
projectDir
=
new
File
(
rootDir
,
'extensions/vp9'
)
project
(
modulePrefix
+
'extension-rtmp'
).
projectDir
=
new
File
(
rootDir
,
'extensions/rtmp'
)
if
(
gradle
.
ext
.
has
(
'exoplayerIncludeCronetExtension'
)
if
(
gradle
.
ext
.
has
(
'exoplayerIncludeCronetExtension'
)
&&
gradle
.
ext
.
exoplayerIncludeCronetExtension
)
{
&&
gradle
.
ext
.
exoplayerIncludeCronetExtension
)
{
...
...
extensions/rtmp/README.md
View file @
75242281
...
@@ -2,33 +2,26 @@
...
@@ -2,33 +2,26 @@
## Description ##
## Description ##
The RTMP Extension is a
n
[
DataSource
][]
implementation for playing
[
RTMP
][]
streaming using
The RTMP Extension is a
[
DataSource
][]
implementation for playing
[
RTMP
][]
[
Librtmp Client for Android
]
.
streams using
[
LibRtmp Client for Android
][
]
.
## Using the extension ##
[
DataSource
]:
https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/upstream/DataSource.html
[
RTMP
]:
https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol
When building
[
MediaSource
][]
, inject
`RtmpDataSourceFactory`
like this:
[
LibRtmp Client for Android
]:
https://github.com/ant-media/LibRtmp-Client-for-Android
```
java
## Using the extension ##
private
MediaSource
buildMediaSource
(
Uri
uri
,
String
overrideExtension
)
{
int
type
=
TextUtils
.
isEmpty
(
overrideExtension
)
?
Util
.
inferContentType
(
uri
)
:
Util
.
inferContentType
(
"."
+
overrideExtension
);
switch
(
type
)
{
// ... other types cases
The easiest way to use the extension is to add it as a gradle dependency:
case
C
.
TYPE_OTHER
:
```
gradle
DataSource
.
Factory
factory
=
uri
.
getScheme
().
equals
(
"rtmp"
)
?
new
RtmpDataSourceFactory
()
:
mediaDataSourceFactory
;
compile
'com.google.android.exoplayer:extension-rtmp:rX.X.X'
return
new
ExtractorMediaSource
(
uri
,
factory
,
new
DefaultExtractorsFactory
(),
mainHandler
,
eventLogger
);
default
:
{
throw
new
IllegalStateException
(
"Unsupported type: "
+
type
);
}
}
}
```
```
where
`rX.X.X`
is the version, which must match the version of the ExoPlayer
library being used.
[
DataSource
]:
https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/upstream/DataSource.html
Alternatively, you can clone the ExoPlayer repository and depend on the module
[
RTMP
]:
https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol
locally. Instructions for doing this can be found in ExoPlayer's
[
Librtmp Client for Android
]:
https://github.com/ant-media/LibRtmp-Client-for-Android
[
top level README
][]
.
[
MediaSource
]:
https://google.github.io/ExoPlayer/doc/reference/com/google/android/exoplayer2/source/MediaSource.html
[
top level README
]:
https://github.com/google/ExoPlayer/blob/release-v2/README.md
extensions/rtmp/build.gradle
View file @
75242281
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// 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.
apply
from:
'../../constants.gradle'
apply
plugin:
'com.android.library'
apply
plugin:
'com.android.library'
android
{
android
{
...
@@ -18,12 +19,14 @@ android {
...
@@ -18,12 +19,14 @@ android {
buildToolsVersion
project
.
ext
.
buildToolsVersion
buildToolsVersion
project
.
ext
.
buildToolsVersion
defaultConfig
{
defaultConfig
{
minSdkVersion
16
// TODO: Lower minSdkVersion as much as possible once this issue in LibRtmp is fixed:
// https://github.com/ant-media/LibRtmp-Client-for-Android/issues/39
minSdkVersion
21
targetSdkVersion
project
.
ext
.
targetSdkVersion
targetSdkVersion
project
.
ext
.
targetSdkVersion
}
}
}
}
dependencies
{
dependencies
{
compile
project
(
':library-core'
)
compile
project
(
':library-core'
)
compile
'net.butterflytv.utils:rtmp-client:0.2.
6
.1'
compile
'net.butterflytv.utils:rtmp-client:0.2.
7
.1'
}
}
extensions/rtmp/src/main/AndroidManifest.xml
View file @
75242281
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 201
6
The Android Open Source Project
<!-- Copyright (C) 201
7
The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License.
...
...
extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSource.java
View file @
75242281
/*
/*
* Copyright (C) 201
6
The Android Open Source Project
* Copyright (C) 201
7
The Android Open Source Project
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -16,55 +16,77 @@
...
@@ -16,55 +16,77 @@
package
com
.
google
.
android
.
exoplayer2
.
ext
.
rtmp
;
package
com
.
google
.
android
.
exoplayer2
.
ext
.
rtmp
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.upstream.DataSpec
;
import
com.google.android.exoplayer2.upstream.TransferListener
;
import
net.butterflytv.rtmp_client.RtmpClient
;
import
java.io.IOException
;
import
java.io.IOException
;
import
net.butterflytv.rtmp_client.RtmpClient
;
import
net.butterflytv.rtmp_client.RtmpClient.RtmpIOException
;
/**
/**
* A Real-Time Messaging Protocol (RTMP) {@link DataSource}.
* A Real-Time Messaging Protocol (RTMP) {@link DataSource}.
*/
*/
public
final
class
RtmpDataSource
implements
DataSource
{
public
final
class
RtmpDataSource
implements
DataSource
{
private
final
RtmpClient
rtmpClient
;
@Nullable
private
final
TransferListener
<?
super
RtmpDataSource
>
listener
;
private
RtmpClient
rtmpClient
;
private
Uri
uri
;
private
Uri
uri
;
public
RtmpDataSource
()
{
public
RtmpDataSource
()
{
rtmpClient
=
new
RtmpClient
(
);
this
(
null
);
}
}
@Override
/**
public
Uri
getUri
()
{
* @param listener An optional listener.
return
uri
;
*/
public
RtmpDataSource
(
@Nullable
TransferListener
<?
super
RtmpDataSource
>
listener
)
{
this
.
listener
=
listener
;
}
}
@Override
@Override
public
long
open
(
DataSpec
dataSpec
)
throws
IOException
{
public
long
open
(
DataSpec
dataSpec
)
throws
RtmpIOException
{
uri
=
dataSpec
.
uri
;
rtmpClient
=
new
RtmpClient
();
int
result
=
rtmpClient
.
open
(
dataSpec
.
uri
.
toString
(),
false
);
rtmpClient
.
open
(
dataSpec
.
uri
.
toString
(),
false
);
if
(
result
<
0
)
{
return
0
;
this
.
uri
=
dataSpec
.
uri
;
if
(
listener
!=
null
)
{
listener
.
onTransferStart
(
this
,
dataSpec
);
}
}
return
C
.
LENGTH_UNSET
;
return
C
.
LENGTH_UNSET
;
}
}
@Override
@Override
public
void
close
()
throws
IOException
{
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
rtmpClient
.
close
();
int
bytesRead
=
rtmpClient
.
read
(
buffer
,
offset
,
readLength
);
if
(
bytesRead
==
-
1
)
{
return
C
.
RESULT_END_OF_INPUT
;
}
if
(
listener
!=
null
)
{
listener
.
onBytesTransferred
(
this
,
bytesRead
);
}
return
bytesRead
;
}
}
@Override
@Override
public
int
read
(
byte
[]
buffer
,
int
offset
,
int
readLength
)
throws
IOException
{
public
void
close
()
{
return
rtmpClient
.
read
(
buffer
,
offset
,
readLength
);
if
(
uri
!=
null
)
{
uri
=
null
;
if
(
listener
!=
null
)
{
listener
.
onTransferEnd
(
this
);
}
}
if
(
rtmpClient
!=
null
)
{
rtmpClient
.
close
();
rtmpClient
=
null
;
}
}
}
public
final
static
class
RtmpDataSourceFactory
implements
DataSource
.
Factory
{
@Override
@Override
public
DataSource
createDataSource
()
{
public
Uri
getUri
()
{
return
new
RtmpDataSource
();
return
uri
;
}
}
}
}
}
extensions/rtmp/src/main/java/com/google/android/exoplayer2/ext/rtmp/RtmpDataSourceFactory.java
0 → 100644
View file @
75242281
/*
* Copyright (C) 2017 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
.
ext
.
rtmp
;
import
android.support.annotation.Nullable
;
import
com.google.android.exoplayer2.upstream.DataSource
;
import
com.google.android.exoplayer2.upstream.HttpDataSource.Factory
;
import
com.google.android.exoplayer2.upstream.TransferListener
;
/**
* A {@link Factory} that produces {@link RtmpDataSource}.
*/
public
final
class
RtmpDataSourceFactory
implements
DataSource
.
Factory
{
@Nullable
private
final
TransferListener
<?
super
RtmpDataSource
>
listener
;
public
RtmpDataSourceFactory
()
{
this
(
null
);
}
/**
* @param listener An optional listener.
*/
public
RtmpDataSourceFactory
(
@Nullable
TransferListener
<?
super
RtmpDataSource
>
listener
)
{
this
.
listener
=
listener
;
}
@Override
public
DataSource
createDataSource
()
{
return
new
RtmpDataSource
(
listener
);
}
}
library/core/src/main/java/com/google/android/exoplayer2/upstream/DefaultDataSource.java
View file @
75242281
...
@@ -17,9 +17,11 @@ package com.google.android.exoplayer2.upstream;
...
@@ -17,9 +17,11 @@ package com.google.android.exoplayer2.upstream;
import
android.content.Context
;
import
android.content.Context
;
import
android.net.Uri
;
import
android.net.Uri
;
import
android.util.Log
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.reflect.InvocationTargetException
;
/**
/**
* A {@link DataSource} that supports multiple URI schemes. The supported schemes are:
* A {@link DataSource} that supports multiple URI schemes. The supported schemes are:
...
@@ -30,6 +32,8 @@ import java.io.IOException;
...
@@ -30,6 +32,8 @@ import java.io.IOException;
* local file URI).
* local file URI).
* <li>asset: For fetching data from an asset in the application's apk (e.g. asset:///media.mp4).
* <li>asset: For fetching data from an asset in the application's apk (e.g. asset:///media.mp4).
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
* <li>content: For fetching data from a content URI (e.g. content://authority/path/123).
* <li>rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an
* explicit dependency on ExoPlayer's RTMP extension.</li>
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4), if
* <li>http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4), if
* constructed using {@link #DefaultDataSource(Context, TransferListener, String, boolean)}, or
* constructed using {@link #DefaultDataSource(Context, TransferListener, String, boolean)}, or
* any other schemes supported by a base data source if constructed using
* any other schemes supported by a base data source if constructed using
...
@@ -38,13 +42,22 @@ import java.io.IOException;
...
@@ -38,13 +42,22 @@ import java.io.IOException;
*/
*/
public
final
class
DefaultDataSource
implements
DataSource
{
public
final
class
DefaultDataSource
implements
DataSource
{
private
static
final
String
TAG
=
"DefaultDataSource"
;
private
static
final
String
SCHEME_ASSET
=
"asset"
;
private
static
final
String
SCHEME_ASSET
=
"asset"
;
private
static
final
String
SCHEME_CONTENT
=
"content"
;
private
static
final
String
SCHEME_CONTENT
=
"content"
;
private
static
final
String
SCHEME_RTMP
=
"rtmp"
;
private
final
Context
context
;
private
final
TransferListener
<?
super
DataSource
>
listener
;
private
final
DataSource
baseDataSource
;
private
final
DataSource
baseDataSource
;
private
final
DataSource
fileDataSource
;
private
final
DataSource
assetDataSource
;
// Lazily initialized.
private
final
DataSource
contentDataSource
;
private
DataSource
fileDataSource
;
private
DataSource
assetDataSource
;
private
DataSource
contentDataSource
;
private
DataSource
rtmpDataSource
;
private
DataSource
dataSource
;
private
DataSource
dataSource
;
...
@@ -95,10 +108,9 @@ public final class DefaultDataSource implements DataSource {
...
@@ -95,10 +108,9 @@ public final class DefaultDataSource implements DataSource {
*/
*/
public
DefaultDataSource
(
Context
context
,
TransferListener
<?
super
DataSource
>
listener
,
public
DefaultDataSource
(
Context
context
,
TransferListener
<?
super
DataSource
>
listener
,
DataSource
baseDataSource
)
{
DataSource
baseDataSource
)
{
this
.
context
=
context
.
getApplicationContext
();
this
.
listener
=
listener
;
this
.
baseDataSource
=
Assertions
.
checkNotNull
(
baseDataSource
);
this
.
baseDataSource
=
Assertions
.
checkNotNull
(
baseDataSource
);
this
.
fileDataSource
=
new
FileDataSource
(
listener
);
this
.
assetDataSource
=
new
AssetDataSource
(
context
,
listener
);
this
.
contentDataSource
=
new
ContentDataSource
(
context
,
listener
);
}
}
@Override
@Override
...
@@ -108,14 +120,16 @@ public final class DefaultDataSource implements DataSource {
...
@@ -108,14 +120,16 @@ public final class DefaultDataSource implements DataSource {
String
scheme
=
dataSpec
.
uri
.
getScheme
();
String
scheme
=
dataSpec
.
uri
.
getScheme
();
if
(
Util
.
isLocalFileUri
(
dataSpec
.
uri
))
{
if
(
Util
.
isLocalFileUri
(
dataSpec
.
uri
))
{
if
(
dataSpec
.
uri
.
getPath
().
startsWith
(
"/android_asset/"
))
{
if
(
dataSpec
.
uri
.
getPath
().
startsWith
(
"/android_asset/"
))
{
dataSource
=
assetDataSource
;
dataSource
=
getAssetDataSource
()
;
}
else
{
}
else
{
dataSource
=
fileDataSource
;
dataSource
=
getFileDataSource
()
;
}
}
}
else
if
(
SCHEME_ASSET
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_ASSET
.
equals
(
scheme
))
{
dataSource
=
assetDataSource
;
dataSource
=
getAssetDataSource
()
;
}
else
if
(
SCHEME_CONTENT
.
equals
(
scheme
))
{
}
else
if
(
SCHEME_CONTENT
.
equals
(
scheme
))
{
dataSource
=
contentDataSource
;
dataSource
=
getContentDataSource
();
}
else
if
(
SCHEME_RTMP
.
equals
(
scheme
))
{
dataSource
=
getRtmpDataSource
();
}
else
{
}
else
{
dataSource
=
baseDataSource
;
dataSource
=
baseDataSource
;
}
}
...
@@ -144,4 +158,48 @@ public final class DefaultDataSource implements DataSource {
...
@@ -144,4 +158,48 @@ public final class DefaultDataSource implements DataSource {
}
}
}
}
private
DataSource
getFileDataSource
()
{
if
(
fileDataSource
==
null
)
{
fileDataSource
=
new
FileDataSource
(
listener
);
}
return
fileDataSource
;
}
private
DataSource
getAssetDataSource
()
{
if
(
assetDataSource
==
null
)
{
assetDataSource
=
new
AssetDataSource
(
context
,
listener
);
}
return
assetDataSource
;
}
private
DataSource
getContentDataSource
()
{
if
(
contentDataSource
==
null
)
{
contentDataSource
=
new
ContentDataSource
(
context
,
listener
);
}
return
contentDataSource
;
}
private
DataSource
getRtmpDataSource
()
{
if
(
rtmpDataSource
==
null
)
{
try
{
Class
<?>
clazz
=
Class
.
forName
(
"com.google.android.exoplayer2.ext.rtmp.RtmpDataSource"
);
rtmpDataSource
=
(
DataSource
)
clazz
.
getDeclaredConstructor
().
newInstance
();
}
catch
(
ClassNotFoundException
e
)
{
Log
.
w
(
TAG
,
"Attempting to play RTMP stream without depending on the RTMP extension"
);
}
catch
(
InstantiationException
e
)
{
Log
.
e
(
TAG
,
"Error instantiating RtmpDataSource"
,
e
);
}
catch
(
IllegalAccessException
e
)
{
Log
.
e
(
TAG
,
"Error instantiating RtmpDataSource"
,
e
);
}
catch
(
NoSuchMethodException
e
)
{
Log
.
e
(
TAG
,
"Error instantiating RtmpDataSource"
,
e
);
}
catch
(
InvocationTargetException
e
)
{
Log
.
e
(
TAG
,
"Error instantiating RtmpDataSource"
,
e
);
}
if
(
rtmpDataSource
==
null
)
{
rtmpDataSource
=
baseDataSource
;
}
}
return
rtmpDataSource
;
}
}
}
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