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:
parent
07ac819a46
commit
d792427ce1
@ -151,6 +151,7 @@ using System.Collections.Generic;
|
|||||||
onEnd={this.onEnd} // Callback when playback finishes
|
onEnd={this.onEnd} // Callback when playback finishes
|
||||||
onError={this.videoError} // Callback when video cannot be loaded
|
onError={this.videoError} // Callback when video cannot be loaded
|
||||||
onBuffer={this.onBuffer} // Callback when remote video is buffering
|
onBuffer={this.onBuffer} // Callback when remote video is buffering
|
||||||
|
onTimedMetadata={this.onTimedMetadata} // Callback when the stream receive some metadata
|
||||||
style={styles.backgroundVideo} />
|
style={styles.backgroundVideo} />
|
||||||
|
|
||||||
// Later to trigger fullscreen
|
// Later to trigger fullscreen
|
||||||
|
8
Video.js
8
Video.js
@ -79,6 +79,12 @@ export default class Video extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_onTimedMetadata = (event) => {
|
||||||
|
if (this.props.onTimedMetadata) {
|
||||||
|
this.props.onTimedMetadata(event.nativeEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
_onFullscreenPlayerWillPresent = (event) => {
|
_onFullscreenPlayerWillPresent = (event) => {
|
||||||
if (this.props.onFullscreenPlayerWillPresent) {
|
if (this.props.onFullscreenPlayerWillPresent) {
|
||||||
this.props.onFullscreenPlayerWillPresent(event.nativeEvent);
|
this.props.onFullscreenPlayerWillPresent(event.nativeEvent);
|
||||||
@ -191,6 +197,7 @@ export default class Video extends Component {
|
|||||||
onVideoSeek: this._onSeek,
|
onVideoSeek: this._onSeek,
|
||||||
onVideoEnd: this._onEnd,
|
onVideoEnd: this._onEnd,
|
||||||
onVideoBuffer: this._onBuffer,
|
onVideoBuffer: this._onBuffer,
|
||||||
|
onTimedMetadata: this._onTimedMetadata,
|
||||||
onVideoFullscreenPlayerWillPresent: this._onFullscreenPlayerWillPresent,
|
onVideoFullscreenPlayerWillPresent: this._onFullscreenPlayerWillPresent,
|
||||||
onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent,
|
onVideoFullscreenPlayerDidPresent: this._onFullscreenPlayerDidPresent,
|
||||||
onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss,
|
onVideoFullscreenPlayerWillDismiss: this._onFullscreenPlayerWillDismiss,
|
||||||
@ -248,6 +255,7 @@ Video.propTypes = {
|
|||||||
onVideoProgress: PropTypes.func,
|
onVideoProgress: PropTypes.func,
|
||||||
onVideoSeek: PropTypes.func,
|
onVideoSeek: PropTypes.func,
|
||||||
onVideoEnd: PropTypes.func,
|
onVideoEnd: PropTypes.func,
|
||||||
|
onTimedMetadata: PropTypes.func,
|
||||||
onVideoFullscreenPlayerWillPresent: PropTypes.func,
|
onVideoFullscreenPlayerWillPresent: PropTypes.func,
|
||||||
onVideoFullscreenPlayerDidPresent: PropTypes.func,
|
onVideoFullscreenPlayerDidPresent: PropTypes.func,
|
||||||
onVideoFullscreenPlayerWillDismiss: PropTypes.func,
|
onVideoFullscreenPlayerWillDismiss: PropTypes.func,
|
||||||
|
@ -4,6 +4,7 @@ import android.annotation.TargetApi;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
import android.view.TextureView;
|
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.ExoPlayer;
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer;
|
import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||||
import com.google.android.exoplayer2.Timeline;
|
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.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.text.Cue;
|
import com.google.android.exoplayer2.text.Cue;
|
||||||
import com.google.android.exoplayer2.text.TextRenderer;
|
import com.google.android.exoplayer2.text.TextRenderer;
|
||||||
@ -96,6 +99,7 @@ public final class ExoPlayerView extends FrameLayout {
|
|||||||
this.player.setVideoListener(null);
|
this.player.setVideoListener(null);
|
||||||
this.player.removeListener(componentListener);
|
this.player.removeListener(componentListener);
|
||||||
this.player.setVideoSurface(null);
|
this.player.setVideoSurface(null);
|
||||||
|
this.player.setMetadataOutput(componentListener);
|
||||||
}
|
}
|
||||||
this.player = player;
|
this.player = player;
|
||||||
shutterView.setVisibility(VISIBLE);
|
shutterView.setVisibility(VISIBLE);
|
||||||
@ -108,6 +112,7 @@ public final class ExoPlayerView extends FrameLayout {
|
|||||||
player.setVideoListener(componentListener);
|
player.setVideoListener(componentListener);
|
||||||
player.addListener(componentListener);
|
player.addListener(componentListener);
|
||||||
player.setTextOutput(componentListener);
|
player.setTextOutput(componentListener);
|
||||||
|
player.setMetadataOutput(componentListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +166,7 @@ public final class ExoPlayerView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
|
private final class ComponentListener implements SimpleExoPlayer.VideoListener,
|
||||||
TextRenderer.Output, ExoPlayer.EventListener {
|
TextRenderer.Output, ExoPlayer.EventListener, MetadataRenderer.Output {
|
||||||
|
|
||||||
// TextRenderer.Output implementation
|
// TextRenderer.Output implementation
|
||||||
|
|
||||||
@ -220,6 +225,10 @@ public final class ExoPlayerView extends FrameLayout {
|
|||||||
updateForCurrentTrackSelections();
|
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.extractor.DefaultExtractorsFactory;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil;
|
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.ExtractorMediaSource;
|
||||||
import com.google.android.exoplayer2.source.LoopingMediaSource;
|
import com.google.android.exoplayer2.source.LoopingMediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
@ -49,11 +51,14 @@ import java.net.CookieManager;
|
|||||||
import java.net.CookiePolicy;
|
import java.net.CookiePolicy;
|
||||||
|
|
||||||
@SuppressLint("ViewConstructor")
|
@SuppressLint("ViewConstructor")
|
||||||
|
|
||||||
class ReactExoplayerView extends FrameLayout implements
|
class ReactExoplayerView extends FrameLayout implements
|
||||||
LifecycleEventListener,
|
LifecycleEventListener,
|
||||||
ExoPlayer.EventListener,
|
ExoPlayer.EventListener,
|
||||||
BecomingNoisyListener,
|
BecomingNoisyListener,
|
||||||
AudioManager.OnAudioFocusChangeListener {
|
AudioManager.OnAudioFocusChangeListener,
|
||||||
|
MetadataRenderer.Output
|
||||||
|
{
|
||||||
|
|
||||||
private static final String TAG = "ReactExoplayerView";
|
private static final String TAG = "ReactExoplayerView";
|
||||||
|
|
||||||
@ -192,6 +197,7 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||||
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl());
|
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl());
|
||||||
player.addListener(this);
|
player.addListener(this);
|
||||||
|
player.setMetadataOutput(this);
|
||||||
exoPlayerView.setPlayer(player);
|
exoPlayerView.setPlayer(player);
|
||||||
if (isTimelineStatic) {
|
if (isTimelineStatic) {
|
||||||
if (playerPosition == C.TIME_UNSET) {
|
if (playerPosition == C.TIME_UNSET) {
|
||||||
@ -247,6 +253,7 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
playerPosition = player.getCurrentPosition();
|
playerPosition = player.getCurrentPosition();
|
||||||
}
|
}
|
||||||
player.release();
|
player.release();
|
||||||
|
player.setMetadataOutput(null);
|
||||||
player = null;
|
player = null;
|
||||||
trackSelector = null;
|
trackSelector = null;
|
||||||
}
|
}
|
||||||
@ -480,6 +487,11 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
playerNeedsSource = true;
|
playerNeedsSource = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMetadata(Metadata metadata) {
|
||||||
|
eventEmitter.timedMetadata(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
// ReactExoplayerViewManager public api
|
// ReactExoplayerViewManager public api
|
||||||
|
|
||||||
public void setSrc(final Uri uri, final String extension) {
|
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.Arguments;
|
||||||
import com.facebook.react.bridge.ReactContext;
|
import com.facebook.react.bridge.ReactContext;
|
||||||
|
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.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.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
class VideoEventEmitter {
|
class VideoEventEmitter {
|
||||||
|
|
||||||
@ -32,6 +39,7 @@ class VideoEventEmitter {
|
|||||||
private static final String EVENT_READY = "onReadyForDisplay";
|
private static final String EVENT_READY = "onReadyForDisplay";
|
||||||
private static final String EVENT_BUFFER = "onVideoBuffer";
|
private static final String EVENT_BUFFER = "onVideoBuffer";
|
||||||
private static final String EVENT_IDLE = "onVideoIdle";
|
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_BECOMING_NOISY = "onAudioBecomingNoisy";
|
||||||
private static final String EVENT_AUDIO_FOCUS_CHANGE = "onAudioFocusChanged";
|
private static final String EVENT_AUDIO_FOCUS_CHANGE = "onAudioFocusChanged";
|
||||||
|
|
||||||
@ -47,6 +55,7 @@ class VideoEventEmitter {
|
|||||||
EVENT_READY,
|
EVENT_READY,
|
||||||
EVENT_BUFFER,
|
EVENT_BUFFER,
|
||||||
EVENT_IDLE,
|
EVENT_IDLE,
|
||||||
|
EVENT_TIMED_METADATA,
|
||||||
EVENT_AUDIO_BECOMING_NOISY,
|
EVENT_AUDIO_BECOMING_NOISY,
|
||||||
EVENT_AUDIO_FOCUS_CHANGE,
|
EVENT_AUDIO_FOCUS_CHANGE,
|
||||||
};
|
};
|
||||||
@ -64,6 +73,7 @@ class VideoEventEmitter {
|
|||||||
EVENT_READY,
|
EVENT_READY,
|
||||||
EVENT_BUFFER,
|
EVENT_BUFFER,
|
||||||
EVENT_IDLE,
|
EVENT_IDLE,
|
||||||
|
EVENT_TIMED_METADATA,
|
||||||
EVENT_AUDIO_BECOMING_NOISY,
|
EVENT_AUDIO_BECOMING_NOISY,
|
||||||
EVENT_AUDIO_FOCUS_CHANGE,
|
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_STRING = "errorString";
|
||||||
private static final String EVENT_PROP_ERROR_EXCEPTION = "";
|
private static final String EVENT_PROP_ERROR_EXCEPTION = "";
|
||||||
|
|
||||||
|
private static final String EVENT_PROP_TIMED_METADATA = "metadata";
|
||||||
|
|
||||||
|
|
||||||
void setViewId(int viewId) {
|
void setViewId(int viewId) {
|
||||||
this.viewId = viewId;
|
this.viewId = viewId;
|
||||||
}
|
}
|
||||||
@ -168,6 +181,36 @@ class VideoEventEmitter {
|
|||||||
receiveEvent(EVENT_ERROR, event);
|
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) {
|
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);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoProgress;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoProgress;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoSeek;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoSeek;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoEnd;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoEnd;
|
||||||
|
@property (nonatomic, copy) RCTBubblingEventBlock onTimedMetadata;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillPresent;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillPresent;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerDidPresent;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerDidPresent;
|
||||||
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillDismiss;
|
@property (nonatomic, copy) RCTBubblingEventBlock onVideoFullscreenPlayerWillDismiss;
|
||||||
|
@ -9,6 +9,7 @@ static NSString *const playbackLikelyToKeepUpKeyPath = @"playbackLikelyToKeepUp"
|
|||||||
static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
|
static NSString *const playbackBufferEmptyKeyPath = @"playbackBufferEmpty";
|
||||||
static NSString *const readyForDisplayKeyPath = @"readyForDisplay";
|
static NSString *const readyForDisplayKeyPath = @"readyForDisplay";
|
||||||
static NSString *const playbackRate = @"rate";
|
static NSString *const playbackRate = @"rate";
|
||||||
|
static NSString *const timedMetadata = @"timedMetadata";
|
||||||
|
|
||||||
@implementation RCTVideo
|
@implementation RCTVideo
|
||||||
{
|
{
|
||||||
@ -226,6 +227,7 @@ static NSString *const playbackRate = @"rate";
|
|||||||
[_playerItem addObserver:self forKeyPath:statusKeyPath options:0 context:nil];
|
[_playerItem addObserver:self forKeyPath:statusKeyPath options:0 context:nil];
|
||||||
[_playerItem addObserver:self forKeyPath:playbackBufferEmptyKeyPath options:0 context:nil];
|
[_playerItem addObserver:self forKeyPath:playbackBufferEmptyKeyPath options:0 context:nil];
|
||||||
[_playerItem addObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath options:0 context:nil];
|
[_playerItem addObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath options:0 context:nil];
|
||||||
|
[_playerItem addObserver:self forKeyPath:timedMetadata options:NSKeyValueObservingOptionNew context:nil];
|
||||||
_playerItemObserversSet = YES;
|
_playerItemObserversSet = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +240,7 @@ static NSString *const playbackRate = @"rate";
|
|||||||
[_playerItem removeObserver:self forKeyPath:statusKeyPath];
|
[_playerItem removeObserver:self forKeyPath:statusKeyPath];
|
||||||
[_playerItem removeObserver:self forKeyPath:playbackBufferEmptyKeyPath];
|
[_playerItem removeObserver:self forKeyPath:playbackBufferEmptyKeyPath];
|
||||||
[_playerItem removeObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath];
|
[_playerItem removeObserver:self forKeyPath:playbackLikelyToKeepUpKeyPath];
|
||||||
|
[_playerItem removeObserver:self forKeyPath:timedMetadata];
|
||||||
_playerItemObserversSet = NO;
|
_playerItemObserversSet = NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,6 +321,34 @@ static NSString *const playbackRate = @"rate";
|
|||||||
{
|
{
|
||||||
if (object == _playerItem) {
|
if (object == _playerItem) {
|
||||||
|
|
||||||
|
// When timeMetadata is read the event onTimedMetadata is triggered
|
||||||
|
if ([keyPath isEqualToString: timedMetadata])
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
NSArray<AVMetadataItem *> *items = [change objectForKey:@"new"];
|
||||||
|
if (items && ![items isEqual:[NSNull null]] && items.count > 0) {
|
||||||
|
|
||||||
|
NSMutableArray *array = [NSMutableArray new];
|
||||||
|
for (AVMetadataItem *item in items) {
|
||||||
|
|
||||||
|
NSString *value = item.value;
|
||||||
|
NSString *identifier = item.identifier;
|
||||||
|
|
||||||
|
if (![value isEqual: [NSNull null]]) {
|
||||||
|
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:@[value, identifier] forKeys:@[@"value", @"identifier"]];
|
||||||
|
|
||||||
|
[array addObject:dictionary];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.onTimedMetadata(@{
|
||||||
|
@"target": self.reactTag,
|
||||||
|
@"metadata": array
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ([keyPath isEqualToString:statusKeyPath]) {
|
if ([keyPath isEqualToString:statusKeyPath]) {
|
||||||
// Handle player item status change.
|
// Handle player item status change.
|
||||||
if (_playerItem.status == AVPlayerItemStatusReadyToPlay) {
|
if (_playerItem.status == AVPlayerItemStatusReadyToPlay) {
|
||||||
|
@ -41,6 +41,7 @@ RCT_EXPORT_VIEW_PROPERTY(onVideoError, RCTBubblingEventBlock);
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoProgress, RCTBubblingEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoSeek, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoSeek, RCTBubblingEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoEnd, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoEnd, RCTBubblingEventBlock);
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(onTimedMetadata, RCTBubblingEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillPresent, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillPresent, RCTBubblingEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidPresent, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerDidPresent, RCTBubblingEventBlock);
|
||||||
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillDismiss, RCTBubblingEventBlock);
|
RCT_EXPORT_VIEW_PROPERTY(onVideoFullscreenPlayerWillDismiss, RCTBubblingEventBlock);
|
||||||
|
Loading…
Reference in New Issue
Block a user