效果图

先上一个效果图:

背景

公司最近在做VR直播平台,VR开发我们用到了Unity,而在Unity中播放视频就需要一款视频插件,我们调研了几个视频插件,记录两个,如下:

Unity视频插件调研

网上搜了搜,最流行的有以下两款Unity插件:

  • AVPro 这个在Unity商店售价150$,最新release版本为1.6.15,功能包括:

Powerful cross-platform video playback solution for Unity.

Native video playback on Android, iOS, macOS and tvOS (Apple TV), WebGL, Windows, Windows Phone and UWP.

Features include:

  • New Unity 2017 supported
  • New New iOS video playback path that uses less memory
  • One API for video playback on all supported platforms
  • Unity 4.6 - 5.x supported
  • 8K video (on supported hardware)
  • VR Support (mono, stereo, equirectangular and cubemap)
  • Transparency support (native and packed)
  • Subtitles support (external SRT)
  • Fast flexible video playback
  • In-editor playback support for Windows and macOS
  • Free watermarked trial version available
  • Components for IMGUI, uGUI and NGUI
  • Over 64 PlayMaker actions included
  • Easy to use drag and drop components
  • Linear and Gamma colour spaces supported
  • Fast native Direct3D, OpenGL and Metal texture updates
  • Desktop support for Hap, Hap Alpha, Hap Q and Hap Q Alpha
  • Streaming video from URL (when supported by platform)

此插件支持HLS视频播放,使用文档很详细,但是此插件没有源码,不适合做以后的个性化开发。

  • 鼎鼎大名的EasyMovieTexture.售价65$,支持功能如下:

Supported resolutions:

  • Android: General devices support up to 1920 * 1080.
    The latest device supports up to 4k.
  • iOS: General devices support up to 1920 * 1080.
    The latest device is support up to 2560 * 1440.
    iPhone 6s Plus supports up to 4k.
  • It also supports StreamingAssets, external storage, and streaming services.
  • Android streaming support list: http, HLS (http live streaming),rtsp
  • iOS streaming support list: http,HLS (http live streaming)
  • EasyMovieTexture requires Android 4.0 or above.
  • EasyMovieTexture requires iOS 6.0 or Above.
  • Unity 4.X requires an iOS Pro.
  • In Unity 5.X it does not require a Pro.
  • Supports multithreaded rendering options. (Only supports Unity 5.X.)

这个插件貌似是个人开发的,没有说明文档,有部分java源码,native code并没有给出。我们需要有源码的插件方便以后的个性化开发。

自己动手,风衣足食

综合以上调研结果,我们决定自己动手实现一个简单能满足我们要求的Unity播放器插件,有两个难点要突破:

  • 一个是找一个合适的开源播放器。
  • 另一个就是如何把播放视频画面映射到Unity中的物体表面,这个是最关键的。

寻找素材

从下面这个帖子中,找到了一些可以参考的资料。

unity 3d 中如何实现以物体的表面作为播放视频的位置,比如在墙面播放视频?

寻找开源播放器

本来打算使用VLC播放器的,但是同事发现有一个商用的开源播放器,并且使用的人数也不少,B站的ijkplayer。正好在上面的帖子中回复人也提到了这个播放器,我们决定使用这个播放器。

如何做视频画面映射

没有一点Unity开发经验,只能从头一点点学起,知乎的帖子里面,有个人回复可以参考OVR里面的例子。阅读了里面的代码,同时也参考了easyMovieTexture中的源码(easyMovie中只有java代码,关键的native code并没有给)。看的有些似懂非懂,尝试了之后,居然成功了。

最关键的一点我描述成下面的话:

将Ijkplayer的AndroidSurfaceTexture纹理ID和Unity中Texture2D的纹理ID分别同时绑定到不同的目标上。AndroidSurfaceTexture绑定到GL_TEXTURE_EXTERNAL_OES,Unity的纹理ID绑定到GL_TEXTURE_2D

从头到尾梳理一遍流程

初始化

  • Unity

Unity端初始化一个Texture2D纹理ID用于显示视频帧。

m_VideoTexture = new Texture2D (Call_GetVideoWidth (), Call_GetVideoHeight (), TextureFormat.RGB565, false);
  • OVR

这里使用了OVR里面的native code,OVR中初始化AndroidSurfaceTexture和相关的函数:

