Android播放器实现视频窗口实时放大缩小功能

很多开发者希望Android播放端实现视频窗口的放大缩小功能,为此,我们做了个简单的demo,通过播放端回调RGB数据,直接在上层view操作处理即可,Github:https://github.com/daniulive/SmarterStreaming

无视频无真相:http://www.iqiyi.com/w_19s9sa7epp.html

基本流程如下:

1. 基础的初始化和参数设定

        libPlayer = new SmartPlayerJniV2();
        myContext = this.getApplicationContext();
        sSurfaceView = (SurfaceView) this.findViewById(R.id.surface);
        surface_renderer = new RGBSurfaceRenderer(sSurfaceView);

private void InitAndSetConfig() {
        playerHandle = libPlayer.SmartPlayerOpen(myContext);

        if (playerHandle == 0) {
            Log.e(TAG, "surfaceHandle with nil..");
            return;
        }

        libPlayer.SetSmartPlayerEventCallbackV2(playerHandle,
                new EventHandeV2());

        libPlayer.SmartPlayerSetBuffer(playerHandle, playBuffer);

        // set report download speed(默认2秒一次回调 用户可自行调整report间隔)
        libPlayer.SmartPlayerSetReportDownloadSpeed(playerHandle, 1, 2);

        libPlayer.SmartPlayerSetFastStartup(playerHandle, isFastStartup ? 1 : 0);

        //设置RTSP超时时间
        int rtsp_timeout = 10;
        libPlayer.SmartPlayerSetRTSPTimeout(playerHandle, rtsp_timeout);

        //设置RTSP TCP/UDP模式自动切换
        int is_auto_switch_tcp_udp = 1;
        libPlayer.SmartPlayerSetRTSPAutoSwitchTcpUdp(playerHandle, is_auto_switch_tcp_udp);

        libPlayer.SmartPlayerSaveImageFlag(playerHandle, 1);

        // It only used when playback RTSP stream..
        // libPlayer.SmartPlayerSetRTSPTcpMode(playerHandle, 1);

        playbackUrl = "rtmp://202.69.69.180:443/webcast/bshdlive-pc";

        //playbackUrl = "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov";

        libPlayer.SmartPlayerSetUrl(playerHandle, playbackUrl);
    }

2.  设置External Render,回调RGBA数据

libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender());

Log.i(TAG, "Start playback stream++");

                InitAndSetConfig();

                // External Render
                libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender());

                libPlayer.SmartPlayerSetAudioOutputType(playerHandle, 0);

                if (isMute) {
                    libPlayer.SmartPlayerSetMute(playerHandle, isMute ? 1
                            : 0);
                }

                if (isHardwareDecoder) {
                    int isSupportHevcHwDecoder = libPlayer.SetSmartPlayerVideoHevcHWDecoder(playerHandle, 1);

                    int isSupportH264HwDecoder = libPlayer
                            .SetSmartPlayerVideoHWDecoder(playerHandle, 1);

                    Log.i(TAG, "isSupportH264HwDecoder: " + isSupportH264HwDecoder + ", isSupportHevcHwDecoder: " + isSupportHevcHwDecoder);
                }

                libPlayer.SmartPlayerSetLowLatencyMode(playerHandle, isLowLatency ? 1
                        : 0);

                libPlayer.SmartPlayerSetFlipVertical(playerHandle, is_flip_vertical ? 1 : 0);

                libPlayer.SmartPlayerSetFlipHorizontal(playerHandle, is_flip_horizontal ? 1 : 0);

                libPlayer.SmartPlayerSetRotation(playerHandle, rotate_degrees);

                int iPlaybackRet = libPlayer
                        .SmartPlayerStartPlay(playerHandle);

                if (iPlaybackRet != 0) {
                    Log.e(TAG, "Call SmartPlayerStartPlay failed..");
                    return;
                }

                surface_renderer.StartRender();

                btnStartStopPlayback.setText("停止播放 ");

                isPlaying = true;
                Log.i(TAG, "Start playback stream--");

