美文网首页
Android 使用vlc播放视频

Android 使用vlc播放视频

作者: 怪咖小青年_56e8 | 来源:发表于2021-01-13 12:36 被阅读0次

    我的需求是播放rtsp视频流,最开始用了Android原生播放器MediaPlayer,但是延迟太大了,感觉要将近10秒,而且不能修改缓冲大小,因为底层写死的(根据Android版本设置了固定的缓冲大小),最终用了开源的vlc

    目前项目中使用vlc播放了rtsp视频流,并且有拍照,录制的功能

    使用vlc播放,vlc使用的是3.0.0的版本

    截图和录制需要在aar中加入Android可调用的方法

    需要将aar放到libs文件下,在gradle中配置

    libvlcaar 配置aar

    然后添加依赖
    compile(name:'libvlc-release-3',ext:'aar')

    具体代码实现如下

    final ArrayList args =new ArrayList<>();//VLC参数

    args.add("--rtsp-tcp");//强制rtsp-tcp,加快加载视频速度

    args.add("--aout=opensles");

    args.add("--audio-time-stretch");

    args.add("--sub-source=marq{marquee=\"%Y-%m-%d,%H:%M:%S\",position=10,color=0xFF0000,size=40}");//这行是可以再vlc窗口右下角添加当前时间的

    args.add("-vvv");

    mLibVLC =new LibVLC(this, args);

    mMediaPlayer =new MediaPlayer(mLibVLC);

    Rect surfaceFrame =textureView.getHolder().getSurfaceFrame();

    //设置vlc视频铺满布局

    mMediaPlayer.getVLCVout().setWindowSize(layout_video.getWidth(), layout_video.getHeight());//宽,高  播放窗口的大小

    mMediaPlayer.setAspectRatio(layout_video.getWidth()+":"+layout_video.getHeight());//宽,高  画面大小

    mMediaPlayer.setScale(0);//这行必须加,为了让视图填满布局

    //添加视图

    IVLCVout vout =mMediaPlayer.getVLCVout();

    vout.setVideoView(textureView);

    vout.attachViews();

            Uri uri = Uri.parse(Path.RTSP_URL);//rtsp流地址或其他流地址//"https://media.w3.org/2010/05/sintel/trailer.mp4"

    final Media media =new Media(mLibVLC, uri);

    int cache =10;

    media.addOption(":network-caching=" + cache);

    media.addOption(":file-caching=" + cache);

    media.addOption(":live-cacheing=" + cache);

    media.addOption(":sout-mux-caching=" + cache);

    media.addOption(":codec=mediacodec,iomx,all");

    mMediaPlayer.setMedia(media);//  

    media.setHWDecoderEnabled(false, false);//设置后才可以录制和截屏,这行必须放在mMediaPlayer.setMedia(media)后面,因为setMedia会设置setHWDecoderEnabled为true

    mMediaPlayer.play();

    这样就可以使用vlc播放rtsp视频了

    vlc截图

    String path1 = Environment.getExternalStorageDirectory().getAbsolutePath()+"/" +"wy";//路径最后不用/,vlc会自己补充

    boolean snapshot =mMediaPlayer.getSnapshot(path1);//这个是vlc  arr里面添加的方法

    //通知系統相冊刷新保持的錄屏,拍照后的图片存放在本地相册

    Intent intent =new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

    intent.setData(Uri.fromFile(new File(path1)));

    sendBroadcast(intent);//不添加的话,相册不会更新,手机图库看不到

    vlc 录制

    boolean onvideo =false;//onvideo是否开始录制false是未录制

    String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/" +"wy";

                            if (!onvideo){

    Thread myThread =new Thread(new Runnable() {

    @Override

                                    public void run() {

    Log.d("record_video",Thread.currentThread().getName());

                                        if (!isStopThread) {

                                            onvideo =true;

                                            boolean record =mMediaPlayer.record(path);//此方法是vlc  源码添加的,开始录制

                                            Log.d("record1",record+"");

                                        }

    }

    });

                                myThread.start();

                                    tv_recordvideo.setText(R.string.textvideo);

                            }else {

    onvideo =false;

                                boolean record =mMediaPlayer.record(null);//结束录制,路径传null

                                Log.d("record2",record+"");

                                tv_recordvideo.setText("");

                                //通知系統相冊刷新保持的錄屏

                                        Intent intent1 =new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

                                        intent1.setData(Uri.fromFile(new File(path)));

                                        sendBroadcast(intent1);

                            }

    oppo手机出现不更新画面

    E/libEGL: eglCreateWindowSurfaceTmpl:729 error 3003 (EGL_BAD_ALLOC)

     E/VLC: [c637e3b0/4338] libvlc gl: cannot create EGL window surface

     E/VLC: [c5a38530/4338] libvlc window: request 1 not implemented

     E/VLC: [bf07af30/3829] libvlc video output: video output creation failed

     E/VLC: [c645ee30/3829] libvlc decoder: failed to create video output

     E/VLC: [c637e430/4339] libvlc window: request 1 not implemented

     E/BufferQueueProducer: [SurfaceView - com.example.activity.MainActivity#0] connect: already connected (cur=1 req=1)

    E/libEGL: eglCreateWindowSurface: native_window_api_connect (win=0xc5a8e808) failed (0xffffffea) (already connected to another API?)

    解决方案:

    android:hardwareAccelerated="true"//在清单文件中添加了这行,开启了硬件加速,不报上面的错了

    然而我用华为手机测试没有这个问题。。。。。

    2021.1.25

    使用vlc播放器播放smb远程共享文件中的mp4视频

    Uri uri = Uri.parse(直接传入smb视频地址);

    获取视频长度:

    mMediaPlayer.setEventListener,设置监听

    IMedia media1 =mMediaPlayer.getMedia();

    media1.parseAsync();//这里同步方法拿到的是0,或者-1,我用了异步解决问题

    chapter = (int)mMediaPlayer.getLength();

    mediaplaye.play();//核心代码,在播放前获取视频长度

    mMediaPlayer.setEventListener(new MediaPlayer.EventListener() {

    @Override

                    public void onEvent(MediaPlayer.Event event) {

    //                    Log.d("mMediaPlayer","event.type=="+ event.type);

                        switch (event.type){

    case Opening:

    Log.d("mMediaPlayer","Opening=="+Opening);

    break;

                            case MediaChanged:

    Log.d("mMediaPlayer","MediaChanged=="+MediaChanged);

    break;

                            case  Buffering:

    Log.d("mMediaPlayer","Buffering=="+Buffering);

    break;

                            case  Playing:

    Log.d("mMediaPlayer","Playing=="+Playing);

    break;

                            case  Paused:

    Log.d("mMediaPlayer","Paused=="+Paused);

    break;

                            case  Stopped:

    Log.d("mMediaPlayer","Stopped=="+Stopped);

    break;

                            case  EndReached:

    //                            textureView.setVisibility(View.INVISIBLE);

    //                            network_layout.setVisibility(View.VISIBLE);

    //                            tv_network.setText("网络连接断开,请重试");

                                Log.d("mMediaPlayer","EndReached=="+EndReached);

    break;

                            case  EncounteredError:

    Log.d("mMediaPlayer","EncounteredError=="+EncounteredError);

    break;

                            case  TimeChanged:

    Log.d("mMediaPlayer","TimeChanged=="+TimeChanged);

    break;

                            case  PositionChanged:

    if (isPositionChanged){

    handler.sendEmptyMessageDelayed(2,0);

                                    isPositionChanged =false;

                                }

    Log.d("mMediaPlayer","PositionChanged=="+PositionChanged);

    break;

                            case  SeekableChanged:

    IMedia media1 =mMediaPlayer.getMedia();

                                media1.parseAsync();

                                chapter = (int)mMediaPlayer.getLength();

                                int time =chapter /1000;

                                int miao = time /60;

                                int i1 = time - (miao *60);

                                if (miao<10){

    if (i1<10){

    String i ="0" + miao +":" +"0" + i1;

                                        pb_seek.setMax(chapter /1000);

                                        tv_pro_right.setText(i);

                                    }else if (i1<60){

    String i ="0" + miao +":" + i1;

                                        pb_seek.setMax(chapter /1000);

                                        tv_pro_right.setText(i);

                                    }

    }else if (miao<60){

    if (i1<10){

    String i = miao +":" +"0" + i1;

                                        pb_seek.setMax(chapter /1000);

                                        tv_pro_right.setText(i);

                                    }else if (i1<60){

    String i = miao +":" + i1;

                                        pb_seek.setMax(chapter /1000);

                                        tv_pro_right.setText(i);

                                    }

    }

    Log.d("time",time+"");

    //                            Message message = new Message();

    //                            Bundle bundle = new Bundle();

    //                            bundle.putInt("time",chapter);

    //

    //                            message.setData(bundle);

    //                            handler.sendMessageDelayed(message,0);

                                Log.d("chapter", chapter +"==="+  media1.getDuration()+"==="+mMediaPlayer.getChapter()+"==="+mMediaPlayer.getTime()+"==="+mMediaPlayer.getLength()+"==="+mMediaPlayer.getPosition()+"==="+mMediaPlayer.getTitle());

                                Log.d("mMediaPlayer","SeekableChanged=="+SeekableChanged);

    break;

                            case  PausableChanged:

    Log.d("mMediaPlayer","PausableChanged=="+PausableChanged);

    break;

                            case  LengthChanged:

    Log.d("mMediaPlayer","LengthChanged=="+LengthChanged);

    break;

                            case  Vout:

    Log.d("mMediaPlayer","Vout=="+Vout);

    break;

                            case  ESAdded:

    Log.d("mMediaPlayer","ESAdded=="+ESAdded);

    break;

                            case  ESDeleted:

    Log.d("mMediaPlayer","ESDeleted=="+ESDeleted);

    break;

                            case  ESSelected :

    Log.d("mMediaPlayer","ESSelected=="+ESSelected);

    break;

                            case  RecordChanged:

    Log.d("mMediaPlayer","RecordChanged=="+RecordChanged);

    break;

                        }

    }

    });

                mMediaPlayer.play();

            }catch (Exception e){

    }

    handler中拿到消息设置进度条

    private void setTimer(){

    timer =new Timer();

            timerTask =new TimerTask() {

    @Override

                public void run() {

    if (mMediaPlayer !=null) {

    if (mMediaPlayer.isPlaying()) {

    runOnUiThread(new Runnable() {

    @Override

                                public void run() {

    Log.d("totalTime",totalTime+"");

                                    pb_seek.setProgress(totalTime);

                                    int i =totalTime /60;

                                    if (totalTime <=chapter /1000) {

    int miao =totalTime - (i *60);

                                        if (i <10) {

    if (miao <10) {

    tv_pro_left.setText("0"+i+":0" + miao +"");

                                            }else if (miao <60) {

    tv_pro_left.setText("0"+i+":" + miao);

                                            }

    }else if (i <60) {

    if (miao <10) {

    tv_pro_left.setText(i+":0" + miao +"");

                                            }else if (miao <60) {

    tv_pro_left.setText(i+":" + miao);

                                            }

    }

    }else {

    return;

                                    }

    totalTime =totalTime +1;

                                }

    });

                        }

    }

    }

    };

            timer.schedule(timerTask, 0, 1000);

        }

    我的progress布局

    <androidx.constraintlayout.widget.ConstraintLayout

        app:layout_constraintHorizontal_chainStyle="spread_inside"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:layout_constraintBottom_toBottomOf="parent"

        tools:ignore="MissingConstraints">

            app:layout_constraintHorizontal_weight="1"

            android:layout_marginLeft="@dimen/dp_3"

            android:id="@+id/tv_pro_left"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            app:layout_constraintLeft_toLeftOf="parent"

            android:text="00:00"/>

            style="?android:attr/progressBarStyleHorizontal"

            android:layout_gravity="center_horizontal"

            android:layout_marginTop="10dp"

            app:layout_constraintHorizontal_weight="4"

            android:id="@+id/pb_seek"

            app:layout_constraintRight_toLeftOf="@id/tv_pro_right"

            app:layout_constraintLeft_toRightOf="@id/tv_pro_left"

            android:layout_width="@dimen/dp_300"

            android:layout_height="wrap_content"

            tools:ignore="MissingConstraints" />

            app:layout_constraintHorizontal_weight="1"

            android:layout_marginRight="@dimen/dp_3"

            app:layout_constraintRight_toRightOf="parent"

            android:id="@+id/tv_pro_right"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="00:00"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

    效果图:

    效果图

    在activity中关闭资源,避免oom

    private void cancelTimer(){

    if (timer !=null) {

    timer.cancel();

            timer =null;

        }

    if (timerTask !=null) {

    timerTask.cancel();

            timerTask =null;

        }

    }

    public void releasePlayer() {

    // mMediaPlayer.setVideoCallback(null, null);

        if (mMediaPlayer!=null){

    mMediaPlayer.stop();

            mMediaPlayer.setEventListener(null);

        }

    if (vout!=null){

    vout.detachViews();

      }

    if (mLibVLC!=null){

    mLibVLC.release();

            mLibVLC =null;

        }

    }

    目前还有一个问题,就是录制视频的时候要讲当前时间录制进去,我的vlc窗口已经添加了时间,知道的大神可以告知一下。

    相关文章

      网友评论

          本文标题:Android 使用vlc播放视频

          本文链接:https://www.haomeiwen.com/subject/vbjuaktx.html