static const char * className = "android/graphics/SurfaceTexture";const jclass surfaceTextureClass = jni->FindClass(className);if ( surfaceTextureClass == 0 ) {FAIL( "FindClass( %s ) failed", className );}// find the constructor that takes an intconst jmethodID constructor = jni->GetMethodID( surfaceTextureClass, "<init>", "(I)V" );if ( constructor == 0 ) {FAIL( "GetMethodID( <init> ) failed" );}jobject obj = jni->NewObject( surfaceTextureClass, constructor, textureId );if ( obj == 0 ) {FAIL( "NewObject() failed" );}javaObject = jni->NewGlobalRef( obj );if ( javaObject == 0 ) {FAIL( "NewGlobalRef() failed" );}// Now that we have a globalRef, we can free the localRefjni->DeleteLocalRef( obj );updateTexImageMethodId = jni->GetMethodID( surfaceTextureClass, "updateTexImage", "()V" );if ( !updateTexImageMethodId ) {FAIL( "couldn't get updateTexImageMethodId" );}getTimestampMethodId = jni->GetMethodID( surfaceTextureClass, "getTimestamp", "()J" );if ( !getTimestampMethodId ) {FAIL( "couldn't get getTimestampMethodId" );}setDefaultBufferSizeMethodId = jni->GetMethodID( surfaceTextureClass, "setDefaultBufferSize", "(II)V" );if ( !setDefaultBufferSizeMethodId ) {FAIL( "couldn't get setDefaultBufferSize" );}// jclass objects are localRefs that need to be freedjni->DeleteLocalRef( surfaceTextureClass );

初始化纹理ID,并将其绑定到目标GL_TEXTURE_2D上:

glGenTextures( 1, &textureId );glBindTexture( GL_TEXTURE_EXTERNAL_OES, textureId );glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR );glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR );glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );glTexParameterf( GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );glBindTexture( GL_TEXTURE_EXTERNAL_OES, 0 );

将Unity的纹理ID传递到OVR中,用于绑定到目标GL_TEXTURE_EXTERNAL_OES上:


jobject OVR_Media_Surface( void * texPtr, int const width, int const height )
{GLuint texId = (GLuint)(size_t)(texPtr);LOG( "OVR_Media_Surface(%i, %i, %i)", texId, width, height );return _msp.VideoSurface.Bind( texId, width, height );
}
  • Ijkplayer

创建一个播放器,注意这里我们使用OVR中已经实例化的AndroidMovieTexture来初始化播放器。

 m_IjkMediaPlayer.setSurface(m_Surface);

刷新

刷新操作由Unity中的Update函数触发,最终在OVR中执行,首先调用AndroidMovieTexture中的Update函数,接下来就是绑定纹理操作,Ijkplayer的纹理ID每刷新一次绑定一次。而Unity的纹理ID只有在视频图像长度或者宽度发生变化才会绑定。