3. 回调RGBA数据:

   class RGBAExternalRender implements NTExternalRender {
        // public static final int NT_FRAME_FORMAT_RGBA = 1;
        // public static final int NT_FRAME_FORMAT_ABGR = 2;
        // public static final int NT_FRAME_FORMAT_I420 = 3;

        private int width_ = 0;
        private int height_ = 0;
        private int row_bytes_ = 0;
        private ByteBuffer rgba_buffer_ = null;

        @Override
        public int getNTFrameFormat() {
            Log.i(TAG, "RGBAExternalRender::getNTFrameFormat return "
                    + NT_FRAME_FORMAT_RGBA);
            return NT_FRAME_FORMAT_RGBA;
        }

        @Override
        public void onNTFrameSizeChanged(int width, int height) {
            width_ = width;
            height_ = height;

            row_bytes_ = width_ * 4;

            Log.i(TAG, "RGBAExternalRender::onNTFrameSizeChanged width_:"
                    + width_ + " height_:" + height_);

            rgba_buffer_ = ByteBuffer.allocateDirect(row_bytes_ * height_);
        }

        @Override
        public ByteBuffer getNTPlaneByteBuffer(int index) {
            if (index == 0) {
                return rgba_buffer_;
            } else {
                Log.e(TAG,
                        "RGBAExternalRender::getNTPlaneByteBuffer index error:"
                                + index);
                return null;
            }
        }

        @Override
        public int getNTPlanePerRowBytes(int index) {
            if (index == 0) {
                return row_bytes_;
            } else {
                Log.e(TAG,
                        "RGBAExternalRender::getNTPlanePerRowBytes index error:"
                                + index);
                return 0;
            }
        }

        public void onNTRenderFrame(int width, int height, long timestamp) {
            if (rgba_buffer_ == null)
                return;

           // rgba_buffer_.rewind();

            // copy buffer

            // test
            // byte[] test_buffer = new byte[16];
            // rgba_buffer_.get(test_buffer);

            //Log.i(TAG, "RGBAExternalRender:onNTRenderFrame w=" + width + " h="
            //        + height + " timestamp=" + timestamp);

            // Log.i(TAG, "RGBAExternalRender:onNTRenderFrame rgba:" +
            // bytesToHexString(test_buffer));

            if ( surface_renderer != null)
            {
                surface_renderer.SetRGBImage(width, height, rgba_buffer_);
            }
        }
    }

4. 对视频view进行放大缩小等状态处理:

        @SuppressLint("ClickableViewAccessibility")
        public RGBSurfaceRenderer(SurfaceView view)
        {
            surface_holder_ = view.getHolder();
            if (surface_holder_ == null)
            {
                Log.e(TAG, "RGBSurfaceRenderer, surfaceHolder with null..");
                return;
            }
            surface_holder_.addCallback(this);

            view.setOnTouchListener(new View.OnTouchListener()
            {
                @Override
                public boolean onTouch(View v, MotionEvent event)
                {
                    Log.e(TAG, "onTouch called..");
                    switch (event.getAction() & MotionEvent.ACTION_MASK) {
                        case MotionEvent.ACTION_DOWN:
                            start_point_.set(event.getX(), event.getY());
                            status_ = DRAG;
                            break;

                        case MotionEvent.ACTION_POINTER_DOWN:
                            float distance = spacing(event);
                            if (distance > 10f) {

                                status_ = ZOOM;
                                start_distance_ = distance;
                            }
                            break;

                        case MotionEvent.ACTION_MOVE:
                            if (status_ == DRAG) {
                                dragAction(event);
                            } else {

                                if (event.getPointerCount() == 1)
                                    return true;
                                zoomAcition(event);
                            }
                            break;
                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_POINTER_UP:
                            status_ = NONE;
                            break;
                        default:
                            break;
                    }

                    return true;
                }
            });

        }

5. 关闭播放:

if (isPlaying) {
                Log.i(TAG, "Stop playback stream++");

                int iRet = libPlayer.SmartPlayerStopPlay(playerHandle);

                if (iRet != 0) {
                    Log.e(TAG, "Call SmartPlayerStopPlay failed..");
                    return;
                }

                surface_renderer.StopRender();

                libPlayer.SmartPlayerClose(playerHandle);
                playerHandle = 0;

                isPlaying = false;
                btnStartStopPlayback.setText("开始播放 ");

                Log.i(TAG, "Stop playback stream--");
            } 

原文地址:https://www.cnblogs.com/daniulivesdk/p/11362781.html

时间: 2024-08-05 13:07:49

