VideoView可以在不停止流的情况下分离和重新连接吗?

Thi*_*Roy 13 android ffmpeg vitamio android-videoview

我正在构建一个应用程序,用户点击按钮以全屏显示视频.最初,视频附加到ViewPager内的视图.为了能够全屏显示,我将其与父项分离,并将其重新连接到根视图.这种方法很好,除非在播放时将视频切换为全屏.当我分离播放VideoView时,它只是停止,我需要重新启动它.这是不可接受的,因为视频在恢复之前开始缓冲.这里是完成分离的代码部分:

    final ViewGroup parent = (ViewGroup) findViewById(R.id.parent);

    final ViewGroup root = (ViewGroup) findViewById(R.id.root);

    Button b = (Button) findViewById(R.id.button);
    b.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            parent.removeView(mVideoView);

            LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
            root.addView(mVideoView, lp);
        }
    });
Run Code Online (Sandbox Code Playgroud)

根据设备,我有一个不同的日志错误.可能是因为实际的视频播放器是由制造商提供的,而不是Android SDK.以下是Nexus 7的错误日志:

10-30 20:26:18.618: D/NvOsDebugPrintf(124): NvMMDecTVMRDestroyParser Begin 
10-30 20:26:18.618: D/NvOsDebugPrintf(124): --------- Closing TVMR Frame Delivery Thread -------------
10-30 20:26:18.678: D/NvOsDebugPrintf(124): ------- NvAvpClose -------
10-30 20:26:18.678: D/NvOsDebugPrintf(124): NvMMDecTVMRDestroyParser Done 
10-30 20:26:18.678: D/NvOsDebugPrintf(124): NvMMLiteTVMRDecPrivateClose Done 
Run Code Online (Sandbox Code Playgroud)

我无法在不停止的情况下分离视频.我尝试使用SurfaceView或TextureView但没有成功.

我也尝试过寻找第三方视频播放器.我发现了一个商业原因(http://www.vitamio.org/),我出于商业原因无法真正使用它.我找到了一个开源的,去年没有更新过(https://code.google.com/p/dolphin-player/).

我目前只在平板电脑上定位Android 4.2或更高版本.


请注意,ViewPager不是全屏.所以我不能使用LayoutParams来制作全屏视频.我需要从ViewPager中的父级删除VideoView并将其添加到根视图以便能够全屏显示.

我正在测试的网址:http://bellvps1.cpl.delvenetworks.com/media/e1b3e24ecb944abd8f4ed823a0b76ddc/68f78d35296243bfb46d2418f03f2fd0/bande-annonce---the-secret-life-of-walter-mitty-1-9efcc5c6e52ac07a3edf84a1b21967995b7796a2.m3u8

woo*_*oot 12

使用a可以实现这种效果TextureView.基本上你要做的是创建一个MediaPlayer实例,prepare()然后启动()它,然后你可以使用MediaPlayer.setSurface()任何方法在TextureView视频播放时改变表面而不改变MediaPlayer对象状态,如android的setSurface()方法文档中所述:

This method can be called in any state and calling it does not change the object state.

请注意这个实现是为了演示,您应该使用mediaplayer.prepareAsync()并等待回调onPreparedListener(),您还需要TextureView根据您的视频大小设置正确的尺寸,处理方向更改,当然还可以在任何地方正确处理异常需要.

activity_main.xml中:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:background="#ff0000" />

    <Button
        android:id="@+id/btn"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="bottom|center_horizontal"
        android:text="Switch to second surface" />

    <TextureView
        android:id="@+id/tv_full"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>
Run Code Online (Sandbox Code Playgroud)

MainActivity.java

public class MainActivity extends Activity {
    private static final String VIDEO_URI = "http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4";

    private TextureView tvFull;
    private MediaPlayer mp;

    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mp = new MediaPlayer();
        try {
            mp.setDataSource(this, Uri.parse(VIDEO_URI));
            mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mp.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ((ViewPager) findViewById(R.id.pager)).setAdapter(new PagerAdapter() {
            @Override public int getCount() {
                return 1;
            }

            @Override public boolean isViewFromObject(View view, Object o) {
                return view == o;
            }

            @Override public Object instantiateItem(ViewGroup container, int position) {
                final TextureView tv = new TextureView(MainActivity.this);

                tv.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
                    @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
                        tv.setSurfaceTextureListener(null);
                        mp.setSurface(new Surface(surfaceTexture));
                        mp.start();
                    }

                    @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {}

                    @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
                        return false;
                    }

                    @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {}
                });

                if (tv.isAvailable()) {
                    tv.getSurfaceTextureListener().onSurfaceTextureAvailable(tv.getSurfaceTexture(),
                            tv.getWidth(), tv.getHeight());
                }

                container.addView(tv, 0);
                return tv;
            }

            @Override public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }
        });

        tvFull = (TextureView) findViewById(R.id.tv_full);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override public void onClick(View view) {
                tvFull.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
                    @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
                        tvFull.setSurfaceTextureListener(null);
                        mp.setSurface(new Surface(surfaceTexture));
                    }

                    @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {

                    }

                    @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
                        return false;
                    }

                    @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

                    }
                });

                if (tvFull.isAvailable()) {
                    tvFull.getSurfaceTextureListener().onSurfaceTextureAvailable(tvFull.getSurfaceTexture(),
                            tvFull.getWidth(), tvFull.getHeight());
                }
            }
        });
    }

    @Override protected void onDestroy() {
        mp.reset();
        mp.release();

        super.onDestroy();
    }
}
Run Code Online (Sandbox Code Playgroud)