我目前正在使用Android端的exoplayer制作RTMP库以进行本机响应。显示视图时,我无法缩放视频。
基本上,我正在准备一个不存在视图的SimpleExoplayer(以开始缓冲),然后在出现react native视图时将其附加到View。我的问题是,它无法按我希望的那样缩放,因此我需要调整React本机视图的大小,然后很好地缩放。
以下是相关代码部分:
负责创建播放器的类:
public class RTMPPlayer{
private static RTMPPlayer sharedPlayer;
public SimpleExoPlayer player;
private Context myContext;
private DefaultBandwidthMeter defaultBandwidthMeter;
private RtmpDataSourceFactory rtmpDataSourceFactory;
private boolean prepared;
private RTMPPlayer(final Context context) {
runOnUiThread(new Runnable(){
public void run() {
// UI code goes here
myContext = context;
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(defaultBandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
DefaultAllocator defaultAllocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
LoadControl loadControl = new DefaultLoadControl(defaultAllocator, 1050, 1600, 1000, 1000, C.LENGTH_UNSET, false);
RenderersFactory renderersFactory = new DefaultRenderersFactory(myContext);
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector, loadControl);
}
});
}
public static RTMPPlayer getSharedPlayer(Context context){
if(sharedPlayer == null) {
sharedPlayer = new RTMPPlayer(context);
}
return sharedPlayer;
}
public void preparePlayer(final String source){
if(prepared){
return;
}
runOnUiThread(new Runnable(){
public void run() {
rtmpDataSourceFactory = new RtmpDataSourceFactory(defaultBandwidthMeter);
MediaSource videoSource = new ExtractorMediaSource.Factory(rtmpDataSourceFactory).createMediaSource(Uri.parse(source));
player.addListener(new RTMPPlayer.PlayerEventListener());
player.setPlayWhenReady(true);
player.seekToDefaultPosition();
player.prepare(videoSource);
prepared = true;
}
});
}
public void releasePlayer() {
runOnUiThread(new Runnable(){
public void run() {
player.release();
player = null;
sharedPlayer = null;
prepared = false;
}
});
}
负责该视图的类:
public class ReactVideoView extends FrameLayout {
private RtmpDataSourceFactory rtmpDataSourceFactory;
private PlayerView playerView;
private Context myContext;
public String source;
public Boolean shouldAutoPlay;
public ReactVideoView(Context context) {
super(context);
createView(context);
}
private void createView(Context context) {
LayoutParams layoutParams = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
playerView = new PlayerView(context);
playerView.setLayoutParams(layoutParams);
playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_ZOOM);
myContext = context;
addView(playerView, 0, layoutParams);
RTMPPlayer playerManager = RTMPPlayer.getSharedPlayer(context);
SimpleExoPlayer player = playerManager.player;
playerView.setUseController(false);
playerView.setPlayer(player);
playerView.requestLayout();
}
//Completely clears the player
public void releasePlayer() {
RTMPPlayer playerManager = RTMPPlayer.getSharedPlayer(myContext);
SimpleExoPlayer player = playerManager.player;
if (player != null) {
playerView.setPlayer(null);
}
}
public void pausePlayer() {
RTMPPlayer playerManager = RTMPPlayer.getSharedPlayer(myContext);
SimpleExoPlayer player = playerManager.player;
if (player != null) {
player.setPlayWhenReady(false);
}
}
public void resumePlayer() {
RTMPPlayer playerManager = RTMPPlayer.getSharedPlayer(myContext);
SimpleExoPlayer player = playerManager.player;
if (player != null) {
player.setPlayWhenReady(true);
player.seekToDefaultPosition();
}
}
}
ViewManager(用于RN):
public class RNVideoViewManager extends SimpleViewManager<ReactVideoView> {
public static final String REACT_CLASS = "RNVideoView";
public Map getExportedCustomBubblingEventTypeConstants() {
return MapBuilder.builder()
.put(
"stateChange",
MapBuilder.of(
"phasedRegistrationNames",
MapBuilder.of("bubbled", "onStateChange")))
.put(
"error",
MapBuilder.of(
"phasedRegistrationNames",
MapBuilder.of("bubbled", "onError")))
.build();
}
@Override
public String getName() {
return REACT_CLASS;
}
@Override
protected ReactVideoView createViewInstance(ThemedReactContext reactContext) {
return new ReactVideoView(reactContext);
}
@ReactProp(name = "pause", defaultBoolean = false)
public void setPause( ReactVideoView view, boolean pause){
if(pause){
view.pausePlayer();
} else {
view.resumePlayer();
}
}
@Override
public void receiveCommand(ReactVideoView view, int commandId, @Nullable ReadableArray args) {
super.receiveCommand(view, commandId, args);
if (commandId == 1) {
view.releasePlayer();
}
}
}
JS视图:
export class VideoView extends React.PureComponent<Props, State> {
video: ?VideoView;
_onStateChange: Function;
_onError: Function;
static emitter = new EventEmitter();
constructor(props: Props) {
super(props);
this.state = {
pause: false
};
this._onStateChange = this._onStateChange.bind(this);
this._onError = this._onError.bind(this);
}
componentDidMount() {
this.addListener();
// initialize the player }
componentWillUnmount() {
VideoView.emitter.removeAllListeners("video-event");
VideoManager.release();
// release the player
UIManager.dispatchViewManagerCommand(findNodeHandle(this.video), 1, null);
}
pauseRendering() {
this.setState({ pause: true });
}
resumeRendering() {
this.setState({ pause: false });
}
addListener() {
VideoView.emitter.addListener("video-event", (message: string) => {
if (message === "STOP_RENDERING") {
this.pauseRendering();
} else if (message === "START_RENDERING") {
this.resumeRendering();
}
});
}
_onError(event) {
if (!this.props.onErrorMessage) {
return;
}
this.props.onErrorMessage(event.nativeEvent.message);
}
_onStateChange(event) {
if (!this.props.onStateChangeMessage) {
return;
}
this.props.onStateChangeMessage(event.nativeEvent.message);
}
render() {
return (
<RNVideo
style={this.props.style}
ref={(videoView: any) => {
this.video = videoView;
}}
pause={this.state.pause}
/>
);
}
}
VideoView.propTypes = {
...ViewPropTypes
};
const RNVideo = requireNativeComponent("RNVideoView", VideoView, {
nativeOnly: {
pause: true,
onStateChange: true,
onError: true,
}
});
基本上,我正在准备播放器。然后附加它,并且不能立即调整大小,我必须旋转设备或调整视图大小,然后正确更新。
我尝试了许多不同的操作,但现在遇到了麻烦,因此不胜感激
谢谢