【《基于android系統的Niconico影視播放器設計》11000字】_第1頁
【《基于android系統的Niconico影視播放器設計》11000字】_第2頁
【《基于android系統的Niconico影視播放器設計》11000字】_第3頁
【《基于android系統的Niconico影視播放器設計》11000字】_第4頁
【《基于android系統的Niconico影視播放器設計》11000字】_第5頁
已閱讀5頁,還剩24頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

基于android系統的Niconico影視播放器設計1.引言 11.1設計的目的及意義 11.2國內外研究現狀 11.3視頻播放器概述 32.系統使用的主要技術 32.1android多媒體系統介紹 32.2android平臺 42.3Android的四大組件 42.4開發(fā)工具Eclipse 42.5Android架構 42.6Eclipse上Android環(huán)境的搭建 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語言。給出了細致的系統設計過程。視頻播放器具有暫停,播放,后退和快進等功能。它具有優(yōu)異的性能,可以在Android系統中單獨運行。具體介紹和解析程序的最首要活動,包含詳細介紹程序運用的結構文件和每個控件的角色。然后,測試該程序并測試了模塊性能的實現,并且包含大量屏幕截圖以展現測試成果,并識別程序中可能出現的問題。開發(fā)的程序界面友好,相對簡單,符合設計要求。關鍵詞:安卓視頻播放ActivityMediaplayer引言1.1設計的目的及意義今天的科學技術正在迅速增長,有各種程序,視頻通話,VOD視頻,在線波,在線閱讀和數據。為了實現這樣的應用,愈來愈多的手機功能是智能的,表明移動互聯網已進入新的時代。新時代的到來也需要一個強大的發(fā)展平臺來支持。因此,操作系統和智能手機技術的研究已成為最活躍的領域之一。由于安卓的開放性,目前安卓系統已經應用到智能終端上。視頻播放器是人們日常使用的重要軟件。設計的基于安卓系統的Niconico視頻播放器安裝在安卓終端上。應用程序具有適當的播放接口,可以從系統數據庫中讀取相應的視頻信息、視頻格式可以自動隨屏幕大小切換視頻比例。許多企業(yè)和個人用安卓開發(fā)視頻播放器,其中moboplayer、RockPlayer、realPlayer、VPlayer等深受用戶喜愛。但是,目前許多播放器功能復雜,形式多樣,消耗大量內存,廣告嵌入過多,用戶無法獲得良好的用戶體驗,因此需要開發(fā)功能全面、簡單易用的視頻播放器。操作強大的解碼能力。由此可見,安卓平臺將對app手機行業(yè)和境外手機平臺產生巨大影響,在未來幾年,安卓本身的重要性將變得更加為人所知[1]。1.2國內外研究現狀常用的播放器有,Xmovie,Mplayer,QuickTime,Mplayer,Xmms,RealPlayer。1.X-Window是一種常用的計算機操作系統,配備有Xmms播放器。Xmms附帶少量視頻、音頻多媒體文件供播放。但這不符合用戶的要求。因此,開發(fā)人員還開發(fā)了許多插件。使用這些Xmms插件,可以支持以更大的格式播放多媒體文件。2.Xmovie經常在電視節(jié)目中使用。電視節(jié)目的要求一般比較簡單,只要求最基本的功能。恰好Xmovie的播放界面也很簡單。用Xmovie玩只能看到基本的快進、倒退、播放鍵。Xmovie的功能和界面一樣簡單,主要控制一些環(huán)境變量,和一些環(huán)境變量。許多人認為Xmovie不應該只播放音頻,因為它用于電視廣播,但實際上Xmovie不僅可以讓視頻圖片播放,mp3音頻也可以進行播放。3.RealPlayer可減少低帶寬傳輸過程中的數據丟失。RealPlayer還可以在在線播放流媒體時保持平穩(wěn)、快速的傳輸。RealPlayer在Linux和window平臺上提供,旨在方便用戶使用。開發(fā)者有意設置接口的基本一致性。在隨后的RealPlayer更新中,添加了一些新功能,以提高RealPlayer的知名度。它不僅可以播放Microsoft視頻,還可以播放音頻文件。此外還添加了一個便攜式接口。4.QuickTime主要是為流媒體文件設計的。QuickTime主要分為三個模塊:文件格式、媒體抽象和內置媒體服務。使用QuickTime時,有一個播放器同名,名為QuickTime。QuickTime的文件名后綴通常是.mov。5.作為專業(yè)的電影播放器,Mplayer可以播放大多數視頻文件。在linux上普遍使用。另一方面,Mplayer可以作為本地解碼器播放電影,而且可以播放SVCD、DVD等形式的電影,還可以播放OGG、VOB等文件。另一方面,Mplayer可以作為播放器在各種條件下工作。Xmms、Xmovie、QuickTime等播放器雖然功能強大,但只能滿足一些固定格式。但現在,這種多樣的社會播放器也有多樣化的趨勢。這些已經不適合我們了。隨著消費者群體的增長、視頻的廣泛多樣性和越來越多的音頻格式,用戶的需求越來越大。原來的播放器已經不適應當前的社會群體了。播放器盡可能多地播放音頻和視頻是當前的研究方向。并且考慮到以后還會出現不同的格式,需要保留擴展當前播放器的能力。同時,用戶體驗也非常重要,也非常關注如何在現有基礎上使功能更加全面。本文主要研究基于Android的在線音樂播放器系統的設計與實現。在系統的設計和實現中,系統主要分為這幾個模塊:音樂下載模塊,用戶列表模塊,音樂檢索模塊,音樂分類模塊,播放控制模塊。本文的主要內容有:(1)收集國內外Android技術的發(fā)展和開發(fā)本系統的意義。(2)Android相關技術的概述和環(huán)境的構建。(3)從幾個不同的方面分析系統的需求和可行性。(4)介紹系統的模塊劃分和功能。(5)上一章的模塊設計比較詳細。(6)介紹系統各模塊的實現過程。(7)系統實現后,介紹系統測試中的一些方法和測試過程2Android開發(fā)技術介紹。1.3視頻播放器概述本項目以Java語言為基礎開發(fā)嵌入式播放器。它具有輕巧、節(jié)省空間但功能齊全的系統的特點。視頻播放器具有以下特點。視頻信息來自手機數據庫。以通用格式(如mkv、flv、MP4、RMVB)播放視頻??梢詫σ曨l文件進行管理,包括增加和刪除功能。為實現全屏播放功能。播放/暫停、上一個、下一個,使用手勢調整音量/亮度。我國嵌入式系統超高級專家沉旭邦院士預測,“嵌入式發(fā)展也將音頻和視頻的回放更方便,適用簡單,是個大的潮流趨勢”。安卓智能手機和平板電腦在市場上廣泛應用,包括辦公軟件、電影和電視音頻軟件、游戲軟件、特定功能的軟件以及許多其他應用程序。本文討論了安卓系統上視頻播放器應用程序的設計與實現。2.系統使用的主要技術2.1android多媒體系統介紹2007年全球發(fā)生了一件事,成立了一個聯盟組織。這些組織包括世界各地的許多公司。他們唯一的目標是讓手機更快更方便。安卓手機從生產開發(fā)到銷售都有一個完整的過程。每個過程都有很多公司。目前,在許多負責各個流程的公司中,有些已經加入了這個聯盟組織。而且今后這個聯盟將越來越龐大。該組織是開放式手持設備聯盟(OpenHandsetAlliance)。安卓是這個聯盟的產物。我相信在不久的將來,安卓一定能站在智能手機的頂點。當時技術不發(fā)達,可用的開發(fā)工具都只是SDK發(fā)行版。用這些簡單的設備開發(fā)g1花了一年時間。幾乎在G1發(fā)布的同時,最早的sdk就被公開了。從此安卓越來越受到重視。安卓平臺的各種應用如雨后春筍般涌現。為了提高Android的知名度,谷歌還舉辦了兩次Android開發(fā)挑戰(zhàn)會議,以刺激應用開發(fā)。隨著G1的增加,應用程序數量也在不斷增加。于是谷歌推出Android作為應用交易市場。通過商業(yè)市場,用戶可以看到別人開發(fā)的應用程序,遇到自己喜歡的應用程序,也可以通過這個商業(yè)市場將應用程序下載到自己的手機上。(1)從多媒體應用的角度來看,包括:輸入和輸出鏈接和中間處理鏈接。(2)安卓內核:OpenCore是一個多媒體框架。從宏觀角度來看,它主要包括PVPlayer:實現媒體播放器功能,執(zhí)行各種音頻和視頻流的播放功能。vaue:例如各式硬件設備。2.2android平臺Android主要是用于移動設備的開源操作系統。用戶使用量大,操作簡單。2.3Android的四大組件1.Activityactivity是一種語言的活動。該應用是視頻播放軟件的主要組成部分。2.Service如果用戶選擇開始播放播放播放列表并退出“活動”(Activity)用戶界面,而不想暫停視頻,則可以使用Service代替Activity來調用播放器。3.BroadcastReceiver在Android中,廣播接收器用于異步接收廣播信息,視頻信息的接受基于廣播接收器。2.4開發(fā)工具EclipseEclipse是基于富客戶機的開發(fā)平臺,即rcp。RCP包括下列組件:主平臺,標準盒式框架(OSGi:OpenServiCeGATEWAYINITIATIVE),可移植組件套件(SWT:eclipse's)2.5開發(fā)語言Java在JVM的開頭,很大程度上降低了Java程序操作,在J2SE1.4.2之后,Java的運行速度有所改善,它具有跨平臺等特點,易于移動應用開發(fā)。2.5Android架構如果一個應用程序運行完美,它需要許多組件一起工作。兩個重要的組件是虛擬機和java編程語言。需要注意的是,當人們提到vm的時候,通常會第一時間想到jvm。雖然都是虛擬機,但是本質真的不一樣。jvm代表java虛擬機。這里的vm代表dvm,是Android技術開發(fā)中的dalivk虛擬機。應用程序運行的先決條件是創(chuàng)建一個對象。dvm的作用是創(chuàng)建這個對象.應用程序由許多部分組成。這些部分稱為組件。這些組件協同工作,使應用程序以有序的方式工作。最重要的組件是活動、服務、內容提供商和廣播接收器?;顒?用戶能看到的屬于視覺UI,而這些UI要想實現,必須依賴動作的生成。有兩種動作。第一種是用戶想運行一個程序時,在主屏幕上點擊應用,第二種是手機根據需要自動選擇程序。服務:服務應用程序適用于運行時間較長的所有程序,如控制應用程序更新的程序。內容提供程序:內容提供程序主要在大型的應用程序中使用廣泛。任何一款大型的應用程序都需要內容提供程序,內容服務程序就好比是數據庫中的一個服務器。在大型的應用程序中時刻進行著數據的傳輸。內容提供程序就可以很好的幫助數據進行傳輸。廣播接收器:程序的運行中最重要的部分就是數據集的傳輸。任何Android應用程序都需要處理龐大的數據集。廣播接收器在應用程序中扮演的角色就是數據的處理者。可是要是認為廣播接收器的作用僅僅只是處理數據那就錯了。他還可以對一個事件做出響應。用戶在下載Android的應用程序時,會同時下載一個.xml的配置文件文件。這個文件里面主要是安裝這款應用程序是所需要的一些配置信息。在應用程序安裝的時候,會首先加載配置文件里面的配置信息。配置文件主要包含安裝應用程序需要的類名以及所安裝的應用程序可以處理的事件。還有必不可少的許可證明。例如,在網絡上搜索下載資料的時候,首先manifest文件的內部會自動的獲取和下載這些資料相關的各種許可,然后會把這些許可羅列出來。大部分的應用程序都會支持這個許可。這種許可的工作機制主要是為了防止用戶不小心下載了惡意的應用程序的時候,應用程序會對設備造成損害。2.6Eclipse上Android環(huán)境的搭建第一步:安裝JDK。1991年sun公司的技術人員開發(fā)出了一款新型的語言Oak。也就是java的前身,在經過了十多年的發(fā)展之后在2009年由Oracle公司收購。被收購之后想要下載jdk就需要到官方網站去進行下載。第二步:配置Windows上JDK的變量環(huán)境。右鍵我的電腦—》屬性—》高級系統設置—》環(huán)境變量安裝jdk只是第一步,緊接著的是環(huán)境變量配置。配置環(huán)境變量主要分為三個部分。JAVA_HOMEJAVA_HOME屬性是電腦里面沒有的。所以要用戶自己添加一個新的JAVA_HOME變量。將jdk安裝完成后在電腦里面的路徑作為變量值。Path和前面的JAVA_HOME屬性不同,Path屬性是電腦里面本來就存在的。打開之后就能直接進行編輯。CLASSPATHjava程序在編譯通過之后會產生.class文件。CLASSPATH的作用就是讓java的運行環(huán)境可以更加準確快速的找到.class文件。在變量值之前需要加上一個“.”表示當前目錄,在執(zhí)行java程序時會用到很多的包,這時就會根據環(huán)境變量里面的路徑去找這些包,這樣的目的,就是告訴給機器這些包的位置。第三步:Eclipse開發(fā)工具的下載與安裝。Eclipse是一個集成的開發(fā)環(huán)境,不需要用戶進行安裝,下載完成后直接找到eclipse的.exe文件即可打開。第四步:AndroidSDK工具的下載與安裝。開發(fā)人員可以從AndroidSDK中獲取sdk提供的一些基本庫和tools工具。sdk工具可以在谷歌的官網進行下載。第五步:為Eclipse安裝ADT插件。選擇eclipse—》help—》installnewsoftware點擊add打開添加的對話框,點擊achive添加ADT壓縮包。2.7OpenCore多媒體框架簡介使用Android進行軟件開發(fā)時。OpenCore是經常用的程序。其中包括了接口的繼承,系統的移植還有功能的封裝。OpenCore這個框架,主要由兩個重要的部分組成:PVPlayer:PVPlayer控制所有Niconico視頻播放器的音視頻的播放。PVAuthor:PVAuthor可以記錄視頻播放器的音視頻也可以記錄圖像。PVPlayer和PVAuthor一般都會放在軟件開發(fā)工具包里面。開發(fā)者可以下載這種工具包,開發(fā)人員可以在軟件開發(fā)工具包的基礎上創(chuàng)建各種各樣的多媒體應用程序。比如在手機里面經常會用到的各種播放器,出外游玩時必不可少的照相機等等。了解OpenCore可以從它的幾個層次上面著手,通過這些層次可以很好的了解到OpenCore的整體架構OSCL:OSCL的全稱是操作系統兼容庫。當應用程序在不同的手機上運行和不同的應用程序一起運行時需要考慮到程序的兼容性。OSCL就是為了讓應用程序可以更好的在不同的操作系統上面運行。OSCL之所以可以完成這一項艱巨的任務是因為他本身就包含了一些系統底層基本的操作。同時還包括了一些基本內容。

PVMF:PVMF的全稱是PV多媒體框架。在PVMF下面有一個NODE組件。NODE雖然只是一個組件,但是在使用OpenCore時可以通過這個組件來實現一個特定的功能。

這里只是簡單的介紹這幾個組件,其實,了解了之后就會發(fā)現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對象狀態(tài)3.5小結設計了功能菜單,控制菜單和其他主要用戶界面模塊的界面、布局和功能。其他模組(例如Toast)則可豐富應用程式并改善使用者體驗。4.系統分析4.1系統可行性分析系統采用Eclipse與AndroidADT的技術實現,Eclipse與AndroidADT技術簡單易用,技術上是可行的。在可行性分析來了解用戶的需求。是要做一個調查,以確保開發(fā)系統可以完成用戶的需求。終于理解用戶的需求,系統必須有認識的發(fā)展,新技術的發(fā)展從經濟、技術、操作等進行了分析。3.1.1技術可行性系統是在Android平臺上進行開發(fā)的。相比ios,Android的以下優(yōu)勢為Android提供技術支持。1、Android物美價廉性能強購買商品時,普通的消費者的大部分都是首先看價格。每個人都想用最少的錢買到最好的商品。蘋果手機不錯,但是價格是安卓的幾倍。蘋果就像一些高端化妝品。大家都想試試效果,但是因為價格高,只能打消這個念頭。而且還有一些非常常見的化妝品,隨處都可以買到,價格也不貴,甚至有些效果可以媲美高端。Android就像這個普通的化妝品,可以給用戶帶來全方位的良好體驗。有時,電話價格不一定與性能成正比。人們希望他們能買到便宜的商品,安卓手機是一種非常經濟的類型。使用蘋果手機的人會覺得蘋果使用起來特別困難,雖然功能很多,但大多數都是普通生活中無法使用的多余功能。相比之下,Android手機簡單易用,甚至有些Android與蘋果在外觀上也相差無幾。使用時,觸摸效果可能更好。與Android的最佳價格相比,大多數人買不起的iphone價格很好。而且在手機性能和使用感覺上不會輸給iphone。2、應用程序發(fā)展迅速原來的電話是那種最普通的電話,只能打電話和接電話。相比之下,手機現在不再叫手機,而是叫智能手機。之前添加的兩個智能詞也足以說明現在手機的能力有多強?,F在,人們的手機上有不同的app,裝載著密麻麻。智能手機在手機市場上可能如此受歡迎,以至于它們也與此密不可分。雖然安卓應用程序在數量上比蘋果大,但在質量上還是無法與蘋果商店的應用程序相比。雖然在質量上比不上IOs,但在數量上卻比不上。例如,在同一時間,安卓開發(fā)的應用程序是蘋果的十倍。而且安卓應用程序的數量還在增加。如此可見,以后Android仍能與IOs競爭。蘋果在下載應用的時候,想要下載一個應用,必須經過復雜的驗證層。有些應用甚至沒有在蘋果的應用商店中發(fā)布。Android可以隨意下載自己喜歡的應用。你能找到的任何東西都可以下載。3、眾多手機廠家的支持蘋果專注于自身從硬件到軟件和促銷。而且這種短期的自我中心主義方法也取得了良好的效果。在這個封閉的空間里,蘋果雖然不斷創(chuàng)新,但最終還是被困在了這個空間里。從短期來看,消費者對新鮮度可以得到很大的滿足。但是,這不利于長期發(fā)展。目前,三星、華為、鬼等市面上一些最受歡迎的Android廠商已經確立了自己的品牌特征。并推出了一系列手機。不僅如此,他們中的很多人,比如三星,還與谷歌建立了技術平臺的開發(fā)。在這些大制造商的領導下,加入這個聯盟的制造商層出不窮。因此,越來越多的手機品牌應運而生。用戶也有更多的選擇,在相互競爭的情況下,Android必然會越來越廣受歡迎。4、運營商的鼎力支持在國內,中國移動、中國聯通、中國電信也趕上了安卓的潮流。都推出了各種手機優(yōu)惠。此外,美國、德國、意大利、日本、法國等國家也有大量來自該陣營的志愿者。這么大的用戶群體的支持,不僅證明了Android的可靠性,也加速了Android在全球的普及。安卓的聯盟與蘋果的聯盟形成鮮明對比。蘋果特有的封閉獨立帶來一定的優(yōu)勢,但同時也對蘋果的制造商和運營商構成威脅。5、眾多的機型和優(yōu)質的配置在激烈的安卓市場競爭中,大型制造商在安卓手機上添加自己的元素,形成安卓手機品牌。形狀多樣,特點各異,黑色技術多種多樣。三星、華為等品牌的多元化將不可避免地促進手機的多元化。這些手機品牌積極創(chuàng)造了自己的品牌,也添加了很多黑色技術,大大滿足了用戶的體驗。相反,蘋果一直很閉關鎖國不接受新鮮事物。由于蘋果系統的不開放性,蘋果的特色都是來自于內部的不懈努力。而Android的開源為程序員提供了不小的便利。每個第三方都可以在原有的Android系統上的軟硬件設施都可以在第三方軟件上增加,在多次的改進研發(fā)與進化之下,Android已經與眾不同,浴火重生。相比蘋果的不開放性,Android的開源給開發(fā)員提供了無限的自由。開發(fā)員可以發(fā)揮天馬行空的想象,讓Android的發(fā)展愈來愈好。4.2系統需求分析根據分析需求,這個系統必須實現以下的功能:(1)實施電話支持的視頻格式文件的播放。作為一個播放器,核心是順利播放視頻文件。手機通常沒有太多的解碼形式,如RMVB。您應該能夠順利地播放,可作為移動電話攜帶的視頻流文件。(2)可以在手機中找到視頻文件。通過自定義文件列表,訪問手機中可訪問的所有視頻文件。因此,無需在系統中的固定位置放置視頻文件。通過創(chuàng)建一個保存視頻文件的新文件夾,然后將視頻文件放在位置。通過這種方式,您可以方便搜索以及觀看視頻文件。(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通過循環(huán)讀取數據進行解處理,解碼,封裝數據。釋放資源在解碼時看到音頻數據直接進入到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維護解碼線程的主要交接函數在上文已經提及。此方法會循環(huán),每次循環(huán)之后會wait,當有signal信號傳來時進行解碼。音頻視頻同步方法:音頻向視頻對齊音頻幀根據視頻幀的時間戳進行渲染。渲染視頻幀時,會將音頻幀與視頻幀的時間戳進行比較。如果差值不在閾值內,則應進行校準。對齊的主要操作是音頻幀。如果音頻幀的時間戳小于視頻幀的時間戳,則需要跳幀,就像快進操作一樣;如果音頻幀的時間戳大于視頻幀的時間戳,則需要等待視頻幀播放。實現方法是在視頻幀追上時,填充空的音頻數據,播放當前的音頻幀數據。優(yōu)點:用戶可以看到視頻的每一幀,并且看起來很流暢缺點:空幀靜音或丟幀會在音頻中出現。視頻向音頻對齊:此方法與以上相反。統一向外部時鐘對齊:從外部提供時鐘,獲取音頻視頻幀的數據時,與外部時鐘對準,如果不超過閾值則直接返回音頻視頻幀,如果超過則進行上述對準操作,分別進行音頻、視頻和外部時鐘。人的耳朵比眼睛敏感得多,如果聲音有跳幀或空幀,我們就容易注意到;視頻中有跳躍幀和重復幀,用眼睛很難分辨。在這個項目中,使用了視頻與音頻的對齊。集合控制系統初始化:初始化包括視頻渲染界面的初始化,音頻播放器初始化。運行:初始化音頻輸出模塊,OpenGLES播放緩沖區(qū)的音頻數據后,返回video_palyer_controller.cpp填充數據。判斷數據的填充方法有幾列,如果最后不滿意,則調用同步模塊的音頻數據的填充方法,填充音頻數據后,向視頻輸出發(fā)送命令,更新畫面,視頻輸出接收到方法后由于整個動作由音頻播放驅動,所以播放暫停等操作只要控制音頻播放模塊即可。銷毀:創(chuàng)建的逆過程為銷毀過程??偨Y看了幾天整個項目的代碼,發(fā)現里面有一個完整的邏輯,有很多實現細節(jié)值得學習。其中Opegl的實現細節(jié)不詳細。通過觀察整個代碼可以得知整個代碼都是有邏輯可言的,簡而言之,如果你不理解它,你可以看到你理解它,并整理代碼的思想。5.2用戶登錄注冊登錄界面設計,給button設置一個id屬性登錄按鈕:Android:id=“@+id/btn_login”,注冊按鈕:Android:id=“@+id/btn_register,”創(chuàng)建好之后再在Mainactivity中創(chuàng)建變量privatebuttonbtnlogin,privatebuttonbtnregister。之后寫代碼Intentin=newIntent(MainActivity.this,LoginActivity.class);//startActivity(in);點擊登錄按鈕后會執(zhí)行此代碼,通過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創(chuàng)建數據庫,數據庫頁面代碼如下: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){//監(jiān)聽VideoViewManager釋放,重置狀態(tài)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. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論