diff --git a/API.md b/API.md
index 625efeb5..f298abf5 100644
--- a/API.md
+++ b/API.md
@@ -320,6 +320,7 @@ var styles = StyleSheet.create({
| Name | Platforms Support |
|-------------------------------------------------------------------------------------------------|---------------------------|
| [onAudioBecomingNoisy](#onaudiobecomingnoisy) | Android, iOS |
+| [onAudioTracks](#onAudioTracks) | Android |
| [onBandwidthUpdate](#onbandwidthupdate) | Android |
| [onBuffer](#onbuffer) | Android, iOS |
| [onEnd](#onend) | All |
@@ -339,6 +340,8 @@ var styles = StyleSheet.create({
| [onRestoreUserInterfaceForPictureInPictureStop](#onrestoreuserinterfaceforpictureinpicturestop) | iOS |
| [onSeek](#onseek) | Android, iOS, Windows UWP |
| [onTimedMetadata](#ontimedmetadata) | Android, iOS |
+| [onTextTracks](#onTextTracks) | Android |
+| [onVideoTracks](#onVideoTracks) | Android |
### Methods
| Name |Plateforms Support |
@@ -684,6 +687,34 @@ Determine whether to repeat the video when the end is reached
Platforms: all
+
+#### onAudioTracks
+Callback function that is called when audio tracks change
+
+Payload:
+
+Property | Type | Description
+--- | --- | ---
+index | number | Internal track ID
+title | string | Descriptive name for the track
+language | string | 2 letter [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) representing the language
+bitrate | number | bitrate of track
+type | string | Mime type of track
+selected | boolean | true if track is playing
+
+Example:
+```
+{
+ audioTracks: [
+ { language: 'es', title: 'Spanish', type: 'audio/mpeg', index: 0, selected: true },
+ { language: 'en', title: 'English', type: 'audio/mpeg', index: 1 }
+ ],
+}
+```
+
+
+Platforms: Android
+
#### reportBandwidth
Determine whether to generate onBandwidthUpdate events. This is needed due to the high frequency of these events on ExoPlayer.
@@ -1347,6 +1378,69 @@ Example:
Platforms: Android, iOS
+#### onTextTracks
+Callback function that is called when text tracks change
+
+Payload:
+
+Property | Type | Description
+--- | --- | ---
+index | number | Internal track ID
+title | string | Descriptive name for the track
+language | string | 2 letter [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) representing the language
+type | string | Mime type of the track
* TextTrackType.SRT - SubRip (.srt)
* TextTrackType.TTML - TTML (.ttml)
* TextTrackType.VTT - WebVTT (.vtt)
iOS only supports VTT, Android supports all 3
+selected | boolean | true if track is playing
+
+
+Example:
+```
+{
+ textTracks: [
+ {
+ index: 0,
+ title: 'Any Time You Like',
+ type: 'srt',
+ selected: true
+ }
+ ]
+}
+```
+
+Platforms: Android
+
+#### onVideoTracks
+Callback function that is called when video tracks change
+
+Payload:
+
+Property | Type | Description
+--- | --- | ---
+trackId | number | Internal track ID
+codecs | string | MimeType of codec used for this track
+width | number | Track width
+height | number | Track height
+bitrate | number | Bitrate in bps
+selected | boolean | true if track is selected for playing
+
+
+Example:
+```
+{
+ videoTracks: [
+ {
+ trackId: 0,
+ codecs: 'video/mp4',
+ width: 1920,
+ height: 1080,
+ bitrate: 10000,
+ selected: true
+ }
+ ]
+}
+```
+
+Platforms: Android
+
### Methods
Methods operate on a ref to the Video element. You can create a ref using code like:
```
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e3ecbca..48703525 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
### Version 6.0.0-alpha.5
+ - Android: add new events on tracks changed to be notified of audio/text/video Tracks update during playback [2806](https://github.com/react-native-video/react-native-video/pull/2806)
- iOS: app crashes on call to presentFullScreenPlayer [#2808](https://github.com/react-native-video/react-native-video/pull/2971)
- Android: Fix publicated progress handler causing duplicated progress event [#2972](https://github.com/react-native-video/react-native-video/pull/2972)
- Android: Fix audio/Subtitle tracks selection [#2979](https://github.com/react-native-video/react-native-video/pull/2979)
diff --git a/Video.js b/Video.js
index e1374725..ac6bc085 100644
--- a/Video.js
+++ b/Video.js
@@ -117,6 +117,24 @@ export default class Video extends Component {
}
};
+ _onAudioTracks = (event) => {
+ if (this.props.onAudioTracks) {
+ this.props.onAudioTracks(event.nativeEvent);
+ }
+ };
+
+ _onTextTracks = (event) => {
+ if (this.props.onTextTracks) {
+ this.props.onTextTracks(event.nativeEvent);
+ }
+ };
+
+ _onVideoTracks = (event) => {
+ if (this.props.onVideoTracks) {
+ this.props.onVideoTracks(event.nativeEvent);
+ }
+ };
+
_onError = (event) => {
if (this.props.onError) {
this.props.onError(event.nativeEvent);
@@ -328,6 +346,9 @@ export default class Video extends Component {
onVideoLoadStart: this._onLoadStart,
onVideoPlaybackStateChanged: this._onPlaybackStateChanged,
onVideoLoad: this._onLoad,
+ onAudioTracks: this._onAudioTracks,
+ onTextTracks: this._onTextTracks,
+ onVideoTracks: this._onVideoTracks,
onVideoError: this._onError,
onVideoProgress: this._onProgress,
onVideoSeek: this._onSeek,
@@ -516,6 +537,9 @@ Video.propTypes = {
onLoadStart: PropTypes.func,
onPlaybackStateChanged: PropTypes.func,
onLoad: PropTypes.func,
+ onAudioTracks: PropTypes.func,
+ onTextTracks: PropTypes.func,
+ onVideoTracks: PropTypes.func,
onBuffer: PropTypes.func,
onError: PropTypes.func,
onProgress: PropTypes.func,
diff --git a/android/src/main/java/com/brentvatne/common/Track.java b/android/src/main/java/com/brentvatne/common/Track.java
new file mode 100644
index 00000000..198f9ec7
--- /dev/null
+++ b/android/src/main/java/com/brentvatne/common/Track.java
@@ -0,0 +1,13 @@
+package com.brentvatne.common;
+import android.net.Uri;
+
+public class Track
+{
+ public String m_title;
+ public Uri m_uri;
+ public String m_mimeType;
+ public String m_language;
+ public boolean m_isSelected;
+ public int m_bitrate;
+ public int m_index;
+}
diff --git a/android/src/main/java/com/brentvatne/common/VideoTrack.java b/android/src/main/java/com/brentvatne/common/VideoTrack.java
new file mode 100644
index 00000000..6eccd983
--- /dev/null
+++ b/android/src/main/java/com/brentvatne/common/VideoTrack.java
@@ -0,0 +1,12 @@
+package com.brentvatne.common;
+
+public class VideoTrack
+{
+ public int m_width = 0;
+ public int m_height = 0;
+ public int m_bitrate = 0;
+ public String m_codecs = "";
+ public int m_id = -1;
+ public String m_trackId = "";
+ public boolean m_isSelected = false;
+}
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
index 10cecff3..3b7df5b2 100644
--- a/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
+++ b/android/src/main/java/com/brentvatne/exoplayer/ExoPlayerView.java
@@ -4,7 +4,6 @@ import android.annotation.TargetApi;
import android.content.Context;
import androidx.core.content.ContextCompat;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.SurfaceView;
@@ -29,7 +28,6 @@ import com.google.android.exoplayer2.video.VideoSize;
import java.util.List;
-@TargetApi(16)
public final class ExoPlayerView extends FrameLayout implements AdViewProvider {
private View surfaceView;
diff --git a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
index c2cd274e..d7ab0761 100644
--- a/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
+++ b/android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
@@ -1,5 +1,10 @@
package com.brentvatne.exoplayer;
+import static com.google.android.exoplayer2.C.CONTENT_TYPE_DASH;
+import static com.google.android.exoplayer2.C.CONTENT_TYPE_HLS;
+import static com.google.android.exoplayer2.C.CONTENT_TYPE_OTHER;
+import static com.google.android.exoplayer2.C.CONTENT_TYPE_SS;
+
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
@@ -17,27 +22,23 @@ import android.view.accessibility.CaptioningManager;
import android.widget.FrameLayout;
import android.widget.ImageButton;
+import androidx.annotation.WorkerThread;
import androidx.activity.OnBackPressedCallback;
+import com.brentvatne.common.Track;
+import com.brentvatne.common.VideoTrack;
import com.brentvatne.react.R;
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
import com.brentvatne.receiver.BecomingNoisyListener;
-import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Dynamic;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
-import com.facebook.react.bridge.WritableArray;
-import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.ThemedReactContext;
-import com.facebook.react.util.RNLog;
import com.google.ads.interactivemedia.v3.api.AdEvent;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
-import com.google.android.exoplayer2.ExoPlaybackException;
-import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
-import com.google.android.exoplayer2.drm.DrmSession.DrmSessionException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackException;
@@ -51,16 +52,12 @@ import com.google.android.exoplayer2.drm.DefaultDrmSessionManagerProvider;
import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.drm.DrmSessionManagerProvider;
-import com.google.android.exoplayer2.drm.ExoMediaDrm;
import com.google.android.exoplayer2.drm.FrameworkMediaDrm;
import com.google.android.exoplayer2.drm.HttpMediaDrmCallback;
-import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
import com.google.android.exoplayer2.drm.UnsupportedDrmException;
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
-import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
import com.google.android.exoplayer2.metadata.Metadata;
-import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MergingMediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
@@ -76,6 +73,7 @@ import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionOverride;
import com.google.android.exoplayer2.ui.PlayerControlView;
import com.google.android.exoplayer2.upstream.BandwidthMeter;
@@ -84,7 +82,6 @@ import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.DefaultAllocator;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.upstream.HttpDataSource;
-import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.source.dash.DashUtil;
@@ -92,7 +89,6 @@ import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
-import com.google.android.exoplayer2.source.dash.manifest.Descriptor;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
@@ -107,9 +103,6 @@ import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.List;
import java.lang.Thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -799,7 +792,7 @@ class ReactExoplayerView extends FrameLayout implements
drmProvider = new DefaultDrmSessionManagerProvider();
}
switch (type) {
- case C.TYPE_SS:
+ case CONTENT_TYPE_SS:
return new SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)
@@ -807,7 +800,7 @@ class ReactExoplayerView extends FrameLayout implements
.setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem);
- case C.TYPE_DASH:
+ case CONTENT_TYPE_DASH:
return new DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)
@@ -815,14 +808,14 @@ class ReactExoplayerView extends FrameLayout implements
.setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem);
- case C.TYPE_HLS:
+ case CONTENT_TYPE_HLS:
return new HlsMediaSource.Factory(
mediaDataSourceFactory
).setDrmSessionManagerProvider(drmProvider)
.setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(mediaItem);
- case C.TYPE_OTHER:
+ case CONTENT_TYPE_OTHER:
return new ProgressiveMediaSource.Factory(
mediaDataSourceFactory
).setDrmSessionManagerProvider(drmProvider)
@@ -1129,25 +1122,42 @@ class ReactExoplayerView extends FrameLayout implements
// Properties that must be accessed on the main thread
long duration = player.getDuration();
long currentPosition = player.getCurrentPosition();
- WritableArray audioTrackInfo = getAudioTrackInfo();
- WritableArray textTrackInfo = getTextTrackInfo();
- int trackRendererIndex = getTrackRendererIndex(C.TRACK_TYPE_VIDEO);
+ ArrayList