当我播放第二个视频时,只显示第一个视频的冻结帧并播放音频
When I play a second video, only a freezed frame of the first video is shown and the audio plays
我的应用有一个正在播放一秒长视频的片段。播放视频后,用户必须按下按钮,然后才能播放新视频。在播放第二个视频之前,我的主要 activity 加载会创建一个新片段并创建新的 Exoplayer 实例。
我第一次播放视频时一切正常。但是,如果我想播放第二个视频,它会显示第一个视频最后一帧的冻结图像并播放第二个视频的声音。
此错误不会出现在 Android 8(API 级别 26)上,但会出现在 Android 8 以下的版本中(我测试了 Android 6 和 Android 7.1)。
鉴于我同时拥有一个带有新 Fragment 的新 Surface 和一个新的 Exoplayer,这对我来说是个谜,为什么上一个视频的最后一帧仍然有数据。
是否有一些我可以调用的函数来删除该数据并获得我在 Android 8 中获得的行为,其中第二个视频在 Android 的早期版本中也可以正常播放?
在我使用 ExoPlayer 之前,普通的 MediaPlayer 也有同样的问题。我创建了一个 minimized example 我遇到的问题:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mButton = findViewById(R.id.button1);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createNewFragment();
}
});
}
private void createNewFragment() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.contentFragment, new VideoFragment());
ft.commit();
}
}
public class VideoFragment extends Fragment implements SurfaceHolder.Callback{
private Context mContext;
private SimpleExoPlayer mPlayer;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.videolayout, container, false);
SurfaceView mSurfaceView = (SurfaceView) view.findViewById(R.id.surface_view1);
SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
surfaceHolder.setSizeFromLayout();
surfaceHolder.addCallback(this);
mContext = inflater.getContext();
return view;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
mPlayer = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);
mPlayer.setVideoSurfaceHolder(holder);
mPlayer.setPlayWhenReady(true);
playVideo(mContext);
}
private void playVideo(Context context){
final RawResourceDataSource rawResourceDataSource = new RawResourceDataSource(context);
int raw_res_id = context.getResources().getIdentifier(
"collect",
"raw",
context.getPackageName());
DataSpec dataSpec = new DataSpec(RawResourceDataSource.buildRawResourceUri(raw_res_id));
try {
rawResourceDataSource.open(dataSpec);
DataSource.Factory factory = new DataSource.Factory() {
@Override
public DataSource createDataSource() {
return rawResourceDataSource;
}
};
MediaSource media_source = new ExtractorMediaSource.Factory(factory).createMediaSource(rawResourceDataSource.getUri());
mPlayer.prepare(media_source);
} catch (RawResourceDataSource.RawResourceDataSourceException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
尝试为 fragmentchange 执行以下代码
final FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment f = new VideoFragment();
transaction.replace(R.id.contentFragment, f).commit();
只需尝试此代码并检查是否发生相同情况
我的应用有一个正在播放一秒长视频的片段。播放视频后,用户必须按下按钮,然后才能播放新视频。在播放第二个视频之前,我的主要 activity 加载会创建一个新片段并创建新的 Exoplayer 实例。
我第一次播放视频时一切正常。但是,如果我想播放第二个视频,它会显示第一个视频最后一帧的冻结图像并播放第二个视频的声音。 此错误不会出现在 Android 8(API 级别 26)上,但会出现在 Android 8 以下的版本中(我测试了 Android 6 和 Android 7.1)。
鉴于我同时拥有一个带有新 Fragment 的新 Surface 和一个新的 Exoplayer,这对我来说是个谜,为什么上一个视频的最后一帧仍然有数据。 是否有一些我可以调用的函数来删除该数据并获得我在 Android 8 中获得的行为,其中第二个视频在 Android 的早期版本中也可以正常播放?
在我使用 ExoPlayer 之前,普通的 MediaPlayer 也有同样的问题。我创建了一个 minimized example 我遇到的问题:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button mButton = findViewById(R.id.button1);
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createNewFragment();
}
});
}
private void createNewFragment() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.contentFragment, new VideoFragment());
ft.commit();
}
}
public class VideoFragment extends Fragment implements SurfaceHolder.Callback{
private Context mContext;
private SimpleExoPlayer mPlayer;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.videolayout, container, false);
SurfaceView mSurfaceView = (SurfaceView) view.findViewById(R.id.surface_view1);
SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
surfaceHolder.setSizeFromLayout();
surfaceHolder.addCallback(this);
mContext = inflater.getContext();
return view;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
mPlayer = ExoPlayerFactory.newSimpleInstance(mContext, trackSelector);
mPlayer.setVideoSurfaceHolder(holder);
mPlayer.setPlayWhenReady(true);
playVideo(mContext);
}
private void playVideo(Context context){
final RawResourceDataSource rawResourceDataSource = new RawResourceDataSource(context);
int raw_res_id = context.getResources().getIdentifier(
"collect",
"raw",
context.getPackageName());
DataSpec dataSpec = new DataSpec(RawResourceDataSource.buildRawResourceUri(raw_res_id));
try {
rawResourceDataSource.open(dataSpec);
DataSource.Factory factory = new DataSource.Factory() {
@Override
public DataSource createDataSource() {
return rawResourceDataSource;
}
};
MediaSource media_source = new ExtractorMediaSource.Factory(factory).createMediaSource(rawResourceDataSource.getUri());
mPlayer.prepare(media_source);
} catch (RawResourceDataSource.RawResourceDataSourceException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
}
尝试为 fragmentchange 执行以下代码
final FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment f = new VideoFragment();
transaction.replace(R.id.contentFragment, f).commit();
只需尝试此代码并检查是否发生相同情况