flv.js 618 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056
  1. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.flvjs = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  2. (function (process,global){
  3. /*!
  4. * @overview es6-promise - a tiny implementation of Promises/A+.
  5. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
  6. * @license Licensed under MIT license
  7. * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
  8. * @version v4.2.5+7f2b526d
  9. */
  10. (function (global, factory) {
  11. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  12. typeof define === 'function' && define.amd ? define(factory) :
  13. (global.ES6Promise = factory());
  14. }(this, (function () { 'use strict';
  15. function objectOrFunction(x) {
  16. var type = typeof x;
  17. return x !== null && (type === 'object' || type === 'function');
  18. }
  19. function isFunction(x) {
  20. return typeof x === 'function';
  21. }
  22. var _isArray = void 0;
  23. if (Array.isArray) {
  24. _isArray = Array.isArray;
  25. } else {
  26. _isArray = function (x) {
  27. return Object.prototype.toString.call(x) === '[object Array]';
  28. };
  29. }
  30. var isArray = _isArray;
  31. var len = 0;
  32. var vertxNext = void 0;
  33. var customSchedulerFn = void 0;
  34. var asap = function asap(callback, arg) {
  35. queue[len] = callback;
  36. queue[len + 1] = arg;
  37. len += 2;
  38. if (len === 2) {
  39. // If len is 2, that means that we need to schedule an async flush.
  40. // If additional callbacks are queued before the queue is flushed, they
  41. // will be processed by this flush that we are scheduling.
  42. if (customSchedulerFn) {
  43. customSchedulerFn(flush);
  44. } else {
  45. scheduleFlush();
  46. }
  47. }
  48. };
  49. function setScheduler(scheduleFn) {
  50. customSchedulerFn = scheduleFn;
  51. }
  52. function setAsap(asapFn) {
  53. asap = asapFn;
  54. }
  55. var browserWindow = typeof window !== 'undefined' ? window : undefined;
  56. var browserGlobal = browserWindow || {};
  57. var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
  58. var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
  59. // test for web worker but not in IE10
  60. var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
  61. // node
  62. function useNextTick() {
  63. // node version 0.10.x displays a deprecation warning when nextTick is used recursively
  64. // see https://github.com/cujojs/when/issues/410 for details
  65. return function () {
  66. return process.nextTick(flush);
  67. };
  68. }
  69. // vertx
  70. function useVertxTimer() {
  71. if (typeof vertxNext !== 'undefined') {
  72. return function () {
  73. vertxNext(flush);
  74. };
  75. }
  76. return useSetTimeout();
  77. }
  78. function useMutationObserver() {
  79. var iterations = 0;
  80. var observer = new BrowserMutationObserver(flush);
  81. var node = document.createTextNode('');
  82. observer.observe(node, { characterData: true });
  83. return function () {
  84. node.data = iterations = ++iterations % 2;
  85. };
  86. }
  87. // web worker
  88. function useMessageChannel() {
  89. var channel = new MessageChannel();
  90. channel.port1.onmessage = flush;
  91. return function () {
  92. return channel.port2.postMessage(0);
  93. };
  94. }
  95. function useSetTimeout() {
  96. // Store setTimeout reference so es6-promise will be unaffected by
  97. // other code modifying setTimeout (like sinon.useFakeTimers())
  98. var globalSetTimeout = setTimeout;
  99. return function () {
  100. return globalSetTimeout(flush, 1);
  101. };
  102. }
  103. var queue = new Array(1000);
  104. function flush() {
  105. for (var i = 0; i < len; i += 2) {
  106. var callback = queue[i];
  107. var arg = queue[i + 1];
  108. callback(arg);
  109. queue[i] = undefined;
  110. queue[i + 1] = undefined;
  111. }
  112. len = 0;
  113. }
  114. function attemptVertx() {
  115. try {
  116. var vertx = Function('return this')().require('vertx');
  117. vertxNext = vertx.runOnLoop || vertx.runOnContext;
  118. return useVertxTimer();
  119. } catch (e) {
  120. return useSetTimeout();
  121. }
  122. }
  123. var scheduleFlush = void 0;
  124. // Decide what async method to use to triggering processing of queued callbacks:
  125. if (isNode) {
  126. scheduleFlush = useNextTick();
  127. } else if (BrowserMutationObserver) {
  128. scheduleFlush = useMutationObserver();
  129. } else if (isWorker) {
  130. scheduleFlush = useMessageChannel();
  131. } else if (browserWindow === undefined && typeof _dereq_ === 'function') {
  132. scheduleFlush = attemptVertx();
  133. } else {
  134. scheduleFlush = useSetTimeout();
  135. }
  136. function then(onFulfillment, onRejection) {
  137. var parent = this;
  138. var child = new this.constructor(noop);
  139. if (child[PROMISE_ID] === undefined) {
  140. makePromise(child);
  141. }
  142. var _state = parent._state;
  143. if (_state) {
  144. var callback = arguments[_state - 1];
  145. asap(function () {
  146. return invokeCallback(_state, child, callback, parent._result);
  147. });
  148. } else {
  149. subscribe(parent, child, onFulfillment, onRejection);
  150. }
  151. return child;
  152. }
  153. /**
  154. `Promise.resolve` returns a promise that will become resolved with the
  155. passed `value`. It is shorthand for the following:
  156. ```javascript
  157. let promise = new Promise(function(resolve, reject){
  158. resolve(1);
  159. });
  160. promise.then(function(value){
  161. // value === 1
  162. });
  163. ```
  164. Instead of writing the above, your code now simply becomes the following:
  165. ```javascript
  166. let promise = Promise.resolve(1);
  167. promise.then(function(value){
  168. // value === 1
  169. });
  170. ```
  171. @method resolve
  172. @static
  173. @param {Any} value value that the returned promise will be resolved with
  174. Useful for tooling.
  175. @return {Promise} a promise that will become fulfilled with the given
  176. `value`
  177. */
  178. function resolve$1(object) {
  179. /*jshint validthis:true */
  180. var Constructor = this;
  181. if (object && typeof object === 'object' && object.constructor === Constructor) {
  182. return object;
  183. }
  184. var promise = new Constructor(noop);
  185. resolve(promise, object);
  186. return promise;
  187. }
  188. var PROMISE_ID = Math.random().toString(36).substring(2);
  189. function noop() {}
  190. var PENDING = void 0;
  191. var FULFILLED = 1;
  192. var REJECTED = 2;
  193. var TRY_CATCH_ERROR = { error: null };
  194. function selfFulfillment() {
  195. return new TypeError("You cannot resolve a promise with itself");
  196. }
  197. function cannotReturnOwn() {
  198. return new TypeError('A promises callback cannot return that same promise.');
  199. }
  200. function getThen(promise) {
  201. try {
  202. return promise.then;
  203. } catch (error) {
  204. TRY_CATCH_ERROR.error = error;
  205. return TRY_CATCH_ERROR;
  206. }
  207. }
  208. function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
  209. try {
  210. then$$1.call(value, fulfillmentHandler, rejectionHandler);
  211. } catch (e) {
  212. return e;
  213. }
  214. }
  215. function handleForeignThenable(promise, thenable, then$$1) {
  216. asap(function (promise) {
  217. var sealed = false;
  218. var error = tryThen(then$$1, thenable, function (value) {
  219. if (sealed) {
  220. return;
  221. }
  222. sealed = true;
  223. if (thenable !== value) {
  224. resolve(promise, value);
  225. } else {
  226. fulfill(promise, value);
  227. }
  228. }, function (reason) {
  229. if (sealed) {
  230. return;
  231. }
  232. sealed = true;
  233. reject(promise, reason);
  234. }, 'Settle: ' + (promise._label || ' unknown promise'));
  235. if (!sealed && error) {
  236. sealed = true;
  237. reject(promise, error);
  238. }
  239. }, promise);
  240. }
  241. function handleOwnThenable(promise, thenable) {
  242. if (thenable._state === FULFILLED) {
  243. fulfill(promise, thenable._result);
  244. } else if (thenable._state === REJECTED) {
  245. reject(promise, thenable._result);
  246. } else {
  247. subscribe(thenable, undefined, function (value) {
  248. return resolve(promise, value);
  249. }, function (reason) {
  250. return reject(promise, reason);
  251. });
  252. }
  253. }
  254. function handleMaybeThenable(promise, maybeThenable, then$$1) {
  255. if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
  256. handleOwnThenable(promise, maybeThenable);
  257. } else {
  258. if (then$$1 === TRY_CATCH_ERROR) {
  259. reject(promise, TRY_CATCH_ERROR.error);
  260. TRY_CATCH_ERROR.error = null;
  261. } else if (then$$1 === undefined) {
  262. fulfill(promise, maybeThenable);
  263. } else if (isFunction(then$$1)) {
  264. handleForeignThenable(promise, maybeThenable, then$$1);
  265. } else {
  266. fulfill(promise, maybeThenable);
  267. }
  268. }
  269. }
  270. function resolve(promise, value) {
  271. if (promise === value) {
  272. reject(promise, selfFulfillment());
  273. } else if (objectOrFunction(value)) {
  274. handleMaybeThenable(promise, value, getThen(value));
  275. } else {
  276. fulfill(promise, value);
  277. }
  278. }
  279. function publishRejection(promise) {
  280. if (promise._onerror) {
  281. promise._onerror(promise._result);
  282. }
  283. publish(promise);
  284. }
  285. function fulfill(promise, value) {
  286. if (promise._state !== PENDING) {
  287. return;
  288. }
  289. promise._result = value;
  290. promise._state = FULFILLED;
  291. if (promise._subscribers.length !== 0) {
  292. asap(publish, promise);
  293. }
  294. }
  295. function reject(promise, reason) {
  296. if (promise._state !== PENDING) {
  297. return;
  298. }
  299. promise._state = REJECTED;
  300. promise._result = reason;
  301. asap(publishRejection, promise);
  302. }
  303. function subscribe(parent, child, onFulfillment, onRejection) {
  304. var _subscribers = parent._subscribers;
  305. var length = _subscribers.length;
  306. parent._onerror = null;
  307. _subscribers[length] = child;
  308. _subscribers[length + FULFILLED] = onFulfillment;
  309. _subscribers[length + REJECTED] = onRejection;
  310. if (length === 0 && parent._state) {
  311. asap(publish, parent);
  312. }
  313. }
  314. function publish(promise) {
  315. var subscribers = promise._subscribers;
  316. var settled = promise._state;
  317. if (subscribers.length === 0) {
  318. return;
  319. }
  320. var child = void 0,
  321. callback = void 0,
  322. detail = promise._result;
  323. for (var i = 0; i < subscribers.length; i += 3) {
  324. child = subscribers[i];
  325. callback = subscribers[i + settled];
  326. if (child) {
  327. invokeCallback(settled, child, callback, detail);
  328. } else {
  329. callback(detail);
  330. }
  331. }
  332. promise._subscribers.length = 0;
  333. }
  334. function tryCatch(callback, detail) {
  335. try {
  336. return callback(detail);
  337. } catch (e) {
  338. TRY_CATCH_ERROR.error = e;
  339. return TRY_CATCH_ERROR;
  340. }
  341. }
  342. function invokeCallback(settled, promise, callback, detail) {
  343. var hasCallback = isFunction(callback),
  344. value = void 0,
  345. error = void 0,
  346. succeeded = void 0,
  347. failed = void 0;
  348. if (hasCallback) {
  349. value = tryCatch(callback, detail);
  350. if (value === TRY_CATCH_ERROR) {
  351. failed = true;
  352. error = value.error;
  353. value.error = null;
  354. } else {
  355. succeeded = true;
  356. }
  357. if (promise === value) {
  358. reject(promise, cannotReturnOwn());
  359. return;
  360. }
  361. } else {
  362. value = detail;
  363. succeeded = true;
  364. }
  365. if (promise._state !== PENDING) {
  366. // noop
  367. } else if (hasCallback && succeeded) {
  368. resolve(promise, value);
  369. } else if (failed) {
  370. reject(promise, error);
  371. } else if (settled === FULFILLED) {
  372. fulfill(promise, value);
  373. } else if (settled === REJECTED) {
  374. reject(promise, value);
  375. }
  376. }
  377. function initializePromise(promise, resolver) {
  378. try {
  379. resolver(function resolvePromise(value) {
  380. resolve(promise, value);
  381. }, function rejectPromise(reason) {
  382. reject(promise, reason);
  383. });
  384. } catch (e) {
  385. reject(promise, e);
  386. }
  387. }
  388. var id = 0;
  389. function nextId() {
  390. return id++;
  391. }
  392. function makePromise(promise) {
  393. promise[PROMISE_ID] = id++;
  394. promise._state = undefined;
  395. promise._result = undefined;
  396. promise._subscribers = [];
  397. }
  398. function validationError() {
  399. return new Error('Array Methods must be provided an Array');
  400. }
  401. var Enumerator = function () {
  402. function Enumerator(Constructor, input) {
  403. this._instanceConstructor = Constructor;
  404. this.promise = new Constructor(noop);
  405. if (!this.promise[PROMISE_ID]) {
  406. makePromise(this.promise);
  407. }
  408. if (isArray(input)) {
  409. this.length = input.length;
  410. this._remaining = input.length;
  411. this._result = new Array(this.length);
  412. if (this.length === 0) {
  413. fulfill(this.promise, this._result);
  414. } else {
  415. this.length = this.length || 0;
  416. this._enumerate(input);
  417. if (this._remaining === 0) {
  418. fulfill(this.promise, this._result);
  419. }
  420. }
  421. } else {
  422. reject(this.promise, validationError());
  423. }
  424. }
  425. Enumerator.prototype._enumerate = function _enumerate(input) {
  426. for (var i = 0; this._state === PENDING && i < input.length; i++) {
  427. this._eachEntry(input[i], i);
  428. }
  429. };
  430. Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {
  431. var c = this._instanceConstructor;
  432. var resolve$$1 = c.resolve;
  433. if (resolve$$1 === resolve$1) {
  434. var _then = getThen(entry);
  435. if (_then === then && entry._state !== PENDING) {
  436. this._settledAt(entry._state, i, entry._result);
  437. } else if (typeof _then !== 'function') {
  438. this._remaining--;
  439. this._result[i] = entry;
  440. } else if (c === Promise$1) {
  441. var promise = new c(noop);
  442. handleMaybeThenable(promise, entry, _then);
  443. this._willSettleAt(promise, i);
  444. } else {
  445. this._willSettleAt(new c(function (resolve$$1) {
  446. return resolve$$1(entry);
  447. }), i);
  448. }
  449. } else {
  450. this._willSettleAt(resolve$$1(entry), i);
  451. }
  452. };
  453. Enumerator.prototype._settledAt = function _settledAt(state, i, value) {
  454. var promise = this.promise;
  455. if (promise._state === PENDING) {
  456. this._remaining--;
  457. if (state === REJECTED) {
  458. reject(promise, value);
  459. } else {
  460. this._result[i] = value;
  461. }
  462. }
  463. if (this._remaining === 0) {
  464. fulfill(promise, this._result);
  465. }
  466. };
  467. Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {
  468. var enumerator = this;
  469. subscribe(promise, undefined, function (value) {
  470. return enumerator._settledAt(FULFILLED, i, value);
  471. }, function (reason) {
  472. return enumerator._settledAt(REJECTED, i, reason);
  473. });
  474. };
  475. return Enumerator;
  476. }();
  477. /**
  478. `Promise.all` accepts an array of promises, and returns a new promise which
  479. is fulfilled with an array of fulfillment values for the passed promises, or
  480. rejected with the reason of the first passed promise to be rejected. It casts all
  481. elements of the passed iterable to promises as it runs this algorithm.
  482. Example:
  483. ```javascript
  484. let promise1 = resolve(1);
  485. let promise2 = resolve(2);
  486. let promise3 = resolve(3);
  487. let promises = [ promise1, promise2, promise3 ];
  488. Promise.all(promises).then(function(array){
  489. // The array here would be [ 1, 2, 3 ];
  490. });
  491. ```
  492. If any of the `promises` given to `all` are rejected, the first promise
  493. that is rejected will be given as an argument to the returned promises's
  494. rejection handler. For example:
  495. Example:
  496. ```javascript
  497. let promise1 = resolve(1);
  498. let promise2 = reject(new Error("2"));
  499. let promise3 = reject(new Error("3"));
  500. let promises = [ promise1, promise2, promise3 ];
  501. Promise.all(promises).then(function(array){
  502. // Code here never runs because there are rejected promises!
  503. }, function(error) {
  504. // error.message === "2"
  505. });
  506. ```
  507. @method all
  508. @static
  509. @param {Array} entries array of promises
  510. @param {String} label optional string for labeling the promise.
  511. Useful for tooling.
  512. @return {Promise} promise that is fulfilled when all `promises` have been
  513. fulfilled, or rejected if any of them become rejected.
  514. @static
  515. */
  516. function all(entries) {
  517. return new Enumerator(this, entries).promise;
  518. }
  519. /**
  520. `Promise.race` returns a new promise which is settled in the same way as the
  521. first passed promise to settle.
  522. Example:
  523. ```javascript
  524. let promise1 = new Promise(function(resolve, reject){
  525. setTimeout(function(){
  526. resolve('promise 1');
  527. }, 200);
  528. });
  529. let promise2 = new Promise(function(resolve, reject){
  530. setTimeout(function(){
  531. resolve('promise 2');
  532. }, 100);
  533. });
  534. Promise.race([promise1, promise2]).then(function(result){
  535. // result === 'promise 2' because it was resolved before promise1
  536. // was resolved.
  537. });
  538. ```
  539. `Promise.race` is deterministic in that only the state of the first
  540. settled promise matters. For example, even if other promises given to the
  541. `promises` array argument are resolved, but the first settled promise has
  542. become rejected before the other promises became fulfilled, the returned
  543. promise will become rejected:
  544. ```javascript
  545. let promise1 = new Promise(function(resolve, reject){
  546. setTimeout(function(){
  547. resolve('promise 1');
  548. }, 200);
  549. });
  550. let promise2 = new Promise(function(resolve, reject){
  551. setTimeout(function(){
  552. reject(new Error('promise 2'));
  553. }, 100);
  554. });
  555. Promise.race([promise1, promise2]).then(function(result){
  556. // Code here never runs
  557. }, function(reason){
  558. // reason.message === 'promise 2' because promise 2 became rejected before
  559. // promise 1 became fulfilled
  560. });
  561. ```
  562. An example real-world use case is implementing timeouts:
  563. ```javascript
  564. Promise.race([ajax('foo.json'), timeout(5000)])
  565. ```
  566. @method race
  567. @static
  568. @param {Array} promises array of promises to observe
  569. Useful for tooling.
  570. @return {Promise} a promise which settles in the same way as the first passed
  571. promise to settle.
  572. */
  573. function race(entries) {
  574. /*jshint validthis:true */
  575. var Constructor = this;
  576. if (!isArray(entries)) {
  577. return new Constructor(function (_, reject) {
  578. return reject(new TypeError('You must pass an array to race.'));
  579. });
  580. } else {
  581. return new Constructor(function (resolve, reject) {
  582. var length = entries.length;
  583. for (var i = 0; i < length; i++) {
  584. Constructor.resolve(entries[i]).then(resolve, reject);
  585. }
  586. });
  587. }
  588. }
  589. /**
  590. `Promise.reject` returns a promise rejected with the passed `reason`.
  591. It is shorthand for the following:
  592. ```javascript
  593. let promise = new Promise(function(resolve, reject){
  594. reject(new Error('WHOOPS'));
  595. });
  596. promise.then(function(value){
  597. // Code here doesn't run because the promise is rejected!
  598. }, function(reason){
  599. // reason.message === 'WHOOPS'
  600. });
  601. ```
  602. Instead of writing the above, your code now simply becomes the following:
  603. ```javascript
  604. let promise = Promise.reject(new Error('WHOOPS'));
  605. promise.then(function(value){
  606. // Code here doesn't run because the promise is rejected!
  607. }, function(reason){
  608. // reason.message === 'WHOOPS'
  609. });
  610. ```
  611. @method reject
  612. @static
  613. @param {Any} reason value that the returned promise will be rejected with.
  614. Useful for tooling.
  615. @return {Promise} a promise rejected with the given `reason`.
  616. */
  617. function reject$1(reason) {
  618. /*jshint validthis:true */
  619. var Constructor = this;
  620. var promise = new Constructor(noop);
  621. reject(promise, reason);
  622. return promise;
  623. }
  624. function needsResolver() {
  625. throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
  626. }
  627. function needsNew() {
  628. throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
  629. }
  630. /**
  631. Promise objects represent the eventual result of an asynchronous operation. The
  632. primary way of interacting with a promise is through its `then` method, which
  633. registers callbacks to receive either a promise's eventual value or the reason
  634. why the promise cannot be fulfilled.
  635. Terminology
  636. -----------
  637. - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
  638. - `thenable` is an object or function that defines a `then` method.
  639. - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
  640. - `exception` is a value that is thrown using the throw statement.
  641. - `reason` is a value that indicates why a promise was rejected.
  642. - `settled` the final resting state of a promise, fulfilled or rejected.
  643. A promise can be in one of three states: pending, fulfilled, or rejected.
  644. Promises that are fulfilled have a fulfillment value and are in the fulfilled
  645. state. Promises that are rejected have a rejection reason and are in the
  646. rejected state. A fulfillment value is never a thenable.
  647. Promises can also be said to *resolve* a value. If this value is also a
  648. promise, then the original promise's settled state will match the value's
  649. settled state. So a promise that *resolves* a promise that rejects will
  650. itself reject, and a promise that *resolves* a promise that fulfills will
  651. itself fulfill.
  652. Basic Usage:
  653. ------------
  654. ```js
  655. let promise = new Promise(function(resolve, reject) {
  656. // on success
  657. resolve(value);
  658. // on failure
  659. reject(reason);
  660. });
  661. promise.then(function(value) {
  662. // on fulfillment
  663. }, function(reason) {
  664. // on rejection
  665. });
  666. ```
  667. Advanced Usage:
  668. ---------------
  669. Promises shine when abstracting away asynchronous interactions such as
  670. `XMLHttpRequest`s.
  671. ```js
  672. function getJSON(url) {
  673. return new Promise(function(resolve, reject){
  674. let xhr = new XMLHttpRequest();
  675. xhr.open('GET', url);
  676. xhr.onreadystatechange = handler;
  677. xhr.responseType = 'json';
  678. xhr.setRequestHeader('Accept', 'application/json');
  679. xhr.send();
  680. function handler() {
  681. if (this.readyState === this.DONE) {
  682. if (this.status === 200) {
  683. resolve(this.response);
  684. } else {
  685. reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
  686. }
  687. }
  688. };
  689. });
  690. }
  691. getJSON('/posts.json').then(function(json) {
  692. // on fulfillment
  693. }, function(reason) {
  694. // on rejection
  695. });
  696. ```
  697. Unlike callbacks, promises are great composable primitives.
  698. ```js
  699. Promise.all([
  700. getJSON('/posts'),
  701. getJSON('/comments')
  702. ]).then(function(values){
  703. values[0] // => postsJSON
  704. values[1] // => commentsJSON
  705. return values;
  706. });
  707. ```
  708. @class Promise
  709. @param {Function} resolver
  710. Useful for tooling.
  711. @constructor
  712. */
  713. var Promise$1 = function () {
  714. function Promise(resolver) {
  715. this[PROMISE_ID] = nextId();
  716. this._result = this._state = undefined;
  717. this._subscribers = [];
  718. if (noop !== resolver) {
  719. typeof resolver !== 'function' && needsResolver();
  720. this instanceof Promise ? initializePromise(this, resolver) : needsNew();
  721. }
  722. }
  723. /**
  724. The primary way of interacting with a promise is through its `then` method,
  725. which registers callbacks to receive either a promise's eventual value or the
  726. reason why the promise cannot be fulfilled.
  727. ```js
  728. findUser().then(function(user){
  729. // user is available
  730. }, function(reason){
  731. // user is unavailable, and you are given the reason why
  732. });
  733. ```
  734. Chaining
  735. --------
  736. The return value of `then` is itself a promise. This second, 'downstream'
  737. promise is resolved with the return value of the first promise's fulfillment
  738. or rejection handler, or rejected if the handler throws an exception.
  739. ```js
  740. findUser().then(function (user) {
  741. return user.name;
  742. }, function (reason) {
  743. return 'default name';
  744. }).then(function (userName) {
  745. // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
  746. // will be `'default name'`
  747. });
  748. findUser().then(function (user) {
  749. throw new Error('Found user, but still unhappy');
  750. }, function (reason) {
  751. throw new Error('`findUser` rejected and we're unhappy');
  752. }).then(function (value) {
  753. // never reached
  754. }, function (reason) {
  755. // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
  756. // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
  757. });
  758. ```
  759. If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
  760. ```js
  761. findUser().then(function (user) {
  762. throw new PedagogicalException('Upstream error');
  763. }).then(function (value) {
  764. // never reached
  765. }).then(function (value) {
  766. // never reached
  767. }, function (reason) {
  768. // The `PedgagocialException` is propagated all the way down to here
  769. });
  770. ```
  771. Assimilation
  772. ------------
  773. Sometimes the value you want to propagate to a downstream promise can only be
  774. retrieved asynchronously. This can be achieved by returning a promise in the
  775. fulfillment or rejection handler. The downstream promise will then be pending
  776. until the returned promise is settled. This is called *assimilation*.
  777. ```js
  778. findUser().then(function (user) {
  779. return findCommentsByAuthor(user);
  780. }).then(function (comments) {
  781. // The user's comments are now available
  782. });
  783. ```
  784. If the assimliated promise rejects, then the downstream promise will also reject.
  785. ```js
  786. findUser().then(function (user) {
  787. return findCommentsByAuthor(user);
  788. }).then(function (comments) {
  789. // If `findCommentsByAuthor` fulfills, we'll have the value here
  790. }, function (reason) {
  791. // If `findCommentsByAuthor` rejects, we'll have the reason here
  792. });
  793. ```
  794. Simple Example
  795. --------------
  796. Synchronous Example
  797. ```javascript
  798. let result;
  799. try {
  800. result = findResult();
  801. // success
  802. } catch(reason) {
  803. // failure
  804. }
  805. ```
  806. Errback Example
  807. ```js
  808. findResult(function(result, err){
  809. if (err) {
  810. // failure
  811. } else {
  812. // success
  813. }
  814. });
  815. ```
  816. Promise Example;
  817. ```javascript
  818. findResult().then(function(result){
  819. // success
  820. }, function(reason){
  821. // failure
  822. });
  823. ```
  824. Advanced Example
  825. --------------
  826. Synchronous Example
  827. ```javascript
  828. let author, books;
  829. try {
  830. author = findAuthor();
  831. books = findBooksByAuthor(author);
  832. // success
  833. } catch(reason) {
  834. // failure
  835. }
  836. ```
  837. Errback Example
  838. ```js
  839. function foundBooks(books) {
  840. }
  841. function failure(reason) {
  842. }
  843. findAuthor(function(author, err){
  844. if (err) {
  845. failure(err);
  846. // failure
  847. } else {
  848. try {
  849. findBoooksByAuthor(author, function(books, err) {
  850. if (err) {
  851. failure(err);
  852. } else {
  853. try {
  854. foundBooks(books);
  855. } catch(reason) {
  856. failure(reason);
  857. }
  858. }
  859. });
  860. } catch(error) {
  861. failure(err);
  862. }
  863. // success
  864. }
  865. });
  866. ```
  867. Promise Example;
  868. ```javascript
  869. findAuthor().
  870. then(findBooksByAuthor).
  871. then(function(books){
  872. // found books
  873. }).catch(function(reason){
  874. // something went wrong
  875. });
  876. ```
  877. @method then
  878. @param {Function} onFulfilled
  879. @param {Function} onRejected
  880. Useful for tooling.
  881. @return {Promise}
  882. */
  883. /**
  884. `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
  885. as the catch block of a try/catch statement.
  886. ```js
  887. function findAuthor(){
  888. throw new Error('couldn't find that author');
  889. }
  890. // synchronous
  891. try {
  892. findAuthor();
  893. } catch(reason) {
  894. // something went wrong
  895. }
  896. // async with promises
  897. findAuthor().catch(function(reason){
  898. // something went wrong
  899. });
  900. ```
  901. @method catch
  902. @param {Function} onRejection
  903. Useful for tooling.
  904. @return {Promise}
  905. */
  906. Promise.prototype.catch = function _catch(onRejection) {
  907. return this.then(null, onRejection);
  908. };
  909. /**
  910. `finally` will be invoked regardless of the promise's fate just as native
  911. try/catch/finally behaves
  912. Synchronous example:
  913. ```js
  914. findAuthor() {
  915. if (Math.random() > 0.5) {
  916. throw new Error();
  917. }
  918. return new Author();
  919. }
  920. try {
  921. return findAuthor(); // succeed or fail
  922. } catch(error) {
  923. return findOtherAuther();
  924. } finally {
  925. // always runs
  926. // doesn't affect the return value
  927. }
  928. ```
  929. Asynchronous example:
  930. ```js
  931. findAuthor().catch(function(reason){
  932. return findOtherAuther();
  933. }).finally(function(){
  934. // author was either found, or not
  935. });
  936. ```
  937. @method finally
  938. @param {Function} callback
  939. @return {Promise}
  940. */
  941. Promise.prototype.finally = function _finally(callback) {
  942. var promise = this;
  943. var constructor = promise.constructor;
  944. if (isFunction(callback)) {
  945. return promise.then(function (value) {
  946. return constructor.resolve(callback()).then(function () {
  947. return value;
  948. });
  949. }, function (reason) {
  950. return constructor.resolve(callback()).then(function () {
  951. throw reason;
  952. });
  953. });
  954. }
  955. return promise.then(callback, callback);
  956. };
  957. return Promise;
  958. }();
  959. Promise$1.prototype.then = then;
  960. Promise$1.all = all;
  961. Promise$1.race = race;
  962. Promise$1.resolve = resolve$1;
  963. Promise$1.reject = reject$1;
  964. Promise$1._setScheduler = setScheduler;
  965. Promise$1._setAsap = setAsap;
  966. Promise$1._asap = asap;
  967. /*global self*/
  968. function polyfill() {
  969. var local = void 0;
  970. if (typeof global !== 'undefined') {
  971. local = global;
  972. } else if (typeof self !== 'undefined') {
  973. local = self;
  974. } else {
  975. try {
  976. local = Function('return this')();
  977. } catch (e) {
  978. throw new Error('polyfill failed because global object is unavailable in this environment');
  979. }
  980. }
  981. var P = local.Promise;
  982. if (P) {
  983. var promiseToString = null;
  984. try {
  985. promiseToString = Object.prototype.toString.call(P.resolve());
  986. } catch (e) {
  987. // silently ignored
  988. }
  989. if (promiseToString === '[object Promise]' && !P.cast) {
  990. return;
  991. }
  992. }
  993. local.Promise = Promise$1;
  994. }
  995. // Strange compat..
  996. Promise$1.polyfill = polyfill;
  997. Promise$1.Promise = Promise$1;
  998. return Promise$1;
  999. })));
  1000. }).call(this,_dereq_('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  1001. },{"_process":3}],2:[function(_dereq_,module,exports){
  1002. // Copyright Joyent, Inc. and other Node contributors.
  1003. //
  1004. // Permission is hereby granted, free of charge, to any person obtaining a
  1005. // copy of this software and associated documentation files (the
  1006. // "Software"), to deal in the Software without restriction, including
  1007. // without limitation the rights to use, copy, modify, merge, publish,
  1008. // distribute, sublicense, and/or sell copies of the Software, and to permit
  1009. // persons to whom the Software is furnished to do so, subject to the
  1010. // following conditions:
  1011. //
  1012. // The above copyright notice and this permission notice shall be included
  1013. // in all copies or substantial portions of the Software.
  1014. //
  1015. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  1016. // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1017. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  1018. // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  1019. // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  1020. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  1021. // USE OR OTHER DEALINGS IN THE SOFTWARE.
  1022. function EventEmitter() {
  1023. this._events = this._events || {};
  1024. this._maxListeners = this._maxListeners || undefined;
  1025. }
  1026. module.exports = EventEmitter;
  1027. // Backwards-compat with node 0.10.x
  1028. EventEmitter.EventEmitter = EventEmitter;
  1029. EventEmitter.prototype._events = undefined;
  1030. EventEmitter.prototype._maxListeners = undefined;
  1031. // By default EventEmitters will print a warning if more than 10 listeners are
  1032. // added to it. This is a useful default which helps finding memory leaks.
  1033. EventEmitter.defaultMaxListeners = 10;
  1034. // Obviously not all Emitters should be limited to 10. This function allows
  1035. // that to be increased. Set to zero for unlimited.
  1036. EventEmitter.prototype.setMaxListeners = function(n) {
  1037. if (!isNumber(n) || n < 0 || isNaN(n))
  1038. throw TypeError('n must be a positive number');
  1039. this._maxListeners = n;
  1040. return this;
  1041. };
  1042. EventEmitter.prototype.emit = function(type) {
  1043. var er, handler, len, args, i, listeners;
  1044. if (!this._events)
  1045. this._events = {};
  1046. // If there is no 'error' event listener then throw.
  1047. if (type === 'error') {
  1048. if (!this._events.error ||
  1049. (isObject(this._events.error) && !this._events.error.length)) {
  1050. er = arguments[1];
  1051. if (er instanceof Error) {
  1052. throw er; // Unhandled 'error' event
  1053. } else {
  1054. // At least give some kind of context to the user
  1055. var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
  1056. err.context = er;
  1057. throw err;
  1058. }
  1059. }
  1060. }
  1061. handler = this._events[type];
  1062. if (isUndefined(handler))
  1063. return false;
  1064. if (isFunction(handler)) {
  1065. switch (arguments.length) {
  1066. // fast cases
  1067. case 1:
  1068. handler.call(this);
  1069. break;
  1070. case 2:
  1071. handler.call(this, arguments[1]);
  1072. break;
  1073. case 3:
  1074. handler.call(this, arguments[1], arguments[2]);
  1075. break;
  1076. // slower
  1077. default:
  1078. args = Array.prototype.slice.call(arguments, 1);
  1079. handler.apply(this, args);
  1080. }
  1081. } else if (isObject(handler)) {
  1082. args = Array.prototype.slice.call(arguments, 1);
  1083. listeners = handler.slice();
  1084. len = listeners.length;
  1085. for (i = 0; i < len; i++)
  1086. listeners[i].apply(this, args);
  1087. }
  1088. return true;
  1089. };
  1090. EventEmitter.prototype.addListener = function(type, listener) {
  1091. var m;
  1092. if (!isFunction(listener))
  1093. throw TypeError('listener must be a function');
  1094. if (!this._events)
  1095. this._events = {};
  1096. // To avoid recursion in the case that type === "newListener"! Before
  1097. // adding it to the listeners, first emit "newListener".
  1098. if (this._events.newListener)
  1099. this.emit('newListener', type,
  1100. isFunction(listener.listener) ?
  1101. listener.listener : listener);
  1102. if (!this._events[type])
  1103. // Optimize the case of one listener. Don't need the extra array object.
  1104. this._events[type] = listener;
  1105. else if (isObject(this._events[type]))
  1106. // If we've already got an array, just append.
  1107. this._events[type].push(listener);
  1108. else
  1109. // Adding the second element, need to change to array.
  1110. this._events[type] = [this._events[type], listener];
  1111. // Check for listener leak
  1112. if (isObject(this._events[type]) && !this._events[type].warned) {
  1113. if (!isUndefined(this._maxListeners)) {
  1114. m = this._maxListeners;
  1115. } else {
  1116. m = EventEmitter.defaultMaxListeners;
  1117. }
  1118. if (m && m > 0 && this._events[type].length > m) {
  1119. this._events[type].warned = true;
  1120. console.error('(node) warning: possible EventEmitter memory ' +
  1121. 'leak detected. %d listeners added. ' +
  1122. 'Use emitter.setMaxListeners() to increase limit.',
  1123. this._events[type].length);
  1124. if (typeof console.trace === 'function') {
  1125. // not supported in IE 10
  1126. console.trace();
  1127. }
  1128. }
  1129. }
  1130. return this;
  1131. };
  1132. EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  1133. EventEmitter.prototype.once = function(type, listener) {
  1134. if (!isFunction(listener))
  1135. throw TypeError('listener must be a function');
  1136. var fired = false;
  1137. function g() {
  1138. this.removeListener(type, g);
  1139. if (!fired) {
  1140. fired = true;
  1141. listener.apply(this, arguments);
  1142. }
  1143. }
  1144. g.listener = listener;
  1145. this.on(type, g);
  1146. return this;
  1147. };
  1148. // emits a 'removeListener' event iff the listener was removed
  1149. EventEmitter.prototype.removeListener = function(type, listener) {
  1150. var list, position, length, i;
  1151. if (!isFunction(listener))
  1152. throw TypeError('listener must be a function');
  1153. if (!this._events || !this._events[type])
  1154. return this;
  1155. list = this._events[type];
  1156. length = list.length;
  1157. position = -1;
  1158. if (list === listener ||
  1159. (isFunction(list.listener) && list.listener === listener)) {
  1160. delete this._events[type];
  1161. if (this._events.removeListener)
  1162. this.emit('removeListener', type, listener);
  1163. } else if (isObject(list)) {
  1164. for (i = length; i-- > 0;) {
  1165. if (list[i] === listener ||
  1166. (list[i].listener && list[i].listener === listener)) {
  1167. position = i;
  1168. break;
  1169. }
  1170. }
  1171. if (position < 0)
  1172. return this;
  1173. if (list.length === 1) {
  1174. list.length = 0;
  1175. delete this._events[type];
  1176. } else {
  1177. list.splice(position, 1);
  1178. }
  1179. if (this._events.removeListener)
  1180. this.emit('removeListener', type, listener);
  1181. }
  1182. return this;
  1183. };
  1184. EventEmitter.prototype.removeAllListeners = function(type) {
  1185. var key, listeners;
  1186. if (!this._events)
  1187. return this;
  1188. // not listening for removeListener, no need to emit
  1189. if (!this._events.removeListener) {
  1190. if (arguments.length === 0)
  1191. this._events = {};
  1192. else if (this._events[type])
  1193. delete this._events[type];
  1194. return this;
  1195. }
  1196. // emit removeListener for all listeners on all events
  1197. if (arguments.length === 0) {
  1198. for (key in this._events) {
  1199. if (key === 'removeListener') continue;
  1200. this.removeAllListeners(key);
  1201. }
  1202. this.removeAllListeners('removeListener');
  1203. this._events = {};
  1204. return this;
  1205. }
  1206. listeners = this._events[type];
  1207. if (isFunction(listeners)) {
  1208. this.removeListener(type, listeners);
  1209. } else if (listeners) {
  1210. // LIFO order
  1211. while (listeners.length)
  1212. this.removeListener(type, listeners[listeners.length - 1]);
  1213. }
  1214. delete this._events[type];
  1215. return this;
  1216. };
  1217. EventEmitter.prototype.listeners = function(type) {
  1218. var ret;
  1219. if (!this._events || !this._events[type])
  1220. ret = [];
  1221. else if (isFunction(this._events[type]))
  1222. ret = [this._events[type]];
  1223. else
  1224. ret = this._events[type].slice();
  1225. return ret;
  1226. };
  1227. EventEmitter.prototype.listenerCount = function(type) {
  1228. if (this._events) {
  1229. var evlistener = this._events[type];
  1230. if (isFunction(evlistener))
  1231. return 1;
  1232. else if (evlistener)
  1233. return evlistener.length;
  1234. }
  1235. return 0;
  1236. };
  1237. EventEmitter.listenerCount = function(emitter, type) {
  1238. return emitter.listenerCount(type);
  1239. };
  1240. function isFunction(arg) {
  1241. return typeof arg === 'function';
  1242. }
  1243. function isNumber(arg) {
  1244. return typeof arg === 'number';
  1245. }
  1246. function isObject(arg) {
  1247. return typeof arg === 'object' && arg !== null;
  1248. }
  1249. function isUndefined(arg) {
  1250. return arg === void 0;
  1251. }
  1252. },{}],3:[function(_dereq_,module,exports){
  1253. // shim for using process in browser
  1254. var process = module.exports = {};
  1255. // cached from whatever global is present so that test runners that stub it
  1256. // don't break things. But we need to wrap it in a try catch in case it is
  1257. // wrapped in strict mode code which doesn't define any globals. It's inside a
  1258. // function because try/catches deoptimize in certain engines.
  1259. var cachedSetTimeout;
  1260. var cachedClearTimeout;
  1261. function defaultSetTimout() {
  1262. throw new Error('setTimeout has not been defined');
  1263. }
  1264. function defaultClearTimeout () {
  1265. throw new Error('clearTimeout has not been defined');
  1266. }
  1267. (function () {
  1268. try {
  1269. if (typeof setTimeout === 'function') {
  1270. cachedSetTimeout = setTimeout;
  1271. } else {
  1272. cachedSetTimeout = defaultSetTimout;
  1273. }
  1274. } catch (e) {
  1275. cachedSetTimeout = defaultSetTimout;
  1276. }
  1277. try {
  1278. if (typeof clearTimeout === 'function') {
  1279. cachedClearTimeout = clearTimeout;
  1280. } else {
  1281. cachedClearTimeout = defaultClearTimeout;
  1282. }
  1283. } catch (e) {
  1284. cachedClearTimeout = defaultClearTimeout;
  1285. }
  1286. } ())
  1287. function runTimeout(fun) {
  1288. if (cachedSetTimeout === setTimeout) {
  1289. //normal enviroments in sane situations
  1290. return setTimeout(fun, 0);
  1291. }
  1292. // if setTimeout wasn't available but was latter defined
  1293. if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
  1294. cachedSetTimeout = setTimeout;
  1295. return setTimeout(fun, 0);
  1296. }
  1297. try {
  1298. // when when somebody has screwed with setTimeout but no I.E. maddness
  1299. return cachedSetTimeout(fun, 0);
  1300. } catch(e){
  1301. try {
  1302. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  1303. return cachedSetTimeout.call(null, fun, 0);
  1304. } catch(e){
  1305. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
  1306. return cachedSetTimeout.call(this, fun, 0);
  1307. }
  1308. }
  1309. }
  1310. function runClearTimeout(marker) {
  1311. if (cachedClearTimeout === clearTimeout) {
  1312. //normal enviroments in sane situations
  1313. return clearTimeout(marker);
  1314. }
  1315. // if clearTimeout wasn't available but was latter defined
  1316. if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
  1317. cachedClearTimeout = clearTimeout;
  1318. return clearTimeout(marker);
  1319. }
  1320. try {
  1321. // when when somebody has screwed with setTimeout but no I.E. maddness
  1322. return cachedClearTimeout(marker);
  1323. } catch (e){
  1324. try {
  1325. // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
  1326. return cachedClearTimeout.call(null, marker);
  1327. } catch (e){
  1328. // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
  1329. // Some versions of I.E. have different rules for clearTimeout vs setTimeout
  1330. return cachedClearTimeout.call(this, marker);
  1331. }
  1332. }
  1333. }
  1334. var queue = [];
  1335. var draining = false;
  1336. var currentQueue;
  1337. var queueIndex = -1;
  1338. function cleanUpNextTick() {
  1339. if (!draining || !currentQueue) {
  1340. return;
  1341. }
  1342. draining = false;
  1343. if (currentQueue.length) {
  1344. queue = currentQueue.concat(queue);
  1345. } else {
  1346. queueIndex = -1;
  1347. }
  1348. if (queue.length) {
  1349. drainQueue();
  1350. }
  1351. }
  1352. function drainQueue() {
  1353. if (draining) {
  1354. return;
  1355. }
  1356. var timeout = runTimeout(cleanUpNextTick);
  1357. draining = true;
  1358. var len = queue.length;
  1359. while(len) {
  1360. currentQueue = queue;
  1361. queue = [];
  1362. while (++queueIndex < len) {
  1363. if (currentQueue) {
  1364. currentQueue[queueIndex].run();
  1365. }
  1366. }
  1367. queueIndex = -1;
  1368. len = queue.length;
  1369. }
  1370. currentQueue = null;
  1371. draining = false;
  1372. runClearTimeout(timeout);
  1373. }
  1374. process.nextTick = function (fun) {
  1375. var args = new Array(arguments.length - 1);
  1376. if (arguments.length > 1) {
  1377. for (var i = 1; i < arguments.length; i++) {
  1378. args[i - 1] = arguments[i];
  1379. }
  1380. }
  1381. queue.push(new Item(fun, args));
  1382. if (queue.length === 1 && !draining) {
  1383. runTimeout(drainQueue);
  1384. }
  1385. };
  1386. // v8 likes predictible objects
  1387. function Item(fun, array) {
  1388. this.fun = fun;
  1389. this.array = array;
  1390. }
  1391. Item.prototype.run = function () {
  1392. this.fun.apply(null, this.array);
  1393. };
  1394. process.title = 'browser';
  1395. process.browser = true;
  1396. process.env = {};
  1397. process.argv = [];
  1398. process.version = ''; // empty string to avoid regexp issues
  1399. process.versions = {};
  1400. function noop() {}
  1401. process.on = noop;
  1402. process.addListener = noop;
  1403. process.once = noop;
  1404. process.off = noop;
  1405. process.removeListener = noop;
  1406. process.removeAllListeners = noop;
  1407. process.emit = noop;
  1408. process.prependListener = noop;
  1409. process.prependOnceListener = noop;
  1410. process.listeners = function (name) { return [] }
  1411. process.binding = function (name) {
  1412. throw new Error('process.binding is not supported');
  1413. };
  1414. process.cwd = function () { return '/' };
  1415. process.chdir = function (dir) {
  1416. throw new Error('process.chdir is not supported');
  1417. };
  1418. process.umask = function() { return 0; };
  1419. },{}],4:[function(_dereq_,module,exports){
  1420. var bundleFn = arguments[3];
  1421. var sources = arguments[4];
  1422. var cache = arguments[5];
  1423. var stringify = JSON.stringify;
  1424. module.exports = function (fn, options) {
  1425. var wkey;
  1426. var cacheKeys = Object.keys(cache);
  1427. for (var i = 0, l = cacheKeys.length; i < l; i++) {
  1428. var key = cacheKeys[i];
  1429. var exp = cache[key].exports;
  1430. // Using babel as a transpiler to use esmodule, the export will always
  1431. // be an object with the default export as a property of it. To ensure
  1432. // the existing api and babel esmodule exports are both supported we
  1433. // check for both
  1434. if (exp === fn || exp && exp.default === fn) {
  1435. wkey = key;
  1436. break;
  1437. }
  1438. }
  1439. if (!wkey) {
  1440. wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
  1441. var wcache = {};
  1442. for (var i = 0, l = cacheKeys.length; i < l; i++) {
  1443. var key = cacheKeys[i];
  1444. wcache[key] = key;
  1445. }
  1446. sources[wkey] = [
  1447. 'function(require,module,exports){' + fn + '(self); }',
  1448. wcache
  1449. ];
  1450. }
  1451. var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
  1452. var scache = {}; scache[wkey] = wkey;
  1453. sources[skey] = [
  1454. 'function(require,module,exports){' +
  1455. // try to call default if defined to also support babel esmodule exports
  1456. 'var f = require(' + stringify(wkey) + ');' +
  1457. '(f.default ? f.default : f)(self);' +
  1458. '}',
  1459. scache
  1460. ];
  1461. var workerSources = {};
  1462. resolveSources(skey);
  1463. function resolveSources(key) {
  1464. workerSources[key] = true;
  1465. for (var depPath in sources[key][1]) {
  1466. var depKey = sources[key][1][depPath];
  1467. if (!workerSources[depKey]) {
  1468. resolveSources(depKey);
  1469. }
  1470. }
  1471. }
  1472. var src = '(' + bundleFn + ')({'
  1473. + Object.keys(workerSources).map(function (key) {
  1474. return stringify(key) + ':['
  1475. + sources[key][0]
  1476. + ',' + stringify(sources[key][1]) + ']'
  1477. ;
  1478. }).join(',')
  1479. + '},{},[' + stringify(skey) + '])'
  1480. ;
  1481. var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
  1482. var blob = new Blob([src], { type: 'text/javascript' });
  1483. if (options && options.bare) { return blob; }
  1484. var workerUrl = URL.createObjectURL(blob);
  1485. var worker = new Worker(workerUrl);
  1486. worker.objectURL = workerUrl;
  1487. return worker;
  1488. };
  1489. },{}],5:[function(_dereq_,module,exports){
  1490. 'use strict';
  1491. Object.defineProperty(exports, "__esModule", {
  1492. value: true
  1493. });
  1494. exports.createDefaultConfig = createDefaultConfig;
  1495. /*
  1496. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  1497. *
  1498. * @author zheng qian <xqq@xqq.im>
  1499. *
  1500. * Licensed under the Apache License, Version 2.0 (the "License");
  1501. * you may not use this file except in compliance with the License.
  1502. * You may obtain a copy of the License at
  1503. *
  1504. * http://www.apache.org/licenses/LICENSE-2.0
  1505. *
  1506. * Unless required by applicable law or agreed to in writing, software
  1507. * distributed under the License is distributed on an "AS IS" BASIS,
  1508. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1509. * See the License for the specific language governing permissions and
  1510. * limitations under the License.
  1511. */
  1512. var defaultConfig = exports.defaultConfig = {
  1513. enableWorker: false,
  1514. enableStashBuffer: true,
  1515. stashInitialSize: undefined,
  1516. isLive: false,
  1517. lazyLoad: true,
  1518. lazyLoadMaxDuration: 3 * 60,
  1519. lazyLoadRecoverDuration: 30,
  1520. deferLoadAfterSourceOpen: true,
  1521. // autoCleanupSourceBuffer: default as false, leave unspecified
  1522. autoCleanupMaxBackwardDuration: 3 * 60,
  1523. autoCleanupMinBackwardDuration: 2 * 60,
  1524. statisticsInfoReportInterval: 600,
  1525. fixAudioTimestampGap: true,
  1526. accurateSeek: false,
  1527. seekType: 'range', // [range, param, custom]
  1528. seekParamStart: 'bstart',
  1529. seekParamEnd: 'bend',
  1530. rangeLoadZeroStart: false,
  1531. customSeekHandler: undefined,
  1532. reuseRedirectedURL: false,
  1533. // referrerPolicy: leave as unspecified
  1534. headers: undefined,
  1535. customLoader: undefined
  1536. };
  1537. function createDefaultConfig() {
  1538. return Object.assign({}, defaultConfig);
  1539. }
  1540. },{}],6:[function(_dereq_,module,exports){
  1541. 'use strict';
  1542. Object.defineProperty(exports, "__esModule", {
  1543. value: true
  1544. });
  1545. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  1546. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  1547. *
  1548. * @author zheng qian <xqq@xqq.im>
  1549. *
  1550. * Licensed under the Apache License, Version 2.0 (the "License");
  1551. * you may not use this file except in compliance with the License.
  1552. * You may obtain a copy of the License at
  1553. *
  1554. * http://www.apache.org/licenses/LICENSE-2.0
  1555. *
  1556. * Unless required by applicable law or agreed to in writing, software
  1557. * distributed under the License is distributed on an "AS IS" BASIS,
  1558. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1559. * See the License for the specific language governing permissions and
  1560. * limitations under the License.
  1561. */
  1562. var _ioController = _dereq_('../io/io-controller.js');
  1563. var _ioController2 = _interopRequireDefault(_ioController);
  1564. var _config = _dereq_('../config.js');
  1565. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  1566. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1567. var Features = function () {
  1568. function Features() {
  1569. _classCallCheck(this, Features);
  1570. }
  1571. _createClass(Features, null, [{
  1572. key: 'supportMSEH264Playback',
  1573. value: function supportMSEH264Playback() {
  1574. return window.MediaSource && window.MediaSource.isTypeSupported('videoFusion/mp4; codecs="avc1.42E01E,mp4a.40.2"');
  1575. }
  1576. }, {
  1577. key: 'supportNetworkStreamIO',
  1578. value: function supportNetworkStreamIO() {
  1579. var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)());
  1580. var loaderType = ioctl.loaderType;
  1581. ioctl.destroy();
  1582. return loaderType == 'fetch-stream-loader' || loaderType == 'xhr-moz-chunked-loader';
  1583. }
  1584. }, {
  1585. key: 'getNetworkLoaderTypeName',
  1586. value: function getNetworkLoaderTypeName() {
  1587. var ioctl = new _ioController2.default({}, (0, _config.createDefaultConfig)());
  1588. var loaderType = ioctl.loaderType;
  1589. ioctl.destroy();
  1590. return loaderType;
  1591. }
  1592. }, {
  1593. key: 'supportNativeMediaPlayback',
  1594. value: function supportNativeMediaPlayback(mimeType) {
  1595. if (Features.videoElement == undefined) {
  1596. Features.videoElement = window.document.createElement('video');
  1597. }
  1598. var canPlay = Features.videoElement.canPlayType(mimeType);
  1599. return canPlay === 'probably' || canPlay == 'maybe';
  1600. }
  1601. }, {
  1602. key: 'getFeatureList',
  1603. value: function getFeatureList() {
  1604. var features = {
  1605. mseFlvPlayback: false,
  1606. mseLiveFlvPlayback: false,
  1607. networkStreamIO: false,
  1608. networkLoaderName: '',
  1609. nativeMP4H264Playback: false,
  1610. nativeWebmVP8Playback: false,
  1611. nativeWebmVP9Playback: false
  1612. };
  1613. features.mseFlvPlayback = Features.supportMSEH264Playback();
  1614. features.networkStreamIO = Features.supportNetworkStreamIO();
  1615. features.networkLoaderName = Features.getNetworkLoaderTypeName();
  1616. features.mseLiveFlvPlayback = features.mseFlvPlayback && features.networkStreamIO;
  1617. features.nativeMP4H264Playback = Features.supportNativeMediaPlayback('videoFusion/mp4; codecs="avc1.42001E, mp4a.40.2"');
  1618. features.nativeWebmVP8Playback = Features.supportNativeMediaPlayback('videoFusion/webm; codecs="vp8.0, vorbis"');
  1619. features.nativeWebmVP9Playback = Features.supportNativeMediaPlayback('videoFusion/webm; codecs="vp9"');
  1620. return features;
  1621. }
  1622. }]);
  1623. return Features;
  1624. }();
  1625. exports.default = Features;
  1626. },{"../config.js":5,"../io/io-controller.js":23}],7:[function(_dereq_,module,exports){
  1627. "use strict";
  1628. Object.defineProperty(exports, "__esModule", {
  1629. value: true
  1630. });
  1631. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  1632. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1633. /*
  1634. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  1635. *
  1636. * @author zheng qian <xqq@xqq.im>
  1637. *
  1638. * Licensed under the Apache License, Version 2.0 (the "License");
  1639. * you may not use this file except in compliance with the License.
  1640. * You may obtain a copy of the License at
  1641. *
  1642. * http://www.apache.org/licenses/LICENSE-2.0
  1643. *
  1644. * Unless required by applicable law or agreed to in writing, software
  1645. * distributed under the License is distributed on an "AS IS" BASIS,
  1646. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1647. * See the License for the specific language governing permissions and
  1648. * limitations under the License.
  1649. */
  1650. var MediaInfo = function () {
  1651. function MediaInfo() {
  1652. _classCallCheck(this, MediaInfo);
  1653. this.mimeType = null;
  1654. this.duration = null;
  1655. this.hasAudio = null;
  1656. this.hasVideo = null;
  1657. this.audioCodec = null;
  1658. this.videoCodec = null;
  1659. this.audioDataRate = null;
  1660. this.videoDataRate = null;
  1661. this.audioSampleRate = null;
  1662. this.audioChannelCount = null;
  1663. this.width = null;
  1664. this.height = null;
  1665. this.fps = null;
  1666. this.profile = null;
  1667. this.level = null;
  1668. this.refFrames = null;
  1669. this.chromaFormat = null;
  1670. this.sarNum = null;
  1671. this.sarDen = null;
  1672. this.metadata = null;
  1673. this.segments = null; // MediaInfo[]
  1674. this.segmentCount = null;
  1675. this.hasKeyframesIndex = null;
  1676. this.keyframesIndex = null;
  1677. }
  1678. _createClass(MediaInfo, [{
  1679. key: "isComplete",
  1680. value: function isComplete() {
  1681. var audioInfoComplete = this.hasAudio === false || this.hasAudio === true && this.audioCodec != null && this.audioSampleRate != null && this.audioChannelCount != null;
  1682. var videoInfoComplete = this.hasVideo === false || this.hasVideo === true && this.videoCodec != null && this.width != null && this.height != null && this.fps != null && this.profile != null && this.level != null && this.refFrames != null && this.chromaFormat != null && this.sarNum != null && this.sarDen != null;
  1683. // keyframesIndex may not be present
  1684. return this.mimeType != null && this.duration != null && this.metadata != null && this.hasKeyframesIndex != null && audioInfoComplete && videoInfoComplete;
  1685. }
  1686. }, {
  1687. key: "isSeekable",
  1688. value: function isSeekable() {
  1689. return this.hasKeyframesIndex === true;
  1690. }
  1691. }, {
  1692. key: "getNearestKeyframe",
  1693. value: function getNearestKeyframe(milliseconds) {
  1694. if (this.keyframesIndex == null) {
  1695. return null;
  1696. }
  1697. var table = this.keyframesIndex;
  1698. var keyframeIdx = this._search(table.times, milliseconds);
  1699. return {
  1700. index: keyframeIdx,
  1701. milliseconds: table.times[keyframeIdx],
  1702. fileposition: table.filepositions[keyframeIdx]
  1703. };
  1704. }
  1705. }, {
  1706. key: "_search",
  1707. value: function _search(list, value) {
  1708. var idx = 0;
  1709. var last = list.length - 1;
  1710. var mid = 0;
  1711. var lbound = 0;
  1712. var ubound = last;
  1713. if (value < list[0]) {
  1714. idx = 0;
  1715. lbound = ubound + 1; // skip search
  1716. }
  1717. while (lbound <= ubound) {
  1718. mid = lbound + Math.floor((ubound - lbound) / 2);
  1719. if (mid === last || value >= list[mid] && value < list[mid + 1]) {
  1720. idx = mid;
  1721. break;
  1722. } else if (list[mid] < value) {
  1723. lbound = mid + 1;
  1724. } else {
  1725. ubound = mid - 1;
  1726. }
  1727. }
  1728. return idx;
  1729. }
  1730. }]);
  1731. return MediaInfo;
  1732. }();
  1733. exports.default = MediaInfo;
  1734. },{}],8:[function(_dereq_,module,exports){
  1735. "use strict";
  1736. Object.defineProperty(exports, "__esModule", {
  1737. value: true
  1738. });
  1739. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  1740. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  1741. /*
  1742. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  1743. *
  1744. * @author zheng qian <xqq@xqq.im>
  1745. *
  1746. * Licensed under the Apache License, Version 2.0 (the "License");
  1747. * you may not use this file except in compliance with the License.
  1748. * You may obtain a copy of the License at
  1749. *
  1750. * http://www.apache.org/licenses/LICENSE-2.0
  1751. *
  1752. * Unless required by applicable law or agreed to in writing, software
  1753. * distributed under the License is distributed on an "AS IS" BASIS,
  1754. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1755. * See the License for the specific language governing permissions and
  1756. * limitations under the License.
  1757. */
  1758. // Represents an media sample (audio / videoFusion)
  1759. var SampleInfo = exports.SampleInfo = function SampleInfo(dts, pts, duration, originalDts, isSync) {
  1760. _classCallCheck(this, SampleInfo);
  1761. this.dts = dts;
  1762. this.pts = pts;
  1763. this.duration = duration;
  1764. this.originalDts = originalDts;
  1765. this.isSyncPoint = isSync;
  1766. this.fileposition = null;
  1767. };
  1768. // Media Segment concept is defined in Media Source Extensions spec.
  1769. // Particularly in ISO BMFF format, an Media Segment contains a moof box followed by a mdat box.
  1770. var MediaSegmentInfo = exports.MediaSegmentInfo = function () {
  1771. function MediaSegmentInfo() {
  1772. _classCallCheck(this, MediaSegmentInfo);
  1773. this.beginDts = 0;
  1774. this.endDts = 0;
  1775. this.beginPts = 0;
  1776. this.endPts = 0;
  1777. this.originalBeginDts = 0;
  1778. this.originalEndDts = 0;
  1779. this.syncPoints = []; // SampleInfo[n], for videoFusion IDR frames only
  1780. this.firstSample = null; // SampleInfo
  1781. this.lastSample = null; // SampleInfo
  1782. }
  1783. _createClass(MediaSegmentInfo, [{
  1784. key: "appendSyncPoint",
  1785. value: function appendSyncPoint(sampleInfo) {
  1786. // also called Random Access Point
  1787. sampleInfo.isSyncPoint = true;
  1788. this.syncPoints.push(sampleInfo);
  1789. }
  1790. }]);
  1791. return MediaSegmentInfo;
  1792. }();
  1793. // Ordered list for recording videoFusion IDR frames, sorted by originalDts
  1794. var IDRSampleList = exports.IDRSampleList = function () {
  1795. function IDRSampleList() {
  1796. _classCallCheck(this, IDRSampleList);
  1797. this._list = [];
  1798. }
  1799. _createClass(IDRSampleList, [{
  1800. key: "clear",
  1801. value: function clear() {
  1802. this._list = [];
  1803. }
  1804. }, {
  1805. key: "appendArray",
  1806. value: function appendArray(syncPoints) {
  1807. var list = this._list;
  1808. if (syncPoints.length === 0) {
  1809. return;
  1810. }
  1811. if (list.length > 0 && syncPoints[0].originalDts < list[list.length - 1].originalDts) {
  1812. this.clear();
  1813. }
  1814. Array.prototype.push.apply(list, syncPoints);
  1815. }
  1816. }, {
  1817. key: "getLastSyncPointBeforeDts",
  1818. value: function getLastSyncPointBeforeDts(dts) {
  1819. if (this._list.length == 0) {
  1820. return null;
  1821. }
  1822. var list = this._list;
  1823. var idx = 0;
  1824. var last = list.length - 1;
  1825. var mid = 0;
  1826. var lbound = 0;
  1827. var ubound = last;
  1828. if (dts < list[0].dts) {
  1829. idx = 0;
  1830. lbound = ubound + 1;
  1831. }
  1832. while (lbound <= ubound) {
  1833. mid = lbound + Math.floor((ubound - lbound) / 2);
  1834. if (mid === last || dts >= list[mid].dts && dts < list[mid + 1].dts) {
  1835. idx = mid;
  1836. break;
  1837. } else if (list[mid].dts < dts) {
  1838. lbound = mid + 1;
  1839. } else {
  1840. ubound = mid - 1;
  1841. }
  1842. }
  1843. return this._list[idx];
  1844. }
  1845. }]);
  1846. return IDRSampleList;
  1847. }();
  1848. // Data structure for recording information of media segments in single track.
  1849. var MediaSegmentInfoList = exports.MediaSegmentInfoList = function () {
  1850. function MediaSegmentInfoList(type) {
  1851. _classCallCheck(this, MediaSegmentInfoList);
  1852. this._type = type;
  1853. this._list = [];
  1854. this._lastAppendLocation = -1; // cached last insert location
  1855. }
  1856. _createClass(MediaSegmentInfoList, [{
  1857. key: "isEmpty",
  1858. value: function isEmpty() {
  1859. return this._list.length === 0;
  1860. }
  1861. }, {
  1862. key: "clear",
  1863. value: function clear() {
  1864. this._list = [];
  1865. this._lastAppendLocation = -1;
  1866. }
  1867. }, {
  1868. key: "_searchNearestSegmentBefore",
  1869. value: function _searchNearestSegmentBefore(originalBeginDts) {
  1870. var list = this._list;
  1871. if (list.length === 0) {
  1872. return -2;
  1873. }
  1874. var last = list.length - 1;
  1875. var mid = 0;
  1876. var lbound = 0;
  1877. var ubound = last;
  1878. var idx = 0;
  1879. if (originalBeginDts < list[0].originalBeginDts) {
  1880. idx = -1;
  1881. return idx;
  1882. }
  1883. while (lbound <= ubound) {
  1884. mid = lbound + Math.floor((ubound - lbound) / 2);
  1885. if (mid === last || originalBeginDts > list[mid].lastSample.originalDts && originalBeginDts < list[mid + 1].originalBeginDts) {
  1886. idx = mid;
  1887. break;
  1888. } else if (list[mid].originalBeginDts < originalBeginDts) {
  1889. lbound = mid + 1;
  1890. } else {
  1891. ubound = mid - 1;
  1892. }
  1893. }
  1894. return idx;
  1895. }
  1896. }, {
  1897. key: "_searchNearestSegmentAfter",
  1898. value: function _searchNearestSegmentAfter(originalBeginDts) {
  1899. return this._searchNearestSegmentBefore(originalBeginDts) + 1;
  1900. }
  1901. }, {
  1902. key: "append",
  1903. value: function append(mediaSegmentInfo) {
  1904. var list = this._list;
  1905. var msi = mediaSegmentInfo;
  1906. var lastAppendIdx = this._lastAppendLocation;
  1907. var insertIdx = 0;
  1908. if (lastAppendIdx !== -1 && lastAppendIdx < list.length && msi.originalBeginDts >= list[lastAppendIdx].lastSample.originalDts && (lastAppendIdx === list.length - 1 || lastAppendIdx < list.length - 1 && msi.originalBeginDts < list[lastAppendIdx + 1].originalBeginDts)) {
  1909. insertIdx = lastAppendIdx + 1; // use cached location idx
  1910. } else {
  1911. if (list.length > 0) {
  1912. insertIdx = this._searchNearestSegmentBefore(msi.originalBeginDts) + 1;
  1913. }
  1914. }
  1915. this._lastAppendLocation = insertIdx;
  1916. this._list.splice(insertIdx, 0, msi);
  1917. }
  1918. }, {
  1919. key: "getLastSegmentBefore",
  1920. value: function getLastSegmentBefore(originalBeginDts) {
  1921. var idx = this._searchNearestSegmentBefore(originalBeginDts);
  1922. if (idx >= 0) {
  1923. return this._list[idx];
  1924. } else {
  1925. // -1
  1926. return null;
  1927. }
  1928. }
  1929. }, {
  1930. key: "getLastSampleBefore",
  1931. value: function getLastSampleBefore(originalBeginDts) {
  1932. var segment = this.getLastSegmentBefore(originalBeginDts);
  1933. if (segment != null) {
  1934. return segment.lastSample;
  1935. } else {
  1936. return null;
  1937. }
  1938. }
  1939. }, {
  1940. key: "getLastSyncPointBefore",
  1941. value: function getLastSyncPointBefore(originalBeginDts) {
  1942. var segmentIdx = this._searchNearestSegmentBefore(originalBeginDts);
  1943. var syncPoints = this._list[segmentIdx].syncPoints;
  1944. while (syncPoints.length === 0 && segmentIdx > 0) {
  1945. segmentIdx--;
  1946. syncPoints = this._list[segmentIdx].syncPoints;
  1947. }
  1948. if (syncPoints.length > 0) {
  1949. return syncPoints[syncPoints.length - 1];
  1950. } else {
  1951. return null;
  1952. }
  1953. }
  1954. }, {
  1955. key: "type",
  1956. get: function get() {
  1957. return this._type;
  1958. }
  1959. }, {
  1960. key: "length",
  1961. get: function get() {
  1962. return this._list.length;
  1963. }
  1964. }]);
  1965. return MediaSegmentInfoList;
  1966. }();
  1967. },{}],9:[function(_dereq_,module,exports){
  1968. 'use strict';
  1969. Object.defineProperty(exports, "__esModule", {
  1970. value: true
  1971. });
  1972. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  1973. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  1974. *
  1975. * @author zheng qian <xqq@xqq.im>
  1976. *
  1977. * Licensed under the Apache License, Version 2.0 (the "License");
  1978. * you may not use this file except in compliance with the License.
  1979. * You may obtain a copy of the License at
  1980. *
  1981. * http://www.apache.org/licenses/LICENSE-2.0
  1982. *
  1983. * Unless required by applicable law or agreed to in writing, software
  1984. * distributed under the License is distributed on an "AS IS" BASIS,
  1985. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1986. * See the License for the specific language governing permissions and
  1987. * limitations under the License.
  1988. */
  1989. var _events = _dereq_('events');
  1990. var _events2 = _interopRequireDefault(_events);
  1991. var _logger = _dereq_('../utils/logger.js');
  1992. var _logger2 = _interopRequireDefault(_logger);
  1993. var _browser = _dereq_('../utils/browser.js');
  1994. var _browser2 = _interopRequireDefault(_browser);
  1995. var _mseEvents = _dereq_('./mse-events.js');
  1996. var _mseEvents2 = _interopRequireDefault(_mseEvents);
  1997. var _mediaSegmentInfo = _dereq_('./media-segment-info.js');
  1998. var _exception = _dereq_('../utils/exception.js');
  1999. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  2000. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  2001. // Media Source Extensions controller
  2002. var MSEController = function () {
  2003. function MSEController(config) {
  2004. _classCallCheck(this, MSEController);
  2005. this.TAG = 'MSEController';
  2006. this._config = config;
  2007. this._emitter = new _events2.default();
  2008. if (this._config.isLive && this._config.autoCleanupSourceBuffer == undefined) {
  2009. // For live stream, do auto cleanup by default
  2010. this._config.autoCleanupSourceBuffer = true;
  2011. }
  2012. this.e = {
  2013. onSourceOpen: this._onSourceOpen.bind(this),
  2014. onSourceEnded: this._onSourceEnded.bind(this),
  2015. onSourceClose: this._onSourceClose.bind(this),
  2016. onSourceBufferError: this._onSourceBufferError.bind(this),
  2017. onSourceBufferUpdateEnd: this._onSourceBufferUpdateEnd.bind(this)
  2018. };
  2019. this._mediaSource = null;
  2020. this._mediaSourceObjectURL = null;
  2021. this._mediaElement = null;
  2022. this._isBufferFull = false;
  2023. this._hasPendingEos = false;
  2024. this._requireSetMediaDuration = false;
  2025. this._pendingMediaDuration = 0;
  2026. this._pendingSourceBufferInit = [];
  2027. this._mimeTypes = {
  2028. video: null,
  2029. audio: null
  2030. };
  2031. this._sourceBuffers = {
  2032. video: null,
  2033. audio: null
  2034. };
  2035. this._lastInitSegments = {
  2036. video: null,
  2037. audio: null
  2038. };
  2039. this._pendingSegments = {
  2040. video: [],
  2041. audio: []
  2042. };
  2043. this._pendingRemoveRanges = {
  2044. video: [],
  2045. audio: []
  2046. };
  2047. this._idrList = new _mediaSegmentInfo.IDRSampleList();
  2048. }
  2049. _createClass(MSEController, [{
  2050. key: 'destroy',
  2051. value: function destroy() {
  2052. if (this._mediaElement || this._mediaSource) {
  2053. this.detachMediaElement();
  2054. }
  2055. this.e = null;
  2056. this._emitter.removeAllListeners();
  2057. this._emitter = null;
  2058. }
  2059. }, {
  2060. key: 'on',
  2061. value: function on(event, listener) {
  2062. this._emitter.addListener(event, listener);
  2063. }
  2064. }, {
  2065. key: 'off',
  2066. value: function off(event, listener) {
  2067. this._emitter.removeListener(event, listener);
  2068. }
  2069. }, {
  2070. key: 'attachMediaElement',
  2071. value: function attachMediaElement(mediaElement) {
  2072. if (this._mediaSource) {
  2073. throw new _exception.IllegalStateException('MediaSource has been attached to an HTMLMediaElement!');
  2074. }
  2075. var ms = this._mediaSource = new window.MediaSource();
  2076. ms.addEventListener('sourceopen', this.e.onSourceOpen);
  2077. ms.addEventListener('sourceended', this.e.onSourceEnded);
  2078. ms.addEventListener('sourceclose', this.e.onSourceClose);
  2079. this._mediaElement = mediaElement;
  2080. this._mediaSourceObjectURL = window.URL.createObjectURL(this._mediaSource);
  2081. mediaElement.src = this._mediaSourceObjectURL;
  2082. }
  2083. }, {
  2084. key: 'detachMediaElement',
  2085. value: function detachMediaElement() {
  2086. if (this._mediaSource) {
  2087. var ms = this._mediaSource;
  2088. for (var type in this._sourceBuffers) {
  2089. // pending segments should be discard
  2090. var ps = this._pendingSegments[type];
  2091. ps.splice(0, ps.length);
  2092. this._pendingSegments[type] = null;
  2093. this._pendingRemoveRanges[type] = null;
  2094. this._lastInitSegments[type] = null;
  2095. // remove all sourcebuffers
  2096. var sb = this._sourceBuffers[type];
  2097. if (sb) {
  2098. if (ms.readyState !== 'closed') {
  2099. // ms edge can throw an error: Unexpected call to method or property access
  2100. try {
  2101. ms.removeSourceBuffer(sb);
  2102. } catch (error) {
  2103. _logger2.default.e(this.TAG, error.message);
  2104. }
  2105. sb.removeEventListener('error', this.e.onSourceBufferError);
  2106. sb.removeEventListener('updateend', this.e.onSourceBufferUpdateEnd);
  2107. }
  2108. this._mimeTypes[type] = null;
  2109. this._sourceBuffers[type] = null;
  2110. }
  2111. }
  2112. if (ms.readyState === 'open') {
  2113. try {
  2114. ms.endOfStream();
  2115. } catch (error) {
  2116. _logger2.default.e(this.TAG, error.message);
  2117. }
  2118. }
  2119. ms.removeEventListener('sourceopen', this.e.onSourceOpen);
  2120. ms.removeEventListener('sourceended', this.e.onSourceEnded);
  2121. ms.removeEventListener('sourceclose', this.e.onSourceClose);
  2122. this._pendingSourceBufferInit = [];
  2123. this._isBufferFull = false;
  2124. this._idrList.clear();
  2125. this._mediaSource = null;
  2126. }
  2127. if (this._mediaElement) {
  2128. this._mediaElement.src = '';
  2129. this._mediaElement.removeAttribute('src');
  2130. this._mediaElement = null;
  2131. }
  2132. if (this._mediaSourceObjectURL) {
  2133. window.URL.revokeObjectURL(this._mediaSourceObjectURL);
  2134. this._mediaSourceObjectURL = null;
  2135. }
  2136. }
  2137. }, {
  2138. key: 'appendInitSegment',
  2139. value: function appendInitSegment(initSegment, deferred) {
  2140. if (!this._mediaSource || this._mediaSource.readyState !== 'open') {
  2141. // sourcebuffer creation requires mediaSource.readyState === 'open'
  2142. // so we defer the sourcebuffer creation, until sourceopen event triggered
  2143. this._pendingSourceBufferInit.push(initSegment);
  2144. // make sure that this InitSegment is in the front of pending segments queue
  2145. this._pendingSegments[initSegment.type].push(initSegment);
  2146. return;
  2147. }
  2148. var is = initSegment;
  2149. var mimeType = '' + is.container;
  2150. if (is.codec && is.codec.length > 0) {
  2151. mimeType += ';codecs=' + is.codec;
  2152. }
  2153. var firstInitSegment = false;
  2154. _logger2.default.v(this.TAG, 'Received Initialization Segment, mimeType: ' + mimeType);
  2155. this._lastInitSegments[is.type] = is;
  2156. if (mimeType !== this._mimeTypes[is.type]) {
  2157. if (!this._mimeTypes[is.type]) {
  2158. // empty, first chance create sourcebuffer
  2159. firstInitSegment = true;
  2160. try {
  2161. var sb = this._sourceBuffers[is.type] = this._mediaSource.addSourceBuffer(mimeType);
  2162. sb.addEventListener('error', this.e.onSourceBufferError);
  2163. sb.addEventListener('updateend', this.e.onSourceBufferUpdateEnd);
  2164. } catch (error) {
  2165. _logger2.default.e(this.TAG, error.message);
  2166. this._emitter.emit(_mseEvents2.default.ERROR, { code: error.code, msg: error.message });
  2167. return;
  2168. }
  2169. } else {
  2170. _logger2.default.v(this.TAG, 'Notice: ' + is.type + ' mimeType changed, origin: ' + this._mimeTypes[is.type] + ', target: ' + mimeType);
  2171. }
  2172. this._mimeTypes[is.type] = mimeType;
  2173. }
  2174. if (!deferred) {
  2175. // deferred means this InitSegment has been pushed to pendingSegments queue
  2176. this._pendingSegments[is.type].push(is);
  2177. }
  2178. if (!firstInitSegment) {
  2179. // append immediately only if init segment in subsequence
  2180. if (this._sourceBuffers[is.type] && !this._sourceBuffers[is.type].updating) {
  2181. this._doAppendSegments();
  2182. }
  2183. }
  2184. if (_browser2.default.safari && is.container === 'audio/mpeg' && is.mediaDuration > 0) {
  2185. // 'audio/mpeg' track under Safari may cause MediaElement's duration to be NaN
  2186. // Manually correct MediaSource.duration to make progress bar seekable, and report right duration
  2187. this._requireSetMediaDuration = true;
  2188. this._pendingMediaDuration = is.mediaDuration / 1000; // in seconds
  2189. this._updateMediaSourceDuration();
  2190. }
  2191. }
  2192. }, {
  2193. key: 'appendMediaSegment',
  2194. value: function appendMediaSegment(mediaSegment) {
  2195. var ms = mediaSegment;
  2196. this._pendingSegments[ms.type].push(ms);
  2197. if (this._config.autoCleanupSourceBuffer && this._needCleanupSourceBuffer()) {
  2198. this._doCleanupSourceBuffer();
  2199. }
  2200. var sb = this._sourceBuffers[ms.type];
  2201. if (sb && !sb.updating && !this._hasPendingRemoveRanges()) {
  2202. this._doAppendSegments();
  2203. }
  2204. }
  2205. }, {
  2206. key: 'seek',
  2207. value: function seek(seconds) {
  2208. // remove all appended buffers
  2209. for (var type in this._sourceBuffers) {
  2210. if (!this._sourceBuffers[type]) {
  2211. continue;
  2212. }
  2213. // abort current buffer append algorithm
  2214. var sb = this._sourceBuffers[type];
  2215. if (this._mediaSource.readyState === 'open') {
  2216. try {
  2217. // If range removal algorithm is running, InvalidStateError will be throwed
  2218. // Ignore it.
  2219. sb.abort();
  2220. } catch (error) {
  2221. _logger2.default.e(this.TAG, error.message);
  2222. }
  2223. }
  2224. // IDRList should be clear
  2225. this._idrList.clear();
  2226. // pending segments should be discard
  2227. var ps = this._pendingSegments[type];
  2228. ps.splice(0, ps.length);
  2229. if (this._mediaSource.readyState === 'closed') {
  2230. // Parent MediaSource object has been detached from HTMLMediaElement
  2231. continue;
  2232. }
  2233. // record ranges to be remove from SourceBuffer
  2234. for (var i = 0; i < sb.buffered.length; i++) {
  2235. var start = sb.buffered.start(i);
  2236. var end = sb.buffered.end(i);
  2237. this._pendingRemoveRanges[type].push({ start: start, end: end });
  2238. }
  2239. // if sb is not updating, let's remove ranges now!
  2240. if (!sb.updating) {
  2241. this._doRemoveRanges();
  2242. }
  2243. // Safari 10 may get InvalidStateError in the later appendBuffer() after SourceBuffer.remove() call
  2244. // Internal parser's state may be invalid at this time. Re-append last InitSegment to workaround.
  2245. // Related issue: https://bugs.webkit.org/show_bug.cgi?id=159230
  2246. if (_browser2.default.safari) {
  2247. var lastInitSegment = this._lastInitSegments[type];
  2248. if (lastInitSegment) {
  2249. this._pendingSegments[type].push(lastInitSegment);
  2250. if (!sb.updating) {
  2251. this._doAppendSegments();
  2252. }
  2253. }
  2254. }
  2255. }
  2256. }
  2257. }, {
  2258. key: 'endOfStream',
  2259. value: function endOfStream() {
  2260. var ms = this._mediaSource;
  2261. var sb = this._sourceBuffers;
  2262. if (!ms || ms.readyState !== 'open') {
  2263. if (ms && ms.readyState === 'closed' && this._hasPendingSegments()) {
  2264. // If MediaSource hasn't turned into open state, and there're pending segments
  2265. // Mark pending endOfStream, defer call until all pending segments appended complete
  2266. this._hasPendingEos = true;
  2267. }
  2268. return;
  2269. }
  2270. if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) {
  2271. // If any sourcebuffer is updating, defer endOfStream operation
  2272. // See _onSourceBufferUpdateEnd()
  2273. this._hasPendingEos = true;
  2274. } else {
  2275. this._hasPendingEos = false;
  2276. // Notify media data loading complete
  2277. // This is helpful for correcting total duration to match last media segment
  2278. // Otherwise MediaElement's ended event may not be triggered
  2279. ms.endOfStream();
  2280. }
  2281. }
  2282. }, {
  2283. key: 'getNearestKeyframe',
  2284. value: function getNearestKeyframe(dts) {
  2285. return this._idrList.getLastSyncPointBeforeDts(dts);
  2286. }
  2287. }, {
  2288. key: '_needCleanupSourceBuffer',
  2289. value: function _needCleanupSourceBuffer() {
  2290. if (!this._config.autoCleanupSourceBuffer) {
  2291. return false;
  2292. }
  2293. var currentTime = this._mediaElement.currentTime;
  2294. for (var type in this._sourceBuffers) {
  2295. var sb = this._sourceBuffers[type];
  2296. if (sb) {
  2297. var buffered = sb.buffered;
  2298. if (buffered.length >= 1) {
  2299. if (currentTime - buffered.start(0) >= this._config.autoCleanupMaxBackwardDuration) {
  2300. return true;
  2301. }
  2302. }
  2303. }
  2304. }
  2305. return false;
  2306. }
  2307. }, {
  2308. key: '_doCleanupSourceBuffer',
  2309. value: function _doCleanupSourceBuffer() {
  2310. var currentTime = this._mediaElement.currentTime;
  2311. for (var type in this._sourceBuffers) {
  2312. var sb = this._sourceBuffers[type];
  2313. if (sb) {
  2314. var buffered = sb.buffered;
  2315. var doRemove = false;
  2316. for (var i = 0; i < buffered.length; i++) {
  2317. var start = buffered.start(i);
  2318. var end = buffered.end(i);
  2319. if (start <= currentTime && currentTime < end + 3) {
  2320. // padding 3 seconds
  2321. if (currentTime - start >= this._config.autoCleanupMaxBackwardDuration) {
  2322. doRemove = true;
  2323. var removeEnd = currentTime - this._config.autoCleanupMinBackwardDuration;
  2324. this._pendingRemoveRanges[type].push({ start: start, end: removeEnd });
  2325. }
  2326. } else if (end < currentTime) {
  2327. doRemove = true;
  2328. this._pendingRemoveRanges[type].push({ start: start, end: end });
  2329. }
  2330. }
  2331. if (doRemove && !sb.updating) {
  2332. this._doRemoveRanges();
  2333. }
  2334. }
  2335. }
  2336. }
  2337. }, {
  2338. key: '_updateMediaSourceDuration',
  2339. value: function _updateMediaSourceDuration() {
  2340. var sb = this._sourceBuffers;
  2341. if (this._mediaElement.readyState === 0 || this._mediaSource.readyState !== 'open') {
  2342. return;
  2343. }
  2344. if (sb.video && sb.video.updating || sb.audio && sb.audio.updating) {
  2345. return;
  2346. }
  2347. var current = this._mediaSource.duration;
  2348. var target = this._pendingMediaDuration;
  2349. if (target > 0 && (isNaN(current) || target > current)) {
  2350. _logger2.default.v(this.TAG, 'Update MediaSource duration from ' + current + ' to ' + target);
  2351. this._mediaSource.duration = target;
  2352. }
  2353. this._requireSetMediaDuration = false;
  2354. this._pendingMediaDuration = 0;
  2355. }
  2356. }, {
  2357. key: '_doRemoveRanges',
  2358. value: function _doRemoveRanges() {
  2359. for (var type in this._pendingRemoveRanges) {
  2360. if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) {
  2361. continue;
  2362. }
  2363. var sb = this._sourceBuffers[type];
  2364. var ranges = this._pendingRemoveRanges[type];
  2365. while (ranges.length && !sb.updating) {
  2366. var range = ranges.shift();
  2367. sb.remove(range.start, range.end);
  2368. }
  2369. }
  2370. }
  2371. }, {
  2372. key: '_doAppendSegments',
  2373. value: function _doAppendSegments() {
  2374. var pendingSegments = this._pendingSegments;
  2375. for (var type in pendingSegments) {
  2376. if (!this._sourceBuffers[type] || this._sourceBuffers[type].updating) {
  2377. continue;
  2378. }
  2379. if (pendingSegments[type].length > 0) {
  2380. var segment = pendingSegments[type].shift();
  2381. if (segment.timestampOffset) {
  2382. // For MPEG audio stream in MSE, if unbuffered-seeking occurred
  2383. // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer.
  2384. var currentOffset = this._sourceBuffers[type].timestampOffset;
  2385. var targetOffset = segment.timestampOffset / 1000; // in seconds
  2386. var delta = Math.abs(currentOffset - targetOffset);
  2387. if (delta > 0.1) {
  2388. // If time delta > 100ms
  2389. _logger2.default.v(this.TAG, 'Update MPEG audio timestampOffset from ' + currentOffset + ' to ' + targetOffset);
  2390. this._sourceBuffers[type].timestampOffset = targetOffset;
  2391. }
  2392. delete segment.timestampOffset;
  2393. }
  2394. if (!segment.data || segment.data.byteLength === 0) {
  2395. // Ignore empty buffer
  2396. continue;
  2397. }
  2398. try {
  2399. this._sourceBuffers[type].appendBuffer(segment.data);
  2400. this._isBufferFull = false;
  2401. if (type === 'video' && segment.hasOwnProperty('info')) {
  2402. this._idrList.appendArray(segment.info.syncPoints);
  2403. }
  2404. } catch (error) {
  2405. this._pendingSegments[type].unshift(segment);
  2406. if (error.code === 22) {
  2407. // QuotaExceededError
  2408. /* Notice that FireFox may not throw QuotaExceededError if SourceBuffer is full
  2409. * Currently we can only do lazy-load to avoid SourceBuffer become scattered.
  2410. * SourceBuffer eviction policy may be changed in future version of FireFox.
  2411. *
  2412. * Related issues:
  2413. * https://bugzilla.mozilla.org/show_bug.cgi?id=1279885
  2414. * https://bugzilla.mozilla.org/show_bug.cgi?id=1280023
  2415. */
  2416. // report buffer full, abort network IO
  2417. if (!this._isBufferFull) {
  2418. this._emitter.emit(_mseEvents2.default.BUFFER_FULL);
  2419. }
  2420. this._isBufferFull = true;
  2421. } else {
  2422. _logger2.default.e(this.TAG, error.message);
  2423. this._emitter.emit(_mseEvents2.default.ERROR, { code: error.code, msg: error.message });
  2424. }
  2425. }
  2426. }
  2427. }
  2428. }
  2429. }, {
  2430. key: '_onSourceOpen',
  2431. value: function _onSourceOpen() {
  2432. _logger2.default.v(this.TAG, 'MediaSource onSourceOpen');
  2433. this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen);
  2434. // deferred sourcebuffer creation / initialization
  2435. if (this._pendingSourceBufferInit.length > 0) {
  2436. var pendings = this._pendingSourceBufferInit;
  2437. while (pendings.length) {
  2438. var segment = pendings.shift();
  2439. this.appendInitSegment(segment, true);
  2440. }
  2441. }
  2442. // there may be some pending media segments, append them
  2443. if (this._hasPendingSegments()) {
  2444. this._doAppendSegments();
  2445. }
  2446. this._emitter.emit(_mseEvents2.default.SOURCE_OPEN);
  2447. }
  2448. }, {
  2449. key: '_onSourceEnded',
  2450. value: function _onSourceEnded() {
  2451. // fired on endOfStream
  2452. _logger2.default.v(this.TAG, 'MediaSource onSourceEnded');
  2453. }
  2454. }, {
  2455. key: '_onSourceClose',
  2456. value: function _onSourceClose() {
  2457. // fired on detaching from media element
  2458. _logger2.default.v(this.TAG, 'MediaSource onSourceClose');
  2459. if (this._mediaSource && this.e != null) {
  2460. this._mediaSource.removeEventListener('sourceopen', this.e.onSourceOpen);
  2461. this._mediaSource.removeEventListener('sourceended', this.e.onSourceEnded);
  2462. this._mediaSource.removeEventListener('sourceclose', this.e.onSourceClose);
  2463. }
  2464. }
  2465. }, {
  2466. key: '_hasPendingSegments',
  2467. value: function _hasPendingSegments() {
  2468. var ps = this._pendingSegments;
  2469. return ps.video.length > 0 || ps.audio.length > 0;
  2470. }
  2471. }, {
  2472. key: '_hasPendingRemoveRanges',
  2473. value: function _hasPendingRemoveRanges() {
  2474. var prr = this._pendingRemoveRanges;
  2475. return prr.video.length > 0 || prr.audio.length > 0;
  2476. }
  2477. }, {
  2478. key: '_onSourceBufferUpdateEnd',
  2479. value: function _onSourceBufferUpdateEnd() {
  2480. if (this._requireSetMediaDuration) {
  2481. this._updateMediaSourceDuration();
  2482. } else if (this._hasPendingRemoveRanges()) {
  2483. this._doRemoveRanges();
  2484. } else if (this._hasPendingSegments()) {
  2485. this._doAppendSegments();
  2486. } else if (this._hasPendingEos) {
  2487. this.endOfStream();
  2488. }
  2489. this._emitter.emit(_mseEvents2.default.UPDATE_END);
  2490. }
  2491. }, {
  2492. key: '_onSourceBufferError',
  2493. value: function _onSourceBufferError(e) {
  2494. _logger2.default.e(this.TAG, 'SourceBuffer Error: ' + e);
  2495. // this error might not always be fatal, just ignore it
  2496. }
  2497. }]);
  2498. return MSEController;
  2499. }();
  2500. exports.default = MSEController;
  2501. },{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./media-segment-info.js":8,"./mse-events.js":10,"events":2}],10:[function(_dereq_,module,exports){
  2502. 'use strict';
  2503. Object.defineProperty(exports, "__esModule", {
  2504. value: true
  2505. });
  2506. /*
  2507. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  2508. *
  2509. * @author zheng qian <xqq@xqq.im>
  2510. *
  2511. * Licensed under the Apache License, Version 2.0 (the "License");
  2512. * you may not use this file except in compliance with the License.
  2513. * You may obtain a copy of the License at
  2514. *
  2515. * http://www.apache.org/licenses/LICENSE-2.0
  2516. *
  2517. * Unless required by applicable law or agreed to in writing, software
  2518. * distributed under the License is distributed on an "AS IS" BASIS,
  2519. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2520. * See the License for the specific language governing permissions and
  2521. * limitations under the License.
  2522. */
  2523. var MSEEvents = {
  2524. ERROR: 'error',
  2525. SOURCE_OPEN: 'source_open',
  2526. UPDATE_END: 'update_end',
  2527. BUFFER_FULL: 'buffer_full'
  2528. };
  2529. exports.default = MSEEvents;
  2530. },{}],11:[function(_dereq_,module,exports){
  2531. 'use strict';
  2532. Object.defineProperty(exports, "__esModule", {
  2533. value: true
  2534. });
  2535. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  2536. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  2537. *
  2538. * @author zheng qian <xqq@xqq.im>
  2539. *
  2540. * Licensed under the Apache License, Version 2.0 (the "License");
  2541. * you may not use this file except in compliance with the License.
  2542. * You may obtain a copy of the License at
  2543. *
  2544. * http://www.apache.org/licenses/LICENSE-2.0
  2545. *
  2546. * Unless required by applicable law or agreed to in writing, software
  2547. * distributed under the License is distributed on an "AS IS" BASIS,
  2548. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2549. * See the License for the specific language governing permissions and
  2550. * limitations under the License.
  2551. */
  2552. var _events = _dereq_('events');
  2553. var _events2 = _interopRequireDefault(_events);
  2554. var _logger = _dereq_('../utils/logger.js');
  2555. var _logger2 = _interopRequireDefault(_logger);
  2556. var _loggingControl = _dereq_('../utils/logging-control.js');
  2557. var _loggingControl2 = _interopRequireDefault(_loggingControl);
  2558. var _transmuxingController = _dereq_('./transmuxing-controller.js');
  2559. var _transmuxingController2 = _interopRequireDefault(_transmuxingController);
  2560. var _transmuxingEvents = _dereq_('./transmuxing-events.js');
  2561. var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents);
  2562. var _transmuxingWorker = _dereq_('./transmuxing-worker.js');
  2563. var _transmuxingWorker2 = _interopRequireDefault(_transmuxingWorker);
  2564. var _mediaInfo = _dereq_('./media-info.js');
  2565. var _mediaInfo2 = _interopRequireDefault(_mediaInfo);
  2566. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  2567. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  2568. var Transmuxer = function () {
  2569. function Transmuxer(mediaDataSource, config) {
  2570. _classCallCheck(this, Transmuxer);
  2571. this.TAG = 'Transmuxer';
  2572. this._emitter = new _events2.default();
  2573. if (config.enableWorker && typeof Worker !== 'undefined') {
  2574. try {
  2575. var work = _dereq_('webworkify');
  2576. this._worker = work(_transmuxingWorker2.default);
  2577. this._workerDestroying = false;
  2578. this._worker.addEventListener('message', this._onWorkerMessage.bind(this));
  2579. this._worker.postMessage({ cmd: 'init', param: [mediaDataSource, config] });
  2580. this.e = {
  2581. onLoggingConfigChanged: this._onLoggingConfigChanged.bind(this)
  2582. };
  2583. _loggingControl2.default.registerListener(this.e.onLoggingConfigChanged);
  2584. this._worker.postMessage({ cmd: 'logging_config', param: _loggingControl2.default.getConfig() });
  2585. } catch (error) {
  2586. _logger2.default.e(this.TAG, 'Error while initialize transmuxing worker, fallback to inline transmuxing');
  2587. this._worker = null;
  2588. this._controller = new _transmuxingController2.default(mediaDataSource, config);
  2589. }
  2590. } else {
  2591. this._controller = new _transmuxingController2.default(mediaDataSource, config);
  2592. }
  2593. if (this._controller) {
  2594. var ctl = this._controller;
  2595. ctl.on(_transmuxingEvents2.default.IO_ERROR, this._onIOError.bind(this));
  2596. ctl.on(_transmuxingEvents2.default.DEMUX_ERROR, this._onDemuxError.bind(this));
  2597. ctl.on(_transmuxingEvents2.default.INIT_SEGMENT, this._onInitSegment.bind(this));
  2598. ctl.on(_transmuxingEvents2.default.MEDIA_SEGMENT, this._onMediaSegment.bind(this));
  2599. ctl.on(_transmuxingEvents2.default.LOADING_COMPLETE, this._onLoadingComplete.bind(this));
  2600. ctl.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, this._onRecoveredEarlyEof.bind(this));
  2601. ctl.on(_transmuxingEvents2.default.MEDIA_INFO, this._onMediaInfo.bind(this));
  2602. ctl.on(_transmuxingEvents2.default.METADATA_ARRIVED, this._onMetaDataArrived.bind(this));
  2603. ctl.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, this._onScriptDataArrived.bind(this));
  2604. ctl.on(_transmuxingEvents2.default.STATISTICS_INFO, this._onStatisticsInfo.bind(this));
  2605. ctl.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, this._onRecommendSeekpoint.bind(this));
  2606. }
  2607. }
  2608. _createClass(Transmuxer, [{
  2609. key: 'destroy',
  2610. value: function destroy() {
  2611. if (this._worker) {
  2612. if (!this._workerDestroying) {
  2613. this._workerDestroying = true;
  2614. this._worker.postMessage({ cmd: 'destroy' });
  2615. _loggingControl2.default.removeListener(this.e.onLoggingConfigChanged);
  2616. this.e = null;
  2617. }
  2618. } else {
  2619. this._controller.destroy();
  2620. this._controller = null;
  2621. }
  2622. this._emitter.removeAllListeners();
  2623. this._emitter = null;
  2624. }
  2625. }, {
  2626. key: 'on',
  2627. value: function on(event, listener) {
  2628. this._emitter.addListener(event, listener);
  2629. }
  2630. }, {
  2631. key: 'off',
  2632. value: function off(event, listener) {
  2633. this._emitter.removeListener(event, listener);
  2634. }
  2635. }, {
  2636. key: 'hasWorker',
  2637. value: function hasWorker() {
  2638. return this._worker != null;
  2639. }
  2640. }, {
  2641. key: 'open',
  2642. value: function open() {
  2643. if (this._worker) {
  2644. this._worker.postMessage({ cmd: 'start' });
  2645. } else {
  2646. this._controller.start();
  2647. }
  2648. }
  2649. }, {
  2650. key: 'close',
  2651. value: function close() {
  2652. if (this._worker) {
  2653. this._worker.postMessage({ cmd: 'stop' });
  2654. } else {
  2655. this._controller.stop();
  2656. }
  2657. }
  2658. }, {
  2659. key: 'seek',
  2660. value: function seek(milliseconds) {
  2661. if (this._worker) {
  2662. this._worker.postMessage({ cmd: 'seek', param: milliseconds });
  2663. } else {
  2664. this._controller.seek(milliseconds);
  2665. }
  2666. }
  2667. }, {
  2668. key: 'pause',
  2669. value: function pause() {
  2670. if (this._worker) {
  2671. this._worker.postMessage({ cmd: 'pause' });
  2672. } else {
  2673. this._controller.pause();
  2674. }
  2675. }
  2676. }, {
  2677. key: 'resume',
  2678. value: function resume() {
  2679. if (this._worker) {
  2680. this._worker.postMessage({ cmd: 'resume' });
  2681. } else {
  2682. this._controller.resume();
  2683. }
  2684. }
  2685. }, {
  2686. key: '_onInitSegment',
  2687. value: function _onInitSegment(type, initSegment) {
  2688. var _this = this;
  2689. // do async invoke
  2690. Promise.resolve().then(function () {
  2691. _this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment);
  2692. });
  2693. }
  2694. }, {
  2695. key: '_onMediaSegment',
  2696. value: function _onMediaSegment(type, mediaSegment) {
  2697. var _this2 = this;
  2698. Promise.resolve().then(function () {
  2699. _this2._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment);
  2700. });
  2701. }
  2702. }, {
  2703. key: '_onLoadingComplete',
  2704. value: function _onLoadingComplete() {
  2705. var _this3 = this;
  2706. Promise.resolve().then(function () {
  2707. _this3._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE);
  2708. });
  2709. }
  2710. }, {
  2711. key: '_onRecoveredEarlyEof',
  2712. value: function _onRecoveredEarlyEof() {
  2713. var _this4 = this;
  2714. Promise.resolve().then(function () {
  2715. _this4._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF);
  2716. });
  2717. }
  2718. }, {
  2719. key: '_onMediaInfo',
  2720. value: function _onMediaInfo(mediaInfo) {
  2721. var _this5 = this;
  2722. Promise.resolve().then(function () {
  2723. _this5._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, mediaInfo);
  2724. });
  2725. }
  2726. }, {
  2727. key: '_onMetaDataArrived',
  2728. value: function _onMetaDataArrived(metadata) {
  2729. var _this6 = this;
  2730. Promise.resolve().then(function () {
  2731. _this6._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata);
  2732. });
  2733. }
  2734. }, {
  2735. key: '_onScriptDataArrived',
  2736. value: function _onScriptDataArrived(data) {
  2737. var _this7 = this;
  2738. Promise.resolve().then(function () {
  2739. _this7._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data);
  2740. });
  2741. }
  2742. }, {
  2743. key: '_onStatisticsInfo',
  2744. value: function _onStatisticsInfo(statisticsInfo) {
  2745. var _this8 = this;
  2746. Promise.resolve().then(function () {
  2747. _this8._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, statisticsInfo);
  2748. });
  2749. }
  2750. }, {
  2751. key: '_onIOError',
  2752. value: function _onIOError(type, info) {
  2753. var _this9 = this;
  2754. Promise.resolve().then(function () {
  2755. _this9._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info);
  2756. });
  2757. }
  2758. }, {
  2759. key: '_onDemuxError',
  2760. value: function _onDemuxError(type, info) {
  2761. var _this10 = this;
  2762. Promise.resolve().then(function () {
  2763. _this10._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info);
  2764. });
  2765. }
  2766. }, {
  2767. key: '_onRecommendSeekpoint',
  2768. value: function _onRecommendSeekpoint(milliseconds) {
  2769. var _this11 = this;
  2770. Promise.resolve().then(function () {
  2771. _this11._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, milliseconds);
  2772. });
  2773. }
  2774. }, {
  2775. key: '_onLoggingConfigChanged',
  2776. value: function _onLoggingConfigChanged(config) {
  2777. if (this._worker) {
  2778. this._worker.postMessage({ cmd: 'logging_config', param: config });
  2779. }
  2780. }
  2781. }, {
  2782. key: '_onWorkerMessage',
  2783. value: function _onWorkerMessage(e) {
  2784. var message = e.data;
  2785. var data = message.data;
  2786. if (message.msg === 'destroyed' || this._workerDestroying) {
  2787. this._workerDestroying = false;
  2788. this._worker.terminate();
  2789. this._worker = null;
  2790. return;
  2791. }
  2792. switch (message.msg) {
  2793. case _transmuxingEvents2.default.INIT_SEGMENT:
  2794. case _transmuxingEvents2.default.MEDIA_SEGMENT:
  2795. this._emitter.emit(message.msg, data.type, data.data);
  2796. break;
  2797. case _transmuxingEvents2.default.LOADING_COMPLETE:
  2798. case _transmuxingEvents2.default.RECOVERED_EARLY_EOF:
  2799. this._emitter.emit(message.msg);
  2800. break;
  2801. case _transmuxingEvents2.default.MEDIA_INFO:
  2802. Object.setPrototypeOf(data, _mediaInfo2.default.prototype);
  2803. this._emitter.emit(message.msg, data);
  2804. break;
  2805. case _transmuxingEvents2.default.METADATA_ARRIVED:
  2806. case _transmuxingEvents2.default.SCRIPTDATA_ARRIVED:
  2807. case _transmuxingEvents2.default.STATISTICS_INFO:
  2808. this._emitter.emit(message.msg, data);
  2809. break;
  2810. case _transmuxingEvents2.default.IO_ERROR:
  2811. case _transmuxingEvents2.default.DEMUX_ERROR:
  2812. this._emitter.emit(message.msg, data.type, data.info);
  2813. break;
  2814. case _transmuxingEvents2.default.RECOMMEND_SEEKPOINT:
  2815. this._emitter.emit(message.msg, data);
  2816. break;
  2817. case 'logcat_callback':
  2818. _logger2.default.emitter.emit('log', data.type, data.logcat);
  2819. break;
  2820. default:
  2821. break;
  2822. }
  2823. }
  2824. }]);
  2825. return Transmuxer;
  2826. }();
  2827. exports.default = Transmuxer;
  2828. },{"../utils/logger.js":41,"../utils/logging-control.js":42,"./media-info.js":7,"./transmuxing-controller.js":12,"./transmuxing-events.js":13,"./transmuxing-worker.js":14,"events":2,"webworkify":4}],12:[function(_dereq_,module,exports){
  2829. 'use strict';
  2830. Object.defineProperty(exports, "__esModule", {
  2831. value: true
  2832. });
  2833. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  2834. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  2835. *
  2836. * @author zheng qian <xqq@xqq.im>
  2837. *
  2838. * Licensed under the Apache License, Version 2.0 (the "License");
  2839. * you may not use this file except in compliance with the License.
  2840. * You may obtain a copy of the License at
  2841. *
  2842. * http://www.apache.org/licenses/LICENSE-2.0
  2843. *
  2844. * Unless required by applicable law or agreed to in writing, software
  2845. * distributed under the License is distributed on an "AS IS" BASIS,
  2846. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  2847. * See the License for the specific language governing permissions and
  2848. * limitations under the License.
  2849. */
  2850. var _events = _dereq_('events');
  2851. var _events2 = _interopRequireDefault(_events);
  2852. var _logger = _dereq_('../utils/logger.js');
  2853. var _logger2 = _interopRequireDefault(_logger);
  2854. var _browser = _dereq_('../utils/browser.js');
  2855. var _browser2 = _interopRequireDefault(_browser);
  2856. var _mediaInfo = _dereq_('./media-info.js');
  2857. var _mediaInfo2 = _interopRequireDefault(_mediaInfo);
  2858. var _flvDemuxer = _dereq_('../demux/flv-demuxer.js');
  2859. var _flvDemuxer2 = _interopRequireDefault(_flvDemuxer);
  2860. var _mp4Remuxer = _dereq_('../remux/mp4-remuxer.js');
  2861. var _mp4Remuxer2 = _interopRequireDefault(_mp4Remuxer);
  2862. var _demuxErrors = _dereq_('../demux/demux-errors.js');
  2863. var _demuxErrors2 = _interopRequireDefault(_demuxErrors);
  2864. var _ioController = _dereq_('../io/io-controller.js');
  2865. var _ioController2 = _interopRequireDefault(_ioController);
  2866. var _transmuxingEvents = _dereq_('./transmuxing-events.js');
  2867. var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents);
  2868. var _loader = _dereq_('../io/loader.js');
  2869. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  2870. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  2871. // Transmuxing (IO, Demuxing, Remuxing) controller, with multipart support
  2872. var TransmuxingController = function () {
  2873. function TransmuxingController(mediaDataSource, config) {
  2874. _classCallCheck(this, TransmuxingController);
  2875. this.TAG = 'TransmuxingController';
  2876. this._emitter = new _events2.default();
  2877. this._config = config;
  2878. // treat single part media as multipart media, which has only one segment
  2879. if (!mediaDataSource.segments) {
  2880. mediaDataSource.segments = [{
  2881. duration: mediaDataSource.duration,
  2882. filesize: mediaDataSource.filesize,
  2883. url: mediaDataSource.url
  2884. }];
  2885. }
  2886. // fill in default IO params if not exists
  2887. if (typeof mediaDataSource.cors !== 'boolean') {
  2888. mediaDataSource.cors = true;
  2889. }
  2890. if (typeof mediaDataSource.withCredentials !== 'boolean') {
  2891. mediaDataSource.withCredentials = false;
  2892. }
  2893. this._mediaDataSource = mediaDataSource;
  2894. this._currentSegmentIndex = 0;
  2895. var totalDuration = 0;
  2896. this._mediaDataSource.segments.forEach(function (segment) {
  2897. // timestampBase for each segment, and calculate total duration
  2898. segment.timestampBase = totalDuration;
  2899. totalDuration += segment.duration;
  2900. // params needed by IOController
  2901. segment.cors = mediaDataSource.cors;
  2902. segment.withCredentials = mediaDataSource.withCredentials;
  2903. // referrer policy control, if exist
  2904. if (config.referrerPolicy) {
  2905. segment.referrerPolicy = config.referrerPolicy;
  2906. }
  2907. });
  2908. if (!isNaN(totalDuration) && this._mediaDataSource.duration !== totalDuration) {
  2909. this._mediaDataSource.duration = totalDuration;
  2910. }
  2911. this._mediaInfo = null;
  2912. this._demuxer = null;
  2913. this._remuxer = null;
  2914. this._ioctl = null;
  2915. this._pendingSeekTime = null;
  2916. this._pendingResolveSeekPoint = null;
  2917. this._statisticsReporter = null;
  2918. }
  2919. _createClass(TransmuxingController, [{
  2920. key: 'destroy',
  2921. value: function destroy() {
  2922. this._mediaInfo = null;
  2923. this._mediaDataSource = null;
  2924. if (this._statisticsReporter) {
  2925. this._disableStatisticsReporter();
  2926. }
  2927. if (this._ioctl) {
  2928. this._ioctl.destroy();
  2929. this._ioctl = null;
  2930. }
  2931. if (this._demuxer) {
  2932. this._demuxer.destroy();
  2933. this._demuxer = null;
  2934. }
  2935. if (this._remuxer) {
  2936. this._remuxer.destroy();
  2937. this._remuxer = null;
  2938. }
  2939. this._emitter.removeAllListeners();
  2940. this._emitter = null;
  2941. }
  2942. }, {
  2943. key: 'on',
  2944. value: function on(event, listener) {
  2945. this._emitter.addListener(event, listener);
  2946. }
  2947. }, {
  2948. key: 'off',
  2949. value: function off(event, listener) {
  2950. this._emitter.removeListener(event, listener);
  2951. }
  2952. }, {
  2953. key: 'start',
  2954. value: function start() {
  2955. this._loadSegment(0);
  2956. this._enableStatisticsReporter();
  2957. }
  2958. }, {
  2959. key: '_loadSegment',
  2960. value: function _loadSegment(segmentIndex, optionalFrom) {
  2961. this._currentSegmentIndex = segmentIndex;
  2962. var dataSource = this._mediaDataSource.segments[segmentIndex];
  2963. var ioctl = this._ioctl = new _ioController2.default(dataSource, this._config, segmentIndex);
  2964. ioctl.onError = this._onIOException.bind(this);
  2965. ioctl.onSeeked = this._onIOSeeked.bind(this);
  2966. ioctl.onComplete = this._onIOComplete.bind(this);
  2967. ioctl.onRedirect = this._onIORedirect.bind(this);
  2968. ioctl.onRecoveredEarlyEof = this._onIORecoveredEarlyEof.bind(this);
  2969. if (optionalFrom) {
  2970. this._demuxer.bindDataSource(this._ioctl);
  2971. } else {
  2972. ioctl.onDataArrival = this._onInitChunkArrival.bind(this);
  2973. }
  2974. ioctl.open(optionalFrom);
  2975. }
  2976. }, {
  2977. key: 'stop',
  2978. value: function stop() {
  2979. this._internalAbort();
  2980. this._disableStatisticsReporter();
  2981. }
  2982. }, {
  2983. key: '_internalAbort',
  2984. value: function _internalAbort() {
  2985. if (this._ioctl) {
  2986. this._ioctl.destroy();
  2987. this._ioctl = null;
  2988. }
  2989. }
  2990. }, {
  2991. key: 'pause',
  2992. value: function pause() {
  2993. // take a rest
  2994. if (this._ioctl && this._ioctl.isWorking()) {
  2995. this._ioctl.pause();
  2996. this._disableStatisticsReporter();
  2997. }
  2998. }
  2999. }, {
  3000. key: 'resume',
  3001. value: function resume() {
  3002. if (this._ioctl && this._ioctl.isPaused()) {
  3003. this._ioctl.resume();
  3004. this._enableStatisticsReporter();
  3005. }
  3006. }
  3007. }, {
  3008. key: 'seek',
  3009. value: function seek(milliseconds) {
  3010. if (this._mediaInfo == null || !this._mediaInfo.isSeekable()) {
  3011. return;
  3012. }
  3013. var targetSegmentIndex = this._searchSegmentIndexContains(milliseconds);
  3014. if (targetSegmentIndex === this._currentSegmentIndex) {
  3015. // intra-segment seeking
  3016. var segmentInfo = this._mediaInfo.segments[targetSegmentIndex];
  3017. if (segmentInfo == undefined) {
  3018. // current segment loading started, but mediainfo hasn't received yet
  3019. // wait for the metadata loaded, then seek to expected position
  3020. this._pendingSeekTime = milliseconds;
  3021. } else {
  3022. var keyframe = segmentInfo.getNearestKeyframe(milliseconds);
  3023. this._remuxer.seek(keyframe.milliseconds);
  3024. this._ioctl.seek(keyframe.fileposition);
  3025. // Will be resolved in _onRemuxerMediaSegmentArrival()
  3026. this._pendingResolveSeekPoint = keyframe.milliseconds;
  3027. }
  3028. } else {
  3029. // cross-segment seeking
  3030. var targetSegmentInfo = this._mediaInfo.segments[targetSegmentIndex];
  3031. if (targetSegmentInfo == undefined) {
  3032. // target segment hasn't been loaded. We need metadata then seek to expected time
  3033. this._pendingSeekTime = milliseconds;
  3034. this._internalAbort();
  3035. this._remuxer.seek();
  3036. this._remuxer.insertDiscontinuity();
  3037. this._loadSegment(targetSegmentIndex);
  3038. // Here we wait for the metadata loaded, then seek to expected position
  3039. } else {
  3040. // We have target segment's metadata, direct seek to target position
  3041. var _keyframe = targetSegmentInfo.getNearestKeyframe(milliseconds);
  3042. this._internalAbort();
  3043. this._remuxer.seek(milliseconds);
  3044. this._remuxer.insertDiscontinuity();
  3045. this._demuxer.resetMediaInfo();
  3046. this._demuxer.timestampBase = this._mediaDataSource.segments[targetSegmentIndex].timestampBase;
  3047. this._loadSegment(targetSegmentIndex, _keyframe.fileposition);
  3048. this._pendingResolveSeekPoint = _keyframe.milliseconds;
  3049. this._reportSegmentMediaInfo(targetSegmentIndex);
  3050. }
  3051. }
  3052. this._enableStatisticsReporter();
  3053. }
  3054. }, {
  3055. key: '_searchSegmentIndexContains',
  3056. value: function _searchSegmentIndexContains(milliseconds) {
  3057. var segments = this._mediaDataSource.segments;
  3058. var idx = segments.length - 1;
  3059. for (var i = 0; i < segments.length; i++) {
  3060. if (milliseconds < segments[i].timestampBase) {
  3061. idx = i - 1;
  3062. break;
  3063. }
  3064. }
  3065. return idx;
  3066. }
  3067. }, {
  3068. key: '_onInitChunkArrival',
  3069. value: function _onInitChunkArrival(data, byteStart) {
  3070. var _this = this;
  3071. var probeData = null;
  3072. var consumed = 0;
  3073. if (byteStart > 0) {
  3074. // IOController seeked immediately after opened, byteStart > 0 callback may received
  3075. this._demuxer.bindDataSource(this._ioctl);
  3076. this._demuxer.timestampBase = this._mediaDataSource.segments[this._currentSegmentIndex].timestampBase;
  3077. consumed = this._demuxer.parseChunks(data, byteStart);
  3078. } else if ((probeData = _flvDemuxer2.default.probe(data)).match) {
  3079. // Always create new FLVDemuxer
  3080. this._demuxer = new _flvDemuxer2.default(probeData, this._config);
  3081. if (!this._remuxer) {
  3082. this._remuxer = new _mp4Remuxer2.default(this._config);
  3083. }
  3084. var mds = this._mediaDataSource;
  3085. if (mds.duration != undefined && !isNaN(mds.duration)) {
  3086. this._demuxer.overridedDuration = mds.duration;
  3087. }
  3088. if (typeof mds.hasAudio === 'boolean') {
  3089. this._demuxer.overridedHasAudio = mds.hasAudio;
  3090. }
  3091. if (typeof mds.hasVideo === 'boolean') {
  3092. this._demuxer.overridedHasVideo = mds.hasVideo;
  3093. }
  3094. this._demuxer.timestampBase = mds.segments[this._currentSegmentIndex].timestampBase;
  3095. this._demuxer.onError = this._onDemuxException.bind(this);
  3096. this._demuxer.onMediaInfo = this._onMediaInfo.bind(this);
  3097. this._demuxer.onMetaDataArrived = this._onMetaDataArrived.bind(this);
  3098. this._demuxer.onScriptDataArrived = this._onScriptDataArrived.bind(this);
  3099. this._remuxer.bindDataSource(this._demuxer.bindDataSource(this._ioctl));
  3100. this._remuxer.onInitSegment = this._onRemuxerInitSegmentArrival.bind(this);
  3101. this._remuxer.onMediaSegment = this._onRemuxerMediaSegmentArrival.bind(this);
  3102. consumed = this._demuxer.parseChunks(data, byteStart);
  3103. } else {
  3104. probeData = null;
  3105. _logger2.default.e(this.TAG, 'Non-FLV, Unsupported media type!');
  3106. Promise.resolve().then(function () {
  3107. _this._internalAbort();
  3108. });
  3109. this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, _demuxErrors2.default.FORMAT_UNSUPPORTED, 'Non-FLV, Unsupported media type');
  3110. consumed = 0;
  3111. }
  3112. return consumed;
  3113. }
  3114. }, {
  3115. key: '_onMediaInfo',
  3116. value: function _onMediaInfo(mediaInfo) {
  3117. var _this2 = this;
  3118. if (this._mediaInfo == null) {
  3119. // Store first segment's mediainfo as global mediaInfo
  3120. this._mediaInfo = Object.assign({}, mediaInfo);
  3121. this._mediaInfo.keyframesIndex = null;
  3122. this._mediaInfo.segments = [];
  3123. this._mediaInfo.segmentCount = this._mediaDataSource.segments.length;
  3124. Object.setPrototypeOf(this._mediaInfo, _mediaInfo2.default.prototype);
  3125. }
  3126. var segmentInfo = Object.assign({}, mediaInfo);
  3127. Object.setPrototypeOf(segmentInfo, _mediaInfo2.default.prototype);
  3128. this._mediaInfo.segments[this._currentSegmentIndex] = segmentInfo;
  3129. // notify mediaInfo update
  3130. this._reportSegmentMediaInfo(this._currentSegmentIndex);
  3131. if (this._pendingSeekTime != null) {
  3132. Promise.resolve().then(function () {
  3133. var target = _this2._pendingSeekTime;
  3134. _this2._pendingSeekTime = null;
  3135. _this2.seek(target);
  3136. });
  3137. }
  3138. }
  3139. }, {
  3140. key: '_onMetaDataArrived',
  3141. value: function _onMetaDataArrived(metadata) {
  3142. this._emitter.emit(_transmuxingEvents2.default.METADATA_ARRIVED, metadata);
  3143. }
  3144. }, {
  3145. key: '_onScriptDataArrived',
  3146. value: function _onScriptDataArrived(data) {
  3147. this._emitter.emit(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, data);
  3148. }
  3149. }, {
  3150. key: '_onIOSeeked',
  3151. value: function _onIOSeeked() {
  3152. this._remuxer.insertDiscontinuity();
  3153. }
  3154. }, {
  3155. key: '_onIOComplete',
  3156. value: function _onIOComplete(extraData) {
  3157. var segmentIndex = extraData;
  3158. var nextSegmentIndex = segmentIndex + 1;
  3159. if (nextSegmentIndex < this._mediaDataSource.segments.length) {
  3160. this._internalAbort();
  3161. this._remuxer.flushStashedSamples();
  3162. this._loadSegment(nextSegmentIndex);
  3163. } else {
  3164. this._remuxer.flushStashedSamples();
  3165. this._emitter.emit(_transmuxingEvents2.default.LOADING_COMPLETE);
  3166. this._disableStatisticsReporter();
  3167. }
  3168. }
  3169. }, {
  3170. key: '_onIORedirect',
  3171. value: function _onIORedirect(redirectedURL) {
  3172. var segmentIndex = this._ioctl.extraData;
  3173. this._mediaDataSource.segments[segmentIndex].redirectedURL = redirectedURL;
  3174. }
  3175. }, {
  3176. key: '_onIORecoveredEarlyEof',
  3177. value: function _onIORecoveredEarlyEof() {
  3178. this._emitter.emit(_transmuxingEvents2.default.RECOVERED_EARLY_EOF);
  3179. }
  3180. }, {
  3181. key: '_onIOException',
  3182. value: function _onIOException(type, info) {
  3183. _logger2.default.e(this.TAG, 'IOException: type = ' + type + ', code = ' + info.code + ', msg = ' + info.msg);
  3184. this._emitter.emit(_transmuxingEvents2.default.IO_ERROR, type, info);
  3185. this._disableStatisticsReporter();
  3186. }
  3187. }, {
  3188. key: '_onDemuxException',
  3189. value: function _onDemuxException(type, info) {
  3190. _logger2.default.e(this.TAG, 'DemuxException: type = ' + type + ', info = ' + info);
  3191. this._emitter.emit(_transmuxingEvents2.default.DEMUX_ERROR, type, info);
  3192. }
  3193. }, {
  3194. key: '_onRemuxerInitSegmentArrival',
  3195. value: function _onRemuxerInitSegmentArrival(type, initSegment) {
  3196. this._emitter.emit(_transmuxingEvents2.default.INIT_SEGMENT, type, initSegment);
  3197. }
  3198. }, {
  3199. key: '_onRemuxerMediaSegmentArrival',
  3200. value: function _onRemuxerMediaSegmentArrival(type, mediaSegment) {
  3201. if (this._pendingSeekTime != null) {
  3202. // Media segments after new-segment cross-seeking should be dropped.
  3203. return;
  3204. }
  3205. this._emitter.emit(_transmuxingEvents2.default.MEDIA_SEGMENT, type, mediaSegment);
  3206. // Resolve pending seekPoint
  3207. if (this._pendingResolveSeekPoint != null && type === 'video') {
  3208. var syncPoints = mediaSegment.info.syncPoints;
  3209. var seekpoint = this._pendingResolveSeekPoint;
  3210. this._pendingResolveSeekPoint = null;
  3211. // Safari: Pass PTS for recommend_seekpoint
  3212. if (_browser2.default.safari && syncPoints.length > 0 && syncPoints[0].originalDts === seekpoint) {
  3213. seekpoint = syncPoints[0].pts;
  3214. }
  3215. // else: use original DTS (keyframe.milliseconds)
  3216. this._emitter.emit(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, seekpoint);
  3217. }
  3218. }
  3219. }, {
  3220. key: '_enableStatisticsReporter',
  3221. value: function _enableStatisticsReporter() {
  3222. if (this._statisticsReporter == null) {
  3223. this._statisticsReporter = self.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval);
  3224. }
  3225. }
  3226. }, {
  3227. key: '_disableStatisticsReporter',
  3228. value: function _disableStatisticsReporter() {
  3229. if (this._statisticsReporter) {
  3230. self.clearInterval(this._statisticsReporter);
  3231. this._statisticsReporter = null;
  3232. }
  3233. }
  3234. }, {
  3235. key: '_reportSegmentMediaInfo',
  3236. value: function _reportSegmentMediaInfo(segmentIndex) {
  3237. var segmentInfo = this._mediaInfo.segments[segmentIndex];
  3238. var exportInfo = Object.assign({}, segmentInfo);
  3239. exportInfo.duration = this._mediaInfo.duration;
  3240. exportInfo.segmentCount = this._mediaInfo.segmentCount;
  3241. delete exportInfo.segments;
  3242. delete exportInfo.keyframesIndex;
  3243. this._emitter.emit(_transmuxingEvents2.default.MEDIA_INFO, exportInfo);
  3244. }
  3245. }, {
  3246. key: '_reportStatisticsInfo',
  3247. value: function _reportStatisticsInfo() {
  3248. var info = {};
  3249. info.url = this._ioctl.currentURL;
  3250. info.hasRedirect = this._ioctl.hasRedirect;
  3251. if (info.hasRedirect) {
  3252. info.redirectedURL = this._ioctl.currentRedirectedURL;
  3253. }
  3254. info.speed = this._ioctl.currentSpeed;
  3255. info.loaderType = this._ioctl.loaderType;
  3256. info.currentSegmentIndex = this._currentSegmentIndex;
  3257. info.totalSegmentCount = this._mediaDataSource.segments.length;
  3258. this._emitter.emit(_transmuxingEvents2.default.STATISTICS_INFO, info);
  3259. }
  3260. }]);
  3261. return TransmuxingController;
  3262. }();
  3263. exports.default = TransmuxingController;
  3264. },{"../demux/demux-errors.js":16,"../demux/flv-demuxer.js":18,"../io/io-controller.js":23,"../io/loader.js":24,"../remux/mp4-remuxer.js":38,"../utils/browser.js":39,"../utils/logger.js":41,"./media-info.js":7,"./transmuxing-events.js":13,"events":2}],13:[function(_dereq_,module,exports){
  3265. 'use strict';
  3266. Object.defineProperty(exports, "__esModule", {
  3267. value: true
  3268. });
  3269. /*
  3270. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3271. *
  3272. * @author zheng qian <xqq@xqq.im>
  3273. *
  3274. * Licensed under the Apache License, Version 2.0 (the "License");
  3275. * you may not use this file except in compliance with the License.
  3276. * You may obtain a copy of the License at
  3277. *
  3278. * http://www.apache.org/licenses/LICENSE-2.0
  3279. *
  3280. * Unless required by applicable law or agreed to in writing, software
  3281. * distributed under the License is distributed on an "AS IS" BASIS,
  3282. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3283. * See the License for the specific language governing permissions and
  3284. * limitations under the License.
  3285. */
  3286. var TransmuxingEvents = {
  3287. IO_ERROR: 'io_error',
  3288. DEMUX_ERROR: 'demux_error',
  3289. INIT_SEGMENT: 'init_segment',
  3290. MEDIA_SEGMENT: 'media_segment',
  3291. LOADING_COMPLETE: 'loading_complete',
  3292. RECOVERED_EARLY_EOF: 'recovered_early_eof',
  3293. MEDIA_INFO: 'media_info',
  3294. METADATA_ARRIVED: 'metadata_arrived',
  3295. SCRIPTDATA_ARRIVED: 'scriptdata_arrived',
  3296. STATISTICS_INFO: 'statistics_info',
  3297. RECOMMEND_SEEKPOINT: 'recommend_seekpoint'
  3298. };
  3299. exports.default = TransmuxingEvents;
  3300. },{}],14:[function(_dereq_,module,exports){
  3301. 'use strict';
  3302. Object.defineProperty(exports, "__esModule", {
  3303. value: true
  3304. });
  3305. var _logger = _dereq_('../utils/logger.js');
  3306. var _logger2 = _interopRequireDefault(_logger);
  3307. var _loggingControl = _dereq_('../utils/logging-control.js');
  3308. var _loggingControl2 = _interopRequireDefault(_loggingControl);
  3309. var _polyfill = _dereq_('../utils/polyfill.js');
  3310. var _polyfill2 = _interopRequireDefault(_polyfill);
  3311. var _transmuxingController = _dereq_('./transmuxing-controller.js');
  3312. var _transmuxingController2 = _interopRequireDefault(_transmuxingController);
  3313. var _transmuxingEvents = _dereq_('./transmuxing-events.js');
  3314. var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents);
  3315. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  3316. /* post message to worker:
  3317. data: {
  3318. cmd: string
  3319. param: any
  3320. }
  3321. receive message from worker:
  3322. data: {
  3323. msg: string,
  3324. data: any
  3325. }
  3326. */
  3327. var TransmuxingWorker = function TransmuxingWorker(self) {
  3328. var TAG = 'TransmuxingWorker';
  3329. var controller = null;
  3330. var logcatListener = onLogcatCallback.bind(this);
  3331. _polyfill2.default.install();
  3332. self.addEventListener('message', function (e) {
  3333. switch (e.data.cmd) {
  3334. case 'init':
  3335. controller = new _transmuxingController2.default(e.data.param[0], e.data.param[1]);
  3336. controller.on(_transmuxingEvents2.default.IO_ERROR, onIOError.bind(this));
  3337. controller.on(_transmuxingEvents2.default.DEMUX_ERROR, onDemuxError.bind(this));
  3338. controller.on(_transmuxingEvents2.default.INIT_SEGMENT, onInitSegment.bind(this));
  3339. controller.on(_transmuxingEvents2.default.MEDIA_SEGMENT, onMediaSegment.bind(this));
  3340. controller.on(_transmuxingEvents2.default.LOADING_COMPLETE, onLoadingComplete.bind(this));
  3341. controller.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, onRecoveredEarlyEof.bind(this));
  3342. controller.on(_transmuxingEvents2.default.MEDIA_INFO, onMediaInfo.bind(this));
  3343. controller.on(_transmuxingEvents2.default.METADATA_ARRIVED, onMetaDataArrived.bind(this));
  3344. controller.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, onScriptDataArrived.bind(this));
  3345. controller.on(_transmuxingEvents2.default.STATISTICS_INFO, onStatisticsInfo.bind(this));
  3346. controller.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, onRecommendSeekpoint.bind(this));
  3347. break;
  3348. case 'destroy':
  3349. if (controller) {
  3350. controller.destroy();
  3351. controller = null;
  3352. }
  3353. self.postMessage({ msg: 'destroyed' });
  3354. break;
  3355. case 'start':
  3356. controller.start();
  3357. break;
  3358. case 'stop':
  3359. controller.stop();
  3360. break;
  3361. case 'seek':
  3362. controller.seek(e.data.param);
  3363. break;
  3364. case 'pause':
  3365. controller.pause();
  3366. break;
  3367. case 'resume':
  3368. controller.resume();
  3369. break;
  3370. case 'logging_config':
  3371. {
  3372. var config = e.data.param;
  3373. _loggingControl2.default.applyConfig(config);
  3374. if (config.enableCallback === true) {
  3375. _loggingControl2.default.addLogListener(logcatListener);
  3376. } else {
  3377. _loggingControl2.default.removeLogListener(logcatListener);
  3378. }
  3379. break;
  3380. }
  3381. }
  3382. });
  3383. function onInitSegment(type, initSegment) {
  3384. var obj = {
  3385. msg: _transmuxingEvents2.default.INIT_SEGMENT,
  3386. data: {
  3387. type: type,
  3388. data: initSegment
  3389. }
  3390. };
  3391. self.postMessage(obj, [initSegment.data]); // data: ArrayBuffer
  3392. }
  3393. function onMediaSegment(type, mediaSegment) {
  3394. var obj = {
  3395. msg: _transmuxingEvents2.default.MEDIA_SEGMENT,
  3396. data: {
  3397. type: type,
  3398. data: mediaSegment
  3399. }
  3400. };
  3401. self.postMessage(obj, [mediaSegment.data]); // data: ArrayBuffer
  3402. }
  3403. function onLoadingComplete() {
  3404. var obj = {
  3405. msg: _transmuxingEvents2.default.LOADING_COMPLETE
  3406. };
  3407. self.postMessage(obj);
  3408. }
  3409. function onRecoveredEarlyEof() {
  3410. var obj = {
  3411. msg: _transmuxingEvents2.default.RECOVERED_EARLY_EOF
  3412. };
  3413. self.postMessage(obj);
  3414. }
  3415. function onMediaInfo(mediaInfo) {
  3416. var obj = {
  3417. msg: _transmuxingEvents2.default.MEDIA_INFO,
  3418. data: mediaInfo
  3419. };
  3420. self.postMessage(obj);
  3421. }
  3422. function onMetaDataArrived(metadata) {
  3423. var obj = {
  3424. msg: _transmuxingEvents2.default.METADATA_ARRIVED,
  3425. data: metadata
  3426. };
  3427. self.postMessage(obj);
  3428. }
  3429. function onScriptDataArrived(data) {
  3430. var obj = {
  3431. msg: _transmuxingEvents2.default.SCRIPTDATA_ARRIVED,
  3432. data: data
  3433. };
  3434. self.postMessage(obj);
  3435. }
  3436. function onStatisticsInfo(statInfo) {
  3437. var obj = {
  3438. msg: _transmuxingEvents2.default.STATISTICS_INFO,
  3439. data: statInfo
  3440. };
  3441. self.postMessage(obj);
  3442. }
  3443. function onIOError(type, info) {
  3444. self.postMessage({
  3445. msg: _transmuxingEvents2.default.IO_ERROR,
  3446. data: {
  3447. type: type,
  3448. info: info
  3449. }
  3450. });
  3451. }
  3452. function onDemuxError(type, info) {
  3453. self.postMessage({
  3454. msg: _transmuxingEvents2.default.DEMUX_ERROR,
  3455. data: {
  3456. type: type,
  3457. info: info
  3458. }
  3459. });
  3460. }
  3461. function onRecommendSeekpoint(milliseconds) {
  3462. self.postMessage({
  3463. msg: _transmuxingEvents2.default.RECOMMEND_SEEKPOINT,
  3464. data: milliseconds
  3465. });
  3466. }
  3467. function onLogcatCallback(type, str) {
  3468. self.postMessage({
  3469. msg: 'logcat_callback',
  3470. data: {
  3471. type: type,
  3472. logcat: str
  3473. }
  3474. });
  3475. }
  3476. }; /*
  3477. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3478. *
  3479. * @author zheng qian <xqq@xqq.im>
  3480. *
  3481. * Licensed under the Apache License, Version 2.0 (the "License");
  3482. * you may not use this file except in compliance with the License.
  3483. * You may obtain a copy of the License at
  3484. *
  3485. * http://www.apache.org/licenses/LICENSE-2.0
  3486. *
  3487. * Unless required by applicable law or agreed to in writing, software
  3488. * distributed under the License is distributed on an "AS IS" BASIS,
  3489. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3490. * See the License for the specific language governing permissions and
  3491. * limitations under the License.
  3492. */
  3493. exports.default = TransmuxingWorker;
  3494. },{"../utils/logger.js":41,"../utils/logging-control.js":42,"../utils/polyfill.js":43,"./transmuxing-controller.js":12,"./transmuxing-events.js":13}],15:[function(_dereq_,module,exports){
  3495. 'use strict';
  3496. Object.defineProperty(exports, "__esModule", {
  3497. value: true
  3498. });
  3499. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  3500. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3501. *
  3502. * @author zheng qian <xqq@xqq.im>
  3503. *
  3504. * Licensed under the Apache License, Version 2.0 (the "License");
  3505. * you may not use this file except in compliance with the License.
  3506. * You may obtain a copy of the License at
  3507. *
  3508. * http://www.apache.org/licenses/LICENSE-2.0
  3509. *
  3510. * Unless required by applicable law or agreed to in writing, software
  3511. * distributed under the License is distributed on an "AS IS" BASIS,
  3512. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3513. * See the License for the specific language governing permissions and
  3514. * limitations under the License.
  3515. */
  3516. var _logger = _dereq_('../utils/logger.js');
  3517. var _logger2 = _interopRequireDefault(_logger);
  3518. var _utf8Conv = _dereq_('../utils/utf8-conv.js');
  3519. var _utf8Conv2 = _interopRequireDefault(_utf8Conv);
  3520. var _exception = _dereq_('../utils/exception.js');
  3521. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  3522. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3523. var le = function () {
  3524. var buf = new ArrayBuffer(2);
  3525. new DataView(buf).setInt16(0, 256, true); // little-endian write
  3526. return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE
  3527. }();
  3528. var AMF = function () {
  3529. function AMF() {
  3530. _classCallCheck(this, AMF);
  3531. }
  3532. _createClass(AMF, null, [{
  3533. key: 'parseScriptData',
  3534. value: function parseScriptData(arrayBuffer, dataOffset, dataSize) {
  3535. var data = {};
  3536. try {
  3537. var name = AMF.parseValue(arrayBuffer, dataOffset, dataSize);
  3538. var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size);
  3539. data[name.data] = value.data;
  3540. } catch (e) {
  3541. _logger2.default.e('AMF', e.toString());
  3542. }
  3543. return data;
  3544. }
  3545. }, {
  3546. key: 'parseObject',
  3547. value: function parseObject(arrayBuffer, dataOffset, dataSize) {
  3548. if (dataSize < 3) {
  3549. throw new _exception.IllegalStateException('Data not enough when parse ScriptDataObject');
  3550. }
  3551. var name = AMF.parseString(arrayBuffer, dataOffset, dataSize);
  3552. var value = AMF.parseValue(arrayBuffer, dataOffset + name.size, dataSize - name.size);
  3553. var isObjectEnd = value.objectEnd;
  3554. return {
  3555. data: {
  3556. name: name.data,
  3557. value: value.data
  3558. },
  3559. size: name.size + value.size,
  3560. objectEnd: isObjectEnd
  3561. };
  3562. }
  3563. }, {
  3564. key: 'parseVariable',
  3565. value: function parseVariable(arrayBuffer, dataOffset, dataSize) {
  3566. return AMF.parseObject(arrayBuffer, dataOffset, dataSize);
  3567. }
  3568. }, {
  3569. key: 'parseString',
  3570. value: function parseString(arrayBuffer, dataOffset, dataSize) {
  3571. if (dataSize < 2) {
  3572. throw new _exception.IllegalStateException('Data not enough when parse String');
  3573. }
  3574. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  3575. var length = v.getUint16(0, !le);
  3576. var str = void 0;
  3577. if (length > 0) {
  3578. str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 2, length));
  3579. } else {
  3580. str = '';
  3581. }
  3582. return {
  3583. data: str,
  3584. size: 2 + length
  3585. };
  3586. }
  3587. }, {
  3588. key: 'parseLongString',
  3589. value: function parseLongString(arrayBuffer, dataOffset, dataSize) {
  3590. if (dataSize < 4) {
  3591. throw new _exception.IllegalStateException('Data not enough when parse LongString');
  3592. }
  3593. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  3594. var length = v.getUint32(0, !le);
  3595. var str = void 0;
  3596. if (length > 0) {
  3597. str = (0, _utf8Conv2.default)(new Uint8Array(arrayBuffer, dataOffset + 4, length));
  3598. } else {
  3599. str = '';
  3600. }
  3601. return {
  3602. data: str,
  3603. size: 4 + length
  3604. };
  3605. }
  3606. }, {
  3607. key: 'parseDate',
  3608. value: function parseDate(arrayBuffer, dataOffset, dataSize) {
  3609. if (dataSize < 10) {
  3610. throw new _exception.IllegalStateException('Data size invalid when parse Date');
  3611. }
  3612. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  3613. var timestamp = v.getFloat64(0, !le);
  3614. var localTimeOffset = v.getInt16(8, !le);
  3615. timestamp += localTimeOffset * 60 * 1000; // get UTC time
  3616. return {
  3617. data: new Date(timestamp),
  3618. size: 8 + 2
  3619. };
  3620. }
  3621. }, {
  3622. key: 'parseValue',
  3623. value: function parseValue(arrayBuffer, dataOffset, dataSize) {
  3624. if (dataSize < 1) {
  3625. throw new _exception.IllegalStateException('Data not enough when parse Value');
  3626. }
  3627. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  3628. var offset = 1;
  3629. var type = v.getUint8(0);
  3630. var value = void 0;
  3631. var objectEnd = false;
  3632. try {
  3633. switch (type) {
  3634. case 0:
  3635. // Number(Double) type
  3636. value = v.getFloat64(1, !le);
  3637. offset += 8;
  3638. break;
  3639. case 1:
  3640. {
  3641. // Boolean type
  3642. var b = v.getUint8(1);
  3643. value = b ? true : false;
  3644. offset += 1;
  3645. break;
  3646. }
  3647. case 2:
  3648. {
  3649. // String type
  3650. var amfstr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1);
  3651. value = amfstr.data;
  3652. offset += amfstr.size;
  3653. break;
  3654. }
  3655. case 3:
  3656. {
  3657. // Object(s) type
  3658. value = {};
  3659. var terminal = 0; // workaround for malformed Objects which has missing ScriptDataObjectEnd
  3660. if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) {
  3661. terminal = 3;
  3662. }
  3663. while (offset < dataSize - 4) {
  3664. // 4 === type(UI8) + ScriptDataObjectEnd(UI24)
  3665. var amfobj = AMF.parseObject(arrayBuffer, dataOffset + offset, dataSize - offset - terminal);
  3666. if (amfobj.objectEnd) break;
  3667. value[amfobj.data.name] = amfobj.data.value;
  3668. offset += amfobj.size;
  3669. }
  3670. if (offset <= dataSize - 3) {
  3671. var marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF;
  3672. if (marker === 9) {
  3673. offset += 3;
  3674. }
  3675. }
  3676. break;
  3677. }
  3678. case 8:
  3679. {
  3680. // ECMA array type (Mixed array)
  3681. value = {};
  3682. offset += 4; // ECMAArrayLength(UI32)
  3683. var _terminal = 0; // workaround for malformed MixedArrays which has missing ScriptDataObjectEnd
  3684. if ((v.getUint32(dataSize - 4, !le) & 0x00FFFFFF) === 9) {
  3685. _terminal = 3;
  3686. }
  3687. while (offset < dataSize - 8) {
  3688. // 8 === type(UI8) + ECMAArrayLength(UI32) + ScriptDataVariableEnd(UI24)
  3689. var amfvar = AMF.parseVariable(arrayBuffer, dataOffset + offset, dataSize - offset - _terminal);
  3690. if (amfvar.objectEnd) break;
  3691. value[amfvar.data.name] = amfvar.data.value;
  3692. offset += amfvar.size;
  3693. }
  3694. if (offset <= dataSize - 3) {
  3695. var _marker = v.getUint32(offset - 1, !le) & 0x00FFFFFF;
  3696. if (_marker === 9) {
  3697. offset += 3;
  3698. }
  3699. }
  3700. break;
  3701. }
  3702. case 9:
  3703. // ScriptDataObjectEnd
  3704. value = undefined;
  3705. offset = 1;
  3706. objectEnd = true;
  3707. break;
  3708. case 10:
  3709. {
  3710. // Strict array type
  3711. // ScriptDataValue[n]. NOTE: according to video_file_format_spec_v10_1.pdf
  3712. value = [];
  3713. var strictArrayLength = v.getUint32(1, !le);
  3714. offset += 4;
  3715. for (var i = 0; i < strictArrayLength; i++) {
  3716. var val = AMF.parseValue(arrayBuffer, dataOffset + offset, dataSize - offset);
  3717. value.push(val.data);
  3718. offset += val.size;
  3719. }
  3720. break;
  3721. }
  3722. case 11:
  3723. {
  3724. // Date type
  3725. var date = AMF.parseDate(arrayBuffer, dataOffset + 1, dataSize - 1);
  3726. value = date.data;
  3727. offset += date.size;
  3728. break;
  3729. }
  3730. case 12:
  3731. {
  3732. // Long string type
  3733. var amfLongStr = AMF.parseString(arrayBuffer, dataOffset + 1, dataSize - 1);
  3734. value = amfLongStr.data;
  3735. offset += amfLongStr.size;
  3736. break;
  3737. }
  3738. default:
  3739. // ignore and skip
  3740. offset = dataSize;
  3741. _logger2.default.w('AMF', 'Unsupported AMF value type ' + type);
  3742. }
  3743. } catch (e) {
  3744. _logger2.default.e('AMF', e.toString());
  3745. }
  3746. return {
  3747. data: value,
  3748. size: offset,
  3749. objectEnd: objectEnd
  3750. };
  3751. }
  3752. }]);
  3753. return AMF;
  3754. }();
  3755. exports.default = AMF;
  3756. },{"../utils/exception.js":40,"../utils/logger.js":41,"../utils/utf8-conv.js":44}],16:[function(_dereq_,module,exports){
  3757. 'use strict';
  3758. Object.defineProperty(exports, "__esModule", {
  3759. value: true
  3760. });
  3761. /*
  3762. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3763. *
  3764. * @author zheng qian <xqq@xqq.im>
  3765. *
  3766. * Licensed under the Apache License, Version 2.0 (the "License");
  3767. * you may not use this file except in compliance with the License.
  3768. * You may obtain a copy of the License at
  3769. *
  3770. * http://www.apache.org/licenses/LICENSE-2.0
  3771. *
  3772. * Unless required by applicable law or agreed to in writing, software
  3773. * distributed under the License is distributed on an "AS IS" BASIS,
  3774. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3775. * See the License for the specific language governing permissions and
  3776. * limitations under the License.
  3777. */
  3778. var DemuxErrors = {
  3779. OK: 'OK',
  3780. FORMAT_ERROR: 'FormatError',
  3781. FORMAT_UNSUPPORTED: 'FormatUnsupported',
  3782. CODEC_UNSUPPORTED: 'CodecUnsupported'
  3783. };
  3784. exports.default = DemuxErrors;
  3785. },{}],17:[function(_dereq_,module,exports){
  3786. 'use strict';
  3787. Object.defineProperty(exports, "__esModule", {
  3788. value: true
  3789. });
  3790. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  3791. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3792. *
  3793. * @author zheng qian <xqq@xqq.im>
  3794. *
  3795. * Licensed under the Apache License, Version 2.0 (the "License");
  3796. * you may not use this file except in compliance with the License.
  3797. * You may obtain a copy of the License at
  3798. *
  3799. * http://www.apache.org/licenses/LICENSE-2.0
  3800. *
  3801. * Unless required by applicable law or agreed to in writing, software
  3802. * distributed under the License is distributed on an "AS IS" BASIS,
  3803. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3804. * See the License for the specific language governing permissions and
  3805. * limitations under the License.
  3806. */
  3807. var _exception = _dereq_('../utils/exception.js');
  3808. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3809. // Exponential-Golomb buffer decoder
  3810. var ExpGolomb = function () {
  3811. function ExpGolomb(uint8array) {
  3812. _classCallCheck(this, ExpGolomb);
  3813. this.TAG = 'ExpGolomb';
  3814. this._buffer = uint8array;
  3815. this._buffer_index = 0;
  3816. this._total_bytes = uint8array.byteLength;
  3817. this._total_bits = uint8array.byteLength * 8;
  3818. this._current_word = 0;
  3819. this._current_word_bits_left = 0;
  3820. }
  3821. _createClass(ExpGolomb, [{
  3822. key: 'destroy',
  3823. value: function destroy() {
  3824. this._buffer = null;
  3825. }
  3826. }, {
  3827. key: '_fillCurrentWord',
  3828. value: function _fillCurrentWord() {
  3829. var buffer_bytes_left = this._total_bytes - this._buffer_index;
  3830. if (buffer_bytes_left <= 0) throw new _exception.IllegalStateException('ExpGolomb: _fillCurrentWord() but no bytes available');
  3831. var bytes_read = Math.min(4, buffer_bytes_left);
  3832. var word = new Uint8Array(4);
  3833. word.set(this._buffer.subarray(this._buffer_index, this._buffer_index + bytes_read));
  3834. this._current_word = new DataView(word.buffer).getUint32(0, false);
  3835. this._buffer_index += bytes_read;
  3836. this._current_word_bits_left = bytes_read * 8;
  3837. }
  3838. }, {
  3839. key: 'readBits',
  3840. value: function readBits(bits) {
  3841. if (bits > 32) throw new _exception.InvalidArgumentException('ExpGolomb: readBits() bits exceeded max 32bits!');
  3842. if (bits <= this._current_word_bits_left) {
  3843. var _result = this._current_word >>> 32 - bits;
  3844. this._current_word <<= bits;
  3845. this._current_word_bits_left -= bits;
  3846. return _result;
  3847. }
  3848. var result = this._current_word_bits_left ? this._current_word : 0;
  3849. result = result >>> 32 - this._current_word_bits_left;
  3850. var bits_need_left = bits - this._current_word_bits_left;
  3851. this._fillCurrentWord();
  3852. var bits_read_next = Math.min(bits_need_left, this._current_word_bits_left);
  3853. var result2 = this._current_word >>> 32 - bits_read_next;
  3854. this._current_word <<= bits_read_next;
  3855. this._current_word_bits_left -= bits_read_next;
  3856. result = result << bits_read_next | result2;
  3857. return result;
  3858. }
  3859. }, {
  3860. key: 'readBool',
  3861. value: function readBool() {
  3862. return this.readBits(1) === 1;
  3863. }
  3864. }, {
  3865. key: 'readByte',
  3866. value: function readByte() {
  3867. return this.readBits(8);
  3868. }
  3869. }, {
  3870. key: '_skipLeadingZero',
  3871. value: function _skipLeadingZero() {
  3872. var zero_count = void 0;
  3873. for (zero_count = 0; zero_count < this._current_word_bits_left; zero_count++) {
  3874. if (0 !== (this._current_word & 0x80000000 >>> zero_count)) {
  3875. this._current_word <<= zero_count;
  3876. this._current_word_bits_left -= zero_count;
  3877. return zero_count;
  3878. }
  3879. }
  3880. this._fillCurrentWord();
  3881. return zero_count + this._skipLeadingZero();
  3882. }
  3883. }, {
  3884. key: 'readUEG',
  3885. value: function readUEG() {
  3886. // unsigned exponential golomb
  3887. var leading_zeros = this._skipLeadingZero();
  3888. return this.readBits(leading_zeros + 1) - 1;
  3889. }
  3890. }, {
  3891. key: 'readSEG',
  3892. value: function readSEG() {
  3893. // signed exponential golomb
  3894. var value = this.readUEG();
  3895. if (value & 0x01) {
  3896. return value + 1 >>> 1;
  3897. } else {
  3898. return -1 * (value >>> 1);
  3899. }
  3900. }
  3901. }]);
  3902. return ExpGolomb;
  3903. }();
  3904. exports.default = ExpGolomb;
  3905. },{"../utils/exception.js":40}],18:[function(_dereq_,module,exports){
  3906. 'use strict';
  3907. Object.defineProperty(exports, "__esModule", {
  3908. value: true
  3909. });
  3910. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  3911. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  3912. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  3913. *
  3914. * @author zheng qian <xqq@xqq.im>
  3915. *
  3916. * Licensed under the Apache License, Version 2.0 (the "License");
  3917. * you may not use this file except in compliance with the License.
  3918. * You may obtain a copy of the License at
  3919. *
  3920. * http://www.apache.org/licenses/LICENSE-2.0
  3921. *
  3922. * Unless required by applicable law or agreed to in writing, software
  3923. * distributed under the License is distributed on an "AS IS" BASIS,
  3924. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3925. * See the License for the specific language governing permissions and
  3926. * limitations under the License.
  3927. */
  3928. var _logger = _dereq_('../utils/logger.js');
  3929. var _logger2 = _interopRequireDefault(_logger);
  3930. var _amfParser = _dereq_('./amf-parser.js');
  3931. var _amfParser2 = _interopRequireDefault(_amfParser);
  3932. var _spsParser = _dereq_('./sps-parser.js');
  3933. var _spsParser2 = _interopRequireDefault(_spsParser);
  3934. var _demuxErrors = _dereq_('./demux-errors.js');
  3935. var _demuxErrors2 = _interopRequireDefault(_demuxErrors);
  3936. var _mediaInfo = _dereq_('../core/media-info.js');
  3937. var _mediaInfo2 = _interopRequireDefault(_mediaInfo);
  3938. var _exception = _dereq_('../utils/exception.js');
  3939. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  3940. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3941. function Swap16(src) {
  3942. return src >>> 8 & 0xFF | (src & 0xFF) << 8;
  3943. }
  3944. function Swap32(src) {
  3945. return (src & 0xFF000000) >>> 24 | (src & 0x00FF0000) >>> 8 | (src & 0x0000FF00) << 8 | (src & 0x000000FF) << 24;
  3946. }
  3947. function ReadBig32(array, index) {
  3948. return array[index] << 24 | array[index + 1] << 16 | array[index + 2] << 8 | array[index + 3];
  3949. }
  3950. var FLVDemuxer = function () {
  3951. function FLVDemuxer(probeData, config) {
  3952. _classCallCheck(this, FLVDemuxer);
  3953. this.TAG = 'FLVDemuxer';
  3954. this._config = config;
  3955. this._onError = null;
  3956. this._onMediaInfo = null;
  3957. this._onMetaDataArrived = null;
  3958. this._onScriptDataArrived = null;
  3959. this._onTrackMetadata = null;
  3960. this._onDataAvailable = null;
  3961. this._dataOffset = probeData.dataOffset;
  3962. this._firstParse = true;
  3963. this._dispatch = false;
  3964. this._hasAudio = probeData.hasAudioTrack;
  3965. this._hasVideo = probeData.hasVideoTrack;
  3966. this._hasAudioFlagOverrided = false;
  3967. this._hasVideoFlagOverrided = false;
  3968. this._audioInitialMetadataDispatched = false;
  3969. this._videoInitialMetadataDispatched = false;
  3970. this._mediaInfo = new _mediaInfo2.default();
  3971. this._mediaInfo.hasAudio = this._hasAudio;
  3972. this._mediaInfo.hasVideo = this._hasVideo;
  3973. this._metadata = null;
  3974. this._audioMetadata = null;
  3975. this._videoMetadata = null;
  3976. this._naluLengthSize = 4;
  3977. this._timestampBase = 0; // int32, in milliseconds
  3978. this._timescale = 1000;
  3979. this._duration = 0; // int32, in milliseconds
  3980. this._durationOverrided = false;
  3981. this._referenceFrameRate = {
  3982. fixed: true,
  3983. fps: 23.976,
  3984. fps_num: 23976,
  3985. fps_den: 1000
  3986. };
  3987. this._flvSoundRateTable = [5500, 11025, 22050, 44100, 48000];
  3988. this._mpegSamplingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];
  3989. this._mpegAudioV10SampleRateTable = [44100, 48000, 32000, 0];
  3990. this._mpegAudioV20SampleRateTable = [22050, 24000, 16000, 0];
  3991. this._mpegAudioV25SampleRateTable = [11025, 12000, 8000, 0];
  3992. this._mpegAudioL1BitRateTable = [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1];
  3993. this._mpegAudioL2BitRateTable = [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, -1];
  3994. this._mpegAudioL3BitRateTable = [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1];
  3995. this._videoTrack = { type: 'video', id: 1, sequenceNumber: 0, samples: [], length: 0 };
  3996. this._audioTrack = { type: 'audio', id: 2, sequenceNumber: 0, samples: [], length: 0 };
  3997. this._littleEndian = function () {
  3998. var buf = new ArrayBuffer(2);
  3999. new DataView(buf).setInt16(0, 256, true); // little-endian write
  4000. return new Int16Array(buf)[0] === 256; // platform-spec read, if equal then LE
  4001. }();
  4002. }
  4003. _createClass(FLVDemuxer, [{
  4004. key: 'destroy',
  4005. value: function destroy() {
  4006. this._mediaInfo = null;
  4007. this._metadata = null;
  4008. this._audioMetadata = null;
  4009. this._videoMetadata = null;
  4010. this._videoTrack = null;
  4011. this._audioTrack = null;
  4012. this._onError = null;
  4013. this._onMediaInfo = null;
  4014. this._onMetaDataArrived = null;
  4015. this._onScriptDataArrived = null;
  4016. this._onTrackMetadata = null;
  4017. this._onDataAvailable = null;
  4018. }
  4019. }, {
  4020. key: 'bindDataSource',
  4021. value: function bindDataSource(loader) {
  4022. loader.onDataArrival = this.parseChunks.bind(this);
  4023. return this;
  4024. }
  4025. // prototype: function(type: string, metadata: any): void
  4026. }, {
  4027. key: 'resetMediaInfo',
  4028. value: function resetMediaInfo() {
  4029. this._mediaInfo = new _mediaInfo2.default();
  4030. }
  4031. }, {
  4032. key: '_isInitialMetadataDispatched',
  4033. value: function _isInitialMetadataDispatched() {
  4034. if (this._hasAudio && this._hasVideo) {
  4035. // both audio & videoFusion
  4036. return this._audioInitialMetadataDispatched && this._videoInitialMetadataDispatched;
  4037. }
  4038. if (this._hasAudio && !this._hasVideo) {
  4039. // audio only
  4040. return this._audioInitialMetadataDispatched;
  4041. }
  4042. if (!this._hasAudio && this._hasVideo) {
  4043. // videoFusion only
  4044. return this._videoInitialMetadataDispatched;
  4045. }
  4046. return false;
  4047. }
  4048. // function parseChunks(chunk: ArrayBuffer, byteStart: number): number;
  4049. }, {
  4050. key: 'parseChunks',
  4051. value: function parseChunks(chunk, byteStart) {
  4052. if (!this._onError || !this._onMediaInfo || !this._onTrackMetadata || !this._onDataAvailable) {
  4053. throw new _exception.IllegalStateException('Flv: onError & onMediaInfo & onTrackMetadata & onDataAvailable callback must be specified');
  4054. }
  4055. var offset = 0;
  4056. var le = this._littleEndian;
  4057. if (byteStart === 0) {
  4058. // buffer with FLV header
  4059. if (chunk.byteLength > 13) {
  4060. var probeData = FLVDemuxer.probe(chunk);
  4061. offset = probeData.dataOffset;
  4062. } else {
  4063. return 0;
  4064. }
  4065. }
  4066. if (this._firstParse) {
  4067. // handle PreviousTagSize0 before Tag1
  4068. this._firstParse = false;
  4069. if (byteStart + offset !== this._dataOffset) {
  4070. _logger2.default.w(this.TAG, 'First time parsing but chunk byteStart invalid!');
  4071. }
  4072. var v = new DataView(chunk, offset);
  4073. var prevTagSize0 = v.getUint32(0, !le);
  4074. if (prevTagSize0 !== 0) {
  4075. _logger2.default.w(this.TAG, 'PrevTagSize0 !== 0 !!!');
  4076. }
  4077. offset += 4;
  4078. }
  4079. while (offset < chunk.byteLength) {
  4080. this._dispatch = true;
  4081. var _v = new DataView(chunk, offset);
  4082. if (offset + 11 + 4 > chunk.byteLength) {
  4083. // data not enough for parsing an flv tag
  4084. break;
  4085. }
  4086. var tagType = _v.getUint8(0);
  4087. var dataSize = _v.getUint32(0, !le) & 0x00FFFFFF;
  4088. if (offset + 11 + dataSize + 4 > chunk.byteLength) {
  4089. // data not enough for parsing actual data body
  4090. break;
  4091. }
  4092. if (tagType !== 8 && tagType !== 9 && tagType !== 18) {
  4093. _logger2.default.w(this.TAG, 'Unsupported tag type ' + tagType + ', skipped');
  4094. // consume the whole tag (skip it)
  4095. offset += 11 + dataSize + 4;
  4096. continue;
  4097. }
  4098. var ts2 = _v.getUint8(4);
  4099. var ts1 = _v.getUint8(5);
  4100. var ts0 = _v.getUint8(6);
  4101. var ts3 = _v.getUint8(7);
  4102. var timestamp = ts0 | ts1 << 8 | ts2 << 16 | ts3 << 24;
  4103. var streamId = _v.getUint32(7, !le) & 0x00FFFFFF;
  4104. if (streamId !== 0) {
  4105. _logger2.default.w(this.TAG, 'Meet tag which has StreamID != 0!');
  4106. }
  4107. var dataOffset = offset + 11;
  4108. switch (tagType) {
  4109. case 8:
  4110. // Audio
  4111. this._parseAudioData(chunk, dataOffset, dataSize, timestamp);
  4112. break;
  4113. case 9:
  4114. // Video
  4115. this._parseVideoData(chunk, dataOffset, dataSize, timestamp, byteStart + offset);
  4116. break;
  4117. case 18:
  4118. // ScriptDataObject
  4119. this._parseScriptData(chunk, dataOffset, dataSize);
  4120. break;
  4121. }
  4122. var prevTagSize = _v.getUint32(11 + dataSize, !le);
  4123. if (prevTagSize !== 11 + dataSize) {
  4124. _logger2.default.w(this.TAG, 'Invalid PrevTagSize ' + prevTagSize);
  4125. }
  4126. offset += 11 + dataSize + 4; // tagBody + dataSize + prevTagSize
  4127. }
  4128. // dispatch parsed frames to consumer (typically, the remuxer)
  4129. if (this._isInitialMetadataDispatched()) {
  4130. if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) {
  4131. this._onDataAvailable(this._audioTrack, this._videoTrack);
  4132. }
  4133. }
  4134. return offset; // consumed bytes, just equals latest offset index
  4135. }
  4136. }, {
  4137. key: '_parseScriptData',
  4138. value: function _parseScriptData(arrayBuffer, dataOffset, dataSize) {
  4139. var scriptData = _amfParser2.default.parseScriptData(arrayBuffer, dataOffset, dataSize);
  4140. if (scriptData.hasOwnProperty('onMetaData')) {
  4141. if (scriptData.onMetaData == null || _typeof(scriptData.onMetaData) !== 'object') {
  4142. _logger2.default.w(this.TAG, 'Invalid onMetaData structure!');
  4143. return;
  4144. }
  4145. if (this._metadata) {
  4146. _logger2.default.w(this.TAG, 'Found another onMetaData tag!');
  4147. }
  4148. this._metadata = scriptData;
  4149. var onMetaData = this._metadata.onMetaData;
  4150. if (this._onMetaDataArrived) {
  4151. this._onMetaDataArrived(Object.assign({}, onMetaData));
  4152. }
  4153. if (typeof onMetaData.hasAudio === 'boolean') {
  4154. // hasAudio
  4155. if (this._hasAudioFlagOverrided === false) {
  4156. this._hasAudio = onMetaData.hasAudio;
  4157. this._mediaInfo.hasAudio = this._hasAudio;
  4158. }
  4159. }
  4160. if (typeof onMetaData.hasVideo === 'boolean') {
  4161. // hasVideo
  4162. if (this._hasVideoFlagOverrided === false) {
  4163. this._hasVideo = onMetaData.hasVideo;
  4164. this._mediaInfo.hasVideo = this._hasVideo;
  4165. }
  4166. }
  4167. if (typeof onMetaData.audiodatarate === 'number') {
  4168. // audiodatarate
  4169. this._mediaInfo.audioDataRate = onMetaData.audiodatarate;
  4170. }
  4171. if (typeof onMetaData.videodatarate === 'number') {
  4172. // videodatarate
  4173. this._mediaInfo.videoDataRate = onMetaData.videodatarate;
  4174. }
  4175. if (typeof onMetaData.width === 'number') {
  4176. // width
  4177. this._mediaInfo.width = onMetaData.width;
  4178. }
  4179. if (typeof onMetaData.height === 'number') {
  4180. // height
  4181. this._mediaInfo.height = onMetaData.height;
  4182. }
  4183. if (typeof onMetaData.duration === 'number') {
  4184. // duration
  4185. if (!this._durationOverrided) {
  4186. var duration = Math.floor(onMetaData.duration * this._timescale);
  4187. this._duration = duration;
  4188. this._mediaInfo.duration = duration;
  4189. }
  4190. } else {
  4191. this._mediaInfo.duration = 0;
  4192. }
  4193. if (typeof onMetaData.framerate === 'number') {
  4194. // framerate
  4195. var fps_num = Math.floor(onMetaData.framerate * 1000);
  4196. if (fps_num > 0) {
  4197. var fps = fps_num / 1000;
  4198. this._referenceFrameRate.fixed = true;
  4199. this._referenceFrameRate.fps = fps;
  4200. this._referenceFrameRate.fps_num = fps_num;
  4201. this._referenceFrameRate.fps_den = 1000;
  4202. this._mediaInfo.fps = fps;
  4203. }
  4204. }
  4205. if (_typeof(onMetaData.keyframes) === 'object') {
  4206. // keyframes
  4207. this._mediaInfo.hasKeyframesIndex = true;
  4208. var keyframes = onMetaData.keyframes;
  4209. this._mediaInfo.keyframesIndex = this._parseKeyframesIndex(keyframes);
  4210. onMetaData.keyframes = null; // keyframes has been extracted, remove it
  4211. } else {
  4212. this._mediaInfo.hasKeyframesIndex = false;
  4213. }
  4214. this._dispatch = false;
  4215. this._mediaInfo.metadata = onMetaData;
  4216. _logger2.default.v(this.TAG, 'Parsed onMetaData');
  4217. if (this._mediaInfo.isComplete()) {
  4218. this._onMediaInfo(this._mediaInfo);
  4219. }
  4220. }
  4221. if (Object.keys(scriptData).length > 0) {
  4222. if (this._onScriptDataArrived) {
  4223. this._onScriptDataArrived(Object.assign({}, scriptData));
  4224. }
  4225. }
  4226. }
  4227. }, {
  4228. key: '_parseKeyframesIndex',
  4229. value: function _parseKeyframesIndex(keyframes) {
  4230. var times = [];
  4231. var filepositions = [];
  4232. // ignore first keyframe which is actually AVC Sequence Header (AVCDecoderConfigurationRecord)
  4233. for (var i = 1; i < keyframes.times.length; i++) {
  4234. var time = this._timestampBase + Math.floor(keyframes.times[i] * 1000);
  4235. times.push(time);
  4236. filepositions.push(keyframes.filepositions[i]);
  4237. }
  4238. return {
  4239. times: times,
  4240. filepositions: filepositions
  4241. };
  4242. }
  4243. }, {
  4244. key: '_parseAudioData',
  4245. value: function _parseAudioData(arrayBuffer, dataOffset, dataSize, tagTimestamp) {
  4246. if (dataSize <= 1) {
  4247. _logger2.default.w(this.TAG, 'Flv: Invalid audio packet, missing SoundData payload!');
  4248. return;
  4249. }
  4250. if (this._hasAudioFlagOverrided === true && this._hasAudio === false) {
  4251. // If hasAudio: false indicated explicitly in MediaDataSource,
  4252. // Ignore all the audio packets
  4253. return;
  4254. }
  4255. var le = this._littleEndian;
  4256. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  4257. var soundSpec = v.getUint8(0);
  4258. var soundFormat = soundSpec >>> 4;
  4259. if (soundFormat !== 2 && soundFormat !== 10) {
  4260. // MP3 or AAC
  4261. this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported audio codec idx: ' + soundFormat);
  4262. return;
  4263. }
  4264. var soundRate = 0;
  4265. var soundRateIndex = (soundSpec & 12) >>> 2;
  4266. if (soundRateIndex >= 0 && soundRateIndex <= 4) {
  4267. soundRate = this._flvSoundRateTable[soundRateIndex];
  4268. } else {
  4269. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid audio sample rate idx: ' + soundRateIndex);
  4270. return;
  4271. }
  4272. var soundSize = (soundSpec & 2) >>> 1; // unused
  4273. var soundType = soundSpec & 1;
  4274. var meta = this._audioMetadata;
  4275. var track = this._audioTrack;
  4276. if (!meta) {
  4277. if (this._hasAudio === false && this._hasAudioFlagOverrided === false) {
  4278. this._hasAudio = true;
  4279. this._mediaInfo.hasAudio = true;
  4280. }
  4281. // initial metadata
  4282. meta = this._audioMetadata = {};
  4283. meta.type = 'audio';
  4284. meta.id = track.id;
  4285. meta.timescale = this._timescale;
  4286. meta.duration = this._duration;
  4287. meta.audioSampleRate = soundRate;
  4288. meta.channelCount = soundType === 0 ? 1 : 2;
  4289. }
  4290. if (soundFormat === 10) {
  4291. // AAC
  4292. var aacData = this._parseAACAudioData(arrayBuffer, dataOffset + 1, dataSize - 1);
  4293. if (aacData == undefined) {
  4294. return;
  4295. }
  4296. if (aacData.packetType === 0) {
  4297. // AAC sequence header (AudioSpecificConfig)
  4298. if (meta.config) {
  4299. _logger2.default.w(this.TAG, 'Found another AudioSpecificConfig!');
  4300. }
  4301. var misc = aacData.data;
  4302. meta.audioSampleRate = misc.samplingRate;
  4303. meta.channelCount = misc.channelCount;
  4304. meta.codec = misc.codec;
  4305. meta.originalCodec = misc.originalCodec;
  4306. meta.config = misc.config;
  4307. // The decode result of an aac sample is 1024 PCM samples
  4308. meta.refSampleDuration = 1024 / meta.audioSampleRate * meta.timescale;
  4309. _logger2.default.v(this.TAG, 'Parsed AudioSpecificConfig');
  4310. if (this._isInitialMetadataDispatched()) {
  4311. // Non-initial metadata, force dispatch (or flush) parsed frames to remuxer
  4312. if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) {
  4313. this._onDataAvailable(this._audioTrack, this._videoTrack);
  4314. }
  4315. } else {
  4316. this._audioInitialMetadataDispatched = true;
  4317. }
  4318. // then notify new metadata
  4319. this._dispatch = false;
  4320. this._onTrackMetadata('audio', meta);
  4321. var mi = this._mediaInfo;
  4322. mi.audioCodec = meta.originalCodec;
  4323. mi.audioSampleRate = meta.audioSampleRate;
  4324. mi.audioChannelCount = meta.channelCount;
  4325. if (mi.hasVideo) {
  4326. if (mi.videoCodec != null) {
  4327. mi.mimeType = 'videoFusion/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"';
  4328. }
  4329. } else {
  4330. mi.mimeType = 'videoFusion/x-flv; codecs="' + mi.audioCodec + '"';
  4331. }
  4332. if (mi.isComplete()) {
  4333. this._onMediaInfo(mi);
  4334. }
  4335. } else if (aacData.packetType === 1) {
  4336. // AAC raw frame data
  4337. var dts = this._timestampBase + tagTimestamp;
  4338. var aacSample = { unit: aacData.data, length: aacData.data.byteLength, dts: dts, pts: dts };
  4339. track.samples.push(aacSample);
  4340. track.length += aacData.data.length;
  4341. } else {
  4342. _logger2.default.e(this.TAG, 'Flv: Unsupported AAC data type ' + aacData.packetType);
  4343. }
  4344. } else if (soundFormat === 2) {
  4345. // MP3
  4346. if (!meta.codec) {
  4347. // We need metadata for mp3 audio track, extract info from frame header
  4348. var _misc = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, true);
  4349. if (_misc == undefined) {
  4350. return;
  4351. }
  4352. meta.audioSampleRate = _misc.samplingRate;
  4353. meta.channelCount = _misc.channelCount;
  4354. meta.codec = _misc.codec;
  4355. meta.originalCodec = _misc.originalCodec;
  4356. // The decode result of an mp3 sample is 1152 PCM samples
  4357. meta.refSampleDuration = 1152 / meta.audioSampleRate * meta.timescale;
  4358. _logger2.default.v(this.TAG, 'Parsed MPEG Audio Frame Header');
  4359. this._audioInitialMetadataDispatched = true;
  4360. this._onTrackMetadata('audio', meta);
  4361. var _mi = this._mediaInfo;
  4362. _mi.audioCodec = meta.codec;
  4363. _mi.audioSampleRate = meta.audioSampleRate;
  4364. _mi.audioChannelCount = meta.channelCount;
  4365. _mi.audioDataRate = _misc.bitRate;
  4366. if (_mi.hasVideo) {
  4367. if (_mi.videoCodec != null) {
  4368. _mi.mimeType = 'videoFusion/x-flv; codecs="' + _mi.videoCodec + ',' + _mi.audioCodec + '"';
  4369. }
  4370. } else {
  4371. _mi.mimeType = 'videoFusion/x-flv; codecs="' + _mi.audioCodec + '"';
  4372. }
  4373. if (_mi.isComplete()) {
  4374. this._onMediaInfo(_mi);
  4375. }
  4376. }
  4377. // This packet is always a valid audio packet, extract it
  4378. var data = this._parseMP3AudioData(arrayBuffer, dataOffset + 1, dataSize - 1, false);
  4379. if (data == undefined) {
  4380. return;
  4381. }
  4382. var _dts = this._timestampBase + tagTimestamp;
  4383. var mp3Sample = { unit: data, length: data.byteLength, dts: _dts, pts: _dts };
  4384. track.samples.push(mp3Sample);
  4385. track.length += data.length;
  4386. }
  4387. }
  4388. }, {
  4389. key: '_parseAACAudioData',
  4390. value: function _parseAACAudioData(arrayBuffer, dataOffset, dataSize) {
  4391. if (dataSize <= 1) {
  4392. _logger2.default.w(this.TAG, 'Flv: Invalid AAC packet, missing AACPacketType or/and Data!');
  4393. return;
  4394. }
  4395. var result = {};
  4396. var array = new Uint8Array(arrayBuffer, dataOffset, dataSize);
  4397. result.packetType = array[0];
  4398. if (array[0] === 0) {
  4399. result.data = this._parseAACAudioSpecificConfig(arrayBuffer, dataOffset + 1, dataSize - 1);
  4400. } else {
  4401. result.data = array.subarray(1);
  4402. }
  4403. return result;
  4404. }
  4405. }, {
  4406. key: '_parseAACAudioSpecificConfig',
  4407. value: function _parseAACAudioSpecificConfig(arrayBuffer, dataOffset, dataSize) {
  4408. var array = new Uint8Array(arrayBuffer, dataOffset, dataSize);
  4409. var config = null;
  4410. /* Audio Object Type:
  4411. 0: Null
  4412. 1: AAC Main
  4413. 2: AAC LC
  4414. 3: AAC SSR (Scalable Sample Rate)
  4415. 4: AAC LTP (Long Term Prediction)
  4416. 5: HE-AAC / SBR (Spectral Band Replication)
  4417. 6: AAC Scalable
  4418. */
  4419. var audioObjectType = 0;
  4420. var originalAudioObjectType = 0;
  4421. var audioExtensionObjectType = null;
  4422. var samplingIndex = 0;
  4423. var extensionSamplingIndex = null;
  4424. // 5 bits
  4425. audioObjectType = originalAudioObjectType = array[0] >>> 3;
  4426. // 4 bits
  4427. samplingIndex = (array[0] & 0x07) << 1 | array[1] >>> 7;
  4428. if (samplingIndex < 0 || samplingIndex >= this._mpegSamplingRates.length) {
  4429. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid sampling frequency index!');
  4430. return;
  4431. }
  4432. var samplingFrequence = this._mpegSamplingRates[samplingIndex];
  4433. // 4 bits
  4434. var channelConfig = (array[1] & 0x78) >>> 3;
  4435. if (channelConfig < 0 || channelConfig >= 8) {
  4436. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: AAC invalid channel configuration');
  4437. return;
  4438. }
  4439. if (audioObjectType === 5) {
  4440. // HE-AAC?
  4441. // 4 bits
  4442. extensionSamplingIndex = (array[1] & 0x07) << 1 | array[2] >>> 7;
  4443. // 5 bits
  4444. audioExtensionObjectType = (array[2] & 0x7C) >>> 2;
  4445. }
  4446. // workarounds for various browsers
  4447. var userAgent = self.navigator.userAgent.toLowerCase();
  4448. if (userAgent.indexOf('firefox') !== -1) {
  4449. // firefox: use SBR (HE-AAC) if freq less than 24kHz
  4450. if (samplingIndex >= 6) {
  4451. audioObjectType = 5;
  4452. config = new Array(4);
  4453. extensionSamplingIndex = samplingIndex - 3;
  4454. } else {
  4455. // use LC-AAC
  4456. audioObjectType = 2;
  4457. config = new Array(2);
  4458. extensionSamplingIndex = samplingIndex;
  4459. }
  4460. } else if (userAgent.indexOf('android') !== -1) {
  4461. // android: always use LC-AAC
  4462. audioObjectType = 2;
  4463. config = new Array(2);
  4464. extensionSamplingIndex = samplingIndex;
  4465. } else {
  4466. // for other browsers, e.g. chrome...
  4467. // Always use HE-AAC to make it easier to switch aac codec profile
  4468. audioObjectType = 5;
  4469. extensionSamplingIndex = samplingIndex;
  4470. config = new Array(4);
  4471. if (samplingIndex >= 6) {
  4472. extensionSamplingIndex = samplingIndex - 3;
  4473. } else if (channelConfig === 1) {
  4474. // Mono channel
  4475. audioObjectType = 2;
  4476. config = new Array(2);
  4477. extensionSamplingIndex = samplingIndex;
  4478. }
  4479. }
  4480. config[0] = audioObjectType << 3;
  4481. config[0] |= (samplingIndex & 0x0F) >>> 1;
  4482. config[1] = (samplingIndex & 0x0F) << 7;
  4483. config[1] |= (channelConfig & 0x0F) << 3;
  4484. if (audioObjectType === 5) {
  4485. config[1] |= (extensionSamplingIndex & 0x0F) >>> 1;
  4486. config[2] = (extensionSamplingIndex & 0x01) << 7;
  4487. // extended audio object type: force to 2 (LC-AAC)
  4488. config[2] |= 2 << 2;
  4489. config[3] = 0;
  4490. }
  4491. return {
  4492. config: config,
  4493. samplingRate: samplingFrequence,
  4494. channelCount: channelConfig,
  4495. codec: 'mp4a.40.' + audioObjectType,
  4496. originalCodec: 'mp4a.40.' + originalAudioObjectType
  4497. };
  4498. }
  4499. }, {
  4500. key: '_parseMP3AudioData',
  4501. value: function _parseMP3AudioData(arrayBuffer, dataOffset, dataSize, requestHeader) {
  4502. if (dataSize < 4) {
  4503. _logger2.default.w(this.TAG, 'Flv: Invalid MP3 packet, header missing!');
  4504. return;
  4505. }
  4506. var le = this._littleEndian;
  4507. var array = new Uint8Array(arrayBuffer, dataOffset, dataSize);
  4508. var result = null;
  4509. if (requestHeader) {
  4510. if (array[0] !== 0xFF) {
  4511. return;
  4512. }
  4513. var ver = array[1] >>> 3 & 0x03;
  4514. var layer = (array[1] & 0x06) >> 1;
  4515. var bitrate_index = (array[2] & 0xF0) >>> 4;
  4516. var sampling_freq_index = (array[2] & 0x0C) >>> 2;
  4517. var channel_mode = array[3] >>> 6 & 0x03;
  4518. var channel_count = channel_mode !== 3 ? 2 : 1;
  4519. var sample_rate = 0;
  4520. var bit_rate = 0;
  4521. var object_type = 34; // Layer-3, listed in MPEG-4 Audio Object Types
  4522. var codec = 'mp3';
  4523. switch (ver) {
  4524. case 0:
  4525. // MPEG 2.5
  4526. sample_rate = this._mpegAudioV25SampleRateTable[sampling_freq_index];
  4527. break;
  4528. case 2:
  4529. // MPEG 2
  4530. sample_rate = this._mpegAudioV20SampleRateTable[sampling_freq_index];
  4531. break;
  4532. case 3:
  4533. // MPEG 1
  4534. sample_rate = this._mpegAudioV10SampleRateTable[sampling_freq_index];
  4535. break;
  4536. }
  4537. switch (layer) {
  4538. case 1:
  4539. // Layer 3
  4540. object_type = 34;
  4541. if (bitrate_index < this._mpegAudioL3BitRateTable.length) {
  4542. bit_rate = this._mpegAudioL3BitRateTable[bitrate_index];
  4543. }
  4544. break;
  4545. case 2:
  4546. // Layer 2
  4547. object_type = 33;
  4548. if (bitrate_index < this._mpegAudioL2BitRateTable.length) {
  4549. bit_rate = this._mpegAudioL2BitRateTable[bitrate_index];
  4550. }
  4551. break;
  4552. case 3:
  4553. // Layer 1
  4554. object_type = 32;
  4555. if (bitrate_index < this._mpegAudioL1BitRateTable.length) {
  4556. bit_rate = this._mpegAudioL1BitRateTable[bitrate_index];
  4557. }
  4558. break;
  4559. }
  4560. result = {
  4561. bitRate: bit_rate,
  4562. samplingRate: sample_rate,
  4563. channelCount: channel_count,
  4564. codec: codec,
  4565. originalCodec: codec
  4566. };
  4567. } else {
  4568. result = array;
  4569. }
  4570. return result;
  4571. }
  4572. }, {
  4573. key: '_parseVideoData',
  4574. value: function _parseVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition) {
  4575. if (dataSize <= 1) {
  4576. _logger2.default.w(this.TAG, 'Flv: Invalid videoFusion packet, missing VideoData payload!');
  4577. return;
  4578. }
  4579. if (this._hasVideoFlagOverrided === true && this._hasVideo === false) {
  4580. // If hasVideo: false indicated explicitly in MediaDataSource,
  4581. // Ignore all the videoFusion packets
  4582. return;
  4583. }
  4584. var spec = new Uint8Array(arrayBuffer, dataOffset, dataSize)[0];
  4585. var frameType = (spec & 240) >>> 4;
  4586. var codecId = spec & 15;
  4587. if (codecId !== 7) {
  4588. this._onError(_demuxErrors2.default.CODEC_UNSUPPORTED, 'Flv: Unsupported codec in videoFusion frame: ' + codecId);
  4589. return;
  4590. }
  4591. this._parseAVCVideoPacket(arrayBuffer, dataOffset + 1, dataSize - 1, tagTimestamp, tagPosition, frameType);
  4592. }
  4593. }, {
  4594. key: '_parseAVCVideoPacket',
  4595. value: function _parseAVCVideoPacket(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType) {
  4596. if (dataSize < 4) {
  4597. _logger2.default.w(this.TAG, 'Flv: Invalid AVC packet, missing AVCPacketType or/and CompositionTime');
  4598. return;
  4599. }
  4600. var le = this._littleEndian;
  4601. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  4602. var packetType = v.getUint8(0);
  4603. var cts_unsigned = v.getUint32(0, !le) & 0x00FFFFFF;
  4604. var cts = cts_unsigned << 8 >> 8; // convert to 24-bit signed int
  4605. if (packetType === 0) {
  4606. // AVCDecoderConfigurationRecord
  4607. this._parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset + 4, dataSize - 4);
  4608. } else if (packetType === 1) {
  4609. // One or more Nalus
  4610. this._parseAVCVideoData(arrayBuffer, dataOffset + 4, dataSize - 4, tagTimestamp, tagPosition, frameType, cts);
  4611. } else if (packetType === 2) {
  4612. // empty, AVC end of sequence
  4613. } else {
  4614. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid videoFusion packet type ' + packetType);
  4615. return;
  4616. }
  4617. }
  4618. }, {
  4619. key: '_parseAVCDecoderConfigurationRecord',
  4620. value: function _parseAVCDecoderConfigurationRecord(arrayBuffer, dataOffset, dataSize) {
  4621. if (dataSize < 7) {
  4622. _logger2.default.w(this.TAG, 'Flv: Invalid AVCDecoderConfigurationRecord, lack of data!');
  4623. return;
  4624. }
  4625. var meta = this._videoMetadata;
  4626. var track = this._videoTrack;
  4627. var le = this._littleEndian;
  4628. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  4629. if (!meta) {
  4630. if (this._hasVideo === false && this._hasVideoFlagOverrided === false) {
  4631. this._hasVideo = true;
  4632. this._mediaInfo.hasVideo = true;
  4633. }
  4634. meta = this._videoMetadata = {};
  4635. meta.type = 'video';
  4636. meta.id = track.id;
  4637. meta.timescale = this._timescale;
  4638. meta.duration = this._duration;
  4639. } else {
  4640. if (typeof meta.avcc !== 'undefined') {
  4641. _logger2.default.w(this.TAG, 'Found another AVCDecoderConfigurationRecord!');
  4642. }
  4643. }
  4644. var version = v.getUint8(0); // configurationVersion
  4645. var avcProfile = v.getUint8(1); // avcProfileIndication
  4646. var profileCompatibility = v.getUint8(2); // profile_compatibility
  4647. var avcLevel = v.getUint8(3); // AVCLevelIndication
  4648. if (version !== 1 || avcProfile === 0) {
  4649. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord');
  4650. return;
  4651. }
  4652. this._naluLengthSize = (v.getUint8(4) & 3) + 1; // lengthSizeMinusOne
  4653. if (this._naluLengthSize !== 3 && this._naluLengthSize !== 4) {
  4654. // holy shit!!!
  4655. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Strange NaluLengthSizeMinusOne: ' + (this._naluLengthSize - 1));
  4656. return;
  4657. }
  4658. var spsCount = v.getUint8(5) & 31; // numOfSequenceParameterSets
  4659. if (spsCount === 0) {
  4660. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No SPS');
  4661. return;
  4662. } else if (spsCount > 1) {
  4663. _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: SPS Count = ' + spsCount);
  4664. }
  4665. var offset = 6;
  4666. for (var i = 0; i < spsCount; i++) {
  4667. var len = v.getUint16(offset, !le); // sequenceParameterSetLength
  4668. offset += 2;
  4669. if (len === 0) {
  4670. continue;
  4671. }
  4672. // Notice: Nalu without startcode header (00 00 00 01)
  4673. var sps = new Uint8Array(arrayBuffer, dataOffset + offset, len);
  4674. offset += len;
  4675. var config = _spsParser2.default.parseSPS(sps);
  4676. if (i !== 0) {
  4677. // ignore other sps's config
  4678. continue;
  4679. }
  4680. meta.codecWidth = config.codec_size.width;
  4681. meta.codecHeight = config.codec_size.height;
  4682. meta.presentWidth = config.present_size.width;
  4683. meta.presentHeight = config.present_size.height;
  4684. meta.profile = config.profile_string;
  4685. meta.level = config.level_string;
  4686. meta.bitDepth = config.bit_depth;
  4687. meta.chromaFormat = config.chroma_format;
  4688. meta.sarRatio = config.sar_ratio;
  4689. meta.frameRate = config.frame_rate;
  4690. if (config.frame_rate.fixed === false || config.frame_rate.fps_num === 0 || config.frame_rate.fps_den === 0) {
  4691. meta.frameRate = this._referenceFrameRate;
  4692. }
  4693. var fps_den = meta.frameRate.fps_den;
  4694. var fps_num = meta.frameRate.fps_num;
  4695. meta.refSampleDuration = meta.timescale * (fps_den / fps_num);
  4696. var codecArray = sps.subarray(1, 4);
  4697. var codecString = 'avc1.';
  4698. for (var j = 0; j < 3; j++) {
  4699. var h = codecArray[j].toString(16);
  4700. if (h.length < 2) {
  4701. h = '0' + h;
  4702. }
  4703. codecString += h;
  4704. }
  4705. meta.codec = codecString;
  4706. var mi = this._mediaInfo;
  4707. mi.width = meta.codecWidth;
  4708. mi.height = meta.codecHeight;
  4709. mi.fps = meta.frameRate.fps;
  4710. mi.profile = meta.profile;
  4711. mi.level = meta.level;
  4712. mi.refFrames = config.ref_frames;
  4713. mi.chromaFormat = config.chroma_format_string;
  4714. mi.sarNum = meta.sarRatio.width;
  4715. mi.sarDen = meta.sarRatio.height;
  4716. mi.videoCodec = codecString;
  4717. if (mi.hasAudio) {
  4718. if (mi.audioCodec != null) {
  4719. mi.mimeType = 'videoFusion/x-flv; codecs="' + mi.videoCodec + ',' + mi.audioCodec + '"';
  4720. }
  4721. } else {
  4722. mi.mimeType = 'videoFusion/x-flv; codecs="' + mi.videoCodec + '"';
  4723. }
  4724. if (mi.isComplete()) {
  4725. this._onMediaInfo(mi);
  4726. }
  4727. }
  4728. var ppsCount = v.getUint8(offset); // numOfPictureParameterSets
  4729. if (ppsCount === 0) {
  4730. this._onError(_demuxErrors2.default.FORMAT_ERROR, 'Flv: Invalid AVCDecoderConfigurationRecord: No PPS');
  4731. return;
  4732. } else if (ppsCount > 1) {
  4733. _logger2.default.w(this.TAG, 'Flv: Strange AVCDecoderConfigurationRecord: PPS Count = ' + ppsCount);
  4734. }
  4735. offset++;
  4736. for (var _i = 0; _i < ppsCount; _i++) {
  4737. var _len = v.getUint16(offset, !le); // pictureParameterSetLength
  4738. offset += 2;
  4739. if (_len === 0) {
  4740. continue;
  4741. }
  4742. // pps is useless for extracting videoFusion information
  4743. offset += _len;
  4744. }
  4745. meta.avcc = new Uint8Array(dataSize);
  4746. meta.avcc.set(new Uint8Array(arrayBuffer, dataOffset, dataSize), 0);
  4747. _logger2.default.v(this.TAG, 'Parsed AVCDecoderConfigurationRecord');
  4748. if (this._isInitialMetadataDispatched()) {
  4749. // flush parsed frames
  4750. if (this._dispatch && (this._audioTrack.length || this._videoTrack.length)) {
  4751. this._onDataAvailable(this._audioTrack, this._videoTrack);
  4752. }
  4753. } else {
  4754. this._videoInitialMetadataDispatched = true;
  4755. }
  4756. // notify new metadata
  4757. this._dispatch = false;
  4758. this._onTrackMetadata('video', meta);
  4759. }
  4760. }, {
  4761. key: '_parseAVCVideoData',
  4762. value: function _parseAVCVideoData(arrayBuffer, dataOffset, dataSize, tagTimestamp, tagPosition, frameType, cts) {
  4763. var le = this._littleEndian;
  4764. var v = new DataView(arrayBuffer, dataOffset, dataSize);
  4765. var units = [],
  4766. length = 0;
  4767. var offset = 0;
  4768. var lengthSize = this._naluLengthSize;
  4769. var dts = this._timestampBase + tagTimestamp;
  4770. var keyframe = frameType === 1; // from FLV Frame Type constants
  4771. while (offset < dataSize) {
  4772. if (offset + 4 >= dataSize) {
  4773. _logger2.default.w(this.TAG, 'Malformed Nalu near timestamp ' + dts + ', offset = ' + offset + ', dataSize = ' + dataSize);
  4774. break; // data not enough for next Nalu
  4775. }
  4776. // Nalu with length-header (AVC1)
  4777. var naluSize = v.getUint32(offset, !le); // Big-Endian read
  4778. if (lengthSize === 3) {
  4779. naluSize >>>= 8;
  4780. }
  4781. if (naluSize > dataSize - lengthSize) {
  4782. _logger2.default.w(this.TAG, 'Malformed Nalus near timestamp ' + dts + ', NaluSize > DataSize!');
  4783. return;
  4784. }
  4785. var unitType = v.getUint8(offset + lengthSize) & 0x1F;
  4786. if (unitType === 5) {
  4787. // IDR
  4788. keyframe = true;
  4789. }
  4790. var data = new Uint8Array(arrayBuffer, dataOffset + offset, lengthSize + naluSize);
  4791. var unit = { type: unitType, data: data };
  4792. units.push(unit);
  4793. length += data.byteLength;
  4794. offset += lengthSize + naluSize;
  4795. }
  4796. if (units.length) {
  4797. var track = this._videoTrack;
  4798. var avcSample = {
  4799. units: units,
  4800. length: length,
  4801. isKeyframe: keyframe,
  4802. dts: dts,
  4803. cts: cts,
  4804. pts: dts + cts
  4805. };
  4806. if (keyframe) {
  4807. avcSample.fileposition = tagPosition;
  4808. }
  4809. track.samples.push(avcSample);
  4810. track.length += length;
  4811. }
  4812. }
  4813. }, {
  4814. key: 'onTrackMetadata',
  4815. get: function get() {
  4816. return this._onTrackMetadata;
  4817. },
  4818. set: function set(callback) {
  4819. this._onTrackMetadata = callback;
  4820. }
  4821. // prototype: function(mediaInfo: MediaInfo): void
  4822. }, {
  4823. key: 'onMediaInfo',
  4824. get: function get() {
  4825. return this._onMediaInfo;
  4826. },
  4827. set: function set(callback) {
  4828. this._onMediaInfo = callback;
  4829. }
  4830. }, {
  4831. key: 'onMetaDataArrived',
  4832. get: function get() {
  4833. return this._onMetaDataArrived;
  4834. },
  4835. set: function set(callback) {
  4836. this._onMetaDataArrived = callback;
  4837. }
  4838. }, {
  4839. key: 'onScriptDataArrived',
  4840. get: function get() {
  4841. return this._onScriptDataArrived;
  4842. },
  4843. set: function set(callback) {
  4844. this._onScriptDataArrived = callback;
  4845. }
  4846. // prototype: function(type: number, info: string): void
  4847. }, {
  4848. key: 'onError',
  4849. get: function get() {
  4850. return this._onError;
  4851. },
  4852. set: function set(callback) {
  4853. this._onError = callback;
  4854. }
  4855. // prototype: function(videoTrack: any, audioTrack: any): void
  4856. }, {
  4857. key: 'onDataAvailable',
  4858. get: function get() {
  4859. return this._onDataAvailable;
  4860. },
  4861. set: function set(callback) {
  4862. this._onDataAvailable = callback;
  4863. }
  4864. // timestamp base for output samples, must be in milliseconds
  4865. }, {
  4866. key: 'timestampBase',
  4867. get: function get() {
  4868. return this._timestampBase;
  4869. },
  4870. set: function set(base) {
  4871. this._timestampBase = base;
  4872. }
  4873. }, {
  4874. key: 'overridedDuration',
  4875. get: function get() {
  4876. return this._duration;
  4877. }
  4878. // Force-override media duration. Must be in milliseconds, int32
  4879. ,
  4880. set: function set(duration) {
  4881. this._durationOverrided = true;
  4882. this._duration = duration;
  4883. this._mediaInfo.duration = duration;
  4884. }
  4885. // Force-override audio track present flag, boolean
  4886. }, {
  4887. key: 'overridedHasAudio',
  4888. set: function set(hasAudio) {
  4889. this._hasAudioFlagOverrided = true;
  4890. this._hasAudio = hasAudio;
  4891. this._mediaInfo.hasAudio = hasAudio;
  4892. }
  4893. // Force-override videoFusion track present flag, boolean
  4894. }, {
  4895. key: 'overridedHasVideo',
  4896. set: function set(hasVideo) {
  4897. this._hasVideoFlagOverrided = true;
  4898. this._hasVideo = hasVideo;
  4899. this._mediaInfo.hasVideo = hasVideo;
  4900. }
  4901. }], [{
  4902. key: 'probe',
  4903. value: function probe(buffer) {
  4904. var data = new Uint8Array(buffer);
  4905. var mismatch = { match: false };
  4906. if (data[0] !== 0x46 || data[1] !== 0x4C || data[2] !== 0x56 || data[3] !== 0x01) {
  4907. return mismatch;
  4908. }
  4909. var hasAudio = (data[4] & 4) >>> 2 !== 0;
  4910. var hasVideo = (data[4] & 1) !== 0;
  4911. var offset = ReadBig32(data, 5);
  4912. if (offset < 9) {
  4913. return mismatch;
  4914. }
  4915. return {
  4916. match: true,
  4917. consumed: offset,
  4918. dataOffset: offset,
  4919. hasAudioTrack: hasAudio,
  4920. hasVideoTrack: hasVideo
  4921. };
  4922. }
  4923. }]);
  4924. return FLVDemuxer;
  4925. }();
  4926. exports.default = FLVDemuxer;
  4927. },{"../core/media-info.js":7,"../utils/exception.js":40,"../utils/logger.js":41,"./amf-parser.js":15,"./demux-errors.js":16,"./sps-parser.js":19}],19:[function(_dereq_,module,exports){
  4928. 'use strict';
  4929. Object.defineProperty(exports, "__esModule", {
  4930. value: true
  4931. });
  4932. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  4933. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  4934. *
  4935. * @author zheng qian <xqq@xqq.im>
  4936. *
  4937. * Licensed under the Apache License, Version 2.0 (the "License");
  4938. * you may not use this file except in compliance with the License.
  4939. * You may obtain a copy of the License at
  4940. *
  4941. * http://www.apache.org/licenses/LICENSE-2.0
  4942. *
  4943. * Unless required by applicable law or agreed to in writing, software
  4944. * distributed under the License is distributed on an "AS IS" BASIS,
  4945. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  4946. * See the License for the specific language governing permissions and
  4947. * limitations under the License.
  4948. */
  4949. var _expGolomb = _dereq_('./exp-golomb.js');
  4950. var _expGolomb2 = _interopRequireDefault(_expGolomb);
  4951. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  4952. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  4953. var SPSParser = function () {
  4954. function SPSParser() {
  4955. _classCallCheck(this, SPSParser);
  4956. }
  4957. _createClass(SPSParser, null, [{
  4958. key: '_ebsp2rbsp',
  4959. value: function _ebsp2rbsp(uint8array) {
  4960. var src = uint8array;
  4961. var src_length = src.byteLength;
  4962. var dst = new Uint8Array(src_length);
  4963. var dst_idx = 0;
  4964. for (var i = 0; i < src_length; i++) {
  4965. if (i >= 2) {
  4966. // Unescape: Skip 0x03 after 00 00
  4967. if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) {
  4968. continue;
  4969. }
  4970. }
  4971. dst[dst_idx] = src[i];
  4972. dst_idx++;
  4973. }
  4974. return new Uint8Array(dst.buffer, 0, dst_idx);
  4975. }
  4976. }, {
  4977. key: 'parseSPS',
  4978. value: function parseSPS(uint8array) {
  4979. var rbsp = SPSParser._ebsp2rbsp(uint8array);
  4980. var gb = new _expGolomb2.default(rbsp);
  4981. gb.readByte();
  4982. var profile_idc = gb.readByte(); // profile_idc
  4983. gb.readByte(); // constraint_set_flags[5] + reserved_zero[3]
  4984. var level_idc = gb.readByte(); // level_idc
  4985. gb.readUEG(); // seq_parameter_set_id
  4986. var profile_string = SPSParser.getProfileString(profile_idc);
  4987. var level_string = SPSParser.getLevelString(level_idc);
  4988. var chroma_format_idc = 1;
  4989. var chroma_format = 420;
  4990. var chroma_format_table = [0, 420, 422, 444];
  4991. var bit_depth = 8;
  4992. if (profile_idc === 100 || profile_idc === 110 || profile_idc === 122 || profile_idc === 244 || profile_idc === 44 || profile_idc === 83 || profile_idc === 86 || profile_idc === 118 || profile_idc === 128 || profile_idc === 138 || profile_idc === 144) {
  4993. chroma_format_idc = gb.readUEG();
  4994. if (chroma_format_idc === 3) {
  4995. gb.readBits(1); // separate_colour_plane_flag
  4996. }
  4997. if (chroma_format_idc <= 3) {
  4998. chroma_format = chroma_format_table[chroma_format_idc];
  4999. }
  5000. bit_depth = gb.readUEG() + 8; // bit_depth_luma_minus8
  5001. gb.readUEG(); // bit_depth_chroma_minus8
  5002. gb.readBits(1); // qpprime_y_zero_transform_bypass_flag
  5003. if (gb.readBool()) {
  5004. // seq_scaling_matrix_present_flag
  5005. var scaling_list_count = chroma_format_idc !== 3 ? 8 : 12;
  5006. for (var i = 0; i < scaling_list_count; i++) {
  5007. if (gb.readBool()) {
  5008. // seq_scaling_list_present_flag
  5009. if (i < 6) {
  5010. SPSParser._skipScalingList(gb, 16);
  5011. } else {
  5012. SPSParser._skipScalingList(gb, 64);
  5013. }
  5014. }
  5015. }
  5016. }
  5017. }
  5018. gb.readUEG(); // log2_max_frame_num_minus4
  5019. var pic_order_cnt_type = gb.readUEG();
  5020. if (pic_order_cnt_type === 0) {
  5021. gb.readUEG(); // log2_max_pic_order_cnt_lsb_minus_4
  5022. } else if (pic_order_cnt_type === 1) {
  5023. gb.readBits(1); // delta_pic_order_always_zero_flag
  5024. gb.readSEG(); // offset_for_non_ref_pic
  5025. gb.readSEG(); // offset_for_top_to_bottom_field
  5026. var num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG();
  5027. for (var _i = 0; _i < num_ref_frames_in_pic_order_cnt_cycle; _i++) {
  5028. gb.readSEG(); // offset_for_ref_frame
  5029. }
  5030. }
  5031. var ref_frames = gb.readUEG(); // max_num_ref_frames
  5032. gb.readBits(1); // gaps_in_frame_num_value_allowed_flag
  5033. var pic_width_in_mbs_minus1 = gb.readUEG();
  5034. var pic_height_in_map_units_minus1 = gb.readUEG();
  5035. var frame_mbs_only_flag = gb.readBits(1);
  5036. if (frame_mbs_only_flag === 0) {
  5037. gb.readBits(1); // mb_adaptive_frame_field_flag
  5038. }
  5039. gb.readBits(1); // direct_8x8_inference_flag
  5040. var frame_crop_left_offset = 0;
  5041. var frame_crop_right_offset = 0;
  5042. var frame_crop_top_offset = 0;
  5043. var frame_crop_bottom_offset = 0;
  5044. var frame_cropping_flag = gb.readBool();
  5045. if (frame_cropping_flag) {
  5046. frame_crop_left_offset = gb.readUEG();
  5047. frame_crop_right_offset = gb.readUEG();
  5048. frame_crop_top_offset = gb.readUEG();
  5049. frame_crop_bottom_offset = gb.readUEG();
  5050. }
  5051. var sar_width = 1,
  5052. sar_height = 1;
  5053. var fps = 0,
  5054. fps_fixed = true,
  5055. fps_num = 0,
  5056. fps_den = 0;
  5057. var vui_parameters_present_flag = gb.readBool();
  5058. if (vui_parameters_present_flag) {
  5059. if (gb.readBool()) {
  5060. // aspect_ratio_info_present_flag
  5061. var aspect_ratio_idc = gb.readByte();
  5062. var sar_w_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
  5063. var sar_h_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
  5064. if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
  5065. sar_width = sar_w_table[aspect_ratio_idc - 1];
  5066. sar_height = sar_h_table[aspect_ratio_idc - 1];
  5067. } else if (aspect_ratio_idc === 255) {
  5068. sar_width = gb.readByte() << 8 | gb.readByte();
  5069. sar_height = gb.readByte() << 8 | gb.readByte();
  5070. }
  5071. }
  5072. if (gb.readBool()) {
  5073. // overscan_info_present_flag
  5074. gb.readBool(); // overscan_appropriate_flag
  5075. }
  5076. if (gb.readBool()) {
  5077. // video_signal_type_present_flag
  5078. gb.readBits(4); // video_format & video_full_range_flag
  5079. if (gb.readBool()) {
  5080. // colour_description_present_flag
  5081. gb.readBits(24); // colour_primaries & transfer_characteristics & matrix_coefficients
  5082. }
  5083. }
  5084. if (gb.readBool()) {
  5085. // chroma_loc_info_present_flag
  5086. gb.readUEG(); // chroma_sample_loc_type_top_field
  5087. gb.readUEG(); // chroma_sample_loc_type_bottom_field
  5088. }
  5089. if (gb.readBool()) {
  5090. // timing_info_present_flag
  5091. var num_units_in_tick = gb.readBits(32);
  5092. var time_scale = gb.readBits(32);
  5093. fps_fixed = gb.readBool(); // fixed_frame_rate_flag
  5094. fps_num = time_scale;
  5095. fps_den = num_units_in_tick * 2;
  5096. fps = fps_num / fps_den;
  5097. }
  5098. }
  5099. var sarScale = 1;
  5100. if (sar_width !== 1 || sar_height !== 1) {
  5101. sarScale = sar_width / sar_height;
  5102. }
  5103. var crop_unit_x = 0,
  5104. crop_unit_y = 0;
  5105. if (chroma_format_idc === 0) {
  5106. crop_unit_x = 1;
  5107. crop_unit_y = 2 - frame_mbs_only_flag;
  5108. } else {
  5109. var sub_wc = chroma_format_idc === 3 ? 1 : 2;
  5110. var sub_hc = chroma_format_idc === 1 ? 2 : 1;
  5111. crop_unit_x = sub_wc;
  5112. crop_unit_y = sub_hc * (2 - frame_mbs_only_flag);
  5113. }
  5114. var codec_width = (pic_width_in_mbs_minus1 + 1) * 16;
  5115. var codec_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16);
  5116. codec_width -= (frame_crop_left_offset + frame_crop_right_offset) * crop_unit_x;
  5117. codec_height -= (frame_crop_top_offset + frame_crop_bottom_offset) * crop_unit_y;
  5118. var present_width = Math.ceil(codec_width * sarScale);
  5119. gb.destroy();
  5120. gb = null;
  5121. return {
  5122. profile_string: profile_string, // baseline, high, high10, ...
  5123. level_string: level_string, // 3, 3.1, 4, 4.1, 5, 5.1, ...
  5124. bit_depth: bit_depth, // 8bit, 10bit, ...
  5125. ref_frames: ref_frames,
  5126. chroma_format: chroma_format, // 4:2:0, 4:2:2, ...
  5127. chroma_format_string: SPSParser.getChromaFormatString(chroma_format),
  5128. frame_rate: {
  5129. fixed: fps_fixed,
  5130. fps: fps,
  5131. fps_den: fps_den,
  5132. fps_num: fps_num
  5133. },
  5134. sar_ratio: {
  5135. width: sar_width,
  5136. height: sar_height
  5137. },
  5138. codec_size: {
  5139. width: codec_width,
  5140. height: codec_height
  5141. },
  5142. present_size: {
  5143. width: present_width,
  5144. height: codec_height
  5145. }
  5146. };
  5147. }
  5148. }, {
  5149. key: '_skipScalingList',
  5150. value: function _skipScalingList(gb, count) {
  5151. var last_scale = 8,
  5152. next_scale = 8;
  5153. var delta_scale = 0;
  5154. for (var i = 0; i < count; i++) {
  5155. if (next_scale !== 0) {
  5156. delta_scale = gb.readSEG();
  5157. next_scale = (last_scale + delta_scale + 256) % 256;
  5158. }
  5159. last_scale = next_scale === 0 ? last_scale : next_scale;
  5160. }
  5161. }
  5162. }, {
  5163. key: 'getProfileString',
  5164. value: function getProfileString(profile_idc) {
  5165. switch (profile_idc) {
  5166. case 66:
  5167. return 'Baseline';
  5168. case 77:
  5169. return 'Main';
  5170. case 88:
  5171. return 'Extended';
  5172. case 100:
  5173. return 'High';
  5174. case 110:
  5175. return 'High10';
  5176. case 122:
  5177. return 'High422';
  5178. case 244:
  5179. return 'High444';
  5180. default:
  5181. return 'Unknown';
  5182. }
  5183. }
  5184. }, {
  5185. key: 'getLevelString',
  5186. value: function getLevelString(level_idc) {
  5187. return (level_idc / 10).toFixed(1);
  5188. }
  5189. }, {
  5190. key: 'getChromaFormatString',
  5191. value: function getChromaFormatString(chroma) {
  5192. switch (chroma) {
  5193. case 420:
  5194. return '4:2:0';
  5195. case 422:
  5196. return '4:2:2';
  5197. case 444:
  5198. return '4:4:4';
  5199. default:
  5200. return 'Unknown';
  5201. }
  5202. }
  5203. }]);
  5204. return SPSParser;
  5205. }();
  5206. exports.default = SPSParser;
  5207. },{"./exp-golomb.js":17}],20:[function(_dereq_,module,exports){
  5208. 'use strict';
  5209. Object.defineProperty(exports, "__esModule", {
  5210. value: true
  5211. });
  5212. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /*
  5213. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  5214. *
  5215. * @author zheng qian <xqq@xqq.im>
  5216. *
  5217. * Licensed under the Apache License, Version 2.0 (the "License");
  5218. * you may not use this file except in compliance with the License.
  5219. * You may obtain a copy of the License at
  5220. *
  5221. * http://www.apache.org/licenses/LICENSE-2.0
  5222. *
  5223. * Unless required by applicable law or agreed to in writing, software
  5224. * distributed under the License is distributed on an "AS IS" BASIS,
  5225. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  5226. * See the License for the specific language governing permissions and
  5227. * limitations under the License.
  5228. */
  5229. var _polyfill = _dereq_('./utils/polyfill.js');
  5230. var _polyfill2 = _interopRequireDefault(_polyfill);
  5231. var _features = _dereq_('./core/features.js');
  5232. var _features2 = _interopRequireDefault(_features);
  5233. var _loader = _dereq_('./io/loader.js');
  5234. var _flvPlayer = _dereq_('./player/flv-player.js');
  5235. var _flvPlayer2 = _interopRequireDefault(_flvPlayer);
  5236. var _nativePlayer = _dereq_('./player/native-player.js');
  5237. var _nativePlayer2 = _interopRequireDefault(_nativePlayer);
  5238. var _playerEvents = _dereq_('./player/player-events.js');
  5239. var _playerEvents2 = _interopRequireDefault(_playerEvents);
  5240. var _playerErrors = _dereq_('./player/player-errors.js');
  5241. var _loggingControl = _dereq_('./utils/logging-control.js');
  5242. var _loggingControl2 = _interopRequireDefault(_loggingControl);
  5243. var _exception = _dereq_('./utils/exception.js');
  5244. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  5245. // here are all the interfaces
  5246. // install polyfills
  5247. _polyfill2.default.install();
  5248. // factory method
  5249. function createPlayer(mediaDataSource, optionalConfig) {
  5250. var mds = mediaDataSource;
  5251. if (mds == null || (typeof mds === 'undefined' ? 'undefined' : _typeof(mds)) !== 'object') {
  5252. throw new _exception.InvalidArgumentException('MediaDataSource must be an javascript object!');
  5253. }
  5254. if (!mds.hasOwnProperty('type')) {
  5255. throw new _exception.InvalidArgumentException('MediaDataSource must has type field to indicate videoFusion file type!');
  5256. }
  5257. switch (mds.type) {
  5258. case 'flv':
  5259. return new _flvPlayer2.default(mds, optionalConfig);
  5260. default:
  5261. return new _nativePlayer2.default(mds, optionalConfig);
  5262. }
  5263. }
  5264. // feature detection
  5265. function isSupported() {
  5266. return _features2.default.supportMSEH264Playback();
  5267. }
  5268. function getFeatureList() {
  5269. return _features2.default.getFeatureList();
  5270. }
  5271. // interfaces
  5272. var flvjs = {};
  5273. flvjs.createPlayer = createPlayer;
  5274. flvjs.isSupported = isSupported;
  5275. flvjs.getFeatureList = getFeatureList;
  5276. flvjs.BaseLoader = _loader.BaseLoader;
  5277. flvjs.LoaderStatus = _loader.LoaderStatus;
  5278. flvjs.LoaderErrors = _loader.LoaderErrors;
  5279. flvjs.Events = _playerEvents2.default;
  5280. flvjs.ErrorTypes = _playerErrors.ErrorTypes;
  5281. flvjs.ErrorDetails = _playerErrors.ErrorDetails;
  5282. flvjs.FlvPlayer = _flvPlayer2.default;
  5283. flvjs.NativePlayer = _nativePlayer2.default;
  5284. flvjs.LoggingControl = _loggingControl2.default;
  5285. Object.defineProperty(flvjs, 'version', {
  5286. enumerable: true,
  5287. get: function get() {
  5288. // replaced by browserify-versionify transform
  5289. return '1.5.0';
  5290. }
  5291. });
  5292. exports.default = flvjs;
  5293. },{"./core/features.js":6,"./io/loader.js":24,"./player/flv-player.js":32,"./player/native-player.js":33,"./player/player-errors.js":34,"./player/player-events.js":35,"./utils/exception.js":40,"./utils/logging-control.js":42,"./utils/polyfill.js":43}],21:[function(_dereq_,module,exports){
  5294. 'use strict';
  5295. // entry/index file
  5296. // make it compatible with browserify's umd wrapper
  5297. module.exports = _dereq_('./flv.js').default;
  5298. },{"./flv.js":20}],22:[function(_dereq_,module,exports){
  5299. 'use strict';
  5300. Object.defineProperty(exports, "__esModule", {
  5301. value: true
  5302. });
  5303. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  5304. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  5305. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  5306. var _logger = _dereq_('../utils/logger.js');
  5307. var _logger2 = _interopRequireDefault(_logger);
  5308. var _browser = _dereq_('../utils/browser.js');
  5309. var _browser2 = _interopRequireDefault(_browser);
  5310. var _loader = _dereq_('./loader.js');
  5311. var _exception = _dereq_('../utils/exception.js');
  5312. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  5313. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  5314. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  5315. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
  5316. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  5317. *
  5318. * @author zheng qian <xqq@xqq.im>
  5319. *
  5320. * Licensed under the Apache License, Version 2.0 (the "License");
  5321. * you may not use this file except in compliance with the License.
  5322. * You may obtain a copy of the License at
  5323. *
  5324. * http://www.apache.org/licenses/LICENSE-2.0
  5325. *
  5326. * Unless required by applicable law or agreed to in writing, software
  5327. * distributed under the License is distributed on an "AS IS" BASIS,
  5328. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  5329. * See the License for the specific language governing permissions and
  5330. * limitations under the License.
  5331. */
  5332. /* fetch + stream IO loader. Currently working on chrome 43+.
  5333. * fetch provides a better alternative http API to XMLHttpRequest
  5334. *
  5335. * fetch spec https://fetch.spec.whatwg.org/
  5336. * stream spec https://streams.spec.whatwg.org/
  5337. */
  5338. var FetchStreamLoader = function (_BaseLoader) {
  5339. _inherits(FetchStreamLoader, _BaseLoader);
  5340. _createClass(FetchStreamLoader, null, [{
  5341. key: 'isSupported',
  5342. value: function isSupported() {
  5343. try {
  5344. // fetch + stream is broken on Microsoft Edge. Disable before build 15048.
  5345. // see https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8196907/
  5346. // Fixed in Jan 10, 2017. Build 15048+ removed from blacklist.
  5347. var isWorkWellEdge = _browser2.default.msedge && _browser2.default.version.minor >= 15048;
  5348. var browserNotBlacklisted = _browser2.default.msedge ? isWorkWellEdge : true;
  5349. return self.fetch && self.ReadableStream && browserNotBlacklisted;
  5350. } catch (e) {
  5351. return false;
  5352. }
  5353. }
  5354. }]);
  5355. function FetchStreamLoader(seekHandler, config) {
  5356. _classCallCheck(this, FetchStreamLoader);
  5357. var _this = _possibleConstructorReturn(this, (FetchStreamLoader.__proto__ || Object.getPrototypeOf(FetchStreamLoader)).call(this, 'fetch-stream-loader'));
  5358. _this.TAG = 'FetchStreamLoader';
  5359. _this._seekHandler = seekHandler;
  5360. _this._config = config;
  5361. _this._needStash = true;
  5362. _this._requestAbort = false;
  5363. _this._contentLength = null;
  5364. _this._receivedLength = 0;
  5365. return _this;
  5366. }
  5367. _createClass(FetchStreamLoader, [{
  5368. key: 'destroy',
  5369. value: function destroy() {
  5370. if (this.isWorking()) {
  5371. this.abort();
  5372. }
  5373. _get(FetchStreamLoader.prototype.__proto__ || Object.getPrototypeOf(FetchStreamLoader.prototype), 'destroy', this).call(this);
  5374. }
  5375. }, {
  5376. key: 'open',
  5377. value: function open(dataSource, range) {
  5378. var _this2 = this;
  5379. this._dataSource = dataSource;
  5380. this._range = range;
  5381. var sourceURL = dataSource.url;
  5382. if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) {
  5383. sourceURL = dataSource.redirectedURL;
  5384. }
  5385. var seekConfig = this._seekHandler.getConfig(sourceURL, range);
  5386. var headers = new self.Headers();
  5387. if (_typeof(seekConfig.headers) === 'object') {
  5388. var configHeaders = seekConfig.headers;
  5389. for (var key in configHeaders) {
  5390. if (configHeaders.hasOwnProperty(key)) {
  5391. headers.append(key, configHeaders[key]);
  5392. }
  5393. }
  5394. }
  5395. var params = {
  5396. method: 'GET',
  5397. headers: headers,
  5398. mode: 'cors',
  5399. cache: 'default',
  5400. // The default policy of Fetch API in the whatwg standard
  5401. // Safari incorrectly indicates 'no-referrer' as default policy, fuck it
  5402. referrerPolicy: 'no-referrer-when-downgrade'
  5403. };
  5404. // add additional headers
  5405. if (_typeof(this._config.headers) === 'object') {
  5406. for (var _key in this._config.headers) {
  5407. headers.append(_key, this._config.headers[_key]);
  5408. }
  5409. }
  5410. // cors is enabled by default
  5411. if (dataSource.cors === false) {
  5412. // no-cors means 'disregard cors policy', which can only be used in ServiceWorker
  5413. params.mode = 'same-origin';
  5414. }
  5415. // withCredentials is disabled by default
  5416. if (dataSource.withCredentials) {
  5417. params.credentials = 'include';
  5418. }
  5419. // referrerPolicy from config
  5420. if (dataSource.referrerPolicy) {
  5421. params.referrerPolicy = dataSource.referrerPolicy;
  5422. }
  5423. this._status = _loader.LoaderStatus.kConnecting;
  5424. self.fetch(seekConfig.url, params).then(function (res) {
  5425. if (_this2._requestAbort) {
  5426. _this2._requestAbort = false;
  5427. _this2._status = _loader.LoaderStatus.kIdle;
  5428. return;
  5429. }
  5430. if (res.ok && res.status >= 200 && res.status <= 299) {
  5431. if (res.url !== seekConfig.url) {
  5432. if (_this2._onURLRedirect) {
  5433. var redirectedURL = _this2._seekHandler.removeURLParameters(res.url);
  5434. _this2._onURLRedirect(redirectedURL);
  5435. }
  5436. }
  5437. var lengthHeader = res.headers.get('Content-Length');
  5438. if (lengthHeader != null) {
  5439. _this2._contentLength = parseInt(lengthHeader);
  5440. if (_this2._contentLength !== 0) {
  5441. if (_this2._onContentLengthKnown) {
  5442. _this2._onContentLengthKnown(_this2._contentLength);
  5443. }
  5444. }
  5445. }
  5446. return _this2._pump.call(_this2, res.body.getReader());
  5447. } else {
  5448. _this2._status = _loader.LoaderStatus.kError;
  5449. if (_this2._onError) {
  5450. _this2._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: res.status, msg: res.statusText });
  5451. } else {
  5452. throw new _exception.RuntimeException('FetchStreamLoader: Http code invalid, ' + res.status + ' ' + res.statusText);
  5453. }
  5454. }
  5455. }).catch(function (e) {
  5456. _this2._status = _loader.LoaderStatus.kError;
  5457. if (_this2._onError) {
  5458. _this2._onError(_loader.LoaderErrors.EXCEPTION, { code: -1, msg: e.message });
  5459. } else {
  5460. throw e;
  5461. }
  5462. });
  5463. }
  5464. }, {
  5465. key: 'abort',
  5466. value: function abort() {
  5467. this._requestAbort = true;
  5468. }
  5469. }, {
  5470. key: '_pump',
  5471. value: function _pump(reader) {
  5472. var _this3 = this;
  5473. // ReadableStreamReader
  5474. return reader.read().then(function (result) {
  5475. if (result.done) {
  5476. // First check received length
  5477. if (_this3._contentLength !== null && _this3._receivedLength < _this3._contentLength) {
  5478. // Report Early-EOF
  5479. _this3._status = _loader.LoaderStatus.kError;
  5480. var type = _loader.LoaderErrors.EARLY_EOF;
  5481. var info = { code: -1, msg: 'Fetch stream meet Early-EOF' };
  5482. if (_this3._onError) {
  5483. _this3._onError(type, info);
  5484. } else {
  5485. throw new _exception.RuntimeException(info.msg);
  5486. }
  5487. } else {
  5488. // OK. Download complete
  5489. _this3._status = _loader.LoaderStatus.kComplete;
  5490. if (_this3._onComplete) {
  5491. _this3._onComplete(_this3._range.from, _this3._range.from + _this3._receivedLength - 1);
  5492. }
  5493. }
  5494. } else {
  5495. if (_this3._requestAbort === true) {
  5496. _this3._requestAbort = false;
  5497. _this3._status = _loader.LoaderStatus.kComplete;
  5498. return reader.cancel();
  5499. }
  5500. _this3._status = _loader.LoaderStatus.kBuffering;
  5501. var chunk = result.value.buffer;
  5502. var byteStart = _this3._range.from + _this3._receivedLength;
  5503. _this3._receivedLength += chunk.byteLength;
  5504. if (_this3._onDataArrival) {
  5505. _this3._onDataArrival(chunk, byteStart, _this3._receivedLength);
  5506. }
  5507. _this3._pump(reader);
  5508. }
  5509. }).catch(function (e) {
  5510. if (e.code === 11 && _browser2.default.msedge) {
  5511. // InvalidStateError on Microsoft Edge
  5512. // Workaround: Edge may throw InvalidStateError after ReadableStreamReader.cancel() call
  5513. // Ignore the unknown exception.
  5514. // Related issue: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11265202/
  5515. return;
  5516. }
  5517. _this3._status = _loader.LoaderStatus.kError;
  5518. var type = 0;
  5519. var info = null;
  5520. if ((e.code === 19 || e.message === 'network error') && ( // NETWORK_ERR
  5521. _this3._contentLength === null || _this3._contentLength !== null && _this3._receivedLength < _this3._contentLength)) {
  5522. type = _loader.LoaderErrors.EARLY_EOF;
  5523. info = { code: e.code, msg: 'Fetch stream meet Early-EOF' };
  5524. } else {
  5525. type = _loader.LoaderErrors.EXCEPTION;
  5526. info = { code: e.code, msg: e.message };
  5527. }
  5528. if (_this3._onError) {
  5529. _this3._onError(type, info);
  5530. } else {
  5531. throw new _exception.RuntimeException(info.msg);
  5532. }
  5533. });
  5534. }
  5535. }]);
  5536. return FetchStreamLoader;
  5537. }(_loader.BaseLoader);
  5538. exports.default = FetchStreamLoader;
  5539. },{"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],23:[function(_dereq_,module,exports){
  5540. 'use strict';
  5541. Object.defineProperty(exports, "__esModule", {
  5542. value: true
  5543. });
  5544. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  5545. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  5546. *
  5547. * @author zheng qian <xqq@xqq.im>
  5548. *
  5549. * Licensed under the Apache License, Version 2.0 (the "License");
  5550. * you may not use this file except in compliance with the License.
  5551. * You may obtain a copy of the License at
  5552. *
  5553. * http://www.apache.org/licenses/LICENSE-2.0
  5554. *
  5555. * Unless required by applicable law or agreed to in writing, software
  5556. * distributed under the License is distributed on an "AS IS" BASIS,
  5557. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  5558. * See the License for the specific language governing permissions and
  5559. * limitations under the License.
  5560. */
  5561. var _logger = _dereq_('../utils/logger.js');
  5562. var _logger2 = _interopRequireDefault(_logger);
  5563. var _speedSampler = _dereq_('./speed-sampler.js');
  5564. var _speedSampler2 = _interopRequireDefault(_speedSampler);
  5565. var _loader = _dereq_('./loader.js');
  5566. var _fetchStreamLoader = _dereq_('./fetch-stream-loader.js');
  5567. var _fetchStreamLoader2 = _interopRequireDefault(_fetchStreamLoader);
  5568. var _xhrMozChunkedLoader = _dereq_('./xhr-moz-chunked-loader.js');
  5569. var _xhrMozChunkedLoader2 = _interopRequireDefault(_xhrMozChunkedLoader);
  5570. var _xhrMsstreamLoader = _dereq_('./xhr-msstream-loader.js');
  5571. var _xhrMsstreamLoader2 = _interopRequireDefault(_xhrMsstreamLoader);
  5572. var _xhrRangeLoader = _dereq_('./xhr-range-loader.js');
  5573. var _xhrRangeLoader2 = _interopRequireDefault(_xhrRangeLoader);
  5574. var _websocketLoader = _dereq_('./websocket-loader.js');
  5575. var _websocketLoader2 = _interopRequireDefault(_websocketLoader);
  5576. var _rangeSeekHandler = _dereq_('./range-seek-handler.js');
  5577. var _rangeSeekHandler2 = _interopRequireDefault(_rangeSeekHandler);
  5578. var _paramSeekHandler = _dereq_('./param-seek-handler.js');
  5579. var _paramSeekHandler2 = _interopRequireDefault(_paramSeekHandler);
  5580. var _exception = _dereq_('../utils/exception.js');
  5581. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  5582. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  5583. /**
  5584. * DataSource: {
  5585. * url: string,
  5586. * filesize: number,
  5587. * cors: boolean,
  5588. * withCredentials: boolean
  5589. * }
  5590. *
  5591. */
  5592. // Manage IO Loaders
  5593. var IOController = function () {
  5594. function IOController(dataSource, config, extraData) {
  5595. _classCallCheck(this, IOController);
  5596. this.TAG = 'IOController';
  5597. this._config = config;
  5598. this._extraData = extraData;
  5599. this._stashInitialSize = 1024 * 384; // default initial size: 384KB
  5600. if (config.stashInitialSize != undefined && config.stashInitialSize > 0) {
  5601. // apply from config
  5602. this._stashInitialSize = config.stashInitialSize;
  5603. }
  5604. this._stashUsed = 0;
  5605. this._stashSize = this._stashInitialSize;
  5606. this._bufferSize = 1024 * 1024 * 3; // initial size: 3MB
  5607. this._stashBuffer = new ArrayBuffer(this._bufferSize);
  5608. this._stashByteStart = 0;
  5609. this._enableStash = true;
  5610. if (config.enableStashBuffer === false) {
  5611. this._enableStash = false;
  5612. }
  5613. this._loader = null;
  5614. this._loaderClass = null;
  5615. this._seekHandler = null;
  5616. this._dataSource = dataSource;
  5617. this._isWebSocketURL = /wss?:\/\/(.+?)/.test(dataSource.url);
  5618. this._refTotalLength = dataSource.filesize ? dataSource.filesize : null;
  5619. this._totalLength = this._refTotalLength;
  5620. this._fullRequestFlag = false;
  5621. this._currentRange = null;
  5622. this._redirectedURL = null;
  5623. this._speedNormalized = 0;
  5624. this._speedSampler = new _speedSampler2.default();
  5625. this._speedNormalizeList = [64, 128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096];
  5626. this._isEarlyEofReconnecting = false;
  5627. this._paused = false;
  5628. this._resumeFrom = 0;
  5629. this._onDataArrival = null;
  5630. this._onSeeked = null;
  5631. this._onError = null;
  5632. this._onComplete = null;
  5633. this._onRedirect = null;
  5634. this._onRecoveredEarlyEof = null;
  5635. this._selectSeekHandler();
  5636. this._selectLoader();
  5637. this._createLoader();
  5638. }
  5639. _createClass(IOController, [{
  5640. key: 'destroy',
  5641. value: function destroy() {
  5642. if (this._loader.isWorking()) {
  5643. this._loader.abort();
  5644. }
  5645. this._loader.destroy();
  5646. this._loader = null;
  5647. this._loaderClass = null;
  5648. this._dataSource = null;
  5649. this._stashBuffer = null;
  5650. this._stashUsed = this._stashSize = this._bufferSize = this._stashByteStart = 0;
  5651. this._currentRange = null;
  5652. this._speedSampler = null;
  5653. this._isEarlyEofReconnecting = false;
  5654. this._onDataArrival = null;
  5655. this._onSeeked = null;
  5656. this._onError = null;
  5657. this._onComplete = null;
  5658. this._onRedirect = null;
  5659. this._onRecoveredEarlyEof = null;
  5660. this._extraData = null;
  5661. }
  5662. }, {
  5663. key: 'isWorking',
  5664. value: function isWorking() {
  5665. return this._loader && this._loader.isWorking() && !this._paused;
  5666. }
  5667. }, {
  5668. key: 'isPaused',
  5669. value: function isPaused() {
  5670. return this._paused;
  5671. }
  5672. }, {
  5673. key: '_selectSeekHandler',
  5674. value: function _selectSeekHandler() {
  5675. var config = this._config;
  5676. if (config.seekType === 'range') {
  5677. this._seekHandler = new _rangeSeekHandler2.default(this._config.rangeLoadZeroStart);
  5678. } else if (config.seekType === 'param') {
  5679. var paramStart = config.seekParamStart || 'bstart';
  5680. var paramEnd = config.seekParamEnd || 'bend';
  5681. this._seekHandler = new _paramSeekHandler2.default(paramStart, paramEnd);
  5682. } else if (config.seekType === 'custom') {
  5683. if (typeof config.customSeekHandler !== 'function') {
  5684. throw new _exception.InvalidArgumentException('Custom seekType specified in config but invalid customSeekHandler!');
  5685. }
  5686. this._seekHandler = new config.customSeekHandler();
  5687. } else {
  5688. throw new _exception.InvalidArgumentException('Invalid seekType in config: ' + config.seekType);
  5689. }
  5690. }
  5691. }, {
  5692. key: '_selectLoader',
  5693. value: function _selectLoader() {
  5694. if (this._config.customLoader != null) {
  5695. this._loaderClass = this._config.customLoader;
  5696. } else if (this._isWebSocketURL) {
  5697. this._loaderClass = _websocketLoader2.default;
  5698. } else if (_fetchStreamLoader2.default.isSupported()) {
  5699. this._loaderClass = _fetchStreamLoader2.default;
  5700. } else if (_xhrMozChunkedLoader2.default.isSupported()) {
  5701. this._loaderClass = _xhrMozChunkedLoader2.default;
  5702. } else if (_xhrRangeLoader2.default.isSupported()) {
  5703. this._loaderClass = _xhrRangeLoader2.default;
  5704. } else {
  5705. throw new _exception.RuntimeException('Your browser doesn\'t support xhr with arraybuffer responseType!');
  5706. }
  5707. }
  5708. }, {
  5709. key: '_createLoader',
  5710. value: function _createLoader() {
  5711. this._loader = new this._loaderClass(this._seekHandler, this._config);
  5712. if (this._loader.needStashBuffer === false) {
  5713. this._enableStash = false;
  5714. }
  5715. this._loader.onContentLengthKnown = this._onContentLengthKnown.bind(this);
  5716. this._loader.onURLRedirect = this._onURLRedirect.bind(this);
  5717. this._loader.onDataArrival = this._onLoaderChunkArrival.bind(this);
  5718. this._loader.onComplete = this._onLoaderComplete.bind(this);
  5719. this._loader.onError = this._onLoaderError.bind(this);
  5720. }
  5721. }, {
  5722. key: 'open',
  5723. value: function open(optionalFrom) {
  5724. this._currentRange = { from: 0, to: -1 };
  5725. if (optionalFrom) {
  5726. this._currentRange.from = optionalFrom;
  5727. }
  5728. this._speedSampler.reset();
  5729. if (!optionalFrom) {
  5730. this._fullRequestFlag = true;
  5731. }
  5732. this._loader.open(this._dataSource, Object.assign({}, this._currentRange));
  5733. }
  5734. }, {
  5735. key: 'abort',
  5736. value: function abort() {
  5737. this._loader.abort();
  5738. if (this._paused) {
  5739. this._paused = false;
  5740. this._resumeFrom = 0;
  5741. }
  5742. }
  5743. }, {
  5744. key: 'pause',
  5745. value: function pause() {
  5746. if (this.isWorking()) {
  5747. this._loader.abort();
  5748. if (this._stashUsed !== 0) {
  5749. this._resumeFrom = this._stashByteStart;
  5750. this._currentRange.to = this._stashByteStart - 1;
  5751. } else {
  5752. this._resumeFrom = this._currentRange.to + 1;
  5753. }
  5754. this._stashUsed = 0;
  5755. this._stashByteStart = 0;
  5756. this._paused = true;
  5757. }
  5758. }
  5759. }, {
  5760. key: 'resume',
  5761. value: function resume() {
  5762. if (this._paused) {
  5763. this._paused = false;
  5764. var bytes = this._resumeFrom;
  5765. this._resumeFrom = 0;
  5766. this._internalSeek(bytes, true);
  5767. }
  5768. }
  5769. }, {
  5770. key: 'seek',
  5771. value: function seek(bytes) {
  5772. this._paused = false;
  5773. this._stashUsed = 0;
  5774. this._stashByteStart = 0;
  5775. this._internalSeek(bytes, true);
  5776. }
  5777. /**
  5778. * When seeking request is from media seeking, unconsumed stash data should be dropped
  5779. * However, stash data shouldn't be dropped if seeking requested from http reconnection
  5780. *
  5781. * @dropUnconsumed: Ignore and discard all unconsumed data in stash buffer
  5782. */
  5783. }, {
  5784. key: '_internalSeek',
  5785. value: function _internalSeek(bytes, dropUnconsumed) {
  5786. if (this._loader.isWorking()) {
  5787. this._loader.abort();
  5788. }
  5789. // dispatch & flush stash buffer before seek
  5790. this._flushStashBuffer(dropUnconsumed);
  5791. this._loader.destroy();
  5792. this._loader = null;
  5793. var requestRange = { from: bytes, to: -1 };
  5794. this._currentRange = { from: requestRange.from, to: -1 };
  5795. this._speedSampler.reset();
  5796. this._stashSize = this._stashInitialSize;
  5797. this._createLoader();
  5798. this._loader.open(this._dataSource, requestRange);
  5799. if (this._onSeeked) {
  5800. this._onSeeked();
  5801. }
  5802. }
  5803. }, {
  5804. key: 'updateUrl',
  5805. value: function updateUrl(url) {
  5806. if (!url || typeof url !== 'string' || url.length === 0) {
  5807. throw new _exception.InvalidArgumentException('Url must be a non-empty string!');
  5808. }
  5809. this._dataSource.url = url;
  5810. // TODO: replace with new url
  5811. }
  5812. }, {
  5813. key: '_expandBuffer',
  5814. value: function _expandBuffer(expectedBytes) {
  5815. var bufferNewSize = this._stashSize;
  5816. while (bufferNewSize + 1024 * 1024 * 1 < expectedBytes) {
  5817. bufferNewSize *= 2;
  5818. }
  5819. bufferNewSize += 1024 * 1024 * 1; // bufferSize = stashSize + 1MB
  5820. if (bufferNewSize === this._bufferSize) {
  5821. return;
  5822. }
  5823. var newBuffer = new ArrayBuffer(bufferNewSize);
  5824. if (this._stashUsed > 0) {
  5825. // copy existing data into new buffer
  5826. var stashOldArray = new Uint8Array(this._stashBuffer, 0, this._stashUsed);
  5827. var stashNewArray = new Uint8Array(newBuffer, 0, bufferNewSize);
  5828. stashNewArray.set(stashOldArray, 0);
  5829. }
  5830. this._stashBuffer = newBuffer;
  5831. this._bufferSize = bufferNewSize;
  5832. }
  5833. }, {
  5834. key: '_normalizeSpeed',
  5835. value: function _normalizeSpeed(input) {
  5836. var list = this._speedNormalizeList;
  5837. var last = list.length - 1;
  5838. var mid = 0;
  5839. var lbound = 0;
  5840. var ubound = last;
  5841. if (input < list[0]) {
  5842. return list[0];
  5843. }
  5844. // binary search
  5845. while (lbound <= ubound) {
  5846. mid = lbound + Math.floor((ubound - lbound) / 2);
  5847. if (mid === last || input >= list[mid] && input < list[mid + 1]) {
  5848. return list[mid];
  5849. } else if (list[mid] < input) {
  5850. lbound = mid + 1;
  5851. } else {
  5852. ubound = mid - 1;
  5853. }
  5854. }
  5855. }
  5856. }, {
  5857. key: '_adjustStashSize',
  5858. value: function _adjustStashSize(normalized) {
  5859. var stashSizeKB = 0;
  5860. if (this._config.isLive) {
  5861. // live stream: always use single normalized speed for size of stashSizeKB
  5862. stashSizeKB = normalized;
  5863. } else {
  5864. if (normalized < 512) {
  5865. stashSizeKB = normalized;
  5866. } else if (normalized >= 512 && normalized <= 1024) {
  5867. stashSizeKB = Math.floor(normalized * 1.5);
  5868. } else {
  5869. stashSizeKB = normalized * 2;
  5870. }
  5871. }
  5872. if (stashSizeKB > 8192) {
  5873. stashSizeKB = 8192;
  5874. }
  5875. var bufferSize = stashSizeKB * 1024 + 1024 * 1024 * 1; // stashSize + 1MB
  5876. if (this._bufferSize < bufferSize) {
  5877. this._expandBuffer(bufferSize);
  5878. }
  5879. this._stashSize = stashSizeKB * 1024;
  5880. }
  5881. }, {
  5882. key: '_dispatchChunks',
  5883. value: function _dispatchChunks(chunks, byteStart) {
  5884. this._currentRange.to = byteStart + chunks.byteLength - 1;
  5885. return this._onDataArrival(chunks, byteStart);
  5886. }
  5887. }, {
  5888. key: '_onURLRedirect',
  5889. value: function _onURLRedirect(redirectedURL) {
  5890. this._redirectedURL = redirectedURL;
  5891. if (this._onRedirect) {
  5892. this._onRedirect(redirectedURL);
  5893. }
  5894. }
  5895. }, {
  5896. key: '_onContentLengthKnown',
  5897. value: function _onContentLengthKnown(contentLength) {
  5898. if (contentLength && this._fullRequestFlag) {
  5899. this._totalLength = contentLength;
  5900. this._fullRequestFlag = false;
  5901. }
  5902. }
  5903. }, {
  5904. key: '_onLoaderChunkArrival',
  5905. value: function _onLoaderChunkArrival(chunk, byteStart, receivedLength) {
  5906. if (!this._onDataArrival) {
  5907. throw new _exception.IllegalStateException('IOController: No existing consumer (onDataArrival) callback!');
  5908. }
  5909. if (this._paused) {
  5910. return;
  5911. }
  5912. if (this._isEarlyEofReconnecting) {
  5913. // Auto-reconnect for EarlyEof succeed, notify to upper-layer by callback
  5914. this._isEarlyEofReconnecting = false;
  5915. if (this._onRecoveredEarlyEof) {
  5916. this._onRecoveredEarlyEof();
  5917. }
  5918. }
  5919. this._speedSampler.addBytes(chunk.byteLength);
  5920. // adjust stash buffer size according to network speed dynamically
  5921. var KBps = this._speedSampler.lastSecondKBps;
  5922. if (KBps !== 0) {
  5923. var normalized = this._normalizeSpeed(KBps);
  5924. if (this._speedNormalized !== normalized) {
  5925. this._speedNormalized = normalized;
  5926. this._adjustStashSize(normalized);
  5927. }
  5928. }
  5929. if (!this._enableStash) {
  5930. // disable stash
  5931. if (this._stashUsed === 0) {
  5932. // dispatch chunk directly to consumer;
  5933. // check ret value (consumed bytes) and stash unconsumed to stashBuffer
  5934. var consumed = this._dispatchChunks(chunk, byteStart);
  5935. if (consumed < chunk.byteLength) {
  5936. // unconsumed data remain.
  5937. var remain = chunk.byteLength - consumed;
  5938. if (remain > this._bufferSize) {
  5939. this._expandBuffer(remain);
  5940. }
  5941. var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  5942. stashArray.set(new Uint8Array(chunk, consumed), 0);
  5943. this._stashUsed += remain;
  5944. this._stashByteStart = byteStart + consumed;
  5945. }
  5946. } else {
  5947. // else: Merge chunk into stashBuffer, and dispatch stashBuffer to consumer.
  5948. if (this._stashUsed + chunk.byteLength > this._bufferSize) {
  5949. this._expandBuffer(this._stashUsed + chunk.byteLength);
  5950. }
  5951. var _stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  5952. _stashArray.set(new Uint8Array(chunk), this._stashUsed);
  5953. this._stashUsed += chunk.byteLength;
  5954. var _consumed = this._dispatchChunks(this._stashBuffer.slice(0, this._stashUsed), this._stashByteStart);
  5955. if (_consumed < this._stashUsed && _consumed > 0) {
  5956. // unconsumed data remain
  5957. var remainArray = new Uint8Array(this._stashBuffer, _consumed);
  5958. _stashArray.set(remainArray, 0);
  5959. }
  5960. this._stashUsed -= _consumed;
  5961. this._stashByteStart += _consumed;
  5962. }
  5963. } else {
  5964. // enable stash
  5965. if (this._stashUsed === 0 && this._stashByteStart === 0) {
  5966. // seeked? or init chunk?
  5967. // This is the first chunk after seek action
  5968. this._stashByteStart = byteStart;
  5969. }
  5970. if (this._stashUsed + chunk.byteLength <= this._stashSize) {
  5971. // just stash
  5972. var _stashArray2 = new Uint8Array(this._stashBuffer, 0, this._stashSize);
  5973. _stashArray2.set(new Uint8Array(chunk), this._stashUsed);
  5974. this._stashUsed += chunk.byteLength;
  5975. } else {
  5976. // stashUsed + chunkSize > stashSize, size limit exceeded
  5977. var _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  5978. if (this._stashUsed > 0) {
  5979. // There're stash datas in buffer
  5980. // dispatch the whole stashBuffer, and stash remain data
  5981. // then append chunk to stashBuffer (stash)
  5982. var buffer = this._stashBuffer.slice(0, this._stashUsed);
  5983. var _consumed2 = this._dispatchChunks(buffer, this._stashByteStart);
  5984. if (_consumed2 < buffer.byteLength) {
  5985. if (_consumed2 > 0) {
  5986. var _remainArray = new Uint8Array(buffer, _consumed2);
  5987. _stashArray3.set(_remainArray, 0);
  5988. this._stashUsed = _remainArray.byteLength;
  5989. this._stashByteStart += _consumed2;
  5990. }
  5991. } else {
  5992. this._stashUsed = 0;
  5993. this._stashByteStart += _consumed2;
  5994. }
  5995. if (this._stashUsed + chunk.byteLength > this._bufferSize) {
  5996. this._expandBuffer(this._stashUsed + chunk.byteLength);
  5997. _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  5998. }
  5999. _stashArray3.set(new Uint8Array(chunk), this._stashUsed);
  6000. this._stashUsed += chunk.byteLength;
  6001. } else {
  6002. // stash buffer empty, but chunkSize > stashSize (oh, holy shit)
  6003. // dispatch chunk directly and stash remain data
  6004. var _consumed3 = this._dispatchChunks(chunk, byteStart);
  6005. if (_consumed3 < chunk.byteLength) {
  6006. var _remain = chunk.byteLength - _consumed3;
  6007. if (_remain > this._bufferSize) {
  6008. this._expandBuffer(_remain);
  6009. _stashArray3 = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  6010. }
  6011. _stashArray3.set(new Uint8Array(chunk, _consumed3), 0);
  6012. this._stashUsed += _remain;
  6013. this._stashByteStart = byteStart + _consumed3;
  6014. }
  6015. }
  6016. }
  6017. }
  6018. }
  6019. }, {
  6020. key: '_flushStashBuffer',
  6021. value: function _flushStashBuffer(dropUnconsumed) {
  6022. if (this._stashUsed > 0) {
  6023. var buffer = this._stashBuffer.slice(0, this._stashUsed);
  6024. var consumed = this._dispatchChunks(buffer, this._stashByteStart);
  6025. var remain = buffer.byteLength - consumed;
  6026. if (consumed < buffer.byteLength) {
  6027. if (dropUnconsumed) {
  6028. _logger2.default.w(this.TAG, remain + ' bytes unconsumed data remain when flush buffer, dropped');
  6029. } else {
  6030. if (consumed > 0) {
  6031. var stashArray = new Uint8Array(this._stashBuffer, 0, this._bufferSize);
  6032. var remainArray = new Uint8Array(buffer, consumed);
  6033. stashArray.set(remainArray, 0);
  6034. this._stashUsed = remainArray.byteLength;
  6035. this._stashByteStart += consumed;
  6036. }
  6037. return 0;
  6038. }
  6039. }
  6040. this._stashUsed = 0;
  6041. this._stashByteStart = 0;
  6042. return remain;
  6043. }
  6044. return 0;
  6045. }
  6046. }, {
  6047. key: '_onLoaderComplete',
  6048. value: function _onLoaderComplete(from, to) {
  6049. // Force-flush stash buffer, and drop unconsumed data
  6050. this._flushStashBuffer(true);
  6051. if (this._onComplete) {
  6052. this._onComplete(this._extraData);
  6053. }
  6054. }
  6055. }, {
  6056. key: '_onLoaderError',
  6057. value: function _onLoaderError(type, data) {
  6058. _logger2.default.e(this.TAG, 'Loader error, code = ' + data.code + ', msg = ' + data.msg);
  6059. this._flushStashBuffer(false);
  6060. if (this._isEarlyEofReconnecting) {
  6061. // Auto-reconnect for EarlyEof failed, throw UnrecoverableEarlyEof error to upper-layer
  6062. this._isEarlyEofReconnecting = false;
  6063. type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF;
  6064. }
  6065. switch (type) {
  6066. case _loader.LoaderErrors.EARLY_EOF:
  6067. {
  6068. if (!this._config.isLive) {
  6069. // Do internal http reconnect if not live stream
  6070. if (this._totalLength) {
  6071. var nextFrom = this._currentRange.to + 1;
  6072. if (nextFrom < this._totalLength) {
  6073. _logger2.default.w(this.TAG, 'Connection lost, trying reconnect...');
  6074. this._isEarlyEofReconnecting = true;
  6075. this._internalSeek(nextFrom, false);
  6076. }
  6077. return;
  6078. }
  6079. // else: We don't know totalLength, throw UnrecoverableEarlyEof
  6080. }
  6081. // live stream: throw UnrecoverableEarlyEof error to upper-layer
  6082. type = _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF;
  6083. break;
  6084. }
  6085. case _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF:
  6086. case _loader.LoaderErrors.CONNECTING_TIMEOUT:
  6087. case _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID:
  6088. case _loader.LoaderErrors.EXCEPTION:
  6089. break;
  6090. }
  6091. if (this._onError) {
  6092. this._onError(type, data);
  6093. } else {
  6094. throw new _exception.RuntimeException('IOException: ' + data.msg);
  6095. }
  6096. }
  6097. }, {
  6098. key: 'status',
  6099. get: function get() {
  6100. return this._loader.status;
  6101. }
  6102. }, {
  6103. key: 'extraData',
  6104. get: function get() {
  6105. return this._extraData;
  6106. },
  6107. set: function set(data) {
  6108. this._extraData = data;
  6109. }
  6110. // prototype: function onDataArrival(chunks: ArrayBuffer, byteStart: number): number
  6111. }, {
  6112. key: 'onDataArrival',
  6113. get: function get() {
  6114. return this._onDataArrival;
  6115. },
  6116. set: function set(callback) {
  6117. this._onDataArrival = callback;
  6118. }
  6119. }, {
  6120. key: 'onSeeked',
  6121. get: function get() {
  6122. return this._onSeeked;
  6123. },
  6124. set: function set(callback) {
  6125. this._onSeeked = callback;
  6126. }
  6127. // prototype: function onError(type: number, info: {code: number, msg: string}): void
  6128. }, {
  6129. key: 'onError',
  6130. get: function get() {
  6131. return this._onError;
  6132. },
  6133. set: function set(callback) {
  6134. this._onError = callback;
  6135. }
  6136. }, {
  6137. key: 'onComplete',
  6138. get: function get() {
  6139. return this._onComplete;
  6140. },
  6141. set: function set(callback) {
  6142. this._onComplete = callback;
  6143. }
  6144. }, {
  6145. key: 'onRedirect',
  6146. get: function get() {
  6147. return this._onRedirect;
  6148. },
  6149. set: function set(callback) {
  6150. this._onRedirect = callback;
  6151. }
  6152. }, {
  6153. key: 'onRecoveredEarlyEof',
  6154. get: function get() {
  6155. return this._onRecoveredEarlyEof;
  6156. },
  6157. set: function set(callback) {
  6158. this._onRecoveredEarlyEof = callback;
  6159. }
  6160. }, {
  6161. key: 'currentURL',
  6162. get: function get() {
  6163. return this._dataSource.url;
  6164. }
  6165. }, {
  6166. key: 'hasRedirect',
  6167. get: function get() {
  6168. return this._redirectedURL != null || this._dataSource.redirectedURL != undefined;
  6169. }
  6170. }, {
  6171. key: 'currentRedirectedURL',
  6172. get: function get() {
  6173. return this._redirectedURL || this._dataSource.redirectedURL;
  6174. }
  6175. // in KB/s
  6176. }, {
  6177. key: 'currentSpeed',
  6178. get: function get() {
  6179. if (this._loaderClass === _xhrRangeLoader2.default) {
  6180. // SpeedSampler is inaccuracy if loader is RangeLoader
  6181. return this._loader.currentSpeed;
  6182. }
  6183. return this._speedSampler.lastSecondKBps;
  6184. }
  6185. }, {
  6186. key: 'loaderType',
  6187. get: function get() {
  6188. return this._loader.type;
  6189. }
  6190. }]);
  6191. return IOController;
  6192. }();
  6193. exports.default = IOController;
  6194. },{"../utils/exception.js":40,"../utils/logger.js":41,"./fetch-stream-loader.js":22,"./loader.js":24,"./param-seek-handler.js":25,"./range-seek-handler.js":26,"./speed-sampler.js":27,"./websocket-loader.js":28,"./xhr-moz-chunked-loader.js":29,"./xhr-msstream-loader.js":30,"./xhr-range-loader.js":31}],24:[function(_dereq_,module,exports){
  6195. 'use strict';
  6196. Object.defineProperty(exports, "__esModule", {
  6197. value: true
  6198. });
  6199. exports.BaseLoader = exports.LoaderErrors = exports.LoaderStatus = undefined;
  6200. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  6201. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6202. *
  6203. * @author zheng qian <xqq@xqq.im>
  6204. *
  6205. * Licensed under the Apache License, Version 2.0 (the "License");
  6206. * you may not use this file except in compliance with the License.
  6207. * You may obtain a copy of the License at
  6208. *
  6209. * http://www.apache.org/licenses/LICENSE-2.0
  6210. *
  6211. * Unless required by applicable law or agreed to in writing, software
  6212. * distributed under the License is distributed on an "AS IS" BASIS,
  6213. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6214. * See the License for the specific language governing permissions and
  6215. * limitations under the License.
  6216. */
  6217. var _exception = _dereq_('../utils/exception.js');
  6218. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6219. var LoaderStatus = exports.LoaderStatus = {
  6220. kIdle: 0,
  6221. kConnecting: 1,
  6222. kBuffering: 2,
  6223. kError: 3,
  6224. kComplete: 4
  6225. };
  6226. var LoaderErrors = exports.LoaderErrors = {
  6227. OK: 'OK',
  6228. EXCEPTION: 'Exception',
  6229. HTTP_STATUS_CODE_INVALID: 'HttpStatusCodeInvalid',
  6230. CONNECTING_TIMEOUT: 'ConnectingTimeout',
  6231. EARLY_EOF: 'EarlyEof',
  6232. UNRECOVERABLE_EARLY_EOF: 'UnrecoverableEarlyEof'
  6233. };
  6234. /* Loader has callbacks which have following prototypes:
  6235. * function onContentLengthKnown(contentLength: number): void
  6236. * function onURLRedirect(url: string): void
  6237. * function onDataArrival(chunk: ArrayBuffer, byteStart: number, receivedLength: number): void
  6238. * function onError(errorType: number, errorInfo: {code: number, msg: string}): void
  6239. * function onComplete(rangeFrom: number, rangeTo: number): void
  6240. */
  6241. var BaseLoader = exports.BaseLoader = function () {
  6242. function BaseLoader(typeName) {
  6243. _classCallCheck(this, BaseLoader);
  6244. this._type = typeName || 'undefined';
  6245. this._status = LoaderStatus.kIdle;
  6246. this._needStash = false;
  6247. // callbacks
  6248. this._onContentLengthKnown = null;
  6249. this._onURLRedirect = null;
  6250. this._onDataArrival = null;
  6251. this._onError = null;
  6252. this._onComplete = null;
  6253. }
  6254. _createClass(BaseLoader, [{
  6255. key: 'destroy',
  6256. value: function destroy() {
  6257. this._status = LoaderStatus.kIdle;
  6258. this._onContentLengthKnown = null;
  6259. this._onURLRedirect = null;
  6260. this._onDataArrival = null;
  6261. this._onError = null;
  6262. this._onComplete = null;
  6263. }
  6264. }, {
  6265. key: 'isWorking',
  6266. value: function isWorking() {
  6267. return this._status === LoaderStatus.kConnecting || this._status === LoaderStatus.kBuffering;
  6268. }
  6269. }, {
  6270. key: 'open',
  6271. // pure virtual
  6272. value: function open(dataSource, range) {
  6273. throw new _exception.NotImplementedException('Unimplemented abstract function!');
  6274. }
  6275. }, {
  6276. key: 'abort',
  6277. value: function abort() {
  6278. throw new _exception.NotImplementedException('Unimplemented abstract function!');
  6279. }
  6280. }, {
  6281. key: 'type',
  6282. get: function get() {
  6283. return this._type;
  6284. }
  6285. }, {
  6286. key: 'status',
  6287. get: function get() {
  6288. return this._status;
  6289. }
  6290. }, {
  6291. key: 'needStashBuffer',
  6292. get: function get() {
  6293. return this._needStash;
  6294. }
  6295. }, {
  6296. key: 'onContentLengthKnown',
  6297. get: function get() {
  6298. return this._onContentLengthKnown;
  6299. },
  6300. set: function set(callback) {
  6301. this._onContentLengthKnown = callback;
  6302. }
  6303. }, {
  6304. key: 'onURLRedirect',
  6305. get: function get() {
  6306. return this._onURLRedirect;
  6307. },
  6308. set: function set(callback) {
  6309. this._onURLRedirect = callback;
  6310. }
  6311. }, {
  6312. key: 'onDataArrival',
  6313. get: function get() {
  6314. return this._onDataArrival;
  6315. },
  6316. set: function set(callback) {
  6317. this._onDataArrival = callback;
  6318. }
  6319. }, {
  6320. key: 'onError',
  6321. get: function get() {
  6322. return this._onError;
  6323. },
  6324. set: function set(callback) {
  6325. this._onError = callback;
  6326. }
  6327. }, {
  6328. key: 'onComplete',
  6329. get: function get() {
  6330. return this._onComplete;
  6331. },
  6332. set: function set(callback) {
  6333. this._onComplete = callback;
  6334. }
  6335. }]);
  6336. return BaseLoader;
  6337. }();
  6338. },{"../utils/exception.js":40}],25:[function(_dereq_,module,exports){
  6339. 'use strict';
  6340. Object.defineProperty(exports, "__esModule", {
  6341. value: true
  6342. });
  6343. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6344. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6345. /*
  6346. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6347. *
  6348. * @author zheng qian <xqq@xqq.im>
  6349. *
  6350. * Licensed under the Apache License, Version 2.0 (the "License");
  6351. * you may not use this file except in compliance with the License.
  6352. * You may obtain a copy of the License at
  6353. *
  6354. * http://www.apache.org/licenses/LICENSE-2.0
  6355. *
  6356. * Unless required by applicable law or agreed to in writing, software
  6357. * distributed under the License is distributed on an "AS IS" BASIS,
  6358. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6359. * See the License for the specific language governing permissions and
  6360. * limitations under the License.
  6361. */
  6362. var ParamSeekHandler = function () {
  6363. function ParamSeekHandler(paramStart, paramEnd) {
  6364. _classCallCheck(this, ParamSeekHandler);
  6365. this._startName = paramStart;
  6366. this._endName = paramEnd;
  6367. }
  6368. _createClass(ParamSeekHandler, [{
  6369. key: 'getConfig',
  6370. value: function getConfig(baseUrl, range) {
  6371. var url = baseUrl;
  6372. if (range.from !== 0 || range.to !== -1) {
  6373. var needAnd = true;
  6374. if (url.indexOf('?') === -1) {
  6375. url += '?';
  6376. needAnd = false;
  6377. }
  6378. if (needAnd) {
  6379. url += '&';
  6380. }
  6381. url += this._startName + '=' + range.from.toString();
  6382. if (range.to !== -1) {
  6383. url += '&' + this._endName + '=' + range.to.toString();
  6384. }
  6385. }
  6386. return {
  6387. url: url,
  6388. headers: {}
  6389. };
  6390. }
  6391. }, {
  6392. key: 'removeURLParameters',
  6393. value: function removeURLParameters(seekedURL) {
  6394. var baseURL = seekedURL.split('?')[0];
  6395. var params = undefined;
  6396. var queryIndex = seekedURL.indexOf('?');
  6397. if (queryIndex !== -1) {
  6398. params = seekedURL.substring(queryIndex + 1);
  6399. }
  6400. var resultParams = '';
  6401. if (params != undefined && params.length > 0) {
  6402. var pairs = params.split('&');
  6403. for (var i = 0; i < pairs.length; i++) {
  6404. var pair = pairs[i].split('=');
  6405. var requireAnd = i > 0;
  6406. if (pair[0] !== this._startName && pair[0] !== this._endName) {
  6407. if (requireAnd) {
  6408. resultParams += '&';
  6409. }
  6410. resultParams += pairs[i];
  6411. }
  6412. }
  6413. }
  6414. return resultParams.length === 0 ? baseURL : baseURL + '?' + resultParams;
  6415. }
  6416. }]);
  6417. return ParamSeekHandler;
  6418. }();
  6419. exports.default = ParamSeekHandler;
  6420. },{}],26:[function(_dereq_,module,exports){
  6421. 'use strict';
  6422. Object.defineProperty(exports, "__esModule", {
  6423. value: true
  6424. });
  6425. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6426. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6427. /*
  6428. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6429. *
  6430. * @author zheng qian <xqq@xqq.im>
  6431. *
  6432. * Licensed under the Apache License, Version 2.0 (the "License");
  6433. * you may not use this file except in compliance with the License.
  6434. * You may obtain a copy of the License at
  6435. *
  6436. * http://www.apache.org/licenses/LICENSE-2.0
  6437. *
  6438. * Unless required by applicable law or agreed to in writing, software
  6439. * distributed under the License is distributed on an "AS IS" BASIS,
  6440. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6441. * See the License for the specific language governing permissions and
  6442. * limitations under the License.
  6443. */
  6444. var RangeSeekHandler = function () {
  6445. function RangeSeekHandler(zeroStart) {
  6446. _classCallCheck(this, RangeSeekHandler);
  6447. this._zeroStart = zeroStart || false;
  6448. }
  6449. _createClass(RangeSeekHandler, [{
  6450. key: 'getConfig',
  6451. value: function getConfig(url, range) {
  6452. var headers = {};
  6453. if (range.from !== 0 || range.to !== -1) {
  6454. var param = void 0;
  6455. if (range.to !== -1) {
  6456. param = 'bytes=' + range.from.toString() + '-' + range.to.toString();
  6457. } else {
  6458. param = 'bytes=' + range.from.toString() + '-';
  6459. }
  6460. headers['Range'] = param;
  6461. } else if (this._zeroStart) {
  6462. headers['Range'] = 'bytes=0-';
  6463. }
  6464. return {
  6465. url: url,
  6466. headers: headers
  6467. };
  6468. }
  6469. }, {
  6470. key: 'removeURLParameters',
  6471. value: function removeURLParameters(seekedURL) {
  6472. return seekedURL;
  6473. }
  6474. }]);
  6475. return RangeSeekHandler;
  6476. }();
  6477. exports.default = RangeSeekHandler;
  6478. },{}],27:[function(_dereq_,module,exports){
  6479. "use strict";
  6480. Object.defineProperty(exports, "__esModule", {
  6481. value: true
  6482. });
  6483. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6484. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6485. /*
  6486. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6487. *
  6488. * @author zheng qian <xqq@xqq.im>
  6489. *
  6490. * Licensed under the Apache License, Version 2.0 (the "License");
  6491. * you may not use this file except in compliance with the License.
  6492. * You may obtain a copy of the License at
  6493. *
  6494. * http://www.apache.org/licenses/LICENSE-2.0
  6495. *
  6496. * Unless required by applicable law or agreed to in writing, software
  6497. * distributed under the License is distributed on an "AS IS" BASIS,
  6498. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6499. * See the License for the specific language governing permissions and
  6500. * limitations under the License.
  6501. */
  6502. // Utility class to calculate realtime network I/O speed
  6503. var SpeedSampler = function () {
  6504. function SpeedSampler() {
  6505. _classCallCheck(this, SpeedSampler);
  6506. // milliseconds
  6507. this._firstCheckpoint = 0;
  6508. this._lastCheckpoint = 0;
  6509. this._intervalBytes = 0;
  6510. this._totalBytes = 0;
  6511. this._lastSecondBytes = 0;
  6512. // compatibility detection
  6513. if (self.performance && self.performance.now) {
  6514. this._now = self.performance.now.bind(self.performance);
  6515. } else {
  6516. this._now = Date.now;
  6517. }
  6518. }
  6519. _createClass(SpeedSampler, [{
  6520. key: "reset",
  6521. value: function reset() {
  6522. this._firstCheckpoint = this._lastCheckpoint = 0;
  6523. this._totalBytes = this._intervalBytes = 0;
  6524. this._lastSecondBytes = 0;
  6525. }
  6526. }, {
  6527. key: "addBytes",
  6528. value: function addBytes(bytes) {
  6529. if (this._firstCheckpoint === 0) {
  6530. this._firstCheckpoint = this._now();
  6531. this._lastCheckpoint = this._firstCheckpoint;
  6532. this._intervalBytes += bytes;
  6533. this._totalBytes += bytes;
  6534. } else if (this._now() - this._lastCheckpoint < 1000) {
  6535. this._intervalBytes += bytes;
  6536. this._totalBytes += bytes;
  6537. } else {
  6538. // duration >= 1000
  6539. this._lastSecondBytes = this._intervalBytes;
  6540. this._intervalBytes = bytes;
  6541. this._totalBytes += bytes;
  6542. this._lastCheckpoint = this._now();
  6543. }
  6544. }
  6545. }, {
  6546. key: "currentKBps",
  6547. get: function get() {
  6548. this.addBytes(0);
  6549. var durationSeconds = (this._now() - this._lastCheckpoint) / 1000;
  6550. if (durationSeconds == 0) durationSeconds = 1;
  6551. return this._intervalBytes / durationSeconds / 1024;
  6552. }
  6553. }, {
  6554. key: "lastSecondKBps",
  6555. get: function get() {
  6556. this.addBytes(0);
  6557. if (this._lastSecondBytes !== 0) {
  6558. return this._lastSecondBytes / 1024;
  6559. } else {
  6560. // lastSecondBytes === 0
  6561. if (this._now() - this._lastCheckpoint >= 500) {
  6562. // if time interval since last checkpoint has exceeded 500ms
  6563. // the speed is nearly accurate
  6564. return this.currentKBps;
  6565. } else {
  6566. // We don't know
  6567. return 0;
  6568. }
  6569. }
  6570. }
  6571. }, {
  6572. key: "averageKBps",
  6573. get: function get() {
  6574. var durationSeconds = (this._now() - this._firstCheckpoint) / 1000;
  6575. return this._totalBytes / durationSeconds / 1024;
  6576. }
  6577. }]);
  6578. return SpeedSampler;
  6579. }();
  6580. exports.default = SpeedSampler;
  6581. },{}],28:[function(_dereq_,module,exports){
  6582. 'use strict';
  6583. Object.defineProperty(exports, "__esModule", {
  6584. value: true
  6585. });
  6586. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  6587. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6588. var _logger = _dereq_('../utils/logger.js');
  6589. var _logger2 = _interopRequireDefault(_logger);
  6590. var _loader = _dereq_('./loader.js');
  6591. var _exception = _dereq_('../utils/exception.js');
  6592. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  6593. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6594. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  6595. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
  6596. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6597. *
  6598. * @author zheng qian <xqq@xqq.im>
  6599. *
  6600. * Licensed under the Apache License, Version 2.0 (the "License");
  6601. * you may not use this file except in compliance with the License.
  6602. * You may obtain a copy of the License at
  6603. *
  6604. * http://www.apache.org/licenses/LICENSE-2.0
  6605. *
  6606. * Unless required by applicable law or agreed to in writing, software
  6607. * distributed under the License is distributed on an "AS IS" BASIS,
  6608. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6609. * See the License for the specific language governing permissions and
  6610. * limitations under the License.
  6611. */
  6612. // For FLV over WebSocket live stream
  6613. var WebSocketLoader = function (_BaseLoader) {
  6614. _inherits(WebSocketLoader, _BaseLoader);
  6615. _createClass(WebSocketLoader, null, [{
  6616. key: 'isSupported',
  6617. value: function isSupported() {
  6618. try {
  6619. return typeof self.WebSocket !== 'undefined';
  6620. } catch (e) {
  6621. return false;
  6622. }
  6623. }
  6624. }]);
  6625. function WebSocketLoader() {
  6626. _classCallCheck(this, WebSocketLoader);
  6627. var _this = _possibleConstructorReturn(this, (WebSocketLoader.__proto__ || Object.getPrototypeOf(WebSocketLoader)).call(this, 'websocket-loader'));
  6628. _this.TAG = 'WebSocketLoader';
  6629. _this._needStash = true;
  6630. _this._ws = null;
  6631. _this._requestAbort = false;
  6632. _this._receivedLength = 0;
  6633. return _this;
  6634. }
  6635. _createClass(WebSocketLoader, [{
  6636. key: 'destroy',
  6637. value: function destroy() {
  6638. if (this._ws) {
  6639. this.abort();
  6640. }
  6641. _get(WebSocketLoader.prototype.__proto__ || Object.getPrototypeOf(WebSocketLoader.prototype), 'destroy', this).call(this);
  6642. }
  6643. }, {
  6644. key: 'open',
  6645. value: function open(dataSource) {
  6646. try {
  6647. var ws = this._ws = new self.WebSocket(dataSource.url);
  6648. ws.binaryType = 'arraybuffer';
  6649. ws.onopen = this._onWebSocketOpen.bind(this);
  6650. ws.onclose = this._onWebSocketClose.bind(this);
  6651. ws.onmessage = this._onWebSocketMessage.bind(this);
  6652. ws.onerror = this._onWebSocketError.bind(this);
  6653. this._status = _loader.LoaderStatus.kConnecting;
  6654. } catch (e) {
  6655. this._status = _loader.LoaderStatus.kError;
  6656. var info = { code: e.code, msg: e.message };
  6657. if (this._onError) {
  6658. this._onError(_loader.LoaderErrors.EXCEPTION, info);
  6659. } else {
  6660. throw new _exception.RuntimeException(info.msg);
  6661. }
  6662. }
  6663. }
  6664. }, {
  6665. key: 'abort',
  6666. value: function abort() {
  6667. var ws = this._ws;
  6668. if (ws && (ws.readyState === 0 || ws.readyState === 1)) {
  6669. // CONNECTING || OPEN
  6670. this._requestAbort = true;
  6671. ws.close();
  6672. }
  6673. this._ws = null;
  6674. this._status = _loader.LoaderStatus.kComplete;
  6675. }
  6676. }, {
  6677. key: '_onWebSocketOpen',
  6678. value: function _onWebSocketOpen(e) {
  6679. this._status = _loader.LoaderStatus.kBuffering;
  6680. }
  6681. }, {
  6682. key: '_onWebSocketClose',
  6683. value: function _onWebSocketClose(e) {
  6684. if (this._requestAbort === true) {
  6685. this._requestAbort = false;
  6686. return;
  6687. }
  6688. this._status = _loader.LoaderStatus.kComplete;
  6689. if (this._onComplete) {
  6690. this._onComplete(0, this._receivedLength - 1);
  6691. }
  6692. }
  6693. }, {
  6694. key: '_onWebSocketMessage',
  6695. value: function _onWebSocketMessage(e) {
  6696. var _this2 = this;
  6697. if (e.data instanceof ArrayBuffer) {
  6698. this._dispatchArrayBuffer(e.data);
  6699. } else if (e.data instanceof Blob) {
  6700. var reader = new FileReader();
  6701. reader.onload = function () {
  6702. _this2._dispatchArrayBuffer(reader.result);
  6703. };
  6704. reader.readAsArrayBuffer(e.data);
  6705. } else {
  6706. this._status = _loader.LoaderStatus.kError;
  6707. var info = { code: -1, msg: 'Unsupported WebSocket message type: ' + e.data.constructor.name };
  6708. if (this._onError) {
  6709. this._onError(_loader.LoaderErrors.EXCEPTION, info);
  6710. } else {
  6711. throw new _exception.RuntimeException(info.msg);
  6712. }
  6713. }
  6714. }
  6715. }, {
  6716. key: '_dispatchArrayBuffer',
  6717. value: function _dispatchArrayBuffer(arraybuffer) {
  6718. var chunk = arraybuffer;
  6719. var byteStart = this._receivedLength;
  6720. this._receivedLength += chunk.byteLength;
  6721. if (this._onDataArrival) {
  6722. this._onDataArrival(chunk, byteStart, this._receivedLength);
  6723. }
  6724. }
  6725. }, {
  6726. key: '_onWebSocketError',
  6727. value: function _onWebSocketError(e) {
  6728. this._status = _loader.LoaderStatus.kError;
  6729. var info = {
  6730. code: e.code,
  6731. msg: e.message
  6732. };
  6733. if (this._onError) {
  6734. this._onError(_loader.LoaderErrors.EXCEPTION, info);
  6735. } else {
  6736. throw new _exception.RuntimeException(info.msg);
  6737. }
  6738. }
  6739. }]);
  6740. return WebSocketLoader;
  6741. }(_loader.BaseLoader);
  6742. exports.default = WebSocketLoader;
  6743. },{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],29:[function(_dereq_,module,exports){
  6744. 'use strict';
  6745. Object.defineProperty(exports, "__esModule", {
  6746. value: true
  6747. });
  6748. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  6749. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  6750. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6751. var _logger = _dereq_('../utils/logger.js');
  6752. var _logger2 = _interopRequireDefault(_logger);
  6753. var _loader = _dereq_('./loader.js');
  6754. var _exception = _dereq_('../utils/exception.js');
  6755. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  6756. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6757. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  6758. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
  6759. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6760. *
  6761. * @author zheng qian <xqq@xqq.im>
  6762. *
  6763. * Licensed under the Apache License, Version 2.0 (the "License");
  6764. * you may not use this file except in compliance with the License.
  6765. * You may obtain a copy of the License at
  6766. *
  6767. * http://www.apache.org/licenses/LICENSE-2.0
  6768. *
  6769. * Unless required by applicable law or agreed to in writing, software
  6770. * distributed under the License is distributed on an "AS IS" BASIS,
  6771. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6772. * See the License for the specific language governing permissions and
  6773. * limitations under the License.
  6774. */
  6775. // For FireFox browser which supports `xhr.responseType = 'moz-chunked-arraybuffer'`
  6776. var MozChunkedLoader = function (_BaseLoader) {
  6777. _inherits(MozChunkedLoader, _BaseLoader);
  6778. _createClass(MozChunkedLoader, null, [{
  6779. key: 'isSupported',
  6780. value: function isSupported() {
  6781. try {
  6782. var xhr = new XMLHttpRequest();
  6783. // Firefox 37- requires .open() to be called before setting responseType
  6784. xhr.open('GET', 'https://example.com', true);
  6785. xhr.responseType = 'moz-chunked-arraybuffer';
  6786. return xhr.responseType === 'moz-chunked-arraybuffer';
  6787. } catch (e) {
  6788. _logger2.default.w('MozChunkedLoader', e.message);
  6789. return false;
  6790. }
  6791. }
  6792. }]);
  6793. function MozChunkedLoader(seekHandler, config) {
  6794. _classCallCheck(this, MozChunkedLoader);
  6795. var _this = _possibleConstructorReturn(this, (MozChunkedLoader.__proto__ || Object.getPrototypeOf(MozChunkedLoader)).call(this, 'xhr-moz-chunked-loader'));
  6796. _this.TAG = 'MozChunkedLoader';
  6797. _this._seekHandler = seekHandler;
  6798. _this._config = config;
  6799. _this._needStash = true;
  6800. _this._xhr = null;
  6801. _this._requestAbort = false;
  6802. _this._contentLength = null;
  6803. _this._receivedLength = 0;
  6804. return _this;
  6805. }
  6806. _createClass(MozChunkedLoader, [{
  6807. key: 'destroy',
  6808. value: function destroy() {
  6809. if (this.isWorking()) {
  6810. this.abort();
  6811. }
  6812. if (this._xhr) {
  6813. this._xhr.onreadystatechange = null;
  6814. this._xhr.onprogress = null;
  6815. this._xhr.onloadend = null;
  6816. this._xhr.onerror = null;
  6817. this._xhr = null;
  6818. }
  6819. _get(MozChunkedLoader.prototype.__proto__ || Object.getPrototypeOf(MozChunkedLoader.prototype), 'destroy', this).call(this);
  6820. }
  6821. }, {
  6822. key: 'open',
  6823. value: function open(dataSource, range) {
  6824. this._dataSource = dataSource;
  6825. this._range = range;
  6826. var sourceURL = dataSource.url;
  6827. if (this._config.reuseRedirectedURL && dataSource.redirectedURL != undefined) {
  6828. sourceURL = dataSource.redirectedURL;
  6829. }
  6830. var seekConfig = this._seekHandler.getConfig(sourceURL, range);
  6831. this._requestURL = seekConfig.url;
  6832. var xhr = this._xhr = new XMLHttpRequest();
  6833. xhr.open('GET', seekConfig.url, true);
  6834. xhr.responseType = 'moz-chunked-arraybuffer';
  6835. xhr.onreadystatechange = this._onReadyStateChange.bind(this);
  6836. xhr.onprogress = this._onProgress.bind(this);
  6837. xhr.onloadend = this._onLoadEnd.bind(this);
  6838. xhr.onerror = this._onXhrError.bind(this);
  6839. // cors is auto detected and enabled by xhr
  6840. // withCredentials is disabled by default
  6841. if (dataSource.withCredentials) {
  6842. xhr.withCredentials = true;
  6843. }
  6844. if (_typeof(seekConfig.headers) === 'object') {
  6845. var headers = seekConfig.headers;
  6846. for (var key in headers) {
  6847. if (headers.hasOwnProperty(key)) {
  6848. xhr.setRequestHeader(key, headers[key]);
  6849. }
  6850. }
  6851. }
  6852. // add additional headers
  6853. if (_typeof(this._config.headers) === 'object') {
  6854. var _headers = this._config.headers;
  6855. for (var _key in _headers) {
  6856. if (_headers.hasOwnProperty(_key)) {
  6857. xhr.setRequestHeader(_key, _headers[_key]);
  6858. }
  6859. }
  6860. }
  6861. this._status = _loader.LoaderStatus.kConnecting;
  6862. xhr.send();
  6863. }
  6864. }, {
  6865. key: 'abort',
  6866. value: function abort() {
  6867. this._requestAbort = true;
  6868. if (this._xhr) {
  6869. this._xhr.abort();
  6870. }
  6871. this._status = _loader.LoaderStatus.kComplete;
  6872. }
  6873. }, {
  6874. key: '_onReadyStateChange',
  6875. value: function _onReadyStateChange(e) {
  6876. var xhr = e.target;
  6877. if (xhr.readyState === 2) {
  6878. // HEADERS_RECEIVED
  6879. if (xhr.responseURL != undefined && xhr.responseURL !== this._requestURL) {
  6880. if (this._onURLRedirect) {
  6881. var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL);
  6882. this._onURLRedirect(redirectedURL);
  6883. }
  6884. }
  6885. if (xhr.status !== 0 && (xhr.status < 200 || xhr.status > 299)) {
  6886. this._status = _loader.LoaderStatus.kError;
  6887. if (this._onError) {
  6888. this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText });
  6889. } else {
  6890. throw new _exception.RuntimeException('MozChunkedLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText);
  6891. }
  6892. } else {
  6893. this._status = _loader.LoaderStatus.kBuffering;
  6894. }
  6895. }
  6896. }
  6897. }, {
  6898. key: '_onProgress',
  6899. value: function _onProgress(e) {
  6900. if (this._status === _loader.LoaderStatus.kError) {
  6901. // Ignore error response
  6902. return;
  6903. }
  6904. if (this._contentLength === null) {
  6905. if (e.total !== null && e.total !== 0) {
  6906. this._contentLength = e.total;
  6907. if (this._onContentLengthKnown) {
  6908. this._onContentLengthKnown(this._contentLength);
  6909. }
  6910. }
  6911. }
  6912. var chunk = e.target.response;
  6913. var byteStart = this._range.from + this._receivedLength;
  6914. this._receivedLength += chunk.byteLength;
  6915. if (this._onDataArrival) {
  6916. this._onDataArrival(chunk, byteStart, this._receivedLength);
  6917. }
  6918. }
  6919. }, {
  6920. key: '_onLoadEnd',
  6921. value: function _onLoadEnd(e) {
  6922. if (this._requestAbort === true) {
  6923. this._requestAbort = false;
  6924. return;
  6925. } else if (this._status === _loader.LoaderStatus.kError) {
  6926. return;
  6927. }
  6928. this._status = _loader.LoaderStatus.kComplete;
  6929. if (this._onComplete) {
  6930. this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
  6931. }
  6932. }
  6933. }, {
  6934. key: '_onXhrError',
  6935. value: function _onXhrError(e) {
  6936. this._status = _loader.LoaderStatus.kError;
  6937. var type = 0;
  6938. var info = null;
  6939. if (this._contentLength && e.loaded < this._contentLength) {
  6940. type = _loader.LoaderErrors.EARLY_EOF;
  6941. info = { code: -1, msg: 'Moz-Chunked stream meet Early-Eof' };
  6942. } else {
  6943. type = _loader.LoaderErrors.EXCEPTION;
  6944. info = { code: -1, msg: e.constructor.name + ' ' + e.type };
  6945. }
  6946. if (this._onError) {
  6947. this._onError(type, info);
  6948. } else {
  6949. throw new _exception.RuntimeException(info.msg);
  6950. }
  6951. }
  6952. }]);
  6953. return MozChunkedLoader;
  6954. }(_loader.BaseLoader);
  6955. exports.default = MozChunkedLoader;
  6956. },{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],30:[function(_dereq_,module,exports){
  6957. 'use strict';
  6958. Object.defineProperty(exports, "__esModule", {
  6959. value: true
  6960. });
  6961. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  6962. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  6963. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  6964. var _logger = _dereq_('../utils/logger.js');
  6965. var _logger2 = _interopRequireDefault(_logger);
  6966. var _loader = _dereq_('./loader.js');
  6967. var _exception = _dereq_('../utils/exception.js');
  6968. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  6969. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  6970. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  6971. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
  6972. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  6973. *
  6974. * @author zheng qian <xqq@xqq.im>
  6975. *
  6976. * Licensed under the Apache License, Version 2.0 (the "License");
  6977. * you may not use this file except in compliance with the License.
  6978. * You may obtain a copy of the License at
  6979. *
  6980. * http://www.apache.org/licenses/LICENSE-2.0
  6981. *
  6982. * Unless required by applicable law or agreed to in writing, software
  6983. * distributed under the License is distributed on an "AS IS" BASIS,
  6984. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6985. * See the License for the specific language governing permissions and
  6986. * limitations under the License.
  6987. */
  6988. /* Notice: ms-stream may cause IE/Edge browser crash if seek too frequently!!!
  6989. * The browser may crash in wininet.dll. Disable for now.
  6990. *
  6991. * For IE11/Edge browser by microsoft which supports `xhr.responseType = 'ms-stream'`
  6992. * Notice that ms-stream API sucks. The buffer is always expanding along with downloading.
  6993. *
  6994. * We need to abort the xhr if buffer size exceeded limit size (e.g. 16 MiB), then do reconnect.
  6995. * in order to release previous ArrayBuffer to avoid memory leak
  6996. *
  6997. * Otherwise, the ArrayBuffer will increase to a terrible size that equals final file size.
  6998. */
  6999. var MSStreamLoader = function (_BaseLoader) {
  7000. _inherits(MSStreamLoader, _BaseLoader);
  7001. _createClass(MSStreamLoader, null, [{
  7002. key: 'isSupported',
  7003. value: function isSupported() {
  7004. try {
  7005. if (typeof self.MSStream === 'undefined' || typeof self.MSStreamReader === 'undefined') {
  7006. return false;
  7007. }
  7008. var xhr = new XMLHttpRequest();
  7009. xhr.open('GET', 'https://example.com', true);
  7010. xhr.responseType = 'ms-stream';
  7011. return xhr.responseType === 'ms-stream';
  7012. } catch (e) {
  7013. _logger2.default.w('MSStreamLoader', e.message);
  7014. return false;
  7015. }
  7016. }
  7017. }]);
  7018. function MSStreamLoader(seekHandler, config) {
  7019. _classCallCheck(this, MSStreamLoader);
  7020. var _this = _possibleConstructorReturn(this, (MSStreamLoader.__proto__ || Object.getPrototypeOf(MSStreamLoader)).call(this, 'xhr-msstream-loader'));
  7021. _this.TAG = 'MSStreamLoader';
  7022. _this._seekHandler = seekHandler;
  7023. _this._config = config;
  7024. _this._needStash = true;
  7025. _this._xhr = null;
  7026. _this._reader = null; // MSStreamReader
  7027. _this._totalRange = null;
  7028. _this._currentRange = null;
  7029. _this._currentRequestURL = null;
  7030. _this._currentRedirectedURL = null;
  7031. _this._contentLength = null;
  7032. _this._receivedLength = 0;
  7033. _this._bufferLimit = 16 * 1024 * 1024; // 16MB
  7034. _this._lastTimeBufferSize = 0;
  7035. _this._isReconnecting = false;
  7036. return _this;
  7037. }
  7038. _createClass(MSStreamLoader, [{
  7039. key: 'destroy',
  7040. value: function destroy() {
  7041. if (this.isWorking()) {
  7042. this.abort();
  7043. }
  7044. if (this._reader) {
  7045. this._reader.onprogress = null;
  7046. this._reader.onload = null;
  7047. this._reader.onerror = null;
  7048. this._reader = null;
  7049. }
  7050. if (this._xhr) {
  7051. this._xhr.onreadystatechange = null;
  7052. this._xhr = null;
  7053. }
  7054. _get(MSStreamLoader.prototype.__proto__ || Object.getPrototypeOf(MSStreamLoader.prototype), 'destroy', this).call(this);
  7055. }
  7056. }, {
  7057. key: 'open',
  7058. value: function open(dataSource, range) {
  7059. this._internalOpen(dataSource, range, false);
  7060. }
  7061. }, {
  7062. key: '_internalOpen',
  7063. value: function _internalOpen(dataSource, range, isSubrange) {
  7064. this._dataSource = dataSource;
  7065. if (!isSubrange) {
  7066. this._totalRange = range;
  7067. } else {
  7068. this._currentRange = range;
  7069. }
  7070. var sourceURL = dataSource.url;
  7071. if (this._config.reuseRedirectedURL) {
  7072. if (this._currentRedirectedURL != undefined) {
  7073. sourceURL = this._currentRedirectedURL;
  7074. } else if (dataSource.redirectedURL != undefined) {
  7075. sourceURL = dataSource.redirectedURL;
  7076. }
  7077. }
  7078. var seekConfig = this._seekHandler.getConfig(sourceURL, range);
  7079. this._currentRequestURL = seekConfig.url;
  7080. var reader = this._reader = new self.MSStreamReader();
  7081. reader.onprogress = this._msrOnProgress.bind(this);
  7082. reader.onload = this._msrOnLoad.bind(this);
  7083. reader.onerror = this._msrOnError.bind(this);
  7084. var xhr = this._xhr = new XMLHttpRequest();
  7085. xhr.open('GET', seekConfig.url, true);
  7086. xhr.responseType = 'ms-stream';
  7087. xhr.onreadystatechange = this._xhrOnReadyStateChange.bind(this);
  7088. xhr.onerror = this._xhrOnError.bind(this);
  7089. if (dataSource.withCredentials) {
  7090. xhr.withCredentials = true;
  7091. }
  7092. if (_typeof(seekConfig.headers) === 'object') {
  7093. var headers = seekConfig.headers;
  7094. for (var key in headers) {
  7095. if (headers.hasOwnProperty(key)) {
  7096. xhr.setRequestHeader(key, headers[key]);
  7097. }
  7098. }
  7099. }
  7100. // add additional headers
  7101. if (_typeof(this._config.headers) === 'object') {
  7102. var _headers = this._config.headers;
  7103. for (var _key in _headers) {
  7104. if (_headers.hasOwnProperty(_key)) {
  7105. xhr.setRequestHeader(_key, _headers[_key]);
  7106. }
  7107. }
  7108. }
  7109. if (this._isReconnecting) {
  7110. this._isReconnecting = false;
  7111. } else {
  7112. this._status = _loader.LoaderStatus.kConnecting;
  7113. }
  7114. xhr.send();
  7115. }
  7116. }, {
  7117. key: 'abort',
  7118. value: function abort() {
  7119. this._internalAbort();
  7120. this._status = _loader.LoaderStatus.kComplete;
  7121. }
  7122. }, {
  7123. key: '_internalAbort',
  7124. value: function _internalAbort() {
  7125. if (this._reader) {
  7126. if (this._reader.readyState === 1) {
  7127. // LOADING
  7128. this._reader.abort();
  7129. }
  7130. this._reader.onprogress = null;
  7131. this._reader.onload = null;
  7132. this._reader.onerror = null;
  7133. this._reader = null;
  7134. }
  7135. if (this._xhr) {
  7136. this._xhr.abort();
  7137. this._xhr.onreadystatechange = null;
  7138. this._xhr = null;
  7139. }
  7140. }
  7141. }, {
  7142. key: '_xhrOnReadyStateChange',
  7143. value: function _xhrOnReadyStateChange(e) {
  7144. var xhr = e.target;
  7145. if (xhr.readyState === 2) {
  7146. // HEADERS_RECEIVED
  7147. if (xhr.status >= 200 && xhr.status <= 299) {
  7148. this._status = _loader.LoaderStatus.kBuffering;
  7149. if (xhr.responseURL != undefined) {
  7150. var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL);
  7151. if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) {
  7152. this._currentRedirectedURL = redirectedURL;
  7153. if (this._onURLRedirect) {
  7154. this._onURLRedirect(redirectedURL);
  7155. }
  7156. }
  7157. }
  7158. var lengthHeader = xhr.getResponseHeader('Content-Length');
  7159. if (lengthHeader != null && this._contentLength == null) {
  7160. var length = parseInt(lengthHeader);
  7161. if (length > 0) {
  7162. this._contentLength = length;
  7163. if (this._onContentLengthKnown) {
  7164. this._onContentLengthKnown(this._contentLength);
  7165. }
  7166. }
  7167. }
  7168. } else {
  7169. this._status = _loader.LoaderStatus.kError;
  7170. if (this._onError) {
  7171. this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText });
  7172. } else {
  7173. throw new _exception.RuntimeException('MSStreamLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText);
  7174. }
  7175. }
  7176. } else if (xhr.readyState === 3) {
  7177. // LOADING
  7178. if (xhr.status >= 200 && xhr.status <= 299) {
  7179. this._status = _loader.LoaderStatus.kBuffering;
  7180. var msstream = xhr.response;
  7181. this._reader.readAsArrayBuffer(msstream);
  7182. }
  7183. }
  7184. }
  7185. }, {
  7186. key: '_xhrOnError',
  7187. value: function _xhrOnError(e) {
  7188. this._status = _loader.LoaderStatus.kError;
  7189. var type = _loader.LoaderErrors.EXCEPTION;
  7190. var info = { code: -1, msg: e.constructor.name + ' ' + e.type };
  7191. if (this._onError) {
  7192. this._onError(type, info);
  7193. } else {
  7194. throw new _exception.RuntimeException(info.msg);
  7195. }
  7196. }
  7197. }, {
  7198. key: '_msrOnProgress',
  7199. value: function _msrOnProgress(e) {
  7200. var reader = e.target;
  7201. var bigbuffer = reader.result;
  7202. if (bigbuffer == null) {
  7203. // result may be null, workaround for buggy M$
  7204. this._doReconnectIfNeeded();
  7205. return;
  7206. }
  7207. var slice = bigbuffer.slice(this._lastTimeBufferSize);
  7208. this._lastTimeBufferSize = bigbuffer.byteLength;
  7209. var byteStart = this._totalRange.from + this._receivedLength;
  7210. this._receivedLength += slice.byteLength;
  7211. if (this._onDataArrival) {
  7212. this._onDataArrival(slice, byteStart, this._receivedLength);
  7213. }
  7214. if (bigbuffer.byteLength >= this._bufferLimit) {
  7215. _logger2.default.v(this.TAG, 'MSStream buffer exceeded max size near ' + (byteStart + slice.byteLength) + ', reconnecting...');
  7216. this._doReconnectIfNeeded();
  7217. }
  7218. }
  7219. }, {
  7220. key: '_doReconnectIfNeeded',
  7221. value: function _doReconnectIfNeeded() {
  7222. if (this._contentLength == null || this._receivedLength < this._contentLength) {
  7223. this._isReconnecting = true;
  7224. this._lastTimeBufferSize = 0;
  7225. this._internalAbort();
  7226. var range = {
  7227. from: this._totalRange.from + this._receivedLength,
  7228. to: -1
  7229. };
  7230. this._internalOpen(this._dataSource, range, true);
  7231. }
  7232. }
  7233. }, {
  7234. key: '_msrOnLoad',
  7235. value: function _msrOnLoad(e) {
  7236. // actually it is onComplete event
  7237. this._status = _loader.LoaderStatus.kComplete;
  7238. if (this._onComplete) {
  7239. this._onComplete(this._totalRange.from, this._totalRange.from + this._receivedLength - 1);
  7240. }
  7241. }
  7242. }, {
  7243. key: '_msrOnError',
  7244. value: function _msrOnError(e) {
  7245. this._status = _loader.LoaderStatus.kError;
  7246. var type = 0;
  7247. var info = null;
  7248. if (this._contentLength && this._receivedLength < this._contentLength) {
  7249. type = _loader.LoaderErrors.EARLY_EOF;
  7250. info = { code: -1, msg: 'MSStream meet Early-Eof' };
  7251. } else {
  7252. type = _loader.LoaderErrors.EARLY_EOF;
  7253. info = { code: -1, msg: e.constructor.name + ' ' + e.type };
  7254. }
  7255. if (this._onError) {
  7256. this._onError(type, info);
  7257. } else {
  7258. throw new _exception.RuntimeException(info.msg);
  7259. }
  7260. }
  7261. }]);
  7262. return MSStreamLoader;
  7263. }(_loader.BaseLoader);
  7264. exports.default = MSStreamLoader;
  7265. },{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24}],31:[function(_dereq_,module,exports){
  7266. 'use strict';
  7267. Object.defineProperty(exports, "__esModule", {
  7268. value: true
  7269. });
  7270. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  7271. var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
  7272. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  7273. var _logger = _dereq_('../utils/logger.js');
  7274. var _logger2 = _interopRequireDefault(_logger);
  7275. var _speedSampler = _dereq_('./speed-sampler.js');
  7276. var _speedSampler2 = _interopRequireDefault(_speedSampler);
  7277. var _loader = _dereq_('./loader.js');
  7278. var _exception = _dereq_('../utils/exception.js');
  7279. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  7280. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  7281. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  7282. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*
  7283. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  7284. *
  7285. * @author zheng qian <xqq@xqq.im>
  7286. *
  7287. * Licensed under the Apache License, Version 2.0 (the "License");
  7288. * you may not use this file except in compliance with the License.
  7289. * You may obtain a copy of the License at
  7290. *
  7291. * http://www.apache.org/licenses/LICENSE-2.0
  7292. *
  7293. * Unless required by applicable law or agreed to in writing, software
  7294. * distributed under the License is distributed on an "AS IS" BASIS,
  7295. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  7296. * See the License for the specific language governing permissions and
  7297. * limitations under the License.
  7298. */
  7299. // Universal IO Loader, implemented by adding Range header in xhr's request header
  7300. var RangeLoader = function (_BaseLoader) {
  7301. _inherits(RangeLoader, _BaseLoader);
  7302. _createClass(RangeLoader, null, [{
  7303. key: 'isSupported',
  7304. value: function isSupported() {
  7305. try {
  7306. var xhr = new XMLHttpRequest();
  7307. xhr.open('GET', 'https://example.com', true);
  7308. xhr.responseType = 'arraybuffer';
  7309. return xhr.responseType === 'arraybuffer';
  7310. } catch (e) {
  7311. _logger2.default.w('RangeLoader', e.message);
  7312. return false;
  7313. }
  7314. }
  7315. }]);
  7316. function RangeLoader(seekHandler, config) {
  7317. _classCallCheck(this, RangeLoader);
  7318. var _this = _possibleConstructorReturn(this, (RangeLoader.__proto__ || Object.getPrototypeOf(RangeLoader)).call(this, 'xhr-range-loader'));
  7319. _this.TAG = 'RangeLoader';
  7320. _this._seekHandler = seekHandler;
  7321. _this._config = config;
  7322. _this._needStash = false;
  7323. _this._chunkSizeKBList = [128, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 5120, 6144, 7168, 8192];
  7324. _this._currentChunkSizeKB = 384;
  7325. _this._currentSpeedNormalized = 0;
  7326. _this._zeroSpeedChunkCount = 0;
  7327. _this._xhr = null;
  7328. _this._speedSampler = new _speedSampler2.default();
  7329. _this._requestAbort = false;
  7330. _this._waitForTotalLength = false;
  7331. _this._totalLengthReceived = false;
  7332. _this._currentRequestURL = null;
  7333. _this._currentRedirectedURL = null;
  7334. _this._currentRequestRange = null;
  7335. _this._totalLength = null; // size of the entire file
  7336. _this._contentLength = null; // Content-Length of entire request range
  7337. _this._receivedLength = 0; // total received bytes
  7338. _this._lastTimeLoaded = 0; // received bytes of current request sub-range
  7339. return _this;
  7340. }
  7341. _createClass(RangeLoader, [{
  7342. key: 'destroy',
  7343. value: function destroy() {
  7344. if (this.isWorking()) {
  7345. this.abort();
  7346. }
  7347. if (this._xhr) {
  7348. this._xhr.onreadystatechange = null;
  7349. this._xhr.onprogress = null;
  7350. this._xhr.onload = null;
  7351. this._xhr.onerror = null;
  7352. this._xhr = null;
  7353. }
  7354. _get(RangeLoader.prototype.__proto__ || Object.getPrototypeOf(RangeLoader.prototype), 'destroy', this).call(this);
  7355. }
  7356. }, {
  7357. key: 'open',
  7358. value: function open(dataSource, range) {
  7359. this._dataSource = dataSource;
  7360. this._range = range;
  7361. this._status = _loader.LoaderStatus.kConnecting;
  7362. var useRefTotalLength = false;
  7363. if (this._dataSource.filesize != undefined && this._dataSource.filesize !== 0) {
  7364. useRefTotalLength = true;
  7365. this._totalLength = this._dataSource.filesize;
  7366. }
  7367. if (!this._totalLengthReceived && !useRefTotalLength) {
  7368. // We need total filesize
  7369. this._waitForTotalLength = true;
  7370. this._internalOpen(this._dataSource, { from: 0, to: -1 });
  7371. } else {
  7372. // We have filesize, start loading
  7373. this._openSubRange();
  7374. }
  7375. }
  7376. }, {
  7377. key: '_openSubRange',
  7378. value: function _openSubRange() {
  7379. var chunkSize = this._currentChunkSizeKB * 1024;
  7380. var from = this._range.from + this._receivedLength;
  7381. var to = from + chunkSize;
  7382. if (this._contentLength != null) {
  7383. if (to - this._range.from >= this._contentLength) {
  7384. to = this._range.from + this._contentLength - 1;
  7385. }
  7386. }
  7387. this._currentRequestRange = { from: from, to: to };
  7388. this._internalOpen(this._dataSource, this._currentRequestRange);
  7389. }
  7390. }, {
  7391. key: '_internalOpen',
  7392. value: function _internalOpen(dataSource, range) {
  7393. this._lastTimeLoaded = 0;
  7394. var sourceURL = dataSource.url;
  7395. if (this._config.reuseRedirectedURL) {
  7396. if (this._currentRedirectedURL != undefined) {
  7397. sourceURL = this._currentRedirectedURL;
  7398. } else if (dataSource.redirectedURL != undefined) {
  7399. sourceURL = dataSource.redirectedURL;
  7400. }
  7401. }
  7402. var seekConfig = this._seekHandler.getConfig(sourceURL, range);
  7403. this._currentRequestURL = seekConfig.url;
  7404. var xhr = this._xhr = new XMLHttpRequest();
  7405. xhr.open('GET', seekConfig.url, true);
  7406. xhr.responseType = 'arraybuffer';
  7407. xhr.onreadystatechange = this._onReadyStateChange.bind(this);
  7408. xhr.onprogress = this._onProgress.bind(this);
  7409. xhr.onload = this._onLoad.bind(this);
  7410. xhr.onerror = this._onXhrError.bind(this);
  7411. if (dataSource.withCredentials) {
  7412. xhr.withCredentials = true;
  7413. }
  7414. if (_typeof(seekConfig.headers) === 'object') {
  7415. var headers = seekConfig.headers;
  7416. for (var key in headers) {
  7417. if (headers.hasOwnProperty(key)) {
  7418. xhr.setRequestHeader(key, headers[key]);
  7419. }
  7420. }
  7421. }
  7422. // add additional headers
  7423. if (_typeof(this._config.headers) === 'object') {
  7424. var _headers = this._config.headers;
  7425. for (var _key in _headers) {
  7426. if (_headers.hasOwnProperty(_key)) {
  7427. xhr.setRequestHeader(_key, _headers[_key]);
  7428. }
  7429. }
  7430. }
  7431. xhr.send();
  7432. }
  7433. }, {
  7434. key: 'abort',
  7435. value: function abort() {
  7436. this._requestAbort = true;
  7437. this._internalAbort();
  7438. this._status = _loader.LoaderStatus.kComplete;
  7439. }
  7440. }, {
  7441. key: '_internalAbort',
  7442. value: function _internalAbort() {
  7443. if (this._xhr) {
  7444. this._xhr.onreadystatechange = null;
  7445. this._xhr.onprogress = null;
  7446. this._xhr.onload = null;
  7447. this._xhr.onerror = null;
  7448. this._xhr.abort();
  7449. this._xhr = null;
  7450. }
  7451. }
  7452. }, {
  7453. key: '_onReadyStateChange',
  7454. value: function _onReadyStateChange(e) {
  7455. var xhr = e.target;
  7456. if (xhr.readyState === 2) {
  7457. // HEADERS_RECEIVED
  7458. if (xhr.responseURL != undefined) {
  7459. // if the browser support this property
  7460. var redirectedURL = this._seekHandler.removeURLParameters(xhr.responseURL);
  7461. if (xhr.responseURL !== this._currentRequestURL && redirectedURL !== this._currentRedirectedURL) {
  7462. this._currentRedirectedURL = redirectedURL;
  7463. if (this._onURLRedirect) {
  7464. this._onURLRedirect(redirectedURL);
  7465. }
  7466. }
  7467. }
  7468. if (xhr.status >= 200 && xhr.status <= 299) {
  7469. if (this._waitForTotalLength) {
  7470. return;
  7471. }
  7472. this._status = _loader.LoaderStatus.kBuffering;
  7473. } else {
  7474. this._status = _loader.LoaderStatus.kError;
  7475. if (this._onError) {
  7476. this._onError(_loader.LoaderErrors.HTTP_STATUS_CODE_INVALID, { code: xhr.status, msg: xhr.statusText });
  7477. } else {
  7478. throw new _exception.RuntimeException('RangeLoader: Http code invalid, ' + xhr.status + ' ' + xhr.statusText);
  7479. }
  7480. }
  7481. }
  7482. }
  7483. }, {
  7484. key: '_onProgress',
  7485. value: function _onProgress(e) {
  7486. if (this._status === _loader.LoaderStatus.kError) {
  7487. // Ignore error response
  7488. return;
  7489. }
  7490. if (this._contentLength === null) {
  7491. var openNextRange = false;
  7492. if (this._waitForTotalLength) {
  7493. this._waitForTotalLength = false;
  7494. this._totalLengthReceived = true;
  7495. openNextRange = true;
  7496. var total = e.total;
  7497. this._internalAbort();
  7498. if (total != null & total !== 0) {
  7499. this._totalLength = total;
  7500. }
  7501. }
  7502. // calculate currrent request range's contentLength
  7503. if (this._range.to === -1) {
  7504. this._contentLength = this._totalLength - this._range.from;
  7505. } else {
  7506. // to !== -1
  7507. this._contentLength = this._range.to - this._range.from + 1;
  7508. }
  7509. if (openNextRange) {
  7510. this._openSubRange();
  7511. return;
  7512. }
  7513. if (this._onContentLengthKnown) {
  7514. this._onContentLengthKnown(this._contentLength);
  7515. }
  7516. }
  7517. var delta = e.loaded - this._lastTimeLoaded;
  7518. this._lastTimeLoaded = e.loaded;
  7519. this._speedSampler.addBytes(delta);
  7520. }
  7521. }, {
  7522. key: '_normalizeSpeed',
  7523. value: function _normalizeSpeed(input) {
  7524. var list = this._chunkSizeKBList;
  7525. var last = list.length - 1;
  7526. var mid = 0;
  7527. var lbound = 0;
  7528. var ubound = last;
  7529. if (input < list[0]) {
  7530. return list[0];
  7531. }
  7532. while (lbound <= ubound) {
  7533. mid = lbound + Math.floor((ubound - lbound) / 2);
  7534. if (mid === last || input >= list[mid] && input < list[mid + 1]) {
  7535. return list[mid];
  7536. } else if (list[mid] < input) {
  7537. lbound = mid + 1;
  7538. } else {
  7539. ubound = mid - 1;
  7540. }
  7541. }
  7542. }
  7543. }, {
  7544. key: '_onLoad',
  7545. value: function _onLoad(e) {
  7546. if (this._status === _loader.LoaderStatus.kError) {
  7547. // Ignore error response
  7548. return;
  7549. }
  7550. if (this._waitForTotalLength) {
  7551. this._waitForTotalLength = false;
  7552. return;
  7553. }
  7554. this._lastTimeLoaded = 0;
  7555. var KBps = this._speedSampler.lastSecondKBps;
  7556. if (KBps === 0) {
  7557. this._zeroSpeedChunkCount++;
  7558. if (this._zeroSpeedChunkCount >= 3) {
  7559. // Try get currentKBps after 3 chunks
  7560. KBps = this._speedSampler.currentKBps;
  7561. }
  7562. }
  7563. if (KBps !== 0) {
  7564. var normalized = this._normalizeSpeed(KBps);
  7565. if (this._currentSpeedNormalized !== normalized) {
  7566. this._currentSpeedNormalized = normalized;
  7567. this._currentChunkSizeKB = normalized;
  7568. }
  7569. }
  7570. var chunk = e.target.response;
  7571. var byteStart = this._range.from + this._receivedLength;
  7572. this._receivedLength += chunk.byteLength;
  7573. var reportComplete = false;
  7574. if (this._contentLength != null && this._receivedLength < this._contentLength) {
  7575. // continue load next chunk
  7576. this._openSubRange();
  7577. } else {
  7578. reportComplete = true;
  7579. }
  7580. // dispatch received chunk
  7581. if (this._onDataArrival) {
  7582. this._onDataArrival(chunk, byteStart, this._receivedLength);
  7583. }
  7584. if (reportComplete) {
  7585. this._status = _loader.LoaderStatus.kComplete;
  7586. if (this._onComplete) {
  7587. this._onComplete(this._range.from, this._range.from + this._receivedLength - 1);
  7588. }
  7589. }
  7590. }
  7591. }, {
  7592. key: '_onXhrError',
  7593. value: function _onXhrError(e) {
  7594. this._status = _loader.LoaderStatus.kError;
  7595. var type = 0;
  7596. var info = null;
  7597. if (this._contentLength && this._receivedLength > 0 && this._receivedLength < this._contentLength) {
  7598. type = _loader.LoaderErrors.EARLY_EOF;
  7599. info = { code: -1, msg: 'RangeLoader meet Early-Eof' };
  7600. } else {
  7601. type = _loader.LoaderErrors.EXCEPTION;
  7602. info = { code: -1, msg: e.constructor.name + ' ' + e.type };
  7603. }
  7604. if (this._onError) {
  7605. this._onError(type, info);
  7606. } else {
  7607. throw new _exception.RuntimeException(info.msg);
  7608. }
  7609. }
  7610. }, {
  7611. key: 'currentSpeed',
  7612. get: function get() {
  7613. return this._speedSampler.lastSecondKBps;
  7614. }
  7615. }]);
  7616. return RangeLoader;
  7617. }(_loader.BaseLoader);
  7618. exports.default = RangeLoader;
  7619. },{"../utils/exception.js":40,"../utils/logger.js":41,"./loader.js":24,"./speed-sampler.js":27}],32:[function(_dereq_,module,exports){
  7620. 'use strict';
  7621. Object.defineProperty(exports, "__esModule", {
  7622. value: true
  7623. });
  7624. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  7625. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  7626. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  7627. *
  7628. * @author zheng qian <xqq@xqq.im>
  7629. *
  7630. * Licensed under the Apache License, Version 2.0 (the "License");
  7631. * you may not use this file except in compliance with the License.
  7632. * You may obtain a copy of the License at
  7633. *
  7634. * http://www.apache.org/licenses/LICENSE-2.0
  7635. *
  7636. * Unless required by applicable law or agreed to in writing, software
  7637. * distributed under the License is distributed on an "AS IS" BASIS,
  7638. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  7639. * See the License for the specific language governing permissions and
  7640. * limitations under the License.
  7641. */
  7642. var _events = _dereq_('events');
  7643. var _events2 = _interopRequireDefault(_events);
  7644. var _logger = _dereq_('../utils/logger.js');
  7645. var _logger2 = _interopRequireDefault(_logger);
  7646. var _browser = _dereq_('../utils/browser.js');
  7647. var _browser2 = _interopRequireDefault(_browser);
  7648. var _playerEvents = _dereq_('./player-events.js');
  7649. var _playerEvents2 = _interopRequireDefault(_playerEvents);
  7650. var _transmuxer = _dereq_('../core/transmuxer.js');
  7651. var _transmuxer2 = _interopRequireDefault(_transmuxer);
  7652. var _transmuxingEvents = _dereq_('../core/transmuxing-events.js');
  7653. var _transmuxingEvents2 = _interopRequireDefault(_transmuxingEvents);
  7654. var _mseController = _dereq_('../core/mse-controller.js');
  7655. var _mseController2 = _interopRequireDefault(_mseController);
  7656. var _mseEvents = _dereq_('../core/mse-events.js');
  7657. var _mseEvents2 = _interopRequireDefault(_mseEvents);
  7658. var _playerErrors = _dereq_('./player-errors.js');
  7659. var _config = _dereq_('../config.js');
  7660. var _exception = _dereq_('../utils/exception.js');
  7661. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  7662. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  7663. var FlvPlayer = function () {
  7664. function FlvPlayer(mediaDataSource, config) {
  7665. _classCallCheck(this, FlvPlayer);
  7666. this.TAG = 'FlvPlayer';
  7667. this._type = 'FlvPlayer';
  7668. this._emitter = new _events2.default();
  7669. this._config = (0, _config.createDefaultConfig)();
  7670. if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
  7671. Object.assign(this._config, config);
  7672. }
  7673. if (mediaDataSource.type.toLowerCase() !== 'flv') {
  7674. throw new _exception.InvalidArgumentException('FlvPlayer requires an flv MediaDataSource input!');
  7675. }
  7676. if (mediaDataSource.isLive === true) {
  7677. this._config.isLive = true;
  7678. }
  7679. this.e = {
  7680. onvLoadedMetadata: this._onvLoadedMetadata.bind(this),
  7681. onvSeeking: this._onvSeeking.bind(this),
  7682. onvCanPlay: this._onvCanPlay.bind(this),
  7683. onvStalled: this._onvStalled.bind(this),
  7684. onvProgress: this._onvProgress.bind(this)
  7685. };
  7686. if (self.performance && self.performance.now) {
  7687. this._now = self.performance.now.bind(self.performance);
  7688. } else {
  7689. this._now = Date.now;
  7690. }
  7691. this._pendingSeekTime = null; // in seconds
  7692. this._requestSetTime = false;
  7693. this._seekpointRecord = null;
  7694. this._progressChecker = null;
  7695. this._mediaDataSource = mediaDataSource;
  7696. this._mediaElement = null;
  7697. this._msectl = null;
  7698. this._transmuxer = null;
  7699. this._mseSourceOpened = false;
  7700. this._hasPendingLoad = false;
  7701. this._receivedCanPlay = false;
  7702. this._mediaInfo = null;
  7703. this._statisticsInfo = null;
  7704. var chromeNeedIDRFix = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661);
  7705. this._alwaysSeekKeyframe = chromeNeedIDRFix || _browser2.default.msedge || _browser2.default.msie ? true : false;
  7706. if (this._alwaysSeekKeyframe) {
  7707. this._config.accurateSeek = false;
  7708. }
  7709. }
  7710. _createClass(FlvPlayer, [{
  7711. key: 'destroy',
  7712. value: function destroy() {
  7713. if (this._progressChecker != null) {
  7714. window.clearInterval(this._progressChecker);
  7715. this._progressChecker = null;
  7716. }
  7717. if (this._transmuxer) {
  7718. this.unload();
  7719. }
  7720. if (this._mediaElement) {
  7721. this.detachMediaElement();
  7722. }
  7723. this.e = null;
  7724. this._mediaDataSource = null;
  7725. this._emitter.removeAllListeners();
  7726. this._emitter = null;
  7727. }
  7728. }, {
  7729. key: 'on',
  7730. value: function on(event, listener) {
  7731. var _this = this;
  7732. if (event === _playerEvents2.default.MEDIA_INFO) {
  7733. if (this._mediaInfo != null) {
  7734. Promise.resolve().then(function () {
  7735. _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo);
  7736. });
  7737. }
  7738. } else if (event === _playerEvents2.default.STATISTICS_INFO) {
  7739. if (this._statisticsInfo != null) {
  7740. Promise.resolve().then(function () {
  7741. _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo);
  7742. });
  7743. }
  7744. }
  7745. this._emitter.addListener(event, listener);
  7746. }
  7747. }, {
  7748. key: 'off',
  7749. value: function off(event, listener) {
  7750. this._emitter.removeListener(event, listener);
  7751. }
  7752. }, {
  7753. key: 'attachMediaElement',
  7754. value: function attachMediaElement(mediaElement) {
  7755. var _this2 = this;
  7756. this._mediaElement = mediaElement;
  7757. mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata);
  7758. mediaElement.addEventListener('seeking', this.e.onvSeeking);
  7759. mediaElement.addEventListener('canplay', this.e.onvCanPlay);
  7760. mediaElement.addEventListener('stalled', this.e.onvStalled);
  7761. mediaElement.addEventListener('progress', this.e.onvProgress);
  7762. this._msectl = new _mseController2.default(this._config);
  7763. this._msectl.on(_mseEvents2.default.UPDATE_END, this._onmseUpdateEnd.bind(this));
  7764. this._msectl.on(_mseEvents2.default.BUFFER_FULL, this._onmseBufferFull.bind(this));
  7765. this._msectl.on(_mseEvents2.default.SOURCE_OPEN, function () {
  7766. _this2._mseSourceOpened = true;
  7767. if (_this2._hasPendingLoad) {
  7768. _this2._hasPendingLoad = false;
  7769. _this2.load();
  7770. }
  7771. });
  7772. this._msectl.on(_mseEvents2.default.ERROR, function (info) {
  7773. _this2._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, _playerErrors.ErrorDetails.MEDIA_MSE_ERROR, info);
  7774. });
  7775. this._msectl.attachMediaElement(mediaElement);
  7776. if (this._pendingSeekTime != null) {
  7777. try {
  7778. mediaElement.currentTime = this._pendingSeekTime;
  7779. this._pendingSeekTime = null;
  7780. } catch (e) {
  7781. // IE11 may throw InvalidStateError if readyState === 0
  7782. // We can defer set currentTime operation after loadedmetadata
  7783. }
  7784. }
  7785. }
  7786. }, {
  7787. key: 'detachMediaElement',
  7788. value: function detachMediaElement() {
  7789. if (this._mediaElement) {
  7790. this._msectl.detachMediaElement();
  7791. this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata);
  7792. this._mediaElement.removeEventListener('seeking', this.e.onvSeeking);
  7793. this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay);
  7794. this._mediaElement.removeEventListener('stalled', this.e.onvStalled);
  7795. this._mediaElement.removeEventListener('progress', this.e.onvProgress);
  7796. this._mediaElement = null;
  7797. }
  7798. if (this._msectl) {
  7799. this._msectl.destroy();
  7800. this._msectl = null;
  7801. }
  7802. }
  7803. }, {
  7804. key: 'load',
  7805. value: function load() {
  7806. var _this3 = this;
  7807. if (!this._mediaElement) {
  7808. throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!');
  7809. }
  7810. if (this._transmuxer) {
  7811. throw new _exception.IllegalStateException('FlvPlayer.load() has been called, please call unload() first!');
  7812. }
  7813. if (this._hasPendingLoad) {
  7814. return;
  7815. }
  7816. if (this._config.deferLoadAfterSourceOpen && this._mseSourceOpened === false) {
  7817. this._hasPendingLoad = true;
  7818. return;
  7819. }
  7820. if (this._mediaElement.readyState > 0) {
  7821. this._requestSetTime = true;
  7822. // IE11 may throw InvalidStateError if readyState === 0
  7823. this._mediaElement.currentTime = 0;
  7824. }
  7825. this._transmuxer = new _transmuxer2.default(this._mediaDataSource, this._config);
  7826. this._transmuxer.on(_transmuxingEvents2.default.INIT_SEGMENT, function (type, is) {
  7827. _this3._msectl.appendInitSegment(is);
  7828. });
  7829. this._transmuxer.on(_transmuxingEvents2.default.MEDIA_SEGMENT, function (type, ms) {
  7830. _this3._msectl.appendMediaSegment(ms);
  7831. // lazyLoad check
  7832. if (_this3._config.lazyLoad && !_this3._config.isLive) {
  7833. var currentTime = _this3._mediaElement.currentTime;
  7834. if (ms.info.endDts >= (currentTime + _this3._config.lazyLoadMaxDuration) * 1000) {
  7835. if (_this3._progressChecker == null) {
  7836. _logger2.default.v(_this3.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task');
  7837. _this3._suspendTransmuxer();
  7838. }
  7839. }
  7840. }
  7841. });
  7842. this._transmuxer.on(_transmuxingEvents2.default.LOADING_COMPLETE, function () {
  7843. _this3._msectl.endOfStream();
  7844. _this3._emitter.emit(_playerEvents2.default.LOADING_COMPLETE);
  7845. });
  7846. this._transmuxer.on(_transmuxingEvents2.default.RECOVERED_EARLY_EOF, function () {
  7847. _this3._emitter.emit(_playerEvents2.default.RECOVERED_EARLY_EOF);
  7848. });
  7849. this._transmuxer.on(_transmuxingEvents2.default.IO_ERROR, function (detail, info) {
  7850. _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.NETWORK_ERROR, detail, info);
  7851. });
  7852. this._transmuxer.on(_transmuxingEvents2.default.DEMUX_ERROR, function (detail, info) {
  7853. _this3._emitter.emit(_playerEvents2.default.ERROR, _playerErrors.ErrorTypes.MEDIA_ERROR, detail, { code: -1, msg: info });
  7854. });
  7855. this._transmuxer.on(_transmuxingEvents2.default.MEDIA_INFO, function (mediaInfo) {
  7856. _this3._mediaInfo = mediaInfo;
  7857. _this3._emitter.emit(_playerEvents2.default.MEDIA_INFO, Object.assign({}, mediaInfo));
  7858. });
  7859. this._transmuxer.on(_transmuxingEvents2.default.METADATA_ARRIVED, function (metadata) {
  7860. _this3._emitter.emit(_playerEvents2.default.METADATA_ARRIVED, metadata);
  7861. });
  7862. this._transmuxer.on(_transmuxingEvents2.default.SCRIPTDATA_ARRIVED, function (data) {
  7863. _this3._emitter.emit(_playerEvents2.default.SCRIPTDATA_ARRIVED, data);
  7864. });
  7865. this._transmuxer.on(_transmuxingEvents2.default.STATISTICS_INFO, function (statInfo) {
  7866. _this3._statisticsInfo = _this3._fillStatisticsInfo(statInfo);
  7867. _this3._emitter.emit(_playerEvents2.default.STATISTICS_INFO, Object.assign({}, _this3._statisticsInfo));
  7868. });
  7869. this._transmuxer.on(_transmuxingEvents2.default.RECOMMEND_SEEKPOINT, function (milliseconds) {
  7870. if (_this3._mediaElement && !_this3._config.accurateSeek) {
  7871. _this3._requestSetTime = true;
  7872. _this3._mediaElement.currentTime = milliseconds / 1000;
  7873. }
  7874. });
  7875. this._transmuxer.open();
  7876. }
  7877. }, {
  7878. key: 'unload',
  7879. value: function unload() {
  7880. if (this._mediaElement) {
  7881. this._mediaElement.pause();
  7882. }
  7883. if (this._msectl) {
  7884. this._msectl.seek(0);
  7885. }
  7886. if (this._transmuxer) {
  7887. this._transmuxer.close();
  7888. this._transmuxer.destroy();
  7889. this._transmuxer = null;
  7890. }
  7891. }
  7892. }, {
  7893. key: 'play',
  7894. value: function play() {
  7895. return this._mediaElement.play();
  7896. }
  7897. }, {
  7898. key: 'pause',
  7899. value: function pause() {
  7900. this._mediaElement.pause();
  7901. }
  7902. }, {
  7903. key: '_fillStatisticsInfo',
  7904. value: function _fillStatisticsInfo(statInfo) {
  7905. statInfo.playerType = this._type;
  7906. if (!(this._mediaElement instanceof HTMLVideoElement)) {
  7907. return statInfo;
  7908. }
  7909. var hasQualityInfo = true;
  7910. var decoded = 0;
  7911. var dropped = 0;
  7912. if (this._mediaElement.getVideoPlaybackQuality) {
  7913. var quality = this._mediaElement.getVideoPlaybackQuality();
  7914. decoded = quality.totalVideoFrames;
  7915. dropped = quality.droppedVideoFrames;
  7916. } else if (this._mediaElement.webkitDecodedFrameCount != undefined) {
  7917. decoded = this._mediaElement.webkitDecodedFrameCount;
  7918. dropped = this._mediaElement.webkitDroppedFrameCount;
  7919. } else {
  7920. hasQualityInfo = false;
  7921. }
  7922. if (hasQualityInfo) {
  7923. statInfo.decodedFrames = decoded;
  7924. statInfo.droppedFrames = dropped;
  7925. }
  7926. return statInfo;
  7927. }
  7928. }, {
  7929. key: '_onmseUpdateEnd',
  7930. value: function _onmseUpdateEnd() {
  7931. if (!this._config.lazyLoad || this._config.isLive) {
  7932. return;
  7933. }
  7934. var buffered = this._mediaElement.buffered;
  7935. var currentTime = this._mediaElement.currentTime;
  7936. var currentRangeStart = 0;
  7937. var currentRangeEnd = 0;
  7938. for (var i = 0; i < buffered.length; i++) {
  7939. var start = buffered.start(i);
  7940. var end = buffered.end(i);
  7941. if (start <= currentTime && currentTime < end) {
  7942. currentRangeStart = start;
  7943. currentRangeEnd = end;
  7944. break;
  7945. }
  7946. }
  7947. if (currentRangeEnd >= currentTime + this._config.lazyLoadMaxDuration && this._progressChecker == null) {
  7948. _logger2.default.v(this.TAG, 'Maximum buffering duration exceeded, suspend transmuxing task');
  7949. this._suspendTransmuxer();
  7950. }
  7951. }
  7952. }, {
  7953. key: '_onmseBufferFull',
  7954. value: function _onmseBufferFull() {
  7955. _logger2.default.v(this.TAG, 'MSE SourceBuffer is full, suspend transmuxing task');
  7956. if (this._progressChecker == null) {
  7957. this._suspendTransmuxer();
  7958. }
  7959. }
  7960. }, {
  7961. key: '_suspendTransmuxer',
  7962. value: function _suspendTransmuxer() {
  7963. if (this._transmuxer) {
  7964. this._transmuxer.pause();
  7965. if (this._progressChecker == null) {
  7966. this._progressChecker = window.setInterval(this._checkProgressAndResume.bind(this), 1000);
  7967. }
  7968. }
  7969. }
  7970. }, {
  7971. key: '_checkProgressAndResume',
  7972. value: function _checkProgressAndResume() {
  7973. var currentTime = this._mediaElement.currentTime;
  7974. var buffered = this._mediaElement.buffered;
  7975. var needResume = false;
  7976. for (var i = 0; i < buffered.length; i++) {
  7977. var from = buffered.start(i);
  7978. var to = buffered.end(i);
  7979. if (currentTime >= from && currentTime < to) {
  7980. if (currentTime >= to - this._config.lazyLoadRecoverDuration) {
  7981. needResume = true;
  7982. }
  7983. break;
  7984. }
  7985. }
  7986. if (needResume) {
  7987. window.clearInterval(this._progressChecker);
  7988. this._progressChecker = null;
  7989. if (needResume) {
  7990. _logger2.default.v(this.TAG, 'Continue loading from paused position');
  7991. this._transmuxer.resume();
  7992. }
  7993. }
  7994. }
  7995. }, {
  7996. key: '_isTimepointBuffered',
  7997. value: function _isTimepointBuffered(seconds) {
  7998. var buffered = this._mediaElement.buffered;
  7999. for (var i = 0; i < buffered.length; i++) {
  8000. var from = buffered.start(i);
  8001. var to = buffered.end(i);
  8002. if (seconds >= from && seconds < to) {
  8003. return true;
  8004. }
  8005. }
  8006. return false;
  8007. }
  8008. }, {
  8009. key: '_internalSeek',
  8010. value: function _internalSeek(seconds) {
  8011. var directSeek = this._isTimepointBuffered(seconds);
  8012. var directSeekBegin = false;
  8013. var directSeekBeginTime = 0;
  8014. if (seconds < 1.0 && this._mediaElement.buffered.length > 0) {
  8015. var videoBeginTime = this._mediaElement.buffered.start(0);
  8016. if (videoBeginTime < 1.0 && seconds < videoBeginTime || _browser2.default.safari) {
  8017. directSeekBegin = true;
  8018. // also workaround for Safari: Seek to 0 may cause videoFusion stuck, use 0.1 to avoid
  8019. directSeekBeginTime = _browser2.default.safari ? 0.1 : videoBeginTime;
  8020. }
  8021. }
  8022. if (directSeekBegin) {
  8023. // seek to videoFusion begin, set currentTime directly if beginPTS buffered
  8024. this._requestSetTime = true;
  8025. this._mediaElement.currentTime = directSeekBeginTime;
  8026. } else if (directSeek) {
  8027. // buffered position
  8028. if (!this._alwaysSeekKeyframe) {
  8029. this._requestSetTime = true;
  8030. this._mediaElement.currentTime = seconds;
  8031. } else {
  8032. var idr = this._msectl.getNearestKeyframe(Math.floor(seconds * 1000));
  8033. this._requestSetTime = true;
  8034. if (idr != null) {
  8035. this._mediaElement.currentTime = idr.dts / 1000;
  8036. } else {
  8037. this._mediaElement.currentTime = seconds;
  8038. }
  8039. }
  8040. if (this._progressChecker != null) {
  8041. this._checkProgressAndResume();
  8042. }
  8043. } else {
  8044. if (this._progressChecker != null) {
  8045. window.clearInterval(this._progressChecker);
  8046. this._progressChecker = null;
  8047. }
  8048. this._msectl.seek(seconds);
  8049. this._transmuxer.seek(Math.floor(seconds * 1000)); // in milliseconds
  8050. // no need to set mediaElement.currentTime if non-accurateSeek,
  8051. // just wait for the recommend_seekpoint callback
  8052. if (this._config.accurateSeek) {
  8053. this._requestSetTime = true;
  8054. this._mediaElement.currentTime = seconds;
  8055. }
  8056. }
  8057. }
  8058. }, {
  8059. key: '_checkAndApplyUnbufferedSeekpoint',
  8060. value: function _checkAndApplyUnbufferedSeekpoint() {
  8061. if (this._seekpointRecord) {
  8062. if (this._seekpointRecord.recordTime <= this._now() - 100) {
  8063. var target = this._mediaElement.currentTime;
  8064. this._seekpointRecord = null;
  8065. if (!this._isTimepointBuffered(target)) {
  8066. if (this._progressChecker != null) {
  8067. window.clearTimeout(this._progressChecker);
  8068. this._progressChecker = null;
  8069. }
  8070. // .currentTime is consists with .buffered timestamp
  8071. // Chrome/Edge use DTS, while FireFox/Safari use PTS
  8072. this._msectl.seek(target);
  8073. this._transmuxer.seek(Math.floor(target * 1000));
  8074. // set currentTime if accurateSeek, or wait for recommend_seekpoint callback
  8075. if (this._config.accurateSeek) {
  8076. this._requestSetTime = true;
  8077. this._mediaElement.currentTime = target;
  8078. }
  8079. }
  8080. } else {
  8081. window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50);
  8082. }
  8083. }
  8084. }
  8085. }, {
  8086. key: '_checkAndResumeStuckPlayback',
  8087. value: function _checkAndResumeStuckPlayback(stalled) {
  8088. var media = this._mediaElement;
  8089. if (stalled || !this._receivedCanPlay || media.readyState < 2) {
  8090. // HAVE_CURRENT_DATA
  8091. var buffered = media.buffered;
  8092. if (buffered.length > 0 && media.currentTime < buffered.start(0)) {
  8093. _logger2.default.w(this.TAG, 'Playback seems stuck at ' + media.currentTime + ', seek to ' + buffered.start(0));
  8094. this._requestSetTime = true;
  8095. this._mediaElement.currentTime = buffered.start(0);
  8096. this._mediaElement.removeEventListener('progress', this.e.onvProgress);
  8097. }
  8098. } else {
  8099. // Playback didn't stuck, remove progress event listener
  8100. this._mediaElement.removeEventListener('progress', this.e.onvProgress);
  8101. }
  8102. }
  8103. }, {
  8104. key: '_onvLoadedMetadata',
  8105. value: function _onvLoadedMetadata(e) {
  8106. if (this._pendingSeekTime != null) {
  8107. this._mediaElement.currentTime = this._pendingSeekTime;
  8108. this._pendingSeekTime = null;
  8109. }
  8110. }
  8111. }, {
  8112. key: '_onvSeeking',
  8113. value: function _onvSeeking(e) {
  8114. // handle seeking request from browser's progress bar
  8115. var target = this._mediaElement.currentTime;
  8116. var buffered = this._mediaElement.buffered;
  8117. if (this._requestSetTime) {
  8118. this._requestSetTime = false;
  8119. return;
  8120. }
  8121. if (target < 1.0 && buffered.length > 0) {
  8122. // seek to videoFusion begin, set currentTime directly if beginPTS buffered
  8123. var videoBeginTime = buffered.start(0);
  8124. if (videoBeginTime < 1.0 && target < videoBeginTime || _browser2.default.safari) {
  8125. this._requestSetTime = true;
  8126. // also workaround for Safari: Seek to 0 may cause videoFusion stuck, use 0.1 to avoid
  8127. this._mediaElement.currentTime = _browser2.default.safari ? 0.1 : videoBeginTime;
  8128. return;
  8129. }
  8130. }
  8131. if (this._isTimepointBuffered(target)) {
  8132. if (this._alwaysSeekKeyframe) {
  8133. var idr = this._msectl.getNearestKeyframe(Math.floor(target * 1000));
  8134. if (idr != null) {
  8135. this._requestSetTime = true;
  8136. this._mediaElement.currentTime = idr.dts / 1000;
  8137. }
  8138. }
  8139. if (this._progressChecker != null) {
  8140. this._checkProgressAndResume();
  8141. }
  8142. return;
  8143. }
  8144. this._seekpointRecord = {
  8145. seekPoint: target,
  8146. recordTime: this._now()
  8147. };
  8148. window.setTimeout(this._checkAndApplyUnbufferedSeekpoint.bind(this), 50);
  8149. }
  8150. }, {
  8151. key: '_onvCanPlay',
  8152. value: function _onvCanPlay(e) {
  8153. this._receivedCanPlay = true;
  8154. this._mediaElement.removeEventListener('canplay', this.e.onvCanPlay);
  8155. }
  8156. }, {
  8157. key: '_onvStalled',
  8158. value: function _onvStalled(e) {
  8159. this._checkAndResumeStuckPlayback(true);
  8160. }
  8161. }, {
  8162. key: '_onvProgress',
  8163. value: function _onvProgress(e) {
  8164. this._checkAndResumeStuckPlayback();
  8165. }
  8166. }, {
  8167. key: 'type',
  8168. get: function get() {
  8169. return this._type;
  8170. }
  8171. }, {
  8172. key: 'buffered',
  8173. get: function get() {
  8174. return this._mediaElement.buffered;
  8175. }
  8176. }, {
  8177. key: 'duration',
  8178. get: function get() {
  8179. return this._mediaElement.duration;
  8180. }
  8181. }, {
  8182. key: 'volume',
  8183. get: function get() {
  8184. return this._mediaElement.volume;
  8185. },
  8186. set: function set(value) {
  8187. this._mediaElement.volume = value;
  8188. }
  8189. }, {
  8190. key: 'muted',
  8191. get: function get() {
  8192. return this._mediaElement.muted;
  8193. },
  8194. set: function set(muted) {
  8195. this._mediaElement.muted = muted;
  8196. }
  8197. }, {
  8198. key: 'currentTime',
  8199. get: function get() {
  8200. if (this._mediaElement) {
  8201. return this._mediaElement.currentTime;
  8202. }
  8203. return 0;
  8204. },
  8205. set: function set(seconds) {
  8206. if (this._mediaElement) {
  8207. this._internalSeek(seconds);
  8208. } else {
  8209. this._pendingSeekTime = seconds;
  8210. }
  8211. }
  8212. }, {
  8213. key: 'mediaInfo',
  8214. get: function get() {
  8215. return Object.assign({}, this._mediaInfo);
  8216. }
  8217. }, {
  8218. key: 'statisticsInfo',
  8219. get: function get() {
  8220. if (this._statisticsInfo == null) {
  8221. this._statisticsInfo = {};
  8222. }
  8223. this._statisticsInfo = this._fillStatisticsInfo(this._statisticsInfo);
  8224. return Object.assign({}, this._statisticsInfo);
  8225. }
  8226. }]);
  8227. return FlvPlayer;
  8228. }();
  8229. exports.default = FlvPlayer;
  8230. },{"../config.js":5,"../core/mse-controller.js":9,"../core/mse-events.js":10,"../core/transmuxer.js":11,"../core/transmuxing-events.js":13,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./player-errors.js":34,"./player-events.js":35,"events":2}],33:[function(_dereq_,module,exports){
  8231. 'use strict';
  8232. Object.defineProperty(exports, "__esModule", {
  8233. value: true
  8234. });
  8235. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  8236. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  8237. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  8238. *
  8239. * @author zheng qian <xqq@xqq.im>
  8240. *
  8241. * Licensed under the Apache License, Version 2.0 (the "License");
  8242. * you may not use this file except in compliance with the License.
  8243. * You may obtain a copy of the License at
  8244. *
  8245. * http://www.apache.org/licenses/LICENSE-2.0
  8246. *
  8247. * Unless required by applicable law or agreed to in writing, software
  8248. * distributed under the License is distributed on an "AS IS" BASIS,
  8249. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8250. * See the License for the specific language governing permissions and
  8251. * limitations under the License.
  8252. */
  8253. var _events = _dereq_('events');
  8254. var _events2 = _interopRequireDefault(_events);
  8255. var _playerEvents = _dereq_('./player-events.js');
  8256. var _playerEvents2 = _interopRequireDefault(_playerEvents);
  8257. var _config = _dereq_('../config.js');
  8258. var _exception = _dereq_('../utils/exception.js');
  8259. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8260. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  8261. // Player wrapper for browser's native player (HTMLVideoElement) without MediaSource src.
  8262. var NativePlayer = function () {
  8263. function NativePlayer(mediaDataSource, config) {
  8264. _classCallCheck(this, NativePlayer);
  8265. this.TAG = 'NativePlayer';
  8266. this._type = 'NativePlayer';
  8267. this._emitter = new _events2.default();
  8268. this._config = (0, _config.createDefaultConfig)();
  8269. if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
  8270. Object.assign(this._config, config);
  8271. }
  8272. if (mediaDataSource.type.toLowerCase() === 'flv') {
  8273. throw new _exception.InvalidArgumentException('NativePlayer does\'t support flv MediaDataSource input!');
  8274. }
  8275. if (mediaDataSource.hasOwnProperty('segments')) {
  8276. throw new _exception.InvalidArgumentException('NativePlayer(' + mediaDataSource.type + ') doesn\'t support multipart playback!');
  8277. }
  8278. this.e = {
  8279. onvLoadedMetadata: this._onvLoadedMetadata.bind(this)
  8280. };
  8281. this._pendingSeekTime = null;
  8282. this._statisticsReporter = null;
  8283. this._mediaDataSource = mediaDataSource;
  8284. this._mediaElement = null;
  8285. }
  8286. _createClass(NativePlayer, [{
  8287. key: 'destroy',
  8288. value: function destroy() {
  8289. if (this._mediaElement) {
  8290. this.unload();
  8291. this.detachMediaElement();
  8292. }
  8293. this.e = null;
  8294. this._mediaDataSource = null;
  8295. this._emitter.removeAllListeners();
  8296. this._emitter = null;
  8297. }
  8298. }, {
  8299. key: 'on',
  8300. value: function on(event, listener) {
  8301. var _this = this;
  8302. if (event === _playerEvents2.default.MEDIA_INFO) {
  8303. if (this._mediaElement != null && this._mediaElement.readyState !== 0) {
  8304. // HAVE_NOTHING
  8305. Promise.resolve().then(function () {
  8306. _this._emitter.emit(_playerEvents2.default.MEDIA_INFO, _this.mediaInfo);
  8307. });
  8308. }
  8309. } else if (event === _playerEvents2.default.STATISTICS_INFO) {
  8310. if (this._mediaElement != null && this._mediaElement.readyState !== 0) {
  8311. Promise.resolve().then(function () {
  8312. _this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, _this.statisticsInfo);
  8313. });
  8314. }
  8315. }
  8316. this._emitter.addListener(event, listener);
  8317. }
  8318. }, {
  8319. key: 'off',
  8320. value: function off(event, listener) {
  8321. this._emitter.removeListener(event, listener);
  8322. }
  8323. }, {
  8324. key: 'attachMediaElement',
  8325. value: function attachMediaElement(mediaElement) {
  8326. this._mediaElement = mediaElement;
  8327. mediaElement.addEventListener('loadedmetadata', this.e.onvLoadedMetadata);
  8328. if (this._pendingSeekTime != null) {
  8329. try {
  8330. mediaElement.currentTime = this._pendingSeekTime;
  8331. this._pendingSeekTime = null;
  8332. } catch (e) {
  8333. // IE11 may throw InvalidStateError if readyState === 0
  8334. // Defer set currentTime operation after loadedmetadata
  8335. }
  8336. }
  8337. }
  8338. }, {
  8339. key: 'detachMediaElement',
  8340. value: function detachMediaElement() {
  8341. if (this._mediaElement) {
  8342. this._mediaElement.src = '';
  8343. this._mediaElement.removeAttribute('src');
  8344. this._mediaElement.removeEventListener('loadedmetadata', this.e.onvLoadedMetadata);
  8345. this._mediaElement = null;
  8346. }
  8347. if (this._statisticsReporter != null) {
  8348. window.clearInterval(this._statisticsReporter);
  8349. this._statisticsReporter = null;
  8350. }
  8351. }
  8352. }, {
  8353. key: 'load',
  8354. value: function load() {
  8355. if (!this._mediaElement) {
  8356. throw new _exception.IllegalStateException('HTMLMediaElement must be attached before load()!');
  8357. }
  8358. this._mediaElement.src = this._mediaDataSource.url;
  8359. if (this._mediaElement.readyState > 0) {
  8360. this._mediaElement.currentTime = 0;
  8361. }
  8362. this._mediaElement.preload = 'auto';
  8363. this._mediaElement.load();
  8364. this._statisticsReporter = window.setInterval(this._reportStatisticsInfo.bind(this), this._config.statisticsInfoReportInterval);
  8365. }
  8366. }, {
  8367. key: 'unload',
  8368. value: function unload() {
  8369. if (this._mediaElement) {
  8370. this._mediaElement.src = '';
  8371. this._mediaElement.removeAttribute('src');
  8372. }
  8373. if (this._statisticsReporter != null) {
  8374. window.clearInterval(this._statisticsReporter);
  8375. this._statisticsReporter = null;
  8376. }
  8377. }
  8378. }, {
  8379. key: 'play',
  8380. value: function play() {
  8381. return this._mediaElement.play();
  8382. }
  8383. }, {
  8384. key: 'pause',
  8385. value: function pause() {
  8386. this._mediaElement.pause();
  8387. }
  8388. }, {
  8389. key: '_onvLoadedMetadata',
  8390. value: function _onvLoadedMetadata(e) {
  8391. if (this._pendingSeekTime != null) {
  8392. this._mediaElement.currentTime = this._pendingSeekTime;
  8393. this._pendingSeekTime = null;
  8394. }
  8395. this._emitter.emit(_playerEvents2.default.MEDIA_INFO, this.mediaInfo);
  8396. }
  8397. }, {
  8398. key: '_reportStatisticsInfo',
  8399. value: function _reportStatisticsInfo() {
  8400. this._emitter.emit(_playerEvents2.default.STATISTICS_INFO, this.statisticsInfo);
  8401. }
  8402. }, {
  8403. key: 'type',
  8404. get: function get() {
  8405. return this._type;
  8406. }
  8407. }, {
  8408. key: 'buffered',
  8409. get: function get() {
  8410. return this._mediaElement.buffered;
  8411. }
  8412. }, {
  8413. key: 'duration',
  8414. get: function get() {
  8415. return this._mediaElement.duration;
  8416. }
  8417. }, {
  8418. key: 'volume',
  8419. get: function get() {
  8420. return this._mediaElement.volume;
  8421. },
  8422. set: function set(value) {
  8423. this._mediaElement.volume = value;
  8424. }
  8425. }, {
  8426. key: 'muted',
  8427. get: function get() {
  8428. return this._mediaElement.muted;
  8429. },
  8430. set: function set(muted) {
  8431. this._mediaElement.muted = muted;
  8432. }
  8433. }, {
  8434. key: 'currentTime',
  8435. get: function get() {
  8436. if (this._mediaElement) {
  8437. return this._mediaElement.currentTime;
  8438. }
  8439. return 0;
  8440. },
  8441. set: function set(seconds) {
  8442. if (this._mediaElement) {
  8443. this._mediaElement.currentTime = seconds;
  8444. } else {
  8445. this._pendingSeekTime = seconds;
  8446. }
  8447. }
  8448. }, {
  8449. key: 'mediaInfo',
  8450. get: function get() {
  8451. var mediaPrefix = this._mediaElement instanceof HTMLAudioElement ? 'audio/' : 'videoFusion/';
  8452. var info = {
  8453. mimeType: mediaPrefix + this._mediaDataSource.type
  8454. };
  8455. if (this._mediaElement) {
  8456. info.duration = Math.floor(this._mediaElement.duration * 1000);
  8457. if (this._mediaElement instanceof HTMLVideoElement) {
  8458. info.width = this._mediaElement.videoWidth;
  8459. info.height = this._mediaElement.videoHeight;
  8460. }
  8461. }
  8462. return info;
  8463. }
  8464. }, {
  8465. key: 'statisticsInfo',
  8466. get: function get() {
  8467. var info = {
  8468. playerType: this._type,
  8469. url: this._mediaDataSource.url
  8470. };
  8471. if (!(this._mediaElement instanceof HTMLVideoElement)) {
  8472. return info;
  8473. }
  8474. var hasQualityInfo = true;
  8475. var decoded = 0;
  8476. var dropped = 0;
  8477. if (this._mediaElement.getVideoPlaybackQuality) {
  8478. var quality = this._mediaElement.getVideoPlaybackQuality();
  8479. decoded = quality.totalVideoFrames;
  8480. dropped = quality.droppedVideoFrames;
  8481. } else if (this._mediaElement.webkitDecodedFrameCount != undefined) {
  8482. decoded = this._mediaElement.webkitDecodedFrameCount;
  8483. dropped = this._mediaElement.webkitDroppedFrameCount;
  8484. } else {
  8485. hasQualityInfo = false;
  8486. }
  8487. if (hasQualityInfo) {
  8488. info.decodedFrames = decoded;
  8489. info.droppedFrames = dropped;
  8490. }
  8491. return info;
  8492. }
  8493. }]);
  8494. return NativePlayer;
  8495. }();
  8496. exports.default = NativePlayer;
  8497. },{"../config.js":5,"../utils/exception.js":40,"./player-events.js":35,"events":2}],34:[function(_dereq_,module,exports){
  8498. 'use strict';
  8499. Object.defineProperty(exports, "__esModule", {
  8500. value: true
  8501. });
  8502. exports.ErrorDetails = exports.ErrorTypes = undefined;
  8503. var _loader = _dereq_('../io/loader.js');
  8504. var _demuxErrors = _dereq_('../demux/demux-errors.js');
  8505. var _demuxErrors2 = _interopRequireDefault(_demuxErrors);
  8506. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  8507. /*
  8508. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  8509. *
  8510. * @author zheng qian <xqq@xqq.im>
  8511. *
  8512. * Licensed under the Apache License, Version 2.0 (the "License");
  8513. * you may not use this file except in compliance with the License.
  8514. * You may obtain a copy of the License at
  8515. *
  8516. * http://www.apache.org/licenses/LICENSE-2.0
  8517. *
  8518. * Unless required by applicable law or agreed to in writing, software
  8519. * distributed under the License is distributed on an "AS IS" BASIS,
  8520. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8521. * See the License for the specific language governing permissions and
  8522. * limitations under the License.
  8523. */
  8524. var ErrorTypes = exports.ErrorTypes = {
  8525. NETWORK_ERROR: 'NetworkError',
  8526. MEDIA_ERROR: 'MediaError',
  8527. OTHER_ERROR: 'OtherError'
  8528. };
  8529. var ErrorDetails = exports.ErrorDetails = {
  8530. NETWORK_EXCEPTION: _loader.LoaderErrors.EXCEPTION,
  8531. NETWORK_STATUS_CODE_INVALID: _loader.LoaderErrors.HTTP_STATUS_CODE_INVALID,
  8532. NETWORK_TIMEOUT: _loader.LoaderErrors.CONNECTING_TIMEOUT,
  8533. NETWORK_UNRECOVERABLE_EARLY_EOF: _loader.LoaderErrors.UNRECOVERABLE_EARLY_EOF,
  8534. MEDIA_MSE_ERROR: 'MediaMSEError',
  8535. MEDIA_FORMAT_ERROR: _demuxErrors2.default.FORMAT_ERROR,
  8536. MEDIA_FORMAT_UNSUPPORTED: _demuxErrors2.default.FORMAT_UNSUPPORTED,
  8537. MEDIA_CODEC_UNSUPPORTED: _demuxErrors2.default.CODEC_UNSUPPORTED
  8538. };
  8539. },{"../demux/demux-errors.js":16,"../io/loader.js":24}],35:[function(_dereq_,module,exports){
  8540. 'use strict';
  8541. Object.defineProperty(exports, "__esModule", {
  8542. value: true
  8543. });
  8544. /*
  8545. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  8546. *
  8547. * @author zheng qian <xqq@xqq.im>
  8548. *
  8549. * Licensed under the Apache License, Version 2.0 (the "License");
  8550. * you may not use this file except in compliance with the License.
  8551. * You may obtain a copy of the License at
  8552. *
  8553. * http://www.apache.org/licenses/LICENSE-2.0
  8554. *
  8555. * Unless required by applicable law or agreed to in writing, software
  8556. * distributed under the License is distributed on an "AS IS" BASIS,
  8557. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8558. * See the License for the specific language governing permissions and
  8559. * limitations under the License.
  8560. */
  8561. var PlayerEvents = {
  8562. ERROR: 'error',
  8563. LOADING_COMPLETE: 'loading_complete',
  8564. RECOVERED_EARLY_EOF: 'recovered_early_eof',
  8565. MEDIA_INFO: 'media_info',
  8566. METADATA_ARRIVED: 'metadata_arrived',
  8567. SCRIPTDATA_ARRIVED: 'scriptdata_arrived',
  8568. STATISTICS_INFO: 'statistics_info'
  8569. };
  8570. exports.default = PlayerEvents;
  8571. },{}],36:[function(_dereq_,module,exports){
  8572. 'use strict';
  8573. Object.defineProperty(exports, "__esModule", {
  8574. value: true
  8575. });
  8576. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  8577. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  8578. /*
  8579. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  8580. *
  8581. * This file is modified from dailymotion's hls.js library (hls.js/src/helper/aac.js)
  8582. * @author zheng qian <xqq@xqq.im>
  8583. *
  8584. * Licensed under the Apache License, Version 2.0 (the "License");
  8585. * you may not use this file except in compliance with the License.
  8586. * You may obtain a copy of the License at
  8587. *
  8588. * http://www.apache.org/licenses/LICENSE-2.0
  8589. *
  8590. * Unless required by applicable law or agreed to in writing, software
  8591. * distributed under the License is distributed on an "AS IS" BASIS,
  8592. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8593. * See the License for the specific language governing permissions and
  8594. * limitations under the License.
  8595. */
  8596. var AAC = function () {
  8597. function AAC() {
  8598. _classCallCheck(this, AAC);
  8599. }
  8600. _createClass(AAC, null, [{
  8601. key: 'getSilentFrame',
  8602. value: function getSilentFrame(codec, channelCount) {
  8603. if (codec === 'mp4a.40.2') {
  8604. // handle LC-AAC
  8605. if (channelCount === 1) {
  8606. return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x23, 0x80]);
  8607. } else if (channelCount === 2) {
  8608. return new Uint8Array([0x21, 0x00, 0x49, 0x90, 0x02, 0x19, 0x00, 0x23, 0x80]);
  8609. } else if (channelCount === 3) {
  8610. return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x8e]);
  8611. } else if (channelCount === 4) {
  8612. return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x80, 0x2c, 0x80, 0x08, 0x02, 0x38]);
  8613. } else if (channelCount === 5) {
  8614. return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x38]);
  8615. } else if (channelCount === 6) {
  8616. return new Uint8Array([0x00, 0xc8, 0x00, 0x80, 0x20, 0x84, 0x01, 0x26, 0x40, 0x08, 0x64, 0x00, 0x82, 0x30, 0x04, 0x99, 0x00, 0x21, 0x90, 0x02, 0x00, 0xb2, 0x00, 0x20, 0x08, 0xe0]);
  8617. }
  8618. } else {
  8619. // handle HE-AAC (mp4a.40.5 / mp4a.40.29)
  8620. if (channelCount === 1) {
  8621. // ffmpeg -y -f lavfi -i "aevalsrc=0:d=0.05" -c:a libfdk_aac -profile:a aac_he -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
  8622. return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x4e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x1c, 0x6, 0xf1, 0xc1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]);
  8623. } else if (channelCount === 2) {
  8624. // ffmpeg -y -f lavfi -i "aevalsrc=0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
  8625. return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]);
  8626. } else if (channelCount === 3) {
  8627. // ffmpeg -y -f lavfi -i "aevalsrc=0|0|0:d=0.05" -c:a libfdk_aac -profile:a aac_he_v2 -b:a 4k output.aac && hexdump -v -e '16/1 "0x%x," "\n"' -v output.aac
  8628. return new Uint8Array([0x1, 0x40, 0x22, 0x80, 0xa3, 0x5e, 0xe6, 0x80, 0xba, 0x8, 0x0, 0x0, 0x0, 0x0, 0x95, 0x0, 0x6, 0xf1, 0xa1, 0xa, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5e]);
  8629. }
  8630. }
  8631. return null;
  8632. }
  8633. }]);
  8634. return AAC;
  8635. }();
  8636. exports.default = AAC;
  8637. },{}],37:[function(_dereq_,module,exports){
  8638. 'use strict';
  8639. Object.defineProperty(exports, "__esModule", {
  8640. value: true
  8641. });
  8642. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  8643. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  8644. /*
  8645. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  8646. *
  8647. * This file is derived from dailymotion's hls.js library (hls.js/src/remux/mp4-generator.js)
  8648. * @author zheng qian <xqq@xqq.im>
  8649. *
  8650. * Licensed under the Apache License, Version 2.0 (the "License");
  8651. * you may not use this file except in compliance with the License.
  8652. * You may obtain a copy of the License at
  8653. *
  8654. * http://www.apache.org/licenses/LICENSE-2.0
  8655. *
  8656. * Unless required by applicable law or agreed to in writing, software
  8657. * distributed under the License is distributed on an "AS IS" BASIS,
  8658. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  8659. * See the License for the specific language governing permissions and
  8660. * limitations under the License.
  8661. */
  8662. // MP4 boxes generator for ISO BMFF (ISO Base Media File Format, defined in ISO/IEC 14496-12)
  8663. var MP4 = function () {
  8664. function MP4() {
  8665. _classCallCheck(this, MP4);
  8666. }
  8667. _createClass(MP4, null, [{
  8668. key: 'init',
  8669. value: function init() {
  8670. MP4.types = {
  8671. avc1: [], avcC: [], btrt: [], dinf: [],
  8672. dref: [], esds: [], ftyp: [], hdlr: [],
  8673. mdat: [], mdhd: [], mdia: [], mfhd: [],
  8674. minf: [], moof: [], moov: [], mp4a: [],
  8675. mvex: [], mvhd: [], sdtp: [], stbl: [],
  8676. stco: [], stsc: [], stsd: [], stsz: [],
  8677. stts: [], tfdt: [], tfhd: [], traf: [],
  8678. trak: [], trun: [], trex: [], tkhd: [],
  8679. vmhd: [], smhd: [], '.mp3': []
  8680. };
  8681. for (var name in MP4.types) {
  8682. if (MP4.types.hasOwnProperty(name)) {
  8683. MP4.types[name] = [name.charCodeAt(0), name.charCodeAt(1), name.charCodeAt(2), name.charCodeAt(3)];
  8684. }
  8685. }
  8686. var constants = MP4.constants = {};
  8687. constants.FTYP = new Uint8Array([0x69, 0x73, 0x6F, 0x6D, // major_brand: isom
  8688. 0x0, 0x0, 0x0, 0x1, // minor_version: 0x01
  8689. 0x69, 0x73, 0x6F, 0x6D, // isom
  8690. 0x61, 0x76, 0x63, 0x31 // avc1
  8691. ]);
  8692. constants.STSD_PREFIX = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8693. 0x00, 0x00, 0x00, 0x01 // entry_count
  8694. ]);
  8695. constants.STTS = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8696. 0x00, 0x00, 0x00, 0x00 // entry_count
  8697. ]);
  8698. constants.STSC = constants.STCO = constants.STTS;
  8699. constants.STSZ = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8700. 0x00, 0x00, 0x00, 0x00, // sample_size
  8701. 0x00, 0x00, 0x00, 0x00 // sample_count
  8702. ]);
  8703. constants.HDLR_VIDEO = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8704. 0x00, 0x00, 0x00, 0x00, // pre_defined
  8705. 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'
  8706. 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes
  8707. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x69, 0x64, 0x65, 0x6F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00 // name: VideoHandler
  8708. ]);
  8709. constants.HDLR_AUDIO = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8710. 0x00, 0x00, 0x00, 0x00, // pre_defined
  8711. 0x73, 0x6F, 0x75, 0x6E, // handler_type: 'soun'
  8712. 0x00, 0x00, 0x00, 0x00, // reserved: 3 * 4 bytes
  8713. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x6F, 0x75, 0x6E, 0x64, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00 // name: SoundHandler
  8714. ]);
  8715. constants.DREF = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8716. 0x00, 0x00, 0x00, 0x01, // entry_count
  8717. 0x00, 0x00, 0x00, 0x0C, // entry_size
  8718. 0x75, 0x72, 0x6C, 0x20, // type 'url '
  8719. 0x00, 0x00, 0x00, 0x01 // version(0) + flags
  8720. ]);
  8721. // Sound media header
  8722. constants.SMHD = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8723. 0x00, 0x00, 0x00, 0x00 // balance(2) + reserved(2)
  8724. ]);
  8725. // videoFusion media header
  8726. constants.VMHD = new Uint8Array([0x00, 0x00, 0x00, 0x01, // version(0) + flags
  8727. 0x00, 0x00, // graphicsmode: 2 bytes
  8728. 0x00, 0x00, 0x00, 0x00, // opcolor: 3 * 2 bytes
  8729. 0x00, 0x00]);
  8730. }
  8731. // Generate a box
  8732. }, {
  8733. key: 'box',
  8734. value: function box(type) {
  8735. var size = 8;
  8736. var result = null;
  8737. var datas = Array.prototype.slice.call(arguments, 1);
  8738. var arrayCount = datas.length;
  8739. for (var i = 0; i < arrayCount; i++) {
  8740. size += datas[i].byteLength;
  8741. }
  8742. result = new Uint8Array(size);
  8743. result[0] = size >>> 24 & 0xFF; // size
  8744. result[1] = size >>> 16 & 0xFF;
  8745. result[2] = size >>> 8 & 0xFF;
  8746. result[3] = size & 0xFF;
  8747. result.set(type, 4); // type
  8748. var offset = 8;
  8749. for (var _i = 0; _i < arrayCount; _i++) {
  8750. // data body
  8751. result.set(datas[_i], offset);
  8752. offset += datas[_i].byteLength;
  8753. }
  8754. return result;
  8755. }
  8756. // emit ftyp & moov
  8757. }, {
  8758. key: 'generateInitSegment',
  8759. value: function generateInitSegment(meta) {
  8760. var ftyp = MP4.box(MP4.types.ftyp, MP4.constants.FTYP);
  8761. var moov = MP4.moov(meta);
  8762. var result = new Uint8Array(ftyp.byteLength + moov.byteLength);
  8763. result.set(ftyp, 0);
  8764. result.set(moov, ftyp.byteLength);
  8765. return result;
  8766. }
  8767. // Movie metadata box
  8768. }, {
  8769. key: 'moov',
  8770. value: function moov(meta) {
  8771. var mvhd = MP4.mvhd(meta.timescale, meta.duration);
  8772. var trak = MP4.trak(meta);
  8773. var mvex = MP4.mvex(meta);
  8774. return MP4.box(MP4.types.moov, mvhd, trak, mvex);
  8775. }
  8776. // Movie header box
  8777. }, {
  8778. key: 'mvhd',
  8779. value: function mvhd(timescale, duration) {
  8780. return MP4.box(MP4.types.mvhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8781. 0x00, 0x00, 0x00, 0x00, // creation_time
  8782. 0x00, 0x00, 0x00, 0x00, // modification_time
  8783. timescale >>> 24 & 0xFF, // timescale: 4 bytes
  8784. timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, // duration: 4 bytes
  8785. duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x01, 0x00, 0x00, // Preferred rate: 1.0
  8786. 0x01, 0x00, 0x00, 0x00, // PreferredVolume(1.0, 2bytes) + reserved(2bytes)
  8787. 0x00, 0x00, 0x00, 0x00, // reserved: 4 + 4 bytes
  8788. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix----
  8789. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // ----end composition matrix----
  8790. 0x00, 0x00, 0x00, 0x00, // ----begin pre_defined 6 * 4 bytes----
  8791. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ----end pre_defined 6 * 4 bytes----
  8792. 0xFF, 0xFF, 0xFF, 0xFF // next_track_ID
  8793. ]));
  8794. }
  8795. // Track box
  8796. }, {
  8797. key: 'trak',
  8798. value: function trak(meta) {
  8799. return MP4.box(MP4.types.trak, MP4.tkhd(meta), MP4.mdia(meta));
  8800. }
  8801. // Track header box
  8802. }, {
  8803. key: 'tkhd',
  8804. value: function tkhd(meta) {
  8805. var trackId = meta.id,
  8806. duration = meta.duration;
  8807. var width = meta.presentWidth,
  8808. height = meta.presentHeight;
  8809. return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, 0x00, 0x00, 0x07, // version(0) + flags
  8810. 0x00, 0x00, 0x00, 0x00, // creation_time
  8811. 0x00, 0x00, 0x00, 0x00, // modification_time
  8812. trackId >>> 24 & 0xFF, // track_ID: 4 bytes
  8813. trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
  8814. duration >>> 24 & 0xFF, // duration: 4 bytes
  8815. duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
  8816. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // layer(2bytes) + alternate_group(2bytes)
  8817. 0x00, 0x00, 0x00, 0x00, // volume(2bytes) + reserved(2bytes)
  8818. 0x00, 0x01, 0x00, 0x00, // ----begin composition matrix----
  8819. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // ----end composition matrix----
  8820. width >>> 8 & 0xFF, // width and height
  8821. width & 0xFF, 0x00, 0x00, height >>> 8 & 0xFF, height & 0xFF, 0x00, 0x00]));
  8822. }
  8823. // Media Box
  8824. }, {
  8825. key: 'mdia',
  8826. value: function mdia(meta) {
  8827. return MP4.box(MP4.types.mdia, MP4.mdhd(meta), MP4.hdlr(meta), MP4.minf(meta));
  8828. }
  8829. // Media header box
  8830. }, {
  8831. key: 'mdhd',
  8832. value: function mdhd(meta) {
  8833. var timescale = meta.timescale;
  8834. var duration = meta.duration;
  8835. return MP4.box(MP4.types.mdhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8836. 0x00, 0x00, 0x00, 0x00, // creation_time
  8837. 0x00, 0x00, 0x00, 0x00, // modification_time
  8838. timescale >>> 24 & 0xFF, // timescale: 4 bytes
  8839. timescale >>> 16 & 0xFF, timescale >>> 8 & 0xFF, timescale & 0xFF, duration >>> 24 & 0xFF, // duration: 4 bytes
  8840. duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, 0x55, 0xC4, // language: und (undetermined)
  8841. 0x00, 0x00 // pre_defined = 0
  8842. ]));
  8843. }
  8844. // Media handler reference box
  8845. }, {
  8846. key: 'hdlr',
  8847. value: function hdlr(meta) {
  8848. var data = null;
  8849. if (meta.type === 'audio') {
  8850. data = MP4.constants.HDLR_AUDIO;
  8851. } else {
  8852. data = MP4.constants.HDLR_VIDEO;
  8853. }
  8854. return MP4.box(MP4.types.hdlr, data);
  8855. }
  8856. // Media infomation box
  8857. }, {
  8858. key: 'minf',
  8859. value: function minf(meta) {
  8860. var xmhd = null;
  8861. if (meta.type === 'audio') {
  8862. xmhd = MP4.box(MP4.types.smhd, MP4.constants.SMHD);
  8863. } else {
  8864. xmhd = MP4.box(MP4.types.vmhd, MP4.constants.VMHD);
  8865. }
  8866. return MP4.box(MP4.types.minf, xmhd, MP4.dinf(), MP4.stbl(meta));
  8867. }
  8868. // Data infomation box
  8869. }, {
  8870. key: 'dinf',
  8871. value: function dinf() {
  8872. var result = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, MP4.constants.DREF));
  8873. return result;
  8874. }
  8875. // Sample table box
  8876. }, {
  8877. key: 'stbl',
  8878. value: function stbl(meta) {
  8879. var result = MP4.box(MP4.types.stbl, // type: stbl
  8880. MP4.stsd(meta), // Sample Description Table
  8881. MP4.box(MP4.types.stts, MP4.constants.STTS), // Time-To-Sample
  8882. MP4.box(MP4.types.stsc, MP4.constants.STSC), // Sample-To-Chunk
  8883. MP4.box(MP4.types.stsz, MP4.constants.STSZ), // Sample size
  8884. MP4.box(MP4.types.stco, MP4.constants.STCO // Chunk offset
  8885. ));
  8886. return result;
  8887. }
  8888. // Sample description box
  8889. }, {
  8890. key: 'stsd',
  8891. value: function stsd(meta) {
  8892. if (meta.type === 'audio') {
  8893. if (meta.codec === 'mp3') {
  8894. return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp3(meta));
  8895. }
  8896. // else: aac -> mp4a
  8897. return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.mp4a(meta));
  8898. } else {
  8899. return MP4.box(MP4.types.stsd, MP4.constants.STSD_PREFIX, MP4.avc1(meta));
  8900. }
  8901. }
  8902. }, {
  8903. key: 'mp3',
  8904. value: function mp3(meta) {
  8905. var channelCount = meta.channelCount;
  8906. var sampleRate = meta.audioSampleRate;
  8907. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4)
  8908. 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
  8909. 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
  8910. 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, // channelCount(2)
  8911. 0x00, 0x10, // sampleSize(2)
  8912. 0x00, 0x00, 0x00, 0x00, // reserved(4)
  8913. sampleRate >>> 8 & 0xFF, // Audio sample rate
  8914. sampleRate & 0xFF, 0x00, 0x00]);
  8915. return MP4.box(MP4.types['.mp3'], data);
  8916. }
  8917. }, {
  8918. key: 'mp4a',
  8919. value: function mp4a(meta) {
  8920. var channelCount = meta.channelCount;
  8921. var sampleRate = meta.audioSampleRate;
  8922. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4)
  8923. 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
  8924. 0x00, 0x00, 0x00, 0x00, // reserved: 2 * 4 bytes
  8925. 0x00, 0x00, 0x00, 0x00, 0x00, channelCount, // channelCount(2)
  8926. 0x00, 0x10, // sampleSize(2)
  8927. 0x00, 0x00, 0x00, 0x00, // reserved(4)
  8928. sampleRate >>> 8 & 0xFF, // Audio sample rate
  8929. sampleRate & 0xFF, 0x00, 0x00]);
  8930. return MP4.box(MP4.types.mp4a, data, MP4.esds(meta));
  8931. }
  8932. }, {
  8933. key: 'esds',
  8934. value: function esds(meta) {
  8935. var config = meta.config || [];
  8936. var configSize = config.length;
  8937. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version 0 + flags
  8938. 0x03, // descriptor_type
  8939. 0x17 + configSize, // length3
  8940. 0x00, 0x01, // es_id
  8941. 0x00, // stream_priority
  8942. 0x04, // descriptor_type
  8943. 0x0F + configSize, // length
  8944. 0x40, // codec: mpeg4_audio
  8945. 0x15, // stream_type: Audio
  8946. 0x00, 0x00, 0x00, // buffer_size
  8947. 0x00, 0x00, 0x00, 0x00, // maxBitrate
  8948. 0x00, 0x00, 0x00, 0x00, // avgBitrate
  8949. 0x05 // descriptor_type
  8950. ].concat([configSize]).concat(config).concat([0x06, 0x01, 0x02 // GASpecificConfig
  8951. ]));
  8952. return MP4.box(MP4.types.esds, data);
  8953. }
  8954. }, {
  8955. key: 'avc1',
  8956. value: function avc1(meta) {
  8957. var avcc = meta.avcc;
  8958. var width = meta.codecWidth,
  8959. height = meta.codecHeight;
  8960. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // reserved(4)
  8961. 0x00, 0x00, 0x00, 0x01, // reserved(2) + data_reference_index(2)
  8962. 0x00, 0x00, 0x00, 0x00, // pre_defined(2) + reserved(2)
  8963. 0x00, 0x00, 0x00, 0x00, // pre_defined: 3 * 4 bytes
  8964. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, width >>> 8 & 0xFF, // width: 2 bytes
  8965. width & 0xFF, height >>> 8 & 0xFF, // height: 2 bytes
  8966. height & 0xFF, 0x00, 0x48, 0x00, 0x00, // horizresolution: 4 bytes
  8967. 0x00, 0x48, 0x00, 0x00, // vertresolution: 4 bytes
  8968. 0x00, 0x00, 0x00, 0x00, // reserved: 4 bytes
  8969. 0x00, 0x01, // frame_count
  8970. 0x0A, // strlen
  8971. 0x78, 0x71, 0x71, 0x2F, // compressorname: 32 bytes
  8972. 0x66, 0x6C, 0x76, 0x2E, 0x6A, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, // depth
  8973. 0xFF, 0xFF // pre_defined = -1
  8974. ]);
  8975. return MP4.box(MP4.types.avc1, data, MP4.box(MP4.types.avcC, avcc));
  8976. }
  8977. // Movie Extends box
  8978. }, {
  8979. key: 'mvex',
  8980. value: function mvex(meta) {
  8981. return MP4.box(MP4.types.mvex, MP4.trex(meta));
  8982. }
  8983. // Track Extends box
  8984. }, {
  8985. key: 'trex',
  8986. value: function trex(meta) {
  8987. var trackId = meta.id;
  8988. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) + flags
  8989. trackId >>> 24 & 0xFF, // track_ID
  8990. trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF, 0x00, 0x00, 0x00, 0x01, // default_sample_description_index
  8991. 0x00, 0x00, 0x00, 0x00, // default_sample_duration
  8992. 0x00, 0x00, 0x00, 0x00, // default_sample_size
  8993. 0x00, 0x01, 0x00, 0x01 // default_sample_flags
  8994. ]);
  8995. return MP4.box(MP4.types.trex, data);
  8996. }
  8997. // Movie fragment box
  8998. }, {
  8999. key: 'moof',
  9000. value: function moof(track, baseMediaDecodeTime) {
  9001. return MP4.box(MP4.types.moof, MP4.mfhd(track.sequenceNumber), MP4.traf(track, baseMediaDecodeTime));
  9002. }
  9003. }, {
  9004. key: 'mfhd',
  9005. value: function mfhd(sequenceNumber) {
  9006. var data = new Uint8Array([0x00, 0x00, 0x00, 0x00, sequenceNumber >>> 24 & 0xFF, // sequence_number: int32
  9007. sequenceNumber >>> 16 & 0xFF, sequenceNumber >>> 8 & 0xFF, sequenceNumber & 0xFF]);
  9008. return MP4.box(MP4.types.mfhd, data);
  9009. }
  9010. // Track fragment box
  9011. }, {
  9012. key: 'traf',
  9013. value: function traf(track, baseMediaDecodeTime) {
  9014. var trackId = track.id;
  9015. // Track fragment header box
  9016. var tfhd = MP4.box(MP4.types.tfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) & flags
  9017. trackId >>> 24 & 0xFF, // track_ID
  9018. trackId >>> 16 & 0xFF, trackId >>> 8 & 0xFF, trackId & 0xFF]));
  9019. // Track Fragment Decode Time
  9020. var tfdt = MP4.box(MP4.types.tfdt, new Uint8Array([0x00, 0x00, 0x00, 0x00, // version(0) & flags
  9021. baseMediaDecodeTime >>> 24 & 0xFF, // baseMediaDecodeTime: int32
  9022. baseMediaDecodeTime >>> 16 & 0xFF, baseMediaDecodeTime >>> 8 & 0xFF, baseMediaDecodeTime & 0xFF]));
  9023. var sdtp = MP4.sdtp(track);
  9024. var trun = MP4.trun(track, sdtp.byteLength + 16 + 16 + 8 + 16 + 8 + 8);
  9025. return MP4.box(MP4.types.traf, tfhd, tfdt, trun, sdtp);
  9026. }
  9027. // Sample Dependency Type box
  9028. }, {
  9029. key: 'sdtp',
  9030. value: function sdtp(track) {
  9031. var samples = track.samples || [];
  9032. var sampleCount = samples.length;
  9033. var data = new Uint8Array(4 + sampleCount);
  9034. // 0~4 bytes: version(0) & flags
  9035. for (var i = 0; i < sampleCount; i++) {
  9036. var flags = samples[i].flags;
  9037. data[i + 4] = flags.isLeading << 6 | // is_leading: 2 (bit)
  9038. flags.dependsOn << 4 // sample_depends_on
  9039. | flags.isDependedOn << 2 // sample_is_depended_on
  9040. | flags.hasRedundancy; // sample_has_redundancy
  9041. }
  9042. return MP4.box(MP4.types.sdtp, data);
  9043. }
  9044. // Track fragment run box
  9045. }, {
  9046. key: 'trun',
  9047. value: function trun(track, offset) {
  9048. var samples = track.samples || [];
  9049. var sampleCount = samples.length;
  9050. var dataSize = 12 + 16 * sampleCount;
  9051. var data = new Uint8Array(dataSize);
  9052. offset += 8 + dataSize;
  9053. data.set([0x00, 0x00, 0x0F, 0x01, // version(0) & flags
  9054. sampleCount >>> 24 & 0xFF, // sample_count
  9055. sampleCount >>> 16 & 0xFF, sampleCount >>> 8 & 0xFF, sampleCount & 0xFF, offset >>> 24 & 0xFF, // data_offset
  9056. offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF], 0);
  9057. for (var i = 0; i < sampleCount; i++) {
  9058. var duration = samples[i].duration;
  9059. var size = samples[i].size;
  9060. var flags = samples[i].flags;
  9061. var cts = samples[i].cts;
  9062. data.set([duration >>> 24 & 0xFF, // sample_duration
  9063. duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, size >>> 24 & 0xFF, // sample_size
  9064. size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, flags.isLeading << 2 | flags.dependsOn, // sample_flags
  9065. flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.isNonSync, 0x00, 0x00, // sample_degradation_priority
  9066. cts >>> 24 & 0xFF, // sample_composition_time_offset
  9067. cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF], 12 + 16 * i);
  9068. }
  9069. return MP4.box(MP4.types.trun, data);
  9070. }
  9071. }, {
  9072. key: 'mdat',
  9073. value: function mdat(data) {
  9074. return MP4.box(MP4.types.mdat, data);
  9075. }
  9076. }]);
  9077. return MP4;
  9078. }();
  9079. MP4.init();
  9080. exports.default = MP4;
  9081. },{}],38:[function(_dereq_,module,exports){
  9082. 'use strict';
  9083. Object.defineProperty(exports, "__esModule", {
  9084. value: true
  9085. });
  9086. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  9087. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  9088. *
  9089. * @author zheng qian <xqq@xqq.im>
  9090. *
  9091. * Licensed under the Apache License, Version 2.0 (the "License");
  9092. * you may not use this file except in compliance with the License.
  9093. * You may obtain a copy of the License at
  9094. *
  9095. * http://www.apache.org/licenses/LICENSE-2.0
  9096. *
  9097. * Unless required by applicable law or agreed to in writing, software
  9098. * distributed under the License is distributed on an "AS IS" BASIS,
  9099. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9100. * See the License for the specific language governing permissions and
  9101. * limitations under the License.
  9102. */
  9103. var _logger = _dereq_('../utils/logger.js');
  9104. var _logger2 = _interopRequireDefault(_logger);
  9105. var _mp4Generator = _dereq_('./mp4-generator.js');
  9106. var _mp4Generator2 = _interopRequireDefault(_mp4Generator);
  9107. var _aacSilent = _dereq_('./aac-silent.js');
  9108. var _aacSilent2 = _interopRequireDefault(_aacSilent);
  9109. var _browser = _dereq_('../utils/browser.js');
  9110. var _browser2 = _interopRequireDefault(_browser);
  9111. var _mediaSegmentInfo = _dereq_('../core/media-segment-info.js');
  9112. var _exception = _dereq_('../utils/exception.js');
  9113. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  9114. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  9115. // Fragmented mp4 remuxer
  9116. var MP4Remuxer = function () {
  9117. function MP4Remuxer(config) {
  9118. _classCallCheck(this, MP4Remuxer);
  9119. this.TAG = 'MP4Remuxer';
  9120. this._config = config;
  9121. this._isLive = config.isLive === true ? true : false;
  9122. this._dtsBase = -1;
  9123. this._dtsBaseInited = false;
  9124. this._audioDtsBase = Infinity;
  9125. this._videoDtsBase = Infinity;
  9126. this._audioNextDts = undefined;
  9127. this._videoNextDts = undefined;
  9128. this._audioStashedLastSample = null;
  9129. this._videoStashedLastSample = null;
  9130. this._audioMeta = null;
  9131. this._videoMeta = null;
  9132. this._audioSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('audio');
  9133. this._videoSegmentInfoList = new _mediaSegmentInfo.MediaSegmentInfoList('video');
  9134. this._onInitSegment = null;
  9135. this._onMediaSegment = null;
  9136. // Workaround for chrome < 50: Always force first sample as a Random Access Point in media segment
  9137. // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412
  9138. this._forceFirstIDR = _browser2.default.chrome && (_browser2.default.version.major < 50 || _browser2.default.version.major === 50 && _browser2.default.version.build < 2661) ? true : false;
  9139. // Workaround for IE11/Edge: Fill silent aac frame after keyframe-seeking
  9140. // Make audio beginDts equals with videoFusion beginDts, in order to fix seek freeze
  9141. this._fillSilentAfterSeek = _browser2.default.msedge || _browser2.default.msie;
  9142. // While only FireFox supports 'audio/mp4, codecs="mp3"', use 'audio/mpeg' for chrome, safari, ...
  9143. this._mp3UseMpegAudio = !_browser2.default.firefox;
  9144. this._fillAudioTimestampGap = this._config.fixAudioTimestampGap;
  9145. }
  9146. _createClass(MP4Remuxer, [{
  9147. key: 'destroy',
  9148. value: function destroy() {
  9149. this._dtsBase = -1;
  9150. this._dtsBaseInited = false;
  9151. this._audioMeta = null;
  9152. this._videoMeta = null;
  9153. this._audioSegmentInfoList.clear();
  9154. this._audioSegmentInfoList = null;
  9155. this._videoSegmentInfoList.clear();
  9156. this._videoSegmentInfoList = null;
  9157. this._onInitSegment = null;
  9158. this._onMediaSegment = null;
  9159. }
  9160. }, {
  9161. key: 'bindDataSource',
  9162. value: function bindDataSource(producer) {
  9163. producer.onDataAvailable = this.remux.bind(this);
  9164. producer.onTrackMetadata = this._onTrackMetadataReceived.bind(this);
  9165. return this;
  9166. }
  9167. /* prototype: function onInitSegment(type: string, initSegment: ArrayBuffer): void
  9168. InitSegment: {
  9169. type: string,
  9170. data: ArrayBuffer,
  9171. codec: string,
  9172. container: string
  9173. }
  9174. */
  9175. }, {
  9176. key: 'insertDiscontinuity',
  9177. value: function insertDiscontinuity() {
  9178. this._audioNextDts = this._videoNextDts = undefined;
  9179. }
  9180. }, {
  9181. key: 'seek',
  9182. value: function seek(originalDts) {
  9183. this._audioStashedLastSample = null;
  9184. this._videoStashedLastSample = null;
  9185. this._videoSegmentInfoList.clear();
  9186. this._audioSegmentInfoList.clear();
  9187. }
  9188. }, {
  9189. key: 'remux',
  9190. value: function remux(audioTrack, videoTrack) {
  9191. if (!this._onMediaSegment) {
  9192. throw new _exception.IllegalStateException('MP4Remuxer: onMediaSegment callback must be specificed!');
  9193. }
  9194. if (!this._dtsBaseInited) {
  9195. this._calculateDtsBase(audioTrack, videoTrack);
  9196. }
  9197. this._remuxVideo(videoTrack);
  9198. this._remuxAudio(audioTrack);
  9199. }
  9200. }, {
  9201. key: '_onTrackMetadataReceived',
  9202. value: function _onTrackMetadataReceived(type, metadata) {
  9203. var metabox = null;
  9204. var container = 'mp4';
  9205. var codec = metadata.codec;
  9206. if (type === 'audio') {
  9207. this._audioMeta = metadata;
  9208. if (metadata.codec === 'mp3' && this._mp3UseMpegAudio) {
  9209. // 'audio/mpeg' for MP3 audio track
  9210. container = 'mpeg';
  9211. codec = '';
  9212. metabox = new Uint8Array();
  9213. } else {
  9214. // 'audio/mp4, codecs="codec"'
  9215. metabox = _mp4Generator2.default.generateInitSegment(metadata);
  9216. }
  9217. } else if (type === 'video') {
  9218. this._videoMeta = metadata;
  9219. metabox = _mp4Generator2.default.generateInitSegment(metadata);
  9220. } else {
  9221. return;
  9222. }
  9223. // dispatch metabox (Initialization Segment)
  9224. if (!this._onInitSegment) {
  9225. throw new _exception.IllegalStateException('MP4Remuxer: onInitSegment callback must be specified!');
  9226. }
  9227. this._onInitSegment(type, {
  9228. type: type,
  9229. data: metabox.buffer,
  9230. codec: codec,
  9231. container: type + '/' + container,
  9232. mediaDuration: metadata.duration // in timescale 1000 (milliseconds)
  9233. });
  9234. }
  9235. }, {
  9236. key: '_calculateDtsBase',
  9237. value: function _calculateDtsBase(audioTrack, videoTrack) {
  9238. if (this._dtsBaseInited) {
  9239. return;
  9240. }
  9241. if (audioTrack.samples && audioTrack.samples.length) {
  9242. this._audioDtsBase = audioTrack.samples[0].dts;
  9243. }
  9244. if (videoTrack.samples && videoTrack.samples.length) {
  9245. this._videoDtsBase = videoTrack.samples[0].dts;
  9246. }
  9247. this._dtsBase = Math.min(this._audioDtsBase, this._videoDtsBase);
  9248. this._dtsBaseInited = true;
  9249. }
  9250. }, {
  9251. key: 'flushStashedSamples',
  9252. value: function flushStashedSamples() {
  9253. var videoSample = this._videoStashedLastSample;
  9254. var audioSample = this._audioStashedLastSample;
  9255. var videoTrack = {
  9256. type: 'video',
  9257. id: 1,
  9258. sequenceNumber: 0,
  9259. samples: [],
  9260. length: 0
  9261. };
  9262. if (videoSample != null) {
  9263. videoTrack.samples.push(videoSample);
  9264. videoTrack.length = videoSample.length;
  9265. }
  9266. var audioTrack = {
  9267. type: 'audio',
  9268. id: 2,
  9269. sequenceNumber: 0,
  9270. samples: [],
  9271. length: 0
  9272. };
  9273. if (audioSample != null) {
  9274. audioTrack.samples.push(audioSample);
  9275. audioTrack.length = audioSample.length;
  9276. }
  9277. this._videoStashedLastSample = null;
  9278. this._audioStashedLastSample = null;
  9279. this._remuxVideo(videoTrack, true);
  9280. this._remuxAudio(audioTrack, true);
  9281. }
  9282. }, {
  9283. key: '_remuxAudio',
  9284. value: function _remuxAudio(audioTrack, force) {
  9285. if (this._audioMeta == null) {
  9286. return;
  9287. }
  9288. var track = audioTrack;
  9289. var samples = track.samples;
  9290. var dtsCorrection = undefined;
  9291. var firstDts = -1,
  9292. lastDts = -1,
  9293. lastPts = -1;
  9294. var refSampleDuration = this._audioMeta.refSampleDuration;
  9295. var mpegRawTrack = this._audioMeta.codec === 'mp3' && this._mp3UseMpegAudio;
  9296. var firstSegmentAfterSeek = this._dtsBaseInited && this._audioNextDts === undefined;
  9297. var insertPrefixSilentFrame = false;
  9298. if (!samples || samples.length === 0) {
  9299. return;
  9300. }
  9301. if (samples.length === 1 && !force) {
  9302. // If [sample count in current batch] === 1 && (force != true)
  9303. // Ignore and keep in demuxer's queue
  9304. return;
  9305. } // else if (force === true) do remux
  9306. var offset = 0;
  9307. var mdatbox = null;
  9308. var mdatBytes = 0;
  9309. // calculate initial mdat size
  9310. if (mpegRawTrack) {
  9311. // for raw mpeg buffer
  9312. offset = 0;
  9313. mdatBytes = track.length;
  9314. } else {
  9315. // for fmp4 mdat box
  9316. offset = 8; // size + type
  9317. mdatBytes = 8 + track.length;
  9318. }
  9319. var lastSample = null;
  9320. // Pop the lastSample and waiting for stash
  9321. if (samples.length > 1) {
  9322. lastSample = samples.pop();
  9323. mdatBytes -= lastSample.length;
  9324. }
  9325. // Insert [stashed lastSample in the previous batch] to the front
  9326. if (this._audioStashedLastSample != null) {
  9327. var sample = this._audioStashedLastSample;
  9328. this._audioStashedLastSample = null;
  9329. samples.unshift(sample);
  9330. mdatBytes += sample.length;
  9331. }
  9332. // Stash the lastSample of current batch, waiting for next batch
  9333. if (lastSample != null) {
  9334. this._audioStashedLastSample = lastSample;
  9335. }
  9336. var firstSampleOriginalDts = samples[0].dts - this._dtsBase;
  9337. // calculate dtsCorrection
  9338. if (this._audioNextDts) {
  9339. dtsCorrection = firstSampleOriginalDts - this._audioNextDts;
  9340. } else {
  9341. // this._audioNextDts == undefined
  9342. if (this._audioSegmentInfoList.isEmpty()) {
  9343. dtsCorrection = 0;
  9344. if (this._fillSilentAfterSeek && !this._videoSegmentInfoList.isEmpty()) {
  9345. if (this._audioMeta.originalCodec !== 'mp3') {
  9346. insertPrefixSilentFrame = true;
  9347. }
  9348. }
  9349. } else {
  9350. var _lastSample = this._audioSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts);
  9351. if (_lastSample != null) {
  9352. var distance = firstSampleOriginalDts - (_lastSample.originalDts + _lastSample.duration);
  9353. if (distance <= 3) {
  9354. distance = 0;
  9355. }
  9356. var expectedDts = _lastSample.dts + _lastSample.duration + distance;
  9357. dtsCorrection = firstSampleOriginalDts - expectedDts;
  9358. } else {
  9359. // lastSample == null, cannot found
  9360. dtsCorrection = 0;
  9361. }
  9362. }
  9363. }
  9364. if (insertPrefixSilentFrame) {
  9365. // align audio segment beginDts to match with current videoFusion segment's beginDts
  9366. var firstSampleDts = firstSampleOriginalDts - dtsCorrection;
  9367. var videoSegment = this._videoSegmentInfoList.getLastSegmentBefore(firstSampleOriginalDts);
  9368. if (videoSegment != null && videoSegment.beginDts < firstSampleDts) {
  9369. var silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount);
  9370. if (silentUnit) {
  9371. var dts = videoSegment.beginDts;
  9372. var silentFrameDuration = firstSampleDts - videoSegment.beginDts;
  9373. _logger2.default.v(this.TAG, 'InsertPrefixSilentAudio: dts: ' + dts + ', duration: ' + silentFrameDuration);
  9374. samples.unshift({ unit: silentUnit, dts: dts, pts: dts });
  9375. mdatBytes += silentUnit.byteLength;
  9376. } // silentUnit == null: Cannot generate, skip
  9377. } else {
  9378. insertPrefixSilentFrame = false;
  9379. }
  9380. }
  9381. var mp4Samples = [];
  9382. // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples
  9383. for (var i = 0; i < samples.length; i++) {
  9384. var _sample = samples[i];
  9385. var unit = _sample.unit;
  9386. var originalDts = _sample.dts - this._dtsBase;
  9387. var _dts = originalDts - dtsCorrection;
  9388. if (firstDts === -1) {
  9389. firstDts = _dts;
  9390. }
  9391. var sampleDuration = 0;
  9392. if (i !== samples.length - 1) {
  9393. var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection;
  9394. sampleDuration = nextDts - _dts;
  9395. } else {
  9396. // the last sample
  9397. if (lastSample != null) {
  9398. // use stashed sample's dts to calculate sample duration
  9399. var _nextDts = lastSample.dts - this._dtsBase - dtsCorrection;
  9400. sampleDuration = _nextDts - _dts;
  9401. } else if (mp4Samples.length >= 1) {
  9402. // use second last sample duration
  9403. sampleDuration = mp4Samples[mp4Samples.length - 1].duration;
  9404. } else {
  9405. // the only one sample, use reference sample duration
  9406. sampleDuration = Math.floor(refSampleDuration);
  9407. }
  9408. }
  9409. var needFillSilentFrames = false;
  9410. var silentFrames = null;
  9411. // Silent frame generation, if large timestamp gap detected && config.fixAudioTimestampGap
  9412. if (sampleDuration > refSampleDuration * 1.5 && this._audioMeta.codec !== 'mp3' && this._fillAudioTimestampGap && !_browser2.default.safari) {
  9413. // We need to insert silent frames to fill timestamp gap
  9414. needFillSilentFrames = true;
  9415. var delta = Math.abs(sampleDuration - refSampleDuration);
  9416. var frameCount = Math.ceil(delta / refSampleDuration);
  9417. var currentDts = _dts + refSampleDuration; // Notice: in float
  9418. _logger2.default.w(this.TAG, 'Large audio timestamp gap detected, may cause AV sync to drift. ' + 'Silent frames will be generated to avoid unsync.\n' + ('dts: ' + (_dts + sampleDuration) + ' ms, expected: ' + (_dts + Math.round(refSampleDuration)) + ' ms, ') + ('delta: ' + Math.round(delta) + ' ms, generate: ' + frameCount + ' frames'));
  9419. var _silentUnit = _aacSilent2.default.getSilentFrame(this._audioMeta.originalCodec, this._audioMeta.channelCount);
  9420. if (_silentUnit == null) {
  9421. _logger2.default.w(this.TAG, 'Unable to generate silent frame for ' + (this._audioMeta.originalCodec + ' with ' + this._audioMeta.channelCount + ' channels, repeat last frame'));
  9422. // Repeat last frame
  9423. _silentUnit = unit;
  9424. }
  9425. silentFrames = [];
  9426. for (var j = 0; j < frameCount; j++) {
  9427. var intDts = Math.round(currentDts); // round to integer
  9428. if (silentFrames.length > 0) {
  9429. // Set previous frame sample duration
  9430. var previousFrame = silentFrames[silentFrames.length - 1];
  9431. previousFrame.duration = intDts - previousFrame.dts;
  9432. }
  9433. var frame = {
  9434. dts: intDts,
  9435. pts: intDts,
  9436. cts: 0,
  9437. unit: _silentUnit,
  9438. size: _silentUnit.byteLength,
  9439. duration: 0, // wait for next sample
  9440. originalDts: originalDts,
  9441. flags: {
  9442. isLeading: 0,
  9443. dependsOn: 1,
  9444. isDependedOn: 0,
  9445. hasRedundancy: 0
  9446. }
  9447. };
  9448. silentFrames.push(frame);
  9449. mdatBytes += frame.size;
  9450. currentDts += refSampleDuration;
  9451. }
  9452. // last frame: align end time to next frame dts
  9453. var lastFrame = silentFrames[silentFrames.length - 1];
  9454. lastFrame.duration = _dts + sampleDuration - lastFrame.dts;
  9455. // silentFrames.forEach((frame) => {
  9456. // Log.w(this.TAG, `SilentAudio: dts: ${frame.dts}, duration: ${frame.duration}`);
  9457. // });
  9458. // Set correct sample duration for current frame
  9459. sampleDuration = Math.round(refSampleDuration);
  9460. }
  9461. mp4Samples.push({
  9462. dts: _dts,
  9463. pts: _dts,
  9464. cts: 0,
  9465. unit: _sample.unit,
  9466. size: _sample.unit.byteLength,
  9467. duration: sampleDuration,
  9468. originalDts: originalDts,
  9469. flags: {
  9470. isLeading: 0,
  9471. dependsOn: 1,
  9472. isDependedOn: 0,
  9473. hasRedundancy: 0
  9474. }
  9475. });
  9476. if (needFillSilentFrames) {
  9477. // Silent frames should be inserted after wrong-duration frame
  9478. mp4Samples.push.apply(mp4Samples, silentFrames);
  9479. }
  9480. }
  9481. // allocate mdatbox
  9482. if (mpegRawTrack) {
  9483. // allocate for raw mpeg buffer
  9484. mdatbox = new Uint8Array(mdatBytes);
  9485. } else {
  9486. // allocate for fmp4 mdat box
  9487. mdatbox = new Uint8Array(mdatBytes);
  9488. // size field
  9489. mdatbox[0] = mdatBytes >>> 24 & 0xFF;
  9490. mdatbox[1] = mdatBytes >>> 16 & 0xFF;
  9491. mdatbox[2] = mdatBytes >>> 8 & 0xFF;
  9492. mdatbox[3] = mdatBytes & 0xFF;
  9493. // type field (fourCC)
  9494. mdatbox.set(_mp4Generator2.default.types.mdat, 4);
  9495. }
  9496. // Write samples into mdatbox
  9497. for (var _i = 0; _i < mp4Samples.length; _i++) {
  9498. var _unit = mp4Samples[_i].unit;
  9499. mdatbox.set(_unit, offset);
  9500. offset += _unit.byteLength;
  9501. }
  9502. var latest = mp4Samples[mp4Samples.length - 1];
  9503. lastDts = latest.dts + latest.duration;
  9504. this._audioNextDts = lastDts;
  9505. // fill media segment info & add to info list
  9506. var info = new _mediaSegmentInfo.MediaSegmentInfo();
  9507. info.beginDts = firstDts;
  9508. info.endDts = lastDts;
  9509. info.beginPts = firstDts;
  9510. info.endPts = lastDts;
  9511. info.originalBeginDts = mp4Samples[0].originalDts;
  9512. info.originalEndDts = latest.originalDts + latest.duration;
  9513. info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, false);
  9514. info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, false);
  9515. if (!this._isLive) {
  9516. this._audioSegmentInfoList.append(info);
  9517. }
  9518. track.samples = mp4Samples;
  9519. track.sequenceNumber++;
  9520. var moofbox = null;
  9521. if (mpegRawTrack) {
  9522. // Generate empty buffer, because useless for raw mpeg
  9523. moofbox = new Uint8Array();
  9524. } else {
  9525. // Generate moof for fmp4 segment
  9526. moofbox = _mp4Generator2.default.moof(track, firstDts);
  9527. }
  9528. track.samples = [];
  9529. track.length = 0;
  9530. var segment = {
  9531. type: 'audio',
  9532. data: this._mergeBoxes(moofbox, mdatbox).buffer,
  9533. sampleCount: mp4Samples.length,
  9534. info: info
  9535. };
  9536. if (mpegRawTrack && firstSegmentAfterSeek) {
  9537. // For MPEG audio stream in MSE, if seeking occurred, before appending new buffer
  9538. // We need explicitly set timestampOffset to the desired point in timeline for mpeg SourceBuffer.
  9539. segment.timestampOffset = firstDts;
  9540. }
  9541. this._onMediaSegment('audio', segment);
  9542. }
  9543. }, {
  9544. key: '_remuxVideo',
  9545. value: function _remuxVideo(videoTrack, force) {
  9546. if (this._videoMeta == null) {
  9547. return;
  9548. }
  9549. var track = videoTrack;
  9550. var samples = track.samples;
  9551. var dtsCorrection = undefined;
  9552. var firstDts = -1,
  9553. lastDts = -1;
  9554. var firstPts = -1,
  9555. lastPts = -1;
  9556. if (!samples || samples.length === 0) {
  9557. return;
  9558. }
  9559. if (samples.length === 1 && !force) {
  9560. // If [sample count in current batch] === 1 && (force != true)
  9561. // Ignore and keep in demuxer's queue
  9562. return;
  9563. } // else if (force === true) do remux
  9564. var offset = 8;
  9565. var mdatbox = null;
  9566. var mdatBytes = 8 + videoTrack.length;
  9567. var lastSample = null;
  9568. // Pop the lastSample and waiting for stash
  9569. if (samples.length > 1) {
  9570. lastSample = samples.pop();
  9571. mdatBytes -= lastSample.length;
  9572. }
  9573. // Insert [stashed lastSample in the previous batch] to the front
  9574. if (this._videoStashedLastSample != null) {
  9575. var sample = this._videoStashedLastSample;
  9576. this._videoStashedLastSample = null;
  9577. samples.unshift(sample);
  9578. mdatBytes += sample.length;
  9579. }
  9580. // Stash the lastSample of current batch, waiting for next batch
  9581. if (lastSample != null) {
  9582. this._videoStashedLastSample = lastSample;
  9583. }
  9584. var firstSampleOriginalDts = samples[0].dts - this._dtsBase;
  9585. // calculate dtsCorrection
  9586. if (this._videoNextDts) {
  9587. dtsCorrection = firstSampleOriginalDts - this._videoNextDts;
  9588. } else {
  9589. // this._videoNextDts == undefined
  9590. if (this._videoSegmentInfoList.isEmpty()) {
  9591. dtsCorrection = 0;
  9592. } else {
  9593. var _lastSample2 = this._videoSegmentInfoList.getLastSampleBefore(firstSampleOriginalDts);
  9594. if (_lastSample2 != null) {
  9595. var distance = firstSampleOriginalDts - (_lastSample2.originalDts + _lastSample2.duration);
  9596. if (distance <= 3) {
  9597. distance = 0;
  9598. }
  9599. var expectedDts = _lastSample2.dts + _lastSample2.duration + distance;
  9600. dtsCorrection = firstSampleOriginalDts - expectedDts;
  9601. } else {
  9602. // lastSample == null, cannot found
  9603. dtsCorrection = 0;
  9604. }
  9605. }
  9606. }
  9607. var info = new _mediaSegmentInfo.MediaSegmentInfo();
  9608. var mp4Samples = [];
  9609. // Correct dts for each sample, and calculate sample duration. Then output to mp4Samples
  9610. for (var i = 0; i < samples.length; i++) {
  9611. var _sample2 = samples[i];
  9612. var originalDts = _sample2.dts - this._dtsBase;
  9613. var isKeyframe = _sample2.isKeyframe;
  9614. var dts = originalDts - dtsCorrection;
  9615. var cts = _sample2.cts;
  9616. var pts = dts + cts;
  9617. if (firstDts === -1) {
  9618. firstDts = dts;
  9619. firstPts = pts;
  9620. }
  9621. var sampleDuration = 0;
  9622. if (i !== samples.length - 1) {
  9623. var nextDts = samples[i + 1].dts - this._dtsBase - dtsCorrection;
  9624. sampleDuration = nextDts - dts;
  9625. } else {
  9626. // the last sample
  9627. if (lastSample != null) {
  9628. // use stashed sample's dts to calculate sample duration
  9629. var _nextDts2 = lastSample.dts - this._dtsBase - dtsCorrection;
  9630. sampleDuration = _nextDts2 - dts;
  9631. } else if (mp4Samples.length >= 1) {
  9632. // use second last sample duration
  9633. sampleDuration = mp4Samples[mp4Samples.length - 1].duration;
  9634. } else {
  9635. // the only one sample, use reference sample duration
  9636. sampleDuration = Math.floor(this._videoMeta.refSampleDuration);
  9637. }
  9638. }
  9639. if (isKeyframe) {
  9640. var syncPoint = new _mediaSegmentInfo.SampleInfo(dts, pts, sampleDuration, _sample2.dts, true);
  9641. syncPoint.fileposition = _sample2.fileposition;
  9642. info.appendSyncPoint(syncPoint);
  9643. }
  9644. mp4Samples.push({
  9645. dts: dts,
  9646. pts: pts,
  9647. cts: cts,
  9648. units: _sample2.units,
  9649. size: _sample2.length,
  9650. isKeyframe: isKeyframe,
  9651. duration: sampleDuration,
  9652. originalDts: originalDts,
  9653. flags: {
  9654. isLeading: 0,
  9655. dependsOn: isKeyframe ? 2 : 1,
  9656. isDependedOn: isKeyframe ? 1 : 0,
  9657. hasRedundancy: 0,
  9658. isNonSync: isKeyframe ? 0 : 1
  9659. }
  9660. });
  9661. }
  9662. // allocate mdatbox
  9663. mdatbox = new Uint8Array(mdatBytes);
  9664. mdatbox[0] = mdatBytes >>> 24 & 0xFF;
  9665. mdatbox[1] = mdatBytes >>> 16 & 0xFF;
  9666. mdatbox[2] = mdatBytes >>> 8 & 0xFF;
  9667. mdatbox[3] = mdatBytes & 0xFF;
  9668. mdatbox.set(_mp4Generator2.default.types.mdat, 4);
  9669. // Write samples into mdatbox
  9670. for (var _i2 = 0; _i2 < mp4Samples.length; _i2++) {
  9671. var units = mp4Samples[_i2].units;
  9672. while (units.length) {
  9673. var unit = units.shift();
  9674. var data = unit.data;
  9675. mdatbox.set(data, offset);
  9676. offset += data.byteLength;
  9677. }
  9678. }
  9679. var latest = mp4Samples[mp4Samples.length - 1];
  9680. lastDts = latest.dts + latest.duration;
  9681. lastPts = latest.pts + latest.duration;
  9682. this._videoNextDts = lastDts;
  9683. // fill media segment info & add to info list
  9684. info.beginDts = firstDts;
  9685. info.endDts = lastDts;
  9686. info.beginPts = firstPts;
  9687. info.endPts = lastPts;
  9688. info.originalBeginDts = mp4Samples[0].originalDts;
  9689. info.originalEndDts = latest.originalDts + latest.duration;
  9690. info.firstSample = new _mediaSegmentInfo.SampleInfo(mp4Samples[0].dts, mp4Samples[0].pts, mp4Samples[0].duration, mp4Samples[0].originalDts, mp4Samples[0].isKeyframe);
  9691. info.lastSample = new _mediaSegmentInfo.SampleInfo(latest.dts, latest.pts, latest.duration, latest.originalDts, latest.isKeyframe);
  9692. if (!this._isLive) {
  9693. this._videoSegmentInfoList.append(info);
  9694. }
  9695. track.samples = mp4Samples;
  9696. track.sequenceNumber++;
  9697. // workaround for chrome < 50: force first sample as a random access point
  9698. // see https://bugs.chromium.org/p/chromium/issues/detail?id=229412
  9699. if (this._forceFirstIDR) {
  9700. var flags = mp4Samples[0].flags;
  9701. flags.dependsOn = 2;
  9702. flags.isNonSync = 0;
  9703. }
  9704. var moofbox = _mp4Generator2.default.moof(track, firstDts);
  9705. track.samples = [];
  9706. track.length = 0;
  9707. this._onMediaSegment('video', {
  9708. type: 'video',
  9709. data: this._mergeBoxes(moofbox, mdatbox).buffer,
  9710. sampleCount: mp4Samples.length,
  9711. info: info
  9712. });
  9713. }
  9714. }, {
  9715. key: '_mergeBoxes',
  9716. value: function _mergeBoxes(moof, mdat) {
  9717. var result = new Uint8Array(moof.byteLength + mdat.byteLength);
  9718. result.set(moof, 0);
  9719. result.set(mdat, moof.byteLength);
  9720. return result;
  9721. }
  9722. }, {
  9723. key: 'onInitSegment',
  9724. get: function get() {
  9725. return this._onInitSegment;
  9726. },
  9727. set: function set(callback) {
  9728. this._onInitSegment = callback;
  9729. }
  9730. /* prototype: function onMediaSegment(type: string, mediaSegment: MediaSegment): void
  9731. MediaSegment: {
  9732. type: string,
  9733. data: ArrayBuffer,
  9734. sampleCount: int32
  9735. info: MediaSegmentInfo
  9736. }
  9737. */
  9738. }, {
  9739. key: 'onMediaSegment',
  9740. get: function get() {
  9741. return this._onMediaSegment;
  9742. },
  9743. set: function set(callback) {
  9744. this._onMediaSegment = callback;
  9745. }
  9746. }]);
  9747. return MP4Remuxer;
  9748. }();
  9749. exports.default = MP4Remuxer;
  9750. },{"../core/media-segment-info.js":8,"../utils/browser.js":39,"../utils/exception.js":40,"../utils/logger.js":41,"./aac-silent.js":36,"./mp4-generator.js":37}],39:[function(_dereq_,module,exports){
  9751. 'use strict';
  9752. Object.defineProperty(exports, "__esModule", {
  9753. value: true
  9754. });
  9755. /*
  9756. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  9757. *
  9758. * @author zheng qian <xqq@xqq.im>
  9759. *
  9760. * Licensed under the Apache License, Version 2.0 (the "License");
  9761. * you may not use this file except in compliance with the License.
  9762. * You may obtain a copy of the License at
  9763. *
  9764. * http://www.apache.org/licenses/LICENSE-2.0
  9765. *
  9766. * Unless required by applicable law or agreed to in writing, software
  9767. * distributed under the License is distributed on an "AS IS" BASIS,
  9768. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9769. * See the License for the specific language governing permissions and
  9770. * limitations under the License.
  9771. */
  9772. var Browser = {};
  9773. function detect() {
  9774. // modified from jquery-browser-plugin
  9775. var ua = self.navigator.userAgent.toLowerCase();
  9776. var match = /(edge)\/([\w.]+)/.exec(ua) || /(opr)[\/]([\w.]+)/.exec(ua) || /(chrome)[ \/]([\w.]+)/.exec(ua) || /(iemobile)[\/]([\w.]+)/.exec(ua) || /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(ua) || /(webkit)[ \/]([\w.]+)/.exec(ua) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || /(msie) ([\w.]+)/.exec(ua) || ua.indexOf('trident') >= 0 && /(rv)(?::| )([\w.]+)/.exec(ua) || ua.indexOf('compatible') < 0 && /(firefox)[ \/]([\w.]+)/.exec(ua) || [];
  9777. var platform_match = /(ipad)/.exec(ua) || /(ipod)/.exec(ua) || /(windows phone)/.exec(ua) || /(iphone)/.exec(ua) || /(kindle)/.exec(ua) || /(android)/.exec(ua) || /(windows)/.exec(ua) || /(mac)/.exec(ua) || /(linux)/.exec(ua) || /(cros)/.exec(ua) || [];
  9778. var matched = {
  9779. browser: match[5] || match[3] || match[1] || '',
  9780. version: match[2] || match[4] || '0',
  9781. majorVersion: match[4] || match[2] || '0',
  9782. platform: platform_match[0] || ''
  9783. };
  9784. var browser = {};
  9785. if (matched.browser) {
  9786. browser[matched.browser] = true;
  9787. var versionArray = matched.majorVersion.split('.');
  9788. browser.version = {
  9789. major: parseInt(matched.majorVersion, 10),
  9790. string: matched.version
  9791. };
  9792. if (versionArray.length > 1) {
  9793. browser.version.minor = parseInt(versionArray[1], 10);
  9794. }
  9795. if (versionArray.length > 2) {
  9796. browser.version.build = parseInt(versionArray[2], 10);
  9797. }
  9798. }
  9799. if (matched.platform) {
  9800. browser[matched.platform] = true;
  9801. }
  9802. if (browser.chrome || browser.opr || browser.safari) {
  9803. browser.webkit = true;
  9804. }
  9805. // MSIE. IE11 has 'rv' identifer
  9806. if (browser.rv || browser.iemobile) {
  9807. if (browser.rv) {
  9808. delete browser.rv;
  9809. }
  9810. var msie = 'msie';
  9811. matched.browser = msie;
  9812. browser[msie] = true;
  9813. }
  9814. // Microsoft Edge
  9815. if (browser.edge) {
  9816. delete browser.edge;
  9817. var msedge = 'msedge';
  9818. matched.browser = msedge;
  9819. browser[msedge] = true;
  9820. }
  9821. // Opera 15+
  9822. if (browser.opr) {
  9823. var opera = 'opera';
  9824. matched.browser = opera;
  9825. browser[opera] = true;
  9826. }
  9827. // Stock android browsers are marked as Safari
  9828. if (browser.safari && browser.android) {
  9829. var android = 'android';
  9830. matched.browser = android;
  9831. browser[android] = true;
  9832. }
  9833. browser.name = matched.browser;
  9834. browser.platform = matched.platform;
  9835. for (var key in Browser) {
  9836. if (Browser.hasOwnProperty(key)) {
  9837. delete Browser[key];
  9838. }
  9839. }
  9840. Object.assign(Browser, browser);
  9841. }
  9842. detect();
  9843. exports.default = Browser;
  9844. },{}],40:[function(_dereq_,module,exports){
  9845. 'use strict';
  9846. Object.defineProperty(exports, "__esModule", {
  9847. value: true
  9848. });
  9849. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  9850. function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  9851. function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  9852. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  9853. /*
  9854. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  9855. *
  9856. * @author zheng qian <xqq@xqq.im>
  9857. *
  9858. * Licensed under the Apache License, Version 2.0 (the "License");
  9859. * you may not use this file except in compliance with the License.
  9860. * You may obtain a copy of the License at
  9861. *
  9862. * http://www.apache.org/licenses/LICENSE-2.0
  9863. *
  9864. * Unless required by applicable law or agreed to in writing, software
  9865. * distributed under the License is distributed on an "AS IS" BASIS,
  9866. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9867. * See the License for the specific language governing permissions and
  9868. * limitations under the License.
  9869. */
  9870. var RuntimeException = exports.RuntimeException = function () {
  9871. function RuntimeException(message) {
  9872. _classCallCheck(this, RuntimeException);
  9873. this._message = message;
  9874. }
  9875. _createClass(RuntimeException, [{
  9876. key: 'toString',
  9877. value: function toString() {
  9878. return this.name + ': ' + this.message;
  9879. }
  9880. }, {
  9881. key: 'name',
  9882. get: function get() {
  9883. return 'RuntimeException';
  9884. }
  9885. }, {
  9886. key: 'message',
  9887. get: function get() {
  9888. return this._message;
  9889. }
  9890. }]);
  9891. return RuntimeException;
  9892. }();
  9893. var IllegalStateException = exports.IllegalStateException = function (_RuntimeException) {
  9894. _inherits(IllegalStateException, _RuntimeException);
  9895. function IllegalStateException(message) {
  9896. _classCallCheck(this, IllegalStateException);
  9897. return _possibleConstructorReturn(this, (IllegalStateException.__proto__ || Object.getPrototypeOf(IllegalStateException)).call(this, message));
  9898. }
  9899. _createClass(IllegalStateException, [{
  9900. key: 'name',
  9901. get: function get() {
  9902. return 'IllegalStateException';
  9903. }
  9904. }]);
  9905. return IllegalStateException;
  9906. }(RuntimeException);
  9907. var InvalidArgumentException = exports.InvalidArgumentException = function (_RuntimeException2) {
  9908. _inherits(InvalidArgumentException, _RuntimeException2);
  9909. function InvalidArgumentException(message) {
  9910. _classCallCheck(this, InvalidArgumentException);
  9911. return _possibleConstructorReturn(this, (InvalidArgumentException.__proto__ || Object.getPrototypeOf(InvalidArgumentException)).call(this, message));
  9912. }
  9913. _createClass(InvalidArgumentException, [{
  9914. key: 'name',
  9915. get: function get() {
  9916. return 'InvalidArgumentException';
  9917. }
  9918. }]);
  9919. return InvalidArgumentException;
  9920. }(RuntimeException);
  9921. var NotImplementedException = exports.NotImplementedException = function (_RuntimeException3) {
  9922. _inherits(NotImplementedException, _RuntimeException3);
  9923. function NotImplementedException(message) {
  9924. _classCallCheck(this, NotImplementedException);
  9925. return _possibleConstructorReturn(this, (NotImplementedException.__proto__ || Object.getPrototypeOf(NotImplementedException)).call(this, message));
  9926. }
  9927. _createClass(NotImplementedException, [{
  9928. key: 'name',
  9929. get: function get() {
  9930. return 'NotImplementedException';
  9931. }
  9932. }]);
  9933. return NotImplementedException;
  9934. }(RuntimeException);
  9935. },{}],41:[function(_dereq_,module,exports){
  9936. 'use strict';
  9937. Object.defineProperty(exports, "__esModule", {
  9938. value: true
  9939. });
  9940. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  9941. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  9942. *
  9943. * @author zheng qian <xqq@xqq.im>
  9944. *
  9945. * Licensed under the Apache License, Version 2.0 (the "License");
  9946. * you may not use this file except in compliance with the License.
  9947. * You may obtain a copy of the License at
  9948. *
  9949. * http://www.apache.org/licenses/LICENSE-2.0
  9950. *
  9951. * Unless required by applicable law or agreed to in writing, software
  9952. * distributed under the License is distributed on an "AS IS" BASIS,
  9953. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9954. * See the License for the specific language governing permissions and
  9955. * limitations under the License.
  9956. */
  9957. var _events = _dereq_('events');
  9958. var _events2 = _interopRequireDefault(_events);
  9959. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  9960. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  9961. var Log = function () {
  9962. function Log() {
  9963. _classCallCheck(this, Log);
  9964. }
  9965. _createClass(Log, null, [{
  9966. key: 'e',
  9967. value: function e(tag, msg) {
  9968. if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG;
  9969. var str = '[' + tag + '] > ' + msg;
  9970. if (Log.ENABLE_CALLBACK) {
  9971. Log.emitter.emit('log', 'error', str);
  9972. }
  9973. if (!Log.ENABLE_ERROR) {
  9974. return;
  9975. }
  9976. if (console.error) {
  9977. console.error(str);
  9978. } else if (console.warn) {
  9979. console.warn(str);
  9980. } else {
  9981. console.log(str);
  9982. }
  9983. }
  9984. }, {
  9985. key: 'i',
  9986. value: function i(tag, msg) {
  9987. if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG;
  9988. var str = '[' + tag + '] > ' + msg;
  9989. if (Log.ENABLE_CALLBACK) {
  9990. Log.emitter.emit('log', 'info', str);
  9991. }
  9992. if (!Log.ENABLE_INFO) {
  9993. return;
  9994. }
  9995. if (console.info) {
  9996. console.info(str);
  9997. } else {
  9998. console.log(str);
  9999. }
  10000. }
  10001. }, {
  10002. key: 'w',
  10003. value: function w(tag, msg) {
  10004. if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG;
  10005. var str = '[' + tag + '] > ' + msg;
  10006. if (Log.ENABLE_CALLBACK) {
  10007. Log.emitter.emit('log', 'warn', str);
  10008. }
  10009. if (!Log.ENABLE_WARN) {
  10010. return;
  10011. }
  10012. if (console.warn) {
  10013. console.warn(str);
  10014. } else {
  10015. console.log(str);
  10016. }
  10017. }
  10018. }, {
  10019. key: 'd',
  10020. value: function d(tag, msg) {
  10021. if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG;
  10022. var str = '[' + tag + '] > ' + msg;
  10023. if (Log.ENABLE_CALLBACK) {
  10024. Log.emitter.emit('log', 'debug', str);
  10025. }
  10026. if (!Log.ENABLE_DEBUG) {
  10027. return;
  10028. }
  10029. if (console.debug) {
  10030. console.debug(str);
  10031. } else {
  10032. console.log(str);
  10033. }
  10034. }
  10035. }, {
  10036. key: 'v',
  10037. value: function v(tag, msg) {
  10038. if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG;
  10039. var str = '[' + tag + '] > ' + msg;
  10040. if (Log.ENABLE_CALLBACK) {
  10041. Log.emitter.emit('log', 'verbose', str);
  10042. }
  10043. if (!Log.ENABLE_VERBOSE) {
  10044. return;
  10045. }
  10046. console.log(str);
  10047. }
  10048. }]);
  10049. return Log;
  10050. }();
  10051. Log.GLOBAL_TAG = 'flv.js';
  10052. Log.FORCE_GLOBAL_TAG = false;
  10053. Log.ENABLE_ERROR = true;
  10054. Log.ENABLE_INFO = true;
  10055. Log.ENABLE_WARN = true;
  10056. Log.ENABLE_DEBUG = true;
  10057. Log.ENABLE_VERBOSE = true;
  10058. Log.ENABLE_CALLBACK = false;
  10059. Log.emitter = new _events2.default();
  10060. exports.default = Log;
  10061. },{"events":2}],42:[function(_dereq_,module,exports){
  10062. 'use strict';
  10063. Object.defineProperty(exports, "__esModule", {
  10064. value: true
  10065. });
  10066. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
  10067. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  10068. *
  10069. * @author zheng qian <xqq@xqq.im>
  10070. *
  10071. * Licensed under the Apache License, Version 2.0 (the "License");
  10072. * you may not use this file except in compliance with the License.
  10073. * You may obtain a copy of the License at
  10074. *
  10075. * http://www.apache.org/licenses/LICENSE-2.0
  10076. *
  10077. * Unless required by applicable law or agreed to in writing, software
  10078. * distributed under the License is distributed on an "AS IS" BASIS,
  10079. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10080. * See the License for the specific language governing permissions and
  10081. * limitations under the License.
  10082. */
  10083. var _events = _dereq_('events');
  10084. var _events2 = _interopRequireDefault(_events);
  10085. var _logger = _dereq_('./logger.js');
  10086. var _logger2 = _interopRequireDefault(_logger);
  10087. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  10088. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  10089. var LoggingControl = function () {
  10090. function LoggingControl() {
  10091. _classCallCheck(this, LoggingControl);
  10092. }
  10093. _createClass(LoggingControl, null, [{
  10094. key: 'getConfig',
  10095. value: function getConfig() {
  10096. return {
  10097. globalTag: _logger2.default.GLOBAL_TAG,
  10098. forceGlobalTag: _logger2.default.FORCE_GLOBAL_TAG,
  10099. enableVerbose: _logger2.default.ENABLE_VERBOSE,
  10100. enableDebug: _logger2.default.ENABLE_DEBUG,
  10101. enableInfo: _logger2.default.ENABLE_INFO,
  10102. enableWarn: _logger2.default.ENABLE_WARN,
  10103. enableError: _logger2.default.ENABLE_ERROR,
  10104. enableCallback: _logger2.default.ENABLE_CALLBACK
  10105. };
  10106. }
  10107. }, {
  10108. key: 'applyConfig',
  10109. value: function applyConfig(config) {
  10110. _logger2.default.GLOBAL_TAG = config.globalTag;
  10111. _logger2.default.FORCE_GLOBAL_TAG = config.forceGlobalTag;
  10112. _logger2.default.ENABLE_VERBOSE = config.enableVerbose;
  10113. _logger2.default.ENABLE_DEBUG = config.enableDebug;
  10114. _logger2.default.ENABLE_INFO = config.enableInfo;
  10115. _logger2.default.ENABLE_WARN = config.enableWarn;
  10116. _logger2.default.ENABLE_ERROR = config.enableError;
  10117. _logger2.default.ENABLE_CALLBACK = config.enableCallback;
  10118. }
  10119. }, {
  10120. key: '_notifyChange',
  10121. value: function _notifyChange() {
  10122. var emitter = LoggingControl.emitter;
  10123. if (emitter.listenerCount('change') > 0) {
  10124. var config = LoggingControl.getConfig();
  10125. emitter.emit('change', config);
  10126. }
  10127. }
  10128. }, {
  10129. key: 'registerListener',
  10130. value: function registerListener(listener) {
  10131. LoggingControl.emitter.addListener('change', listener);
  10132. }
  10133. }, {
  10134. key: 'removeListener',
  10135. value: function removeListener(listener) {
  10136. LoggingControl.emitter.removeListener('change', listener);
  10137. }
  10138. }, {
  10139. key: 'addLogListener',
  10140. value: function addLogListener(listener) {
  10141. _logger2.default.emitter.addListener('log', listener);
  10142. if (_logger2.default.emitter.listenerCount('log') > 0) {
  10143. _logger2.default.ENABLE_CALLBACK = true;
  10144. LoggingControl._notifyChange();
  10145. }
  10146. }
  10147. }, {
  10148. key: 'removeLogListener',
  10149. value: function removeLogListener(listener) {
  10150. _logger2.default.emitter.removeListener('log', listener);
  10151. if (_logger2.default.emitter.listenerCount('log') === 0) {
  10152. _logger2.default.ENABLE_CALLBACK = false;
  10153. LoggingControl._notifyChange();
  10154. }
  10155. }
  10156. }, {
  10157. key: 'forceGlobalTag',
  10158. get: function get() {
  10159. return _logger2.default.FORCE_GLOBAL_TAG;
  10160. },
  10161. set: function set(enable) {
  10162. _logger2.default.FORCE_GLOBAL_TAG = enable;
  10163. LoggingControl._notifyChange();
  10164. }
  10165. }, {
  10166. key: 'globalTag',
  10167. get: function get() {
  10168. return _logger2.default.GLOBAL_TAG;
  10169. },
  10170. set: function set(tag) {
  10171. _logger2.default.GLOBAL_TAG = tag;
  10172. LoggingControl._notifyChange();
  10173. }
  10174. }, {
  10175. key: 'enableAll',
  10176. get: function get() {
  10177. return _logger2.default.ENABLE_VERBOSE && _logger2.default.ENABLE_DEBUG && _logger2.default.ENABLE_INFO && _logger2.default.ENABLE_WARN && _logger2.default.ENABLE_ERROR;
  10178. },
  10179. set: function set(enable) {
  10180. _logger2.default.ENABLE_VERBOSE = enable;
  10181. _logger2.default.ENABLE_DEBUG = enable;
  10182. _logger2.default.ENABLE_INFO = enable;
  10183. _logger2.default.ENABLE_WARN = enable;
  10184. _logger2.default.ENABLE_ERROR = enable;
  10185. LoggingControl._notifyChange();
  10186. }
  10187. }, {
  10188. key: 'enableDebug',
  10189. get: function get() {
  10190. return _logger2.default.ENABLE_DEBUG;
  10191. },
  10192. set: function set(enable) {
  10193. _logger2.default.ENABLE_DEBUG = enable;
  10194. LoggingControl._notifyChange();
  10195. }
  10196. }, {
  10197. key: 'enableVerbose',
  10198. get: function get() {
  10199. return _logger2.default.ENABLE_VERBOSE;
  10200. },
  10201. set: function set(enable) {
  10202. _logger2.default.ENABLE_VERBOSE = enable;
  10203. LoggingControl._notifyChange();
  10204. }
  10205. }, {
  10206. key: 'enableInfo',
  10207. get: function get() {
  10208. return _logger2.default.ENABLE_INFO;
  10209. },
  10210. set: function set(enable) {
  10211. _logger2.default.ENABLE_INFO = enable;
  10212. LoggingControl._notifyChange();
  10213. }
  10214. }, {
  10215. key: 'enableWarn',
  10216. get: function get() {
  10217. return _logger2.default.ENABLE_WARN;
  10218. },
  10219. set: function set(enable) {
  10220. _logger2.default.ENABLE_WARN = enable;
  10221. LoggingControl._notifyChange();
  10222. }
  10223. }, {
  10224. key: 'enableError',
  10225. get: function get() {
  10226. return _logger2.default.ENABLE_ERROR;
  10227. },
  10228. set: function set(enable) {
  10229. _logger2.default.ENABLE_ERROR = enable;
  10230. LoggingControl._notifyChange();
  10231. }
  10232. }]);
  10233. return LoggingControl;
  10234. }();
  10235. LoggingControl.emitter = new _events2.default();
  10236. exports.default = LoggingControl;
  10237. },{"./logger.js":41,"events":2}],43:[function(_dereq_,module,exports){
  10238. 'use strict';
  10239. Object.defineProperty(exports, "__esModule", {
  10240. value: true
  10241. });
  10242. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  10243. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  10244. /*
  10245. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  10246. *
  10247. * @author zheng qian <xqq@xqq.im>
  10248. *
  10249. * Licensed under the Apache License, Version 2.0 (the "License");
  10250. * you may not use this file except in compliance with the License.
  10251. * You may obtain a copy of the License at
  10252. *
  10253. * http://www.apache.org/licenses/LICENSE-2.0
  10254. *
  10255. * Unless required by applicable law or agreed to in writing, software
  10256. * distributed under the License is distributed on an "AS IS" BASIS,
  10257. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10258. * See the License for the specific language governing permissions and
  10259. * limitations under the License.
  10260. */
  10261. var Polyfill = function () {
  10262. function Polyfill() {
  10263. _classCallCheck(this, Polyfill);
  10264. }
  10265. _createClass(Polyfill, null, [{
  10266. key: 'install',
  10267. value: function install() {
  10268. // ES6 Object.setPrototypeOf
  10269. Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
  10270. obj.__proto__ = proto;
  10271. return obj;
  10272. };
  10273. // ES6 Object.assign
  10274. Object.assign = Object.assign || function (target) {
  10275. if (target === undefined || target === null) {
  10276. throw new TypeError('Cannot convert undefined or null to object');
  10277. }
  10278. var output = Object(target);
  10279. for (var i = 1; i < arguments.length; i++) {
  10280. var source = arguments[i];
  10281. if (source !== undefined && source !== null) {
  10282. for (var key in source) {
  10283. if (source.hasOwnProperty(key)) {
  10284. output[key] = source[key];
  10285. }
  10286. }
  10287. }
  10288. }
  10289. return output;
  10290. };
  10291. // ES6 Promise (missing support in IE11)
  10292. if (typeof self.Promise !== 'function') {
  10293. _dereq_('es6-promise').polyfill();
  10294. }
  10295. }
  10296. }]);
  10297. return Polyfill;
  10298. }();
  10299. Polyfill.install();
  10300. exports.default = Polyfill;
  10301. },{"es6-promise":1}],44:[function(_dereq_,module,exports){
  10302. 'use strict';
  10303. Object.defineProperty(exports, "__esModule", {
  10304. value: true
  10305. });
  10306. /*
  10307. * Copyright (C) 2016 Bilibili. All Rights Reserved.
  10308. *
  10309. * This file is derived from C++ project libWinTF8 (https://github.com/m13253/libWinTF8)
  10310. * @author zheng qian <xqq@xqq.im>
  10311. *
  10312. * Licensed under the Apache License, Version 2.0 (the "License");
  10313. * you may not use this file except in compliance with the License.
  10314. * You may obtain a copy of the License at
  10315. *
  10316. * http://www.apache.org/licenses/LICENSE-2.0
  10317. *
  10318. * Unless required by applicable law or agreed to in writing, software
  10319. * distributed under the License is distributed on an "AS IS" BASIS,
  10320. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10321. * See the License for the specific language governing permissions and
  10322. * limitations under the License.
  10323. */
  10324. function checkContinuation(uint8array, start, checkLength) {
  10325. var array = uint8array;
  10326. if (start + checkLength < array.length) {
  10327. while (checkLength--) {
  10328. if ((array[++start] & 0xC0) !== 0x80) return false;
  10329. }
  10330. return true;
  10331. } else {
  10332. return false;
  10333. }
  10334. }
  10335. function decodeUTF8(uint8array) {
  10336. var out = [];
  10337. var input = uint8array;
  10338. var i = 0;
  10339. var length = uint8array.length;
  10340. while (i < length) {
  10341. if (input[i] < 0x80) {
  10342. out.push(String.fromCharCode(input[i]));
  10343. ++i;
  10344. continue;
  10345. } else if (input[i] < 0xC0) {
  10346. // fallthrough
  10347. } else if (input[i] < 0xE0) {
  10348. if (checkContinuation(input, i, 1)) {
  10349. var ucs4 = (input[i] & 0x1F) << 6 | input[i + 1] & 0x3F;
  10350. if (ucs4 >= 0x80) {
  10351. out.push(String.fromCharCode(ucs4 & 0xFFFF));
  10352. i += 2;
  10353. continue;
  10354. }
  10355. }
  10356. } else if (input[i] < 0xF0) {
  10357. if (checkContinuation(input, i, 2)) {
  10358. var _ucs = (input[i] & 0xF) << 12 | (input[i + 1] & 0x3F) << 6 | input[i + 2] & 0x3F;
  10359. if (_ucs >= 0x800 && (_ucs & 0xF800) !== 0xD800) {
  10360. out.push(String.fromCharCode(_ucs & 0xFFFF));
  10361. i += 3;
  10362. continue;
  10363. }
  10364. }
  10365. } else if (input[i] < 0xF8) {
  10366. if (checkContinuation(input, i, 3)) {
  10367. var _ucs2 = (input[i] & 0x7) << 18 | (input[i + 1] & 0x3F) << 12 | (input[i + 2] & 0x3F) << 6 | input[i + 3] & 0x3F;
  10368. if (_ucs2 > 0x10000 && _ucs2 < 0x110000) {
  10369. _ucs2 -= 0x10000;
  10370. out.push(String.fromCharCode(_ucs2 >>> 10 | 0xD800));
  10371. out.push(String.fromCharCode(_ucs2 & 0x3FF | 0xDC00));
  10372. i += 4;
  10373. continue;
  10374. }
  10375. }
  10376. }
  10377. out.push(String.fromCharCode(0xFFFD));
  10378. ++i;
  10379. }
  10380. return out.join('');
  10381. }
  10382. exports.default = decodeUTF8;
  10383. },{}]},{},[21])(21)
  10384. });
  10385. //# sourceMappingURL=flv.js.map