void MediaSurface::Update()
{if ( !AndroidSurfaceTexture ){LOG( "!AndroidSurfaceTexture" );return;}if ( TexId <= 0 ){//LOG( "TexId <= 0" );return;}AndroidSurfaceTexture->Update();if ( AndroidSurfaceTexture->GetNanoTimeStamp() == LastSurfaceTexNanoTimeStamp ){//LOG( "No new surface!" );return;}LastSurfaceTexNanoTimeStamp = AndroidSurfaceTexture->GetNanoTimeStamp()// If the SurfaceTexture has changed dimensions, we need to// reallocate the texture and FBO.glActiveTexture( GL_TEXTURE0 );glBindTexture( GL_TEXTURE_EXTERNAL_OES, AndroidSurfaceTexture->GetTextureId() );if ( TexIdWidth != BoundWidth || TexIdHeight != BoundHeight ){LOG( "New surface size: %ix%i", BoundWidth, BoundHeight );TexIdWidth = BoundWidth;TexIdHeight = BoundHeight;if ( Fbo ){glDeleteFramebuffers( 1, &Fbo );}glActiveTexture( GL_TEXTURE1 );glBindTexture( GL_TEXTURE_2D, TexId );glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA,TexIdWidth, TexIdHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );glBindTexture( GL_TEXTURE_2D, 0 );glActiveTexture( GL_TEXTURE0 );glGenFramebuffers( 1, &Fbo );glBindFramebuffer( GL_FRAMEBUFFER, Fbo );glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,TexId, 0 );glBindFramebuffer( GL_FRAMEBUFFER, 0 );}
}

最后的结果可能是这个样子的:Ijkplayer负责推动视频不停向前播放,播放器的纹理也会不停刷新,这会带动Unity纹理跟着刷新,最终显示在Unity的Material上。

作者: HarlanC

博客地址: http://www.cnblogs.com/harlanc/
个人博客: http://www.harlancn.me/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接

如果觉的博主写的可以,收到您的赞会是很大的动力,如果您觉的不好,您可以投反对票,但麻烦您留言写下问题在哪里,这样才能共同进步。谢谢!

记录一款Unity VR视频播放器插件的开发相关推荐

  1. 【Unity3D自学记录】制作VR视频播放器

    最近VR火的不要不要的,但是综合起来,VR资源最多的还是全景图片和全景视频,今天在这里给大家简单介绍一下如何用Unity制作简单的VR视频播放器. 首先找到EasyMovieTexture这个插件,A ...

  2. 基于uni-app开发的一款视频播放器插件

    yy-video-player 基于uni-app开发的一款视频播放器插件,开箱即用,具有视频下载,页面返回,弹幕,进度条等功能. 插件地址:https://ext.dcloud.net.cn/plu ...

  3. 关于Unity视频播放器插件 AVPro Video(二)3D物体上视频播放

    1.官网下载该插件或者我分享的链接: 链接:https://pan.baidu.com/s/1boGeJ8r 密码:mvbf 2.新建项目创建主要控制物体 3.创建对于视频播放在3D物体身上的材质 4 ...

  4. html5播放器 迅雷,搜狗浏览器HTML5视频播放器插件(HTML5.Video.Player)

    一款搜狗浏览器的HTML5视频播放器插件,安装后可以使用HTML5方式播放优酷.土豆.爱奇艺.搜狐视频.迅雷离线.腾讯视频.56视频等网站的视频,避免使用adobe flash player插件,降低 ...

  5. 适配手机VR眼镜的VR视频播放器种类大全

    随着移动终端的普及和VR市场的快速发展,越来越多的资本盯上了手机端VR内容的打造,希望在VR行业占领自己的半壁江山,现在也有越来越多的VR视频播放器,今天小九就为大家带来几个适配手机VR眼镜的VR视频 ...

  6. Android 全景视频播放器(VR视频播放器探索)

    最近VR相关的新闻都刷爆了.淘宝也即将发布vr 购物 buy++.即使现在已经有太多针对虚拟现实(VR)的炒作,但这一行业仍处于初期阶段.资源少之又少,即使有,现在也不会开源的.所以对于我们这种打算要 ...

  7. android vr视频播放器,VR视频播放器(VR Player)使用教程

    现在拥有VR虚拟现实眼镜的小伙伴越来越多,可VR视频资源并不多.有什么办法可以将普通视频转换成左右分屏的3D视频呢?今天魅族溜小编带来一款非常强大的VR视频播放器及使用教程,下面一起看看吧! 1.首先 ...

  8. Android 全景视频播放器(VR视频播放器探索二)

        上次随便写着玩的  http://blog.csdn.net/ai_yong_jie/article/details/51159367   Android 全景视频播放器(VR视频播放器探索一 ...

  9. web player html5源码,GitHub - WEBHH/DanmuPlayer: Html5弹幕视频播放器插件

    DanmuPlayer ##Html5弹幕视频播放器插件 Danmmu Player是一个具备弹幕功能的Html5视频播放器. 具备弹幕视频播放,接受用户发送彩色弹幕,实时调解弹幕显示效果等功能. D ...

最新文章

  1. RFC2616中文版(9)方法定义
  2. 5 关于数据仓库维度数据处理的方法探究系列——缓慢变化维处理——全历史记录...
  3. MySQL常用简单小命令
  4. php自定义中文分词方法,PHPAnalysis中文分词类详解
  5. 1262. 可被三整除的最大和(贪心||动态规划)
  6. [Codevs] 1004 四子连棋
  7. Python笔记-对字符串进行URL编码及解码
  8. Ubuntu 10.04编译安装insigh-6.8-1
  9. linux java服务,在Linux上运行Java应用程序即服务
  10. python下载docx模块_怎么下载python-docx模块
  11. 阿里程序员常用的15款开发者工具
  12. linux 密码输入回显星号
  13. python 求偏导数 调用偏导数函数的输入
  14. 百度重度依赖者谈谈恶意点击
  15. 记一次线上微信公众号迁移遇到的坑
  16. 学习php开发难吗,PHP开发自学难吗,PHP自学要多长时间?
  17. 喜迎国庆-好礼大放送
  18. python 判断字符串是否是纯中文或者英文
  19. 如何查看电脑端口占用
  20. Bugku Misc 我永远喜欢穹妹

热门文章

  1. 风景类Midjouney prompt提示词
  2. Spring实战(第四版)读书笔记08——处理自动装配的歧义性
  3. golang的GJSON库
  4. IO流如何选择字节流和字符流??
  5. 如何证明服从卡方分布_为什么(n-1)s^2/σ^2服从自由度为n-1卡方分布?
  6. 简单3dsmax城堡
  7. 一文搞懂AVB的使用
  8. CentOS下安装无线网卡驱动
  9. 模糊聚类分析和模式识别
  10. 中职计算机应用基础教案1,中职计算机应用基础教案