版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于android系统的Niconico影视播放器设计1.引言 11.1设计的目的及意义 11.2国内外研究现状 11.3视频播放器概述 32.系统使用的主要技术 32.1android多媒体系统介绍 32.2android平台 42.3Android的四大组件 42.4开发工具Eclipse 42.5Android架构 42.6Eclipse上Android环境的搭建 52.7OpenCore多媒体框架简介 63.播放器结构 63.1文件列表界面 63.2控制菜单 63.3Toast模块 73.4Mediaplayer视频技术 73.5小结 84.系统分析 84.1系统可行性分析 84.2系统需求分析 95.系统实现 105.1系统设计 105.2用户登录注册 125.3视频播放实现 155.4系统展示 25结论 28参考文献 28摘要:随着android系统的广泛使用,大多数用户要求使用用户界面友好和个性化的视频播放器。由此实现了一款音乐视频播放器,采取Android系统技术,并利用了Java语言。给出了细致的系统设计过程。视频播放器具有暂停,播放,后退和快进等功能。它具有优异的性能,可以在Android系统中单独运行。具体介绍和解析程序的最首要活动,包含详细介绍程序运用的结构文件和每个控件的角色。然后,测试该程序并测试了模块性能的实现,并且包含大量屏幕截图以展现测试成果,并识别程序中可能出现的问题。开发的程序界面友好,相对简单,符合设计要求。关键词:安卓视频播放ActivityMediaplayer引言1.1设计的目的及意义今天的科学技术正在迅速增长,有各种程序,视频通话,VOD视频,在线波,在线阅读和数据。为了实现这样的应用,愈来愈多的手机功能是智能的,表明移动互联网已进入新的时代。新时代的到来也需要一个强大的发展平台来支持。因此,操作系统和智能手机技术的研究已成为最活跃的领域之一。由于安卓的开放性,目前安卓系统已经应用到智能终端上。视频播放器是人们日常使用的重要软件。设计的基于安卓系统的Niconico视频播放器安装在安卓终端上。应用程序具有适当的播放接口,可以从系统数据库中读取相应的视频信息、视频格式可以自动随屏幕大小切换视频比例。许多企业和个人用安卓开发视频播放器,其中moboplayer、RockPlayer、realPlayer、VPlayer等深受用户喜爱。但是,目前许多播放器功能复杂,形式多样,消耗大量内存,广告嵌入过多,用户无法获得良好的用户体验,因此需要开发功能全面、简单易用的视频播放器。操作强大的解码能力。由此可见,安卓平台将对app手机行业和境外手机平台产生巨大影响,在未来几年,安卓本身的重要性将变得更加为人所知[1]。1.2国内外研究现状常用的播放器有,Xmovie,Mplayer,QuickTime,Mplayer,Xmms,RealPlayer。1.X-Window是一种常用的计算机操作系统,配备有Xmms播放器。Xmms附带少量视频、音频多媒体文件供播放。但这不符合用户的要求。因此,开发人员还开发了许多插件。使用这些Xmms插件,可以支持以更大的格式播放多媒体文件。2.Xmovie经常在电视节目中使用。电视节目的要求一般比较简单,只要求最基本的功能。恰好Xmovie的播放界面也很简单。用Xmovie玩只能看到基本的快进、倒退、播放键。Xmovie的功能和界面一样简单,主要控制一些环境变量,和一些环境变量。许多人认为Xmovie不应该只播放音频,因为它用于电视广播,但实际上Xmovie不仅可以让视频图片播放,mp3音频也可以进行播放。3.RealPlayer可减少低带宽传输过程中的数据丢失。RealPlayer还可以在在线播放流媒体时保持平稳、快速的传输。RealPlayer在Linux和window平台上提供,旨在方便用户使用。开发者有意设置接口的基本一致性。在随后的RealPlayer更新中,添加了一些新功能,以提高RealPlayer的知名度。它不仅可以播放Microsoft视频,还可以播放音频文件。此外还添加了一个便携式接口。4.QuickTime主要是为流媒体文件设计的。QuickTime主要分为三个模块:文件格式、媒体抽象和内置媒体服务。使用QuickTime时,有一个播放器同名,名为QuickTime。QuickTime的文件名后缀通常是.mov。5.作为专业的电影播放器,Mplayer可以播放大多数视频文件。在linux上普遍使用。另一方面,Mplayer可以作为本地解码器播放电影,而且可以播放SVCD、DVD等形式的电影,还可以播放OGG、VOB等文件。另一方面,Mplayer可以作为播放器在各种条件下工作。Xmms、Xmovie、QuickTime等播放器虽然功能强大,但只能满足一些固定格式。但现在,这种多样的社会播放器也有多样化的趋势。这些已经不适合我们了。随着消费者群体的增长、视频的广泛多样性和越来越多的音频格式,用户的需求越来越大。原来的播放器已经不适应当前的社会群体了。播放器尽可能多地播放音频和视频是当前的研究方向。并且考虑到以后还会出现不同的格式,需要保留扩展当前播放器的能力。同时,用户体验也非常重要,也非常关注如何在现有基础上使功能更加全面。本文主要研究基于Android的在线音乐播放器系统的设计与实现。在系统的设计和实现中,系统主要分为这几个模块:音乐下载模块,用户列表模块,音乐检索模块,音乐分类模块,播放控制模块。本文的主要内容有:(1)收集国内外Android技术的发展和开发本系统的意义。(2)Android相关技术的概述和环境的构建。(3)从几个不同的方面分析系统的需求和可行性。(4)介绍系统的模块划分和功能。(5)上一章的模块设计比较详细。(6)介绍系统各模块的实现过程。(7)系统实现后,介绍系统测试中的一些方法和测试过程2Android开发技术介绍。1.3视频播放器概述本项目以Java语言为基础开发嵌入式播放器。它具有轻巧、节省空间但功能齐全的系统的特点。视频播放器具有以下特点。视频信息来自手机数据库。以通用格式(如mkv、flv、MP4、RMVB)播放视频。可以对视频文件进行管理,包括增加和删除功能。为实现全屏播放功能。播放/暂停、上一个、下一个,使用手势调整音量/亮度。我国嵌入式系统超高级专家沉旭邦院士预测,“嵌入式发展也将音频和视频的回放更方便,适用简单,是个大的潮流趋势”。安卓智能手机和平板电脑在市场上广泛应用,包括办公软件、电影和电视音频软件、游戏软件、特定功能的软件以及许多其他应用程序。本文讨论了安卓系统上视频播放器应用程序的设计与实现。2.系统使用的主要技术2.1android多媒体系统介绍2007年全球发生了一件事,成立了一个联盟组织。这些组织包括世界各地的许多公司。他们唯一的目标是让手机更快更方便。安卓手机从生产开发到销售都有一个完整的过程。每个过程都有很多公司。目前,在许多负责各个流程的公司中,有些已经加入了这个联盟组织。而且今后这个联盟将越来越庞大。该组织是开放式手持设备联盟(OpenHandsetAlliance)。安卓是这个联盟的产物。我相信在不久的将来,安卓一定能站在智能手机的顶点。当时技术不发达,可用的开发工具都只是SDK发行版。用这些简单的设备开发g1花了一年时间。几乎在G1发布的同时,最早的sdk就被公开了。从此安卓越来越受到重视。安卓平台的各种应用如雨后春笋般涌现。为了提高Android的知名度,谷歌还举办了两次Android开发挑战会议,以刺激应用开发。随着G1的增加,应用程序数量也在不断增加。于是谷歌推出Android作为应用交易市场。通过商业市场,用户可以看到别人开发的应用程序,遇到自己喜欢的应用程序,也可以通过这个商业市场将应用程序下载到自己的手机上。(1)从多媒体应用的角度来看,包括:输入和输出链接和中间处理链接。(2)安卓内核:OpenCore是一个多媒体框架。从宏观角度来看,它主要包括PVPlayer:实现媒体播放器功能,执行各种音频和视频流的播放功能。vaue:例如各式硬件设备。2.2android平台Android主要是用于移动设备的开源操作系统。用户使用量大,操作简单。2.3Android的四大组件1.Activityactivity是一种语言的活动。该应用是视频播放软件的主要组成部分。2.Service如果用户选择开始播放播放播放列表并退出“活动”(Activity)用户界面,而不想暂停视频,则可以使用Service代替Activity来调用播放器。3.BroadcastReceiver在Android中,广播接收器用于异步接收广播信息,视频信息的接受基于广播接收器。2.4开发工具EclipseEclipse是基于富客户机的开发平台,即rcp。RCP包括下列组件:主平台,标准盒式框架(OSGi:OpenServiCeGATEWAYINITIATIVE),可移植组件套件(SWT:eclipse's)2.5开发语言Java在JVM的开头,很大程度上降低了Java程序操作,在J2SE1.4.2之后,Java的运行速度有所改善,它具有跨平台等特点,易于移动应用开发。2.5Android架构如果一个应用程序运行完美,它需要许多组件一起工作。两个重要的组件是虚拟机和java编程语言。需要注意的是,当人们提到vm的时候,通常会第一时间想到jvm。虽然都是虚拟机,但是本质真的不一样。jvm代表java虚拟机。这里的vm代表dvm,是Android技术开发中的dalivk虚拟机。应用程序运行的先决条件是创建一个对象。dvm的作用是创建这个对象.应用程序由许多部分组成。这些部分称为组件。这些组件协同工作,使应用程序以有序的方式工作。最重要的组件是活动、服务、内容提供商和广播接收器。活动:用户能看到的属于视觉UI,而这些UI要想实现,必须依赖动作的生成。有两种动作。第一种是用户想运行一个程序时,在主屏幕上点击应用,第二种是手机根据需要自动选择程序。服务:服务应用程序适用于运行时间较长的所有程序,如控制应用程序更新的程序。内容提供程序:内容提供程序主要在大型的应用程序中使用广泛。任何一款大型的应用程序都需要内容提供程序,内容服务程序就好比是数据库中的一个服务器。在大型的应用程序中时刻进行着数据的传输。内容提供程序就可以很好的帮助数据进行传输。广播接收器:程序的运行中最重要的部分就是数据集的传输。任何Android应用程序都需要处理庞大的数据集。广播接收器在应用程序中扮演的角色就是数据的处理者。可是要是认为广播接收器的作用仅仅只是处理数据那就错了。他还可以对一个事件做出响应。用户在下载Android的应用程序时,会同时下载一个.xml的配置文件文件。这个文件里面主要是安装这款应用程序是所需要的一些配置信息。在应用程序安装的时候,会首先加载配置文件里面的配置信息。配置文件主要包含安装应用程序需要的类名以及所安装的应用程序可以处理的事件。还有必不可少的许可证明。例如,在网络上搜索下载资料的时候,首先manifest文件的内部会自动的获取和下载这些资料相关的各种许可,然后会把这些许可罗列出来。大部分的应用程序都会支持这个许可。这种许可的工作机制主要是为了防止用户不小心下载了恶意的应用程序的时候,应用程序会对设备造成损害。2.6Eclipse上Android环境的搭建第一步:安装JDK。1991年sun公司的技术人员开发出了一款新型的语言Oak。也就是java的前身,在经过了十多年的发展之后在2009年由Oracle公司收购。被收购之后想要下载jdk就需要到官方网站去进行下载。第二步:配置Windows上JDK的变量环境。右键我的电脑—》属性—》高级系统设置—》环境变量安装jdk只是第一步,紧接着的是环境变量配置。配置环境变量主要分为三个部分。JAVA_HOMEJAVA_HOME属性是电脑里面没有的。所以要用户自己添加一个新的JAVA_HOME变量。将jdk安装完成后在电脑里面的路径作为变量值。Path和前面的JAVA_HOME属性不同,Path属性是电脑里面本来就存在的。打开之后就能直接进行编辑。CLASSPATHjava程序在编译通过之后会产生.class文件。CLASSPATH的作用就是让java的运行环境可以更加准确快速的找到.class文件。在变量值之前需要加上一个“.”表示当前目录,在执行java程序时会用到很多的包,这时就会根据环境变量里面的路径去找这些包,这样的目的,就是告诉给机器这些包的位置。第三步:Eclipse开发工具的下载与安装。Eclipse是一个集成的开发环境,不需要用户进行安装,下载完成后直接找到eclipse的.exe文件即可打开。第四步:AndroidSDK工具的下载与安装。开发人员可以从AndroidSDK中获取sdk提供的一些基本库和tools工具。sdk工具可以在谷歌的官网进行下载。第五步:为Eclipse安装ADT插件。选择eclipse—》help—》installnewsoftware点击add打开添加的对话框,点击achive添加ADT压缩包。2.7OpenCore多媒体框架简介使用Android进行软件开发时。OpenCore是经常用的程序。其中包括了接口的继承,系统的移植还有功能的封装。OpenCore这个框架,主要由两个重要的部分组成:PVPlayer:PVPlayer控制所有Niconico视频播放器的音视频的播放。PVAuthor:PVAuthor可以记录视频播放器的音视频也可以记录图像。PVPlayer和PVAuthor一般都会放在软件开发工具包里面。开发者可以下载这种工具包,开发人员可以在软件开发工具包的基础上创建各种各样的多媒体应用程序。比如在手机里面经常会用到的各种播放器,出外游玩时必不可少的照相机等等。了解OpenCore可以从它的几个层次上面着手,通过这些层次可以很好的了解到OpenCore的整体架构OSCL:OSCL的全称是操作系统兼容库。当应用程序在不同的手机上运行和不同的应用程序一起运行时需要考虑到程序的兼容性。OSCL就是为了让应用程序可以更好的在不同的操作系统上面运行。OSCL之所以可以完成这一项艰巨的任务是因为他本身就包含了一些系统底层基本的操作。同时还包括了一些基本内容。
PVMF:PVMF的全称是PV多媒体框架。在PVMF下面有一个NODE组件。NODE虽然只是一个组件,但是在使用OpenCore时可以通过这个组件来实现一个特定的功能。
这里只是简单的介绍这几个组件,其实,了解了之后就会发现OpenCore中的内容远远不止这些。:从播放的角度,PVPlayer即可以被当作接收器又可以被看成输出设备。当他是接收时接收的是文件,当他被看成是输出设备时,不仅可以输出的音频流还可以输出视频流,因为PVPlayer包含了对音频视频的控制,解码等功能还包含了对文件的解析。因为用户除了从本地播放外还需要联网播放。所以PVPlayer还包含了RTSP实时流协议。
从媒体流记录的方面看,因为PVAuthor的功能主要是通过手机摄像头和麦克风等设备对音频视频和图片进行记录,接受这些输入之后它会将流的同步还有视频流和音频流的编码文件一起形成一个文件并进行输出。3.播放器结构Android为AppDevelopers提供丰富的SDK,Android应用程序可以从文件组合中看到近似结构,主要由源文件,布局文件和资源文件组成。3.1文件列表界面文件列表信息将在每个视频的标题下显示。播放列表是一张列表视图。采用listview显示。3.2控制菜单控件菜单是最常用的界面,应简洁易用。控制菜单大致可分为两部分。进度列上方有一个进度列,其中包含目前时间和总时间。您可以从此处轻松查看当前进度信息。播放视讯时,选取范围会显示在上方和下方。除控制菜单外,此界面还应显示视频窗口和标题。由于视讯是全萤幕视讯,因此标题和控制项功能表会与视讯重叠。因此,它适用于结构件布局。),以显示视频内容(视频显示的最低级别)。接下来的线性布局,它显示标题的内容,默认情况下位于底部。进度条是从左到右排列依次是当前时间、文本、进度条和总时间,用户移托进度条时,必须与当前时间成比例地跳跃。3.3Toast模块tots模块是基于Android的tots控制包。Toast模组会显示提示讯息并自动消失。3.4Mediaplayer视频技术图1Mediaplayer对象状态3.5小结设计了功能菜单,控制菜单和其他主要用户界面模块的界面、布局和功能。其他模组(例如Toast)则可丰富应用程式并改善使用者体验。4.系统分析4.1系统可行性分析系统采用Eclipse与AndroidADT的技术实现,Eclipse与AndroidADT技术简单易用,技术上是可行的。在可行性分析来了解用户的需求。是要做一个调查,以确保开发系统可以完成用户的需求。终于理解用户的需求,系统必须有认识的发展,新技术的发展从经济、技术、操作等进行了分析。3.1.1技术可行性系统是在Android平台上进行开发的。相比ios,Android的以下优势为Android提供技术支持。1、Android物美价廉性能强购买商品时,普通的消费者的大部分都是首先看价格。每个人都想用最少的钱买到最好的商品。苹果手机不错,但是价格是安卓的几倍。苹果就像一些高端化妆品。大家都想试试效果,但是因为价格高,只能打消这个念头。而且还有一些非常常见的化妆品,随处都可以买到,价格也不贵,甚至有些效果可以媲美高端。Android就像这个普通的化妆品,可以给用户带来全方位的良好体验。有时,电话价格不一定与性能成正比。人们希望他们能买到便宜的商品,安卓手机是一种非常经济的类型。使用苹果手机的人会觉得苹果使用起来特别困难,虽然功能很多,但大多数都是普通生活中无法使用的多余功能。相比之下,Android手机简单易用,甚至有些Android与苹果在外观上也相差无几。使用时,触摸效果可能更好。与Android的最佳价格相比,大多数人买不起的iphone价格很好。而且在手机性能和使用感觉上不会输给iphone。2、应用程序发展迅速原来的电话是那种最普通的电话,只能打电话和接电话。相比之下,手机现在不再叫手机,而是叫智能手机。之前添加的两个智能词也足以说明现在手机的能力有多强。现在,人们的手机上有不同的app,装载着密麻麻。智能手机在手机市场上可能如此受欢迎,以至于它们也与此密不可分。虽然安卓应用程序在数量上比苹果大,但在质量上还是无法与苹果商店的应用程序相比。虽然在质量上比不上IOs,但在数量上却比不上。例如,在同一时间,安卓开发的应用程序是苹果的十倍。而且安卓应用程序的数量还在增加。如此可见,以后Android仍能与IOs竞争。苹果在下载应用的时候,想要下载一个应用,必须经过复杂的验证层。有些应用甚至没有在苹果的应用商店中发布。Android可以随意下载自己喜欢的应用。你能找到的任何东西都可以下载。3、众多手机厂家的支持苹果专注于自身从硬件到软件和促销。而且这种短期的自我中心主义方法也取得了良好的效果。在这个封闭的空间里,苹果虽然不断创新,但最终还是被困在了这个空间里。从短期来看,消费者对新鲜度可以得到很大的满足。但是,这不利于长期发展。目前,三星、华为、鬼等市面上一些最受欢迎的Android厂商已经确立了自己的品牌特征。并推出了一系列手机。不仅如此,他们中的很多人,比如三星,还与谷歌建立了技术平台的开发。在这些大制造商的领导下,加入这个联盟的制造商层出不穷。因此,越来越多的手机品牌应运而生。用户也有更多的选择,在相互竞争的情况下,Android必然会越来越广受欢迎。4、运营商的鼎力支持在国内,中国移动、中国联通、中国电信也赶上了安卓的潮流。都推出了各种手机优惠。此外,美国、德国、意大利、日本、法国等国家也有大量来自该阵营的志愿者。这么大的用户群体的支持,不仅证明了Android的可靠性,也加速了Android在全球的普及。安卓的联盟与苹果的联盟形成鲜明对比。苹果特有的封闭独立带来一定的优势,但同时也对苹果的制造商和运营商构成威胁。5、众多的机型和优质的配置在激烈的安卓市场竞争中,大型制造商在安卓手机上添加自己的元素,形成安卓手机品牌。形状多样,特点各异,黑色技术多种多样。三星、华为等品牌的多元化将不可避免地促进手机的多元化。这些手机品牌积极创造了自己的品牌,也添加了很多黑色技术,大大满足了用户的体验。相反,苹果一直很闭关锁国不接受新鲜事物。由于苹果系统的不开放性,苹果的特色都是来自于内部的不懈努力。而Android的开源为程序员提供了不小的便利。每个第三方都可以在原有的Android系统上的软硬件设施都可以在第三方软件上增加,在多次的改进研发与进化之下,Android已经与众不同,浴火重生。相比苹果的不开放性,Android的开源给开发员提供了无限的自由。开发员可以发挥天马行空的想象,让Android的发展愈来愈好。4.2系统需求分析根据分析需求,这个系统必须实现以下的功能:(1)实施电话支持的视频格式文件的播放。作为一个播放器,核心是顺利播放视频文件。手机通常没有太多的解码形式,如RMVB。您应该能够顺利地播放,可作为移动电话携带的视频流文件。(2)可以在手机中找到视频文件。通过自定义文件列表,访问手机中可访问的所有视频文件。因此,无需在系统中的固定位置放置视频文件。通过创建一个保存视频文件的新文件夹,然后将视频文件放在位置。通过这种方式,您可以方便搜索以及观看视频文件。(3)能够检索AndroidSDCard中的所有视频文件。智能视频搜索是一种快速查找使用SD卡的视频文件的快速方法。(4)可以读取视频文件的一般信息。播放视频文件时,屏幕上的屏幕上会显示视频名称和视频长度等信息。5.系统实现5.1系统设计设计的Android视频播放器应用程序主要由MediaplayerActivity,MediaListActivity,FileChooserActivity,UpdateMediaListActivity四个activity所组成。在布局文件中,添加用来实现相应部分功能的各种控件。系统结构框图如图2所示。图2系统结构框图整体设计框架播放本地的视频文件需要封装一个输入模块,输入模块需要开启一个线程用来处理解封装和解码,把得到的初始数据放到音频和视频的列表中。输出模块:以音频为主的输出可以听到声音,以视频为主的输出,可以看到画面。音频视频的输出单独的线程来管理音频视频的输出。音视频同步由于输出模块是单独播放的,音画同时播放没有办法保证,所以引入此模块来解决问题,并且其包括输出模块、输入模块与音视频队列,接着接入导入音视频数据的接口,音视频的同步问题随即解决。对外调度器此模块集成音视频输出模块,音视频同步模块,以确保数据正确输出,并对外提供播放视频的控制接口。整体大体类结构AudioOutput为音频输出模块,音频渲染位于一个单独线程,在运行过程中通过注册过来的回掉函数获取音频数据VideoOutput为视频输出模块,通过OpenGLES来进行渲染视频,之后开启子线程运行OpenGLES渲染过的视频,在程序运行过程中注册回掉函数用于获取视频数据。AVSynchronizer为音视频同步模块,为VideoPlayerController提供接口,包括开始、结束、以及获取对应时间轴的视频帧和获取音频数据。AudioFrame为音频帧,记录时间戳、具体数据等信息,以及音频的数据格式。VideoFrame为视频帧,记录具体的数据、宽、高、以及视频格式,时间戳等信息。AudioFrameQueue为音频队列,用于存储音频帧,由于消费者与生产者同时访问列表中的元素为音频播放线程和解码线程,它通过弹出和压入操作使客户端音视频同步得到实现,同时保证线程的安全性。VideoFrameQueue为视频队列,用于存储视频帧,功能如上所示处理视频。VideoDecoder为输入解码模块,主要功能是向同步模块提供接口:包括打开和关闭文件资源、解码出长度一定的音视频帧。音视频输入模块实现对于VideoDecoder类的实现。其使用FFmpeg来处理解码操作,封装格式拆分等。打开文件openFiledecodeFrames通过循环读取数据进行解处理,解码,封装数据。释放资源在解码时看到音频数据直接进入到av_synchronizer.cpp的音频队列audioFrameQueue,而视频数据回掉到circleFrameTextureQueue中。音视频输出模块的实现模块由video_output.cpp负责视频文件的输出,audio_output.cpp负责音频文件的输出。音频输出使用OpenSLES进行音频输出。主要类实现为audio_output.cpp。video_player_controller.cpp中通过初始化AudioOutput类传入以此获取数据的回掉函数。audio_output.cpp中registerPlayerCallback播放结束时从传入回掉函数中获取音频数据并在自己的队列中放入。audio_output.cpp中提供播放控制按钮,stopde,pause,play,start。视频输出在类文件video_output.cpp中封装。渲染视频画面通过OpenGLES实现,之后渲染视频帧通过开启一个单独的线程。数据的处理方式和音频类似,通过回掉来获取要渲染的视频帧数据。音视频同步模块实现音视频同步,维护解码线程是音频视频模块主要的工作。文件为av_synchronizer.cpp维护解码线程的主要交接函数在上文已经提及。此方法会循环,每次循环之后会wait,当有signal信号传来时进行解码。音频视频同步方法:音频向视频对齐音频帧根据视频帧的时间戳进行渲染。渲染视频帧时,会将音频帧与视频帧的时间戳进行比较。如果差值不在阈值内,则应进行校准。对齐的主要操作是音频帧。如果音频帧的时间戳小于视频帧的时间戳,则需要跳帧,就像快进操作一样;如果音频帧的时间戳大于视频帧的时间戳,则需要等待视频帧播放。实现方法是在视频帧追上时,填充空的音频数据,播放当前的音频帧数据。优点:用户可以看到视频的每一帧,并且看起来很流畅缺点:空帧静音或丢帧会在音频中出现。视频向音频对齐:此方法与以上相反。统一向外部时钟对齐:从外部提供时钟,获取音频视频帧的数据时,与外部时钟对准,如果不超过阈值则直接返回音频视频帧,如果超过则进行上述对准操作,分别进行音频、视频和外部时钟。人的耳朵比眼睛敏感得多,如果声音有跳帧或空帧,我们就容易注意到;视频中有跳跃帧和重复帧,用眼睛很难分辨。在这个项目中,使用了视频与音频的对齐。集合控制系统初始化:初始化包括视频渲染界面的初始化,音频播放器初始化。运行:初始化音频输出模块,OpenGLES播放缓冲区的音频数据后,返回video_palyer_controller.cpp填充数据。判断数据的填充方法有几列,如果最后不满意,则调用同步模块的音频数据的填充方法,填充音频数据后,向视频输出发送命令,更新画面,视频输出接收到方法后由于整个动作由音频播放驱动,所以播放暂停等操作只要控制音频播放模块即可。销毁:创建的逆过程为销毁过程。总结看了几天整个项目的代码,发现里面有一个完整的逻辑,有很多实现细节值得学习。其中Opegl的实现细节不详细。通过观察整个代码可以得知整个代码都是有逻辑可言的,简而言之,如果你不理解它,你可以看到你理解它,并整理代码的思想。5.2用户登录注册登录界面设计,给button设置一个id属性登录按钮:Android:id=“@+id/btn_login”,注册按钮:Android:id=“@+id/btn_register,”创建好之后再在Mainactivity中创建变量privatebuttonbtnlogin,privatebuttonbtnregister。之后写代码Intentin=newIntent(MainActivity.this,LoginActivity.class);//startActivity(in);点击登录按钮后会执行此代码,通过MainActivity跳转到LoginActivity页面来。登陆页面布局:用户名密码登录界面与底部的登录按钮是垂直分布的,我们通过线性布局包裹起来,注册页面同上。登陆界面代码如下:packagecom.ttit.myapp.activity;importandroid.content.Intent;importandroid.util.Log;importandroid.view.View;importandroid.widget.Button;importandroid.widget.EditText;importcom.google.gson.Gson;importcom.ttit.myapp.R;importcom.ttit.myapp.api.Api;importcom.ttit.myapp.api.ApiConfig;importcom.ttit.myapp.api.TtitCallback;importcom.ttit.myapp.entity.LoginResponse;importcom.ttit.myapp.util.StringUtils;importjava.util.HashMap;publicclassLoginActivityextendsBaseActivity{privateEditTextetAccount;privateEditTextetPwd;privateButtonbtnLogin;@OverrideprotectedintinitLayout(){returnR.layout.activity_login;}@OverrideprotectedvoidinitView(){etAccount=findViewById(R.id.et_account);etPwd=findViewById(R.id.et_pwd);btnLogin=findViewById(R.id.btn_login);}@OverrideprotectedvoidinitData(){btnLogin.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewv){Stringaccount=etAccount.getText().toString().trim();Stringpwd=etPwd.getText().toString().trim();login(account,pwd);}});}privatevoidlogin(Stringaccount,Stringpwd){if(StringUtils.isEmpty(account)){showToast("请输入账号");return;}if(StringUtils.isEmpty(pwd)){showToast("请输入密码");return;}HashMap<String,Object>params=newHashMap<String,Object>();params.put("mobile",account);params.put("password",pwd);Api.config(ApiConfig.LOGIN,params).postRequest(this,newTtitCallback(){@OverridepublicvoidonSuccess(finalStringres){Log.e("onSuccess",res);Gsongson=newGson();LoginResponseloginResponse=gson.fromJson(res,LoginResponse.class);if(loginResponse.getCode()==0){Stringtoken=loginResponse.getToken();insertVal("token",token);navigateToWithFlag(HomeActivity.class,Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);showToastSync("登录成功");}else{showToastSync("登录失败");}}@OverridepublicvoidonFailure(Exceptione){}});}注册页面与上相似。使用软件Navicatpremium创建数据库,数据库页面代码如下:packagecom.ttit.myapp.api;publicclassApiConfig{publicstaticfinalintPAGE_SIZE=5;publicstaticfinalStringBASE_URl="2:8080/renren-fast";publicstaticfinalStringLOGIN="/app/login";//登录publicstaticfinalStringREGISTER="/app/register";//注册publicstaticfinalStringVIDEO_LIST_ALL="/app/videolist/listAll";//所有类型视频列表publicstaticfinalStringVIDEO_LIST_BY_CATEGORY="/app/videolist/getListByCategoryId";//各类型视频列表publicstaticfinalStringVIDEO_CATEGORY_LIST="/app/videocategory/list";//视频类型列表publicstaticfinalStringNEWS_LIST="/app/news/api/list";//资讯列表publicstaticfinalStringVIDEO_UPDATE_COUNT="/app/videolist/updateCount";//更新点赞,收藏,评论publicstaticfinalStringVIDEO_MYCOLLECT="/app/videolist/mycollect";//我的收藏5.3视频播放实现首页功能实现与视频播放功能实现代码如下:packagecom.ttit.myapp.fragment;importandroid.content.pm.ActivityInfo;importandroid.os.Handler;importandroid.os.Message;importandroid.view.View;importandroid.widget.FrameLayout;importandroidx.annotation.NonNull;importandroidx.recyclerview.widget.LinearLayoutManager;importandroidx.recyclerview.widget.RecyclerView;importcom.dueeeke.videocontroller.StandardVideoController;importponent.CompleteView;importponent.ErrorView;importponent.GestureView;importponent.TitleView;importponent.VodControlView;importcom.dueeeke.videoplayer.player.VideoView;importcom.google.gson.Gson;importcom.scwang.smartrefresh.layout.api.RefreshLayout;importcom.scwang.smartrefresh.layout.listener.OnLoadMoreListener;importcom.scwang.smartrefresh.layout.listener.OnRefreshListener;importcom.ttit.myapp.R;importcom.ttit.myapp.adapter.VideoAdapter;importcom.ttit.myapp.api.Api;importcom.ttit.myapp.api.ApiConfig;importcom.ttit.myapp.api.TtitCallback;importcom.ttit.myapp.entity.VideoEntity;importcom.ttit.myapp.entity.VideoListResponse;importcom.ttit.myapp.listener.OnItemChildClickListener;importcom.ttit.myapp.util.Tag;importcom.ttit.myapp.util.Utils;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;publicclassVideoFragmentextendsBaseFragmentimplementsOnItemChildClickListener{privateintcategoryId;privateRecyclerViewrecyclerView;privateRefreshLayoutrefreshLayout;privateintpageNum=1;privateVideoAdaptervideoAdapter;privateList<VideoEntity>datas=newArrayList<>();privateLinearLayoutManagerlinearLayoutManager;protectedVideoViewmVideoView;protectedStandardVideoControllermController;protectedErrorViewmErrorView;protectedCompleteViewmCompleteView;protectedTitleViewmTitleView;/***当前播放的位置*/protectedintmCurPos=-1;/***上次播放的位置,用于页面切回来之后恢复播放*/protectedintmLastPos=mCurPos;privateHandlermHandler=newHandler(){@OverridepublicvoidhandleMessage(@NonNullMessagemsg){super.handleMessage(msg);switch(msg.what){case0:videoAdapter.setDatas(datas);videoAdapter.notifyDataSetChanged();break;}}};publicVideoFragment(){}publicstaticVideoFragmentnewInstance(intcategoryId){VideoFragmentfragment=newVideoFragment();fragment.categoryId=categoryId;returnfragment;}@OverrideprotectedintinitLayout(){returnR.layout.fragment_video;}@OverrideprotectedvoidinitView(){initVideoView();recyclerView=mRootView.findViewById(R.id.recyclerView);refreshLayout=mRootView.findViewById(R.id.refreshLayout);}@OverrideprotectedvoidinitData(){linearLayoutManager=newLinearLayoutManager(getActivity());linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);recyclerView.setLayoutManager(linearLayoutManager);videoAdapter=newVideoAdapter(getActivity());videoAdapter.setOnItemChildClickListener(this);recyclerView.setAdapter(videoAdapter);recyclerView.addOnChildAttachStateChangeListener(newRecyclerView.OnChildAttachStateChangeListener(){@OverridepublicvoidonChildViewAttachedToWindow(@NonNullViewview){}@OverridepublicvoidonChildViewDetachedFromWindow(@NonNullViewview){FrameLayoutplayerContainer=view.findViewById(R.id.player_container);Viewv=playerContainer.getChildAt(0);if(v!=null&&v==mVideoView&&!mVideoView.isFullScreen()){releaseVideoView();}}});refreshLayout.setOnRefreshListener(newOnRefreshListener(){@OverridepublicvoidonRefresh(RefreshLayoutrefreshlayout){pageNum=1;getVideoList(true);}});refreshLayout.setOnLoadMoreListener(newOnLoadMoreListener(){@OverridepublicvoidonLoadMore(RefreshLayoutrefreshlayout){pageNum++;getVideoList(false);}});getVideoList(true);}protectedvoidinitVideoView(){mVideoView=newVideoView(getActivity());mVideoView.setOnStateChangeListener(newcom.dueeeke.videoplayer.player.VideoView.SimpleOnStateChangeListener(){@OverridepublicvoidonPlayStateChanged(intplayState){//监听VideoViewManager释放,重置状态if(playState==com.dueeeke.videoplayer.player.VideoView.STATE_IDLE){Utils.removeViewFormParent(mVideoView);mLastPos=mCurPos;mCurPos=-1;}}});mController=newStandardVideoController(getActivity());mErrorView=newErrorView(getActivity());mController.addControlComponent(mErrorView);mCompleteView=newCompleteView(getActivity());mController.addControlComponent(mCompleteView);mTitleView=newTitleView(getActivity());mController.addControlComponent(mTitleView);mController.addControlComponent(newVodControlView(getActivity()));mController.addControlComponent(newGestureView(getActivity()));mController.setEnableOrientation(true);mVideoView.setVideoController(mController);}@OverridepublicvoidonPause(){super.onPause();pause();}/***由于onPause必须调用super。故增加此方法,*子类将会重写此方法,改变onPause的逻辑*/protectedvoidpause(){releaseVideoView();}@OverridepublicvoidonResume(){super.onResume();resume();}/***由于onResume必须调用super。故增加此方法,*子类将会重写此方法,改变onResume的逻辑*/protectedvoidresume(){if(mLastPos==-1)return;//恢复上次播放的位置startPlay(mLastPos);}/***PrepareView被点击*/@OverridepublicvoidonItemChildClick(intposition){startPlay(position);}/***开始播放**@paramposition列表位置*/protectedvoidstartPlay(intposition){if(mCurPos==position)return;if(mCurPos!=-1){releaseVideoView();}VideoEntityvideoEntity=datas.get(position);//边播边存//StringproxyUrl=ProxyVideoCacheManager.getProxy(getActivity()).getProxyUrl(videoBean.getUrl());//mVideoView.setUrl(proxyUrl);mVideoView.setUrl(videoEntity.getPlayurl());mTitleView.setTitle(videoEntity.getVtitle());ViewitemView=linearLayoutManager.findViewByPosition(position);if(itemView==null)return;VideoAdapter.ViewHolderviewHolder=(VideoAdapter.ViewHolder)itemView.getTag();//把列表中预置的PrepareView添加到控制器中,注意isPrivate此处只能为true。mController.addControlComponent(viewHolder.mPrepareView,true);Utils.removeViewFormParent(mVideoView);viewHolder.mPlayerContainer.addView(mVideoView,0);//播放之前将VideoView添加到VideoViewManager以便在别的页面也能操作它getVideoViewManager().add(mVideoView,Tag.LIST);mVideoView.start();mCurPos=position;}privatevoidreleaseVideoView(){mVideoView.release();if(mVideoView.isFullScreen()){mVideoView.stopFullScreen();}if(getActivity().getRequestedOrientation()!=ActivityInfo.SCREEN_ORIENTATION_PORTRAIT){getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);}mCurPos=-1;}privatevoidgetVideoList(finalbooleanisRefresh){HashMap<String,Object>params=newHashMap<>();params.put("page",pageNum);params.put("limit",ApiConfig.PAGE_SIZE);params.put("categoryId",categoryId);Api.config(ApiConfig.VIDEO_LIST_BY_CATEGORY,params).getRequest(getActivity(),newTtitCallback(){@OverridepublicvoidonSuccess(finalStringres){if(isRefresh){refreshLayout.finishRefresh(true);}else{refreshLayout.finishLoadMore(true);}VideoListResponseresponse=newGson().fromJson(res,VideoListResponse.class);if(response!=null&&response.getCode()==0){List<VideoEntity>list=response.getPage().getList();if(list!=null&&list.size()>0){if(isRefresh){datas=list;}else{datas.addAll(list);}mHandler.sendEmptyMessage(0);}else{if(isRefresh){showToastSync("暂时无数据");}else{showToastSync("没有更多数据");}}}}@OverridepublicvoidonFailure(Exceptione){if(isRefresh){refreshLayout.finishRefresh(true);
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 虚拟现实在大学地理教学中的沉浸式应用课题报告教学研究课题报告
- 2025年生态湿地公园生态湿地恢复与技术创新可行性研究报告
- 2026年注册会计师综合试题集财务报告与税务知识
- 2025广东东莞市大湾区大学行政岗位招聘1人备考题库有完整答案详解
- 2026年燕山大学选聘实验人员2名备考题库有答案详解
- 2026年上半年北大荒农垦集团有限公司事业单位公开招聘工作人员112人备考题库及1套完整答案详解
- 企业费用预算管理工具
- XX初中八年级下学期物理实验操作考核方案
- 供应链优化分析工具成本控制与策略制定
- 2026届德州市高三语文上学期期末考试卷附答案解析
- 仓库货物摆放标准培训课件
- 2023年运动控制工程师年度总结及下一年展望
- 江苏省高级人民法院劳动争议案件审理指南
- 低蛋白血症的护理查房知识ppt
- 2023自愿离婚协议书范文(3篇)
- 眼科常见疾病诊疗规范诊疗指南2022版
- 30以内加法运算有进位1000题1
- 战略成本1-6章toc经典案例
- 新药临床使用观察表
- GB/T 34202-2017球墨铸铁管、管件及附件环氧涂层(重防腐)
- DB37-T 5026-2022《居住建筑节能设计标准》
评论
0/150
提交评论