Android MediaPlayer setNextMediaPlayer无法正常工作

时间:2014-08-19 05:36:20

标签: android xamarin xamarin.android android-mediaplayer android-videoview

我的目标是创建一个可以在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?

3 个答案:

答案 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中运行所有东西来克服这个限制,但这完全是一个独立的野兽来处理。

<强>结论

如果您遇到类似上述问题的问题,那么您无能为力,因为它严重依赖于硬件。