Android播放器实现视频窗口实时放大缩小功能的相关文章

github上十二款最著名的Android播放器开源项目

Android第一神器-Xposed框架,堪称黑科技,功能强大! 1.ijkplayer 项目地址:https://github.com/Bilibili/ijkplayer 介绍:Ijkplayer 是Bilibili发布的基于 FFplay 的轻量级 Android/iOS 视频播放器.实现了跨平台功能,API 易于集成:编译配置可裁剪,方便控制安装包大小:支持硬件加速解码,更加省电:提供 Android 平台下应用弹幕集成的解决方案. 2.ExoPlayer 项目地址:https://gi

使用scratch3.0制作《礼佛大忏悔文》播放器及视频

使用scratch3.0制作<礼佛大忏悔文>播放器及视频 缘起 缘起: 拜忏的音乐不能自由定制,做视频和音频处理又很专业,普通人只能望而兴叹. 目的: 由<礼佛大忏悔文>做为因子,通过一个小时的学习,让大家掌握音频.视频的基本制作,能通过软件录制一个自己定制的<礼佛大忏悔文>软件. 推而广之,可以进行<弟子规><岳阳楼记><桃花源记>等等的视频MV的录制. 使用工具: scratch 3.0 下载地址 用于程序生成忏悔文所有动画.音频

用简单的方法,在android上实现手势放大缩小功能

package com.example.eventtest; import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.gesture.GestureOverlayView; import android.gesture.GestureOverlayView.OnGestureListener; import android.graphics.Point; i

鼠标滚轮图片放大缩小功能,使用layer弹框后不起作用

今天在项目中遇到的一个问题:点击按钮使用layer弹框弹出一张图片,需要加一个鼠标滚轮放大缩小,图片也跟着放大缩小的功能.于是在网上找了一个demo. DEMO: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="

android播放器:mediaplayer

近几天的主要问题在于播放器.原来采用的方案最终发现存在问题无法实施,只好临时替换.想起最开始就曾经想用的android提供的VideoView和MediaPlayer组件,开始替换,然后就是一堆问题.网上查到的大部分资料都没有解决问题,无意中搜到这篇文章,感觉还不错的问题总结,希望能帮我解决问题吧,也希望对正在学习的人能有所帮助. 主要内容来自于(原文网址):http://www.boyunjian.com/do/article/snapshot.do?uid=34531852526006352

Android——播放器和图片轮播

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent

[Android]可缩放性ImageView(可以放大缩小)

由于项目需求的原因,最近一直在研究可缩放性ImageView,用本文来记录一下最近所学: 该ImageView的实现功能有: 1)初步打开时,图片按比例满屏(填充ImageView)显示. 2)在放大缩小过程中,可以控制最大放大比例和最小缩小比例. 3)在缩放过程中,若图片的宽或高小于ImageView,则在图片在宽或高居中显示. 4)在放大后,可以移动图片,并且限制好移动的边界,不会超出图片. 5)实现双击放大或缩小的功能.(若当前图片显示为最大的比例则缩小为最小比例,若不是最小比例则放大了最

支持8K播放且低延时高并发全功能的流媒体播放器EasyPlayerPro如何播放H.265视频?

需求分析 一般对于一个播放器,应该支持如下几种显示模式: 等比例,最大化区域显示,不裁剪 等比例,最大区域显示,裁剪 拉伸显示,铺满全屏 要实现这几种显示模式.其实只要对播放控件的布局进行些许调整即可. 那EasyPlayer是怎么实现的呢?EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP.RTMP.HTTP.HLS.UDP.RTP.File等多种流媒体协议播放.支持本地文件播放,支持本地抓拍.本地录像.播放旋转.多屏播放.倍数播放等多种功能特性,核心基于ffmpeg,稳定.高

Chromium为视频标签&lt;video&gt;创建播放器的过程分析

Chromium是通过WebKit解析网页内容的.当WebKit遇到<video>标签时,就会创建一个播放器实例.WebKit是平台无关的,而播放器实现是平台相关的.因此,WebKit并没有自己实现播放器,而仅仅是创建一个播放器接口.通过这个播放器接口,可以使用平台提供的播放器来播放视频的内容.这就简化了Chromium对视频标签的支持.本文接下来就分析Chromium为视频标签创建播放器的过程. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 以And