chore(android): Fix/make videoEventEmitter agnostic on player (#3281)

This commit is contained in:
Olivier Bouillet 2023-10-12 21:46:40 +02:00 committed by GitHub
parent a4073d3e70
commit ad581ea2dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 84 additions and 65 deletions

View File

@ -0,0 +1,8 @@
package com.brentvatne.common.API
class TimedMetadata {
@kotlin.jvm.JvmField
var m_Identifier: String? = null
@kotlin.jvm.JvmField
var m_Value: String? = null
}

View File

@ -1,8 +1,9 @@
package com.brentvatne.exoplayer; package com.brentvatne.common.react;
import androidx.annotation.StringDef; import androidx.annotation.StringDef;
import android.view.View; import android.view.View;
import com.brentvatne.common.API.TimedMetadata;
import com.brentvatne.common.Track; import com.brentvatne.common.Track;
import com.brentvatne.common.VideoTrack; import com.brentvatne.common.VideoTrack;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
@ -10,10 +11,6 @@ import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.RCTEventEmitter; import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.emsg.EventMessage;
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -21,13 +18,13 @@ import java.io.StringWriter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayList; import java.util.ArrayList;
class VideoEventEmitter { public class VideoEventEmitter {
private final RCTEventEmitter eventEmitter; private final RCTEventEmitter eventEmitter;
private int viewId = View.NO_ID; private int viewId = View.NO_ID;
VideoEventEmitter(ReactContext reactContext) { public VideoEventEmitter(ReactContext reactContext) {
this.eventEmitter = reactContext.getJSModule(RCTEventEmitter.class); this.eventEmitter = reactContext.getJSModule(RCTEventEmitter.class);
} }
@ -58,7 +55,7 @@ class VideoEventEmitter {
private static final String EVENT_VIDEO_TRACKS = "onVideoTracks"; private static final String EVENT_VIDEO_TRACKS = "onVideoTracks";
private static final String EVENT_ON_RECEIVE_AD_EVENT = "onReceiveAdEvent"; private static final String EVENT_ON_RECEIVE_AD_EVENT = "onReceiveAdEvent";
static final String[] Events = { public static final String[] Events = {
EVENT_LOAD_START, EVENT_LOAD_START,
EVENT_LOAD, EVENT_LOAD,
EVENT_ERROR, EVENT_ERROR,
@ -156,11 +153,11 @@ class VideoEventEmitter {
private static final String EVENT_PROP_IS_PLAYING = "isPlaying"; private static final String EVENT_PROP_IS_PLAYING = "isPlaying";
void setViewId(int viewId) { public void setViewId(int viewId) {
this.viewId = viewId; this.viewId = viewId;
} }
void loadStart() { public void loadStart() {
receiveEvent(EVENT_LOAD_START, null); receiveEvent(EVENT_LOAD_START, null);
} }
@ -241,7 +238,7 @@ class VideoEventEmitter {
} }
private void load(double duration, double currentPosition, int videoWidth, int videoHeight, public void load(double duration, double currentPosition, int videoWidth, int videoHeight,
WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks, String trackId) { WritableArray audioTracks, WritableArray textTracks, WritableArray videoTracks, String trackId) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
event.putDouble(EVENT_PROP_DURATION, duration / 1000D); event.putDouble(EVENT_PROP_DURATION, duration / 1000D);
@ -286,7 +283,7 @@ class VideoEventEmitter {
receiveEvent(EVENT_VIDEO_TRACKS, arrayToObject(EVENT_PROP_VIDEO_TRACKS, videoTracksToArray(videoTracks))); receiveEvent(EVENT_VIDEO_TRACKS, arrayToObject(EVENT_PROP_VIDEO_TRACKS, videoTracksToArray(videoTracks)));
} }
void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration, double currentPlaybackTime) { public void progressChanged(double currentPosition, double bufferedDuration, double seekableDuration, double currentPlaybackTime) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D); event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D); event.putDouble(EVENT_PROP_PLAYABLE_DURATION, bufferedDuration / 1000D);
@ -295,7 +292,7 @@ class VideoEventEmitter {
receiveEvent(EVENT_PROGRESS, event); receiveEvent(EVENT_PROGRESS, event);
} }
void bandwidthReport(double bitRateEstimate, int height, int width, String id) { public void bandwidthReport(double bitRateEstimate, int height, int width, String id) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate); event.putDouble(EVENT_PROP_BITRATE, bitRateEstimate);
event.putInt(EVENT_PROP_WIDTH, width); event.putInt(EVENT_PROP_WIDTH, width);
@ -304,58 +301,58 @@ class VideoEventEmitter {
receiveEvent(EVENT_BANDWIDTH, event); receiveEvent(EVENT_BANDWIDTH, event);
} }
void seek(long currentPosition, long seekTime) { public void seek(long currentPosition, long seekTime) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D); event.putDouble(EVENT_PROP_CURRENT_TIME, currentPosition / 1000D);
event.putDouble(EVENT_PROP_SEEK_TIME, seekTime / 1000D); event.putDouble(EVENT_PROP_SEEK_TIME, seekTime / 1000D);
receiveEvent(EVENT_SEEK, event); receiveEvent(EVENT_SEEK, event);
} }
void ready() { public void ready() {
receiveEvent(EVENT_READY, null); receiveEvent(EVENT_READY, null);
} }
void buffering(boolean isBuffering) { public void buffering(boolean isBuffering) {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
map.putBoolean(EVENT_PROP_IS_BUFFERING, isBuffering); map.putBoolean(EVENT_PROP_IS_BUFFERING, isBuffering);
receiveEvent(EVENT_BUFFER, map); receiveEvent(EVENT_BUFFER, map);
} }
void playbackStateChanged(boolean isPlaying) { public void playbackStateChanged(boolean isPlaying) {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
map.putBoolean(EVENT_PROP_IS_PLAYING, isPlaying); map.putBoolean(EVENT_PROP_IS_PLAYING, isPlaying);
receiveEvent(EVENT_PLAYBACK_STATE_CHANGED, map); receiveEvent(EVENT_PLAYBACK_STATE_CHANGED, map);
} }
void idle() { public void idle() {
receiveEvent(EVENT_IDLE, null); receiveEvent(EVENT_IDLE, null);
} }
void end() { public void end() {
receiveEvent(EVENT_END, null); receiveEvent(EVENT_END, null);
} }
void fullscreenWillPresent() { public void fullscreenWillPresent() {
receiveEvent(EVENT_FULLSCREEN_WILL_PRESENT, null); receiveEvent(EVENT_FULLSCREEN_WILL_PRESENT, null);
} }
void fullscreenDidPresent() { public void fullscreenDidPresent() {
receiveEvent(EVENT_FULLSCREEN_DID_PRESENT, null); receiveEvent(EVENT_FULLSCREEN_DID_PRESENT, null);
} }
void fullscreenWillDismiss() { public void fullscreenWillDismiss() {
receiveEvent(EVENT_FULLSCREEN_WILL_DISMISS, null); receiveEvent(EVENT_FULLSCREEN_WILL_DISMISS, null);
} }
void fullscreenDidDismiss() { public void fullscreenDidDismiss() {
receiveEvent(EVENT_FULLSCREEN_DID_DISMISS, null); receiveEvent(EVENT_FULLSCREEN_DID_DISMISS, null);
} }
void error(String errorString, Exception exception) { public void error(String errorString, Exception exception) {
_error(errorString, exception, "0001"); _error(errorString, exception, "0001");
} }
void error(String errorString, Exception exception, String errorCode) { public void error(String errorString, Exception exception, String errorCode) {
_error(errorString, exception, errorCode); _error(errorString, exception, errorCode);
} }
@ -376,48 +373,24 @@ class VideoEventEmitter {
receiveEvent(EVENT_ERROR, event); receiveEvent(EVENT_ERROR, event);
} }
void playbackRateChange(float rate) { public void playbackRateChange(float rate) {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
map.putDouble(EVENT_PROP_PLAYBACK_RATE, (double)rate); map.putDouble(EVENT_PROP_PLAYBACK_RATE, (double)rate);
receiveEvent(EVENT_PLAYBACK_RATE_CHANGE, map); receiveEvent(EVENT_PLAYBACK_RATE_CHANGE, map);
} }
void timedMetadata(Metadata metadata) {
public void timedMetadata(ArrayList<TimedMetadata> _metadataArrayList) {
if (_metadataArrayList.size() == 0) {
return;
}
WritableArray metadataArray = Arguments.createArray(); WritableArray metadataArray = Arguments.createArray();
for (int i = 0; i < metadata.length(); i++) { for (int i = 0; i < _metadataArrayList.size(); i++) {
WritableMap map = Arguments.createMap();
Metadata.Entry entry = metadata.get(i); map.putString("identifier", _metadataArrayList.get(i).m_Identifier);
map.putString("value", _metadataArrayList.get(i).m_Value);
if (entry instanceof Id3Frame) { metadataArray.pushMap(map);
Id3Frame frame = (Id3Frame) entry;
String value = "";
if (frame instanceof TextInformationFrame) {
TextInformationFrame txxxFrame = (TextInformationFrame) frame;
value = txxxFrame.value;
}
String identifier = frame.id;
WritableMap map = Arguments.createMap();
map.putString("identifier", identifier);
map.putString("value", value);
metadataArray.pushMap(map);
} else if (entry instanceof EventMessage) {
EventMessage eventMessage = (EventMessage) entry;
WritableMap map = Arguments.createMap();
map.putString("identifier", eventMessage.schemeIdUri);
map.putString("value", eventMessage.value);
metadataArray.pushMap(map);
}
} }
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
@ -425,17 +398,17 @@ class VideoEventEmitter {
receiveEvent(EVENT_TIMED_METADATA, event); receiveEvent(EVENT_TIMED_METADATA, event);
} }
void audioFocusChanged(boolean hasFocus) { public void audioFocusChanged(boolean hasFocus) {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
map.putBoolean(EVENT_PROP_HAS_AUDIO_FOCUS, hasFocus); map.putBoolean(EVENT_PROP_HAS_AUDIO_FOCUS, hasFocus);
receiveEvent(EVENT_AUDIO_FOCUS_CHANGE, map); receiveEvent(EVENT_AUDIO_FOCUS_CHANGE, map);
} }
void audioBecomingNoisy() { public void audioBecomingNoisy() {
receiveEvent(EVENT_AUDIO_BECOMING_NOISY, null); receiveEvent(EVENT_AUDIO_BECOMING_NOISY, null);
} }
void receiveAdEvent(String event) { public void receiveAdEvent(String event) {
WritableMap map = Arguments.createMap(); WritableMap map = Arguments.createMap();
map.putString("event", event); map.putString("event", event);

View File

@ -26,8 +26,10 @@ import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedCallback;
import com.brentvatne.common.API.TimedMetadata;
import com.brentvatne.common.Track; import com.brentvatne.common.Track;
import com.brentvatne.common.VideoTrack; import com.brentvatne.common.VideoTrack;
import com.brentvatne.common.react.VideoEventEmitter;
import com.brentvatne.common.toolbox.DebugLog; import com.brentvatne.common.toolbox.DebugLog;
import com.brentvatne.exoplayer.AudioOutput; import com.brentvatne.exoplayer.AudioOutput;
import com.brentvatne.react.R; import com.brentvatne.react.R;
@ -93,6 +95,10 @@ 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.Period;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet; 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.Representation;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.emsg.EventMessage;
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader; import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
@ -1475,7 +1481,38 @@ public class ReactExoplayerView extends FrameLayout implements
@Override @Override
public void onMetadata(@NonNull Metadata metadata) { public void onMetadata(@NonNull Metadata metadata) {
eventEmitter.timedMetadata(metadata); ArrayList<TimedMetadata> metadataArray = new ArrayList<>();
for (int i = 0; i < metadata.length(); i++) {
Metadata.Entry entry = metadata.get(i);
if (entry instanceof Id3Frame) {
Id3Frame frame = (Id3Frame) metadata.get(i);
String value = "";
if (frame instanceof TextInformationFrame) {
TextInformationFrame txxxFrame = (TextInformationFrame) frame;
value = txxxFrame.value;
}
String identifier = frame.id;
TimedMetadata timedMetadata = new TimedMetadata();
timedMetadata.m_Identifier = identifier;
timedMetadata.m_Value = value;
metadataArray.add(timedMetadata);
} else if (entry instanceof EventMessage) {
EventMessage eventMessage = (EventMessage) entry;
TimedMetadata timedMetadata = new TimedMetadata();
timedMetadata.m_Identifier = eventMessage.schemeIdUri;
timedMetadata.m_Value = eventMessage.value;
metadataArray.add(timedMetadata);
} else {
DebugLog.d(TAG, "unhandled metadata " + entry.toString());
}
}
eventEmitter.timedMetadata(metadataArray);
} }
// ReactExoplayerViewManager public api // ReactExoplayerViewManager public api

View File

@ -6,6 +6,7 @@ import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.brentvatne.common.react.VideoEventEmitter;
import com.brentvatne.common.toolbox.DebugLog; import com.brentvatne.common.toolbox.DebugLog;
import com.brentvatne.common.toolbox.ReactBridgeUtils; import com.brentvatne.common.toolbox.ReactBridgeUtils;
import com.brentvatne.exoplayer.AudioOutput; import com.brentvatne.exoplayer.AudioOutput;