在线视频功能所需修改

在线视频所需修改


背景


Android平台的视频框架是在(Vitamio)框架的基础上实现的。基于此框架产品实现了视频播放功能。

目前产品的video库支持俩种位置的资源加载:

 1. 本地视频资源
 2. ewp服务器视频资源

需要增加在线视频的加载:

 1. 外网的url地址
 2. ewp的url地址

产品代码的分析


当报文存在video:load("video.mp4"); 加载视频的脚本时,首先会初始化一个com.rytong.emp.gui.video.AndroidVideoPlayer视频播放器,并对需要加载视频地址的进行处理:

if (mPath.startsWith("/")) {
            String sourceUrl = EMPConfig.newInstance().getServerUri().concat(mPath);// 下载地址
            mPath = mPath.substring(mPath.lastIndexOf("/") + 1, mPath.length());
            mPath = mResources.downloadAndSaveFile(sourceUrl, mPath);
            source = mPath;
        } else if(mPath.startsWith("http://")){
            // DoNothing for Now
        } else {
            source = mResources.getLocalFilePath(mPath);
        }

由此代码可以看出,以http://开头的视频没做处理。只是对ewp服务器的视频地址以及本地视频地址进行加载。

private void setVideoSource(VideoView video, Object source) {
//对ewp服务器和本地视频地址分别处理之后,把得到的文件地址或者AssetFileDescriptor/FileDescriptor加载到VideoView上。
        if (source instanceof String) {

            video.setVideoPath((String) source);
        } else {

            FileDescriptor file = null;
            long startoffset = 0;
            long length = 0;
            if (source instanceof AssetFileDescriptor) {

                AssetFileDescriptor descriptor = (AssetFileDescriptor) source;
                file = descriptor.getFileDescriptor();
                startoffset = descriptor.getStartOffset();
                length = descriptor.getLength();
            } else if (source instanceof FileDescriptor) {

                file = (FileDescriptor) source;
            }
            if (file == null) {

                return;
            }
            video.setVideoFileDescriptor(file, startoffset, length);
        }
    }

所需要的修改


根据对产品代码的分析,实现对外网在线视频地址的加载,我们只需要在mPath.startsWith("http://") 的判断中做一些处理即可。

else if(mPath.startsWith("http://")){
            // 得到视频地址为后续加载使用
            source = mPath;
        }

实现对在线播放ewp服务器视频避免下载视频时需要做如下修改:

if (mPath.startsWith("/")) {
            String sourceUrl = EMPConfig.newInstance().getServerUri().concat(mPath);// 拼接后的视频地址,并且是以http://开头的

            source = sourceUrl;//保留拼接后的url地址
        } 

加载视频的时候做如下处理:

if (source instanceof String) {

    if(source.toString().startsWith("http://")){
            video.setVideoURI(Uri.parse(source.toString()));

    }else{
            video.setVideoPath((String) source);
    }
}

在线视频边下边播所需修改


实现此需求网络请求需要使用实时的流媒体传输协议,而最真实的流媒体协议传输格式并不是普通的http方式,而是rtsp,那样的话得搭建专门的流媒体服务器,成本比较高,采用普通的http方式,实现的是一种伪流媒体传输,但是对于常用的视频缓存播放也足够了。原理比较简单,就是把视频加载了一段后,就送到播放器播放,如果出现了错误,则优先缓存一部分文件,然后再继续播放,类似的处理过程循环往复。

if (source instanceof String) {
            if(source.toString().startsWith("http://")){
                //不现在直接播放,此处先注释掉
//              video.setVideoURI(Uri.parse(source.toString()));
                //伪流媒体传输处理方式
                remoteUrl = source.toString();
                mAndroidGUIFactory.mEMPRender.runTask(new EMPThreadPool.Task(100) {
                    @Override
                    public void doRun() throws Exception {
                        FileOutputStream out = null;
                        InputStream is = null;

                        try {
                            //应用系统方式处理网络链接
                            URL url = new URL(remoteUrl);
                            HttpURLConnection httpConnection = (HttpURLConnection) url
                                    .openConnection();
                            //预缓存文件的地址
                            if (localUrl == null) {
                                localUrl = Environment.getExternalStorageDirectory()
                                        .getAbsolutePath()
                                        + "/VideoCache/"
                                        + System.currentTimeMillis() + ".mp4";
                            }

                            System.out.println("localUrl: " + localUrl);

                            File cacheFile = new File(localUrl);
                            if (!cacheFile.exists()) {
                                cacheFile.getParentFile().mkdirs();
                                cacheFile.createNewFile();
                            }
                            readSize = cacheFile.length();
                            System.out.println("readSize1: " + readSize);
                            out = new FileOutputStream(cacheFile, true);
                            httpConnection.setRequestProperty("User-Agent", "NetFox");
                            httpConnection.setRequestProperty("RANGE", "bytes="
                                    + readSize + "-");
                            is = httpConnection.getInputStream();
                            mediaLength = httpConnection.getContentLength();
                            if (mediaLength == -1) {
                                return;
                            }
                            mediaLength += readSize;//得到可以播放的大小
                            System.out.println("mediaLength: " + mediaLength);
                            byte buf[] = new byte[4 * 1024];
                            int size = 0;
                            long lastReadSize = 0; 
                            while ((size = is.read(buf)) != -1) {
                                try {
                                    out.write(buf, 0, size);
                                    readSize += size;
                                    System.out.println("readSize2: " + readSize);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                                //预缓存是否结束
                                if (!isready) {
                                    if ((readSize - lastReadSize) > READY_BUFF) {
                                        lastReadSize = readSize;
                                        video.setVideoPath(localUrl);
                                        isready = true;
                                    }
                                } else {
                                    //结束预缓存后,每次播放交换缓存的数据,遇到错误,缓存区动态扩展
                                    if ((readSize - lastReadSize) > CACHE_BUFF
                                            * (errorCnt + 1)) {
                                        lastReadSize = readSize;
                                        video.setVideoPath(localUrl);
                                    }
                                }
                            }
                            video.setVideoPath(localUrl);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            if (out != null) {
                                try {
                                    out.close();
                                } catch (IOException e) {
                                }
                            }
                            if (is != null) {
                                try {
                                    is.close();
                                } catch (IOException e) {
                                    //
                                }
                            }
                        }
                    }
                    });
                }else{
                    video.setVideoPath((String) source);
                }
        } 

存在的问题


上述针对在线视频播放所作的修改,在网络请求方面都是通过系统的方法处理的 。访问ewp服务器没有利用产品的网络请求方式,客户端与服务器没有建立加密信道,请求和返回的数据也没有做加解密处理。这是因为通过网络请求得到的视频数据是Byte类型的,而系统加载视频的方法只支持FileDescriptor,string(文件路径) ,uri 三种类型。而系统对这三种类型处理是native方法。如果要实现直接播放byte数据的话,需用C/C++语言,会涉及一些网络协议和视频编码格式的问题 。存在一定难度,需要进一步研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值