Added onTimedMetadata callback for iOS player and Exoplayer (#487)
* added listener for timedMetadata event. * added callback in RCTVideo for the timed metadata * exposing onTimedMetadata to JS * added forgotten method declaration * returning array of string values * added metadata type to the array * added onMetadata method * overridden onMetadata method on exoplayer2 * added format of return value from onMetadata * added function reference in README file
This commit is contained in:
committed by
Matt Apperson
parent
07ac819a46
commit
d792427ce1
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.TextureView;
|
||||
@@ -16,6 +17,8 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.ExoPlayer;
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.metadata.MetadataRenderer;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.text.Cue;
|
||||
import com.google.android.exoplayer2.text.TextRenderer;
|
||||
@@ -96,6 +99,7 @@ public final class ExoPlayerView extends FrameLayout {
|
||||
this.player.setVideoListener(null);
|
||||
this.player.removeListener(componentListener);
|
||||
this.player.setVideoSurface(null);
|
||||
this.player.setMetadataOutput(componentListener);
|
||||
}
|
||||
this.player = player;
|
||||
shutterView.setVisibility(VISIBLE);
|
||||
@@ -108,6 +112,7 @@ public final class ExoPlayerView extends FrameLayout {
|
||||
player.setVideoListener(componentListener);
|
||||
player.addListener(componentListener);
|
||||
player.setTextOutput(componentListener);
|
||||
player.setMetadataOutput(componentListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +166,7 @@ public final class ExoPlayerView extends FrameLayout {
|
||||
}
|
||||
|
||||
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
|
||||
TextRenderer.Output, ExoPlayer.EventListener {
|
||||
TextRenderer.Output, ExoPlayer.EventListener, MetadataRenderer.Output {
|
||||
|
||||
// TextRenderer.Output implementation
|
||||
|
||||
@@ -220,6 +225,10 @@ public final class ExoPlayerView extends FrameLayout {
|
||||
updateForCurrentTrackSelections();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMetadata(Metadata metadata) {
|
||||
Log.d("onMetadata", "onMetadata");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -26,6 +26,8 @@ import com.google.android.exoplayer2.Timeline;
|
||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||
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.metadata.MetadataRenderer;
|
||||
import com.google.android.exoplayer2.source.ExtractorMediaSource;
|
||||
import com.google.android.exoplayer2.source.LoopingMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
@@ -49,11 +51,14 @@ import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
|
||||
class ReactExoplayerView extends FrameLayout implements
|
||||
LifecycleEventListener,
|
||||
ExoPlayer.EventListener,
|
||||
BecomingNoisyListener,
|
||||
AudioManager.OnAudioFocusChangeListener {
|
||||
AudioManager.OnAudioFocusChangeListener,
|
||||
MetadataRenderer.Output
|
||||
{
|
||||
|
||||
private static final String TAG = "ReactExoplayerView";
|
||||
|
||||
@@ -192,6 +197,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl());
|
||||
player.addListener(this);
|
||||
player.setMetadataOutput(this);
|
||||
exoPlayerView.setPlayer(player);
|
||||
if (isTimelineStatic) {
|
||||
if (playerPosition == C.TIME_UNSET) {
|
||||
@@ -247,6 +253,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
playerPosition = player.getCurrentPosition();
|
||||
}
|
||||
player.release();
|
||||
player.setMetadataOutput(null);
|
||||
player = null;
|
||||
trackSelector = null;
|
||||
}
|
||||
@@ -480,6 +487,11 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
playerNeedsSource = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMetadata(Metadata metadata) {
|
||||
eventEmitter.timedMetadata(metadata);
|
||||
}
|
||||
|
||||
// ReactExoplayerViewManager public api
|
||||
|
||||
public void setSrc(final Uri uri, final String extension) {
|
||||
|
@@ -5,11 +5,18 @@ import android.view.View;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.google.android.exoplayer2.metadata.Metadata;
|
||||
import com.google.android.exoplayer2.metadata.id3.BinaryFrame;
|
||||
import com.google.android.exoplayer2.metadata.id3.Id3Frame;
|
||||
import com.google.android.exoplayer2.metadata.id3.TxxxFrame;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class VideoEventEmitter {
|
||||
|
||||
@@ -32,6 +39,7 @@ class VideoEventEmitter {
|
||||
private static final String EVENT_READY = "onReadyForDisplay";
|
||||
private static final String EVENT_BUFFER = "onVideoBuffer";
|
||||
private static final String EVENT_IDLE = "onVideoIdle";
|
||||
private static final String EVENT_TIMED_METADATA = "onTimedMetadata";
|
||||
private static final String EVENT_AUDIO_BECOMING_NOISY = "onAudioBecomingNoisy";
|
||||
private static final String EVENT_AUDIO_FOCUS_CHANGE = "onAudioFocusChanged";
|
||||
|
||||
@@ -47,6 +55,7 @@ class VideoEventEmitter {
|
||||
EVENT_READY,
|
||||
EVENT_BUFFER,
|
||||
EVENT_IDLE,
|
||||
EVENT_TIMED_METADATA,
|
||||
EVENT_AUDIO_BECOMING_NOISY,
|
||||
EVENT_AUDIO_FOCUS_CHANGE,
|
||||
};
|
||||
@@ -64,6 +73,7 @@ class VideoEventEmitter {
|
||||
EVENT_READY,
|
||||
EVENT_BUFFER,
|
||||
EVENT_IDLE,
|
||||
EVENT_TIMED_METADATA,
|
||||
EVENT_AUDIO_BECOMING_NOISY,
|
||||
EVENT_AUDIO_FOCUS_CHANGE,
|
||||
})
|
||||
@@ -92,6 +102,9 @@ class VideoEventEmitter {
|
||||
private static final String EVENT_PROP_ERROR_STRING = "errorString";
|
||||
private static final String EVENT_PROP_ERROR_EXCEPTION = "";
|
||||
|
||||
private static final String EVENT_PROP_TIMED_METADATA = "metadata";
|
||||
|
||||
|
||||
void setViewId(int viewId) {
|
||||
this.viewId = viewId;
|
||||
}
|
||||
@@ -168,6 +181,36 @@ class VideoEventEmitter {
|
||||
receiveEvent(EVENT_ERROR, event);
|
||||
}
|
||||
|
||||
void timedMetadata(Metadata metadata) {
|
||||
WritableArray metadataArray = Arguments.createArray();
|
||||
|
||||
for (int i = 0; i < metadata.length(); i++) {
|
||||
|
||||
|
||||
Id3Frame frame = (Id3Frame) metadata.get(i);
|
||||
|
||||
String value = "";
|
||||
|
||||
if (frame instanceof TxxxFrame) {
|
||||
TxxxFrame txxxFrame = (TxxxFrame) frame;
|
||||
value = txxxFrame.value;
|
||||
}
|
||||
|
||||
String identifier = frame.id;
|
||||
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putString("identifier", identifier);
|
||||
map.putString("value", value);
|
||||
|
||||
metadataArray.pushMap(map);
|
||||
|
||||
}
|
||||
|
||||
WritableMap event = Arguments.createMap();
|
||||
event.putArray(EVENT_PROP_TIMED_METADATA, metadataArray);
|
||||
receiveEvent(EVENT_TIMED_METADATA, event);
|
||||
}
|
||||
|
||||
void audioFocusChanged(boolean hasFocus) {
|
||||
WritableMap map = Arguments.createMap();
|
||||
map.putBoolean(EVENT_PROP_HAS_AUDIO_FOCUS, hasFocus);
|
||||
|
Reference in New Issue
Block a user