我的目标是创建一个可以在VideoView
播放列表中播放视频的pre-defined
。
我正在尝试使用MediaPlayer.setNextMediaPlayer(...)
来实现两个视频之间的无缝转换。但是,当第一个视频完成播放时,第二个视频将不会按照文档自动启动。
Xamarin Android代码:
Queue<MediaPlayer> MediaPlayerList = null;
private void PlayVideo()
{
MediaPlayerList = new Queue<MediaPlayer>();
//Let's go ahead and create all media players
VideoView_CurrentVideoView = new VideoView(this);
VideoView_CurrentVideoView.Completion += mVideoView_Completion;
VideoView_CurrentVideoView.Prepared += mVideoView_Prepared;
//Let's prepare all MediaPlayer
for (int i = 0; i < VideoView_CurrentVideoChannel.VideoAssetList.Count; i++)
{
string filePath = FilePath[i];
if (i == 0)
{
VideoView_CurrentVideoView.SetVideoPath(filePath);
VideoContainer.AddView(VideoView_CurrentVideoView);
}
else
{
MediaPlayer mpNew = new MediaPlayer();
mpNew.SetDataSource(filePath);
MediaPlayerList.Enqueue(mpNew);
}
}
VideoView_CurrentVideoView.Start();
}
void mVideoView_Completion(object sender, EventArgs e)
{
MediaPlayer mp = (MediaPlayer)sender;
mp.Release();
}
void mVideoView_Prepared(object sender, EventArgs e)
{
MediaPlayer mp = (MediaPlayer)sender;
//Take the next available MediaPlayer from the queue
MediaPlayer nextMediaPlayer = MediaPlayerList.Dequeue();
//Put the current MediaPlayer at the end of the queue
MediaPlayerList.Enqueue(mp);
nextMediaPlayer.Prepare();
mp.SetNextMediaPlayer(nextMediaPlayer);
}
任何帮助或建议将不胜感激。这是用Xamarin Android
编码的。
更新#1:将.Prepare()移离Prepared()事件后
Queue<string> VideoListQueue = null;
MediaPlayer NextMediaPlayer = null;
private void PlayVideo()
{
string filePath = FilePath[0];
//Create video view
if (VideoContainer.ChildCount == 0)
{
//setup the videoview container
VideoView_CurrentVideoView = new VideoView(this);
VideoView_CurrentVideoView.Info += VideoView_CurrentVideoView_Info;
VideoView_CurrentVideoView.Error += VideoView_CurrentVideoView_Error;
LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.FillParent);
param.LeftMargin = 0;
param.RightMargin = 0;
param.BottomMargin = 0;
param.TopMargin = 0;
VideoView_CurrentVideoView.LayoutParameters = param;
VideoView_CurrentVideoView.LayoutParameters.Width = ViewGroup.LayoutParams.FillParent;
VideoView_CurrentVideoView.LayoutParameters.Height = ViewGroup.LayoutParams.FillParent;
VideoView_CurrentVideoView.Completion += VideoView_CurrentVideoView_Completion;
VideoView_CurrentVideoView.Prepared += VideoView_CurrentVideoView_Prepared;
VideoContainer.AddView(VideoView_CurrentVideoView);
}
VideoView_CurrentVideoView.SetVideoPath(filePath);
VideoView_CurrentVideoView.SeekTo(0);
VideoView_CurrentVideoView.Start();
}
void VideoView_CurrentVideoView_Prepared(object sender, EventArgs e)
{
//Do nothing at this moment
MediaPlayer mp = (MediaPlayer)sender;
}
void VideoView_CurrentVideoView_Completion(object sender, EventArgs e)
{
//GC the finished MediaPlayer
MediaPlayer mp = (MediaPlayer)sender;
mp.Reset();
mp.Release();
mp = null;
//Preparing the next MediaPlayer
MediaPlayer currentPlayer = NextMediaPlayer;
NextMediaPlayer = SetupNextMediaPlayer();
currentPlayer.SetNextMediaPlayer(NextMediaPlayer);
}
MediaPlayer SetupNextMediaPlayer()
{
MediaPlayer mp = new MediaPlayer();
//When the video start playing, let's get ready for next one
string sourceURL = VideoListQueue.Dequeue();
VideoListQueue.Enqueue(sourceURL);
string filePath = sourceURL;
mp = new MediaPlayer();
mp.Info += VideoView_CurrentVideoView_Info;
mp.Completion += VideoView_CurrentVideoView_Completion;
mp.Prepared += VideoView_CurrentVideoView_Prepared;
mp.SetDataSource(filePath);
mp.Prepare();
//Fire back the created MediaPlayer object to the caller
return mp;
}
void VideoView_CurrentVideoView_Info(object sender, MediaPlayer.InfoEventArgs e)
{
Console.WriteLine("What = " + e.What);
switch (e.What)
{
case MediaInfo.VideoRenderingStart:
{
//This is only happening on video first started
NextMediaPlayer = SetupNextMediaPlayer();
e.Mp.SetNextMediaPlayer(NextMediaPlayer);
break;
}
}
}
void VideoView_CurrentVideoView_Error(object sender, MediaPlayer.ErrorEventArgs e)
{
e.Handled = true;
}
此时,媒体播放器将在第一个视频完成后开始播放第二个视频。但是,第二个视频只有声音,没有视频显示。
任何人都知道我做错了什么?我有一种感觉,它必须对未连接到SurfaceView的MediaPlayer做一些事情。但是,我使用VideoView创建了视图,如何从VideoView获取Surface?
答案 0 :(得分:1)
关于仅使用声音播放第二个视频:尝试使用以下方法为每个MediaPlayer实现OnCompletionListener侦听器:
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.setDisplay(null); //for current mediaPlayer
nextMediaPlayer.setDisplay(getHolder()); //for next video
}
});
我无法说这是无间隙的,但不知何故它有效。要归档这个,我不使用标准的VideoView,而是自定义View,它从SurfaceView扩展。
答案 1 :(得分:0)
如果您准备并在.Completion事件上播放下一个媒体播放器怎么办?你试试吗?虽然它可能有一个小延迟
答案 2 :(得分:0)
经过多年的测试,所有硬件都不会出现此问题。例如,我在Nexus7上运行相同的APK,它似乎是无缝的,一切正常。相反,如果我在Amlogic媒体播放器板上运行它,它将呈现上述问题。
我决定关闭这篇文章,结论是它与硬件有关。我知道有人通过在OpenGL中运行所有东西来克服这个限制,但这完全是一个独立的野兽来处理。
<强>结论强>
如果您遇到类似上述问题的问题,那么您无能为力,因为它严重依赖于硬件。