xbmc-gotham_rbp_backports.patch 764 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377143781437914380143811438214383143841438514386143871438814389143901439114392143931439414395143961439714398143991440014401144021440314404144051440614407144081440914410144111441214413144141441514416144171441814419144201442114422144231442414425144261442714428144291443014431144321443314434144351443614437144381443914440144411444214443144441444514446144471444814449144501445114452144531445414455144561445714458144591446014461144621446314464144651446614467144681446914470144711447214473144741447514476144771447814479144801448114482144831448414485144861448714488144891449014491144921449314494144951449614497144981449914500145011450214503145041450514506145071450814509145101451114512145131451414515145161451714518145191452014521145221452314524145251452614527145281452914530145311453214533145341453514536145371453814539145401454114542145431454414545145461454714548145491455014551145521455314554145551455614557145581455914560145611456214563145641456514566145671456814569145701457114572145731457414575145761457714578145791458014581145821458314584145851458614587145881458914590145911459214593145941459514596145971459814599146001460114602146031460414605146061460714608146091461014611146121461314614146151461614617146181461914620146211462214623146241462514626146271462814629146301463114632146331463414635146361463714638146391464014641146421464314644146451464614647146481464914650146511465214653146541465514656146571465814659146601466114662146631466414665146661466714668146691467014671146721467314674146751467614677146781467914680146811468214683146841468514686146871468814689146901469114692146931469414695146961469714698146991470014701147021470314704147051470614707147081470914710147111471214713147141471514716147171471814719147201472114722147231472414725147261472714728147291473014731147321473314734147351473614737147381473914740147411474214743147441474514746147471474814749147501475114752147531475414755147561475714758147591476014761147621476314764147651476614767147681476914770147711477214773147741477514776147771477814779147801478114782147831478414785147861478714788147891479014791147921479314794147951479614797147981479914800148011480214803148041480514806148071480814809148101481114812148131481414815148161481714818148191482014821148221482314824148251482614827148281482914830148311483214833148341483514836148371483814839148401484114842148431484414845148461484714848148491485014851148521485314854148551485614857148581485914860148611486214863148641486514866148671486814869148701487114872148731487414875148761487714878148791488014881148821488314884148851488614887148881488914890148911489214893148941489514896148971489814899149001490114902149031490414905149061490714908149091491014911149121491314914149151491614917149181491914920149211492214923149241492514926149271492814929149301493114932149331493414935149361493714938149391494014941149421494314944149451494614947149481494914950149511495214953149541495514956149571495814959149601496114962149631496414965149661496714968149691497014971149721497314974149751497614977149781497914980149811498214983149841498514986149871498814989149901499114992149931499414995149961499714998149991500015001150021500315004150051500615007150081500915010150111501215013150141501515016150171501815019150201502115022150231502415025150261502715028150291503015031150321503315034150351503615037150381503915040150411504215043150441504515046150471504815049150501505115052150531505415055150561505715058150591506015061150621506315064150651506615067150681506915070150711507215073150741507515076150771507815079150801508115082150831508415085150861508715088150891509015091150921509315094150951509615097150981509915100151011510215103151041510515106151071510815109151101511115112151131511415115151161511715118151191512015121151221512315124151251512615127151281512915130151311513215133151341513515136151371513815139151401514115142151431514415145151461514715148151491515015151151521515315154151551515615157151581515915160151611516215163151641516515166151671516815169151701517115172151731517415175151761517715178151791518015181151821518315184151851518615187151881518915190151911519215193151941519515196151971519815199152001520115202152031520415205152061520715208152091521015211152121521315214152151521615217152181521915220152211522215223152241522515226152271522815229152301523115232152331523415235152361523715238152391524015241152421524315244152451524615247152481524915250152511525215253152541525515256152571525815259152601526115262152631526415265152661526715268152691527015271152721527315274152751527615277152781527915280152811528215283152841528515286152871528815289152901529115292152931529415295152961529715298152991530015301153021530315304153051530615307153081530915310153111531215313153141531515316153171531815319153201532115322153231532415325153261532715328153291533015331153321533315334153351533615337153381533915340153411534215343153441534515346153471534815349153501535115352153531535415355153561535715358153591536015361153621536315364153651536615367153681536915370153711537215373153741537515376153771537815379153801538115382153831538415385153861538715388153891539015391153921539315394153951539615397153981539915400154011540215403154041540515406154071540815409154101541115412154131541415415154161541715418154191542015421154221542315424154251542615427154281542915430154311543215433154341543515436154371543815439154401544115442154431544415445154461544715448154491545015451154521545315454154551545615457154581545915460154611546215463154641546515466154671546815469154701547115472154731547415475154761547715478154791548015481154821548315484154851548615487154881548915490154911549215493154941549515496154971549815499155001550115502155031550415505155061550715508155091551015511155121551315514155151551615517155181551915520155211552215523155241552515526155271552815529155301553115532155331553415535155361553715538155391554015541155421554315544155451554615547155481554915550155511555215553155541555515556155571555815559155601556115562155631556415565155661556715568155691557015571155721557315574155751557615577155781557915580155811558215583155841558515586155871558815589155901559115592155931559415595155961559715598155991560015601156021560315604156051560615607156081560915610156111561215613156141561515616156171561815619156201562115622156231562415625156261562715628156291563015631156321563315634156351563615637156381563915640156411564215643156441564515646156471564815649156501565115652156531565415655156561565715658156591566015661156621566315664156651566615667156681566915670156711567215673156741567515676156771567815679156801568115682156831568415685156861568715688156891569015691156921569315694156951569615697156981569915700157011570215703157041570515706157071570815709157101571115712157131571415715157161571715718157191572015721157221572315724157251572615727157281572915730157311573215733157341573515736157371573815739157401574115742157431574415745157461574715748157491575015751157521575315754157551575615757157581575915760157611576215763157641576515766157671576815769157701577115772157731577415775157761577715778157791578015781157821578315784157851578615787157881578915790157911579215793157941579515796157971579815799158001580115802158031580415805158061580715808158091581015811158121581315814158151581615817158181581915820158211582215823158241582515826158271582815829158301583115832158331583415835158361583715838158391584015841158421584315844158451584615847158481584915850158511585215853158541585515856158571585815859158601586115862158631586415865158661586715868158691587015871158721587315874158751587615877158781587915880158811588215883158841588515886158871588815889158901589115892158931589415895158961589715898158991590015901159021590315904159051590615907159081590915910159111591215913159141591515916159171591815919159201592115922159231592415925159261592715928159291593015931159321593315934159351593615937159381593915940159411594215943159441594515946159471594815949159501595115952159531595415955159561595715958159591596015961159621596315964159651596615967159681596915970159711597215973159741597515976159771597815979159801598115982159831598415985159861598715988159891599015991159921599315994159951599615997159981599916000160011600216003160041600516006160071600816009160101601116012160131601416015160161601716018160191602016021160221602316024160251602616027160281602916030160311603216033160341603516036160371603816039160401604116042160431604416045160461604716048160491605016051160521605316054160551605616057160581605916060160611606216063160641606516066160671606816069160701607116072160731607416075160761607716078160791608016081160821608316084160851608616087160881608916090160911609216093160941609516096160971609816099161001610116102161031610416105161061610716108161091611016111161121611316114161151611616117161181611916120161211612216123161241612516126161271612816129161301613116132161331613416135161361613716138161391614016141161421614316144161451614616147161481614916150161511615216153161541615516156161571615816159161601616116162161631616416165161661616716168161691617016171161721617316174161751617616177161781617916180161811618216183161841618516186161871618816189161901619116192161931619416195161961619716198161991620016201162021620316204162051620616207162081620916210162111621216213162141621516216162171621816219162201622116222162231622416225162261622716228162291623016231162321623316234162351623616237162381623916240162411624216243162441624516246162471624816249162501625116252162531625416255162561625716258162591626016261162621626316264162651626616267162681626916270162711627216273162741627516276162771627816279162801628116282162831628416285162861628716288162891629016291162921629316294162951629616297162981629916300163011630216303163041630516306163071630816309163101631116312163131631416315163161631716318163191632016321163221632316324163251632616327163281632916330163311633216333163341633516336163371633816339163401634116342163431634416345163461634716348163491635016351163521635316354163551635616357163581635916360163611636216363163641636516366163671636816369163701637116372163731637416375163761637716378163791638016381163821638316384163851638616387163881638916390163911639216393163941639516396163971639816399164001640116402164031640416405164061640716408164091641016411164121641316414164151641616417164181641916420164211642216423164241642516426164271642816429164301643116432164331643416435164361643716438164391644016441164421644316444164451644616447164481644916450164511645216453164541645516456164571645816459164601646116462164631646416465164661646716468164691647016471164721647316474164751647616477164781647916480164811648216483164841648516486164871648816489164901649116492164931649416495164961649716498164991650016501165021650316504165051650616507165081650916510165111651216513165141651516516165171651816519165201652116522165231652416525165261652716528165291653016531165321653316534165351653616537165381653916540165411654216543165441654516546165471654816549165501655116552165531655416555165561655716558165591656016561165621656316564165651656616567165681656916570165711657216573165741657516576165771657816579165801658116582165831658416585165861658716588165891659016591165921659316594165951659616597165981659916600166011660216603166041660516606166071660816609166101661116612166131661416615166161661716618166191662016621166221662316624166251662616627166281662916630166311663216633166341663516636166371663816639166401664116642166431664416645166461664716648166491665016651166521665316654166551665616657166581665916660166611666216663166641666516666166671666816669166701667116672166731667416675166761667716678166791668016681166821668316684166851668616687166881668916690166911669216693166941669516696166971669816699167001670116702167031670416705167061670716708167091671016711167121671316714167151671616717167181671916720167211672216723167241672516726167271672816729167301673116732167331673416735167361673716738167391674016741167421674316744167451674616747167481674916750167511675216753167541675516756167571675816759167601676116762167631676416765167661676716768167691677016771167721677316774167751677616777167781677916780167811678216783167841678516786167871678816789167901679116792167931679416795167961679716798167991680016801168021680316804168051680616807168081680916810168111681216813168141681516816168171681816819168201682116822168231682416825168261682716828168291683016831168321683316834168351683616837168381683916840168411684216843168441684516846168471684816849168501685116852168531685416855168561685716858168591686016861168621686316864168651686616867168681686916870168711687216873168741687516876168771687816879168801688116882168831688416885168861688716888168891689016891168921689316894168951689616897168981689916900169011690216903169041690516906169071690816909169101691116912169131691416915169161691716918169191692016921169221692316924169251692616927169281692916930169311693216933169341693516936169371693816939169401694116942169431694416945169461694716948169491695016951169521695316954169551695616957169581695916960169611696216963169641696516966169671696816969169701697116972169731697416975169761697716978169791698016981169821698316984169851698616987169881698916990169911699216993169941699516996169971699816999170001700117002170031700417005170061700717008170091701017011170121701317014170151701617017170181701917020170211702217023170241702517026170271702817029170301703117032170331703417035170361703717038170391704017041170421704317044170451704617047170481704917050170511705217053170541705517056170571705817059170601706117062170631706417065170661706717068170691707017071170721707317074170751707617077170781707917080170811708217083170841708517086170871708817089170901709117092170931709417095170961709717098170991710017101171021710317104171051710617107171081710917110171111711217113171141711517116171171711817119171201712117122171231712417125171261712717128171291713017131171321713317134171351713617137171381713917140171411714217143171441714517146171471714817149171501715117152171531715417155171561715717158171591716017161171621716317164171651716617167171681716917170171711717217173171741717517176171771717817179171801718117182171831718417185171861718717188171891719017191171921719317194171951719617197171981719917200172011720217203172041720517206172071720817209172101721117212172131721417215172161721717218172191722017221172221722317224172251722617227172281722917230172311723217233172341723517236172371723817239172401724117242172431724417245172461724717248172491725017251172521725317254172551725617257172581725917260172611726217263172641726517266172671726817269172701727117272172731727417275172761727717278172791728017281172821728317284172851728617287172881728917290172911729217293172941729517296172971729817299173001730117302173031730417305173061730717308173091731017311173121731317314173151731617317173181731917320173211732217323173241732517326173271732817329173301733117332173331733417335173361733717338173391734017341173421734317344173451734617347173481734917350173511735217353173541735517356173571735817359173601736117362173631736417365173661736717368173691737017371173721737317374173751737617377173781737917380173811738217383173841738517386173871738817389173901739117392173931739417395173961739717398173991740017401174021740317404174051740617407174081740917410174111741217413174141741517416174171741817419174201742117422174231742417425174261742717428174291743017431174321743317434174351743617437174381743917440174411744217443174441744517446174471744817449174501745117452174531745417455174561745717458174591746017461174621746317464174651746617467174681746917470174711747217473174741747517476174771747817479174801748117482174831748417485174861748717488174891749017491174921749317494174951749617497174981749917500175011750217503175041750517506175071750817509175101751117512175131751417515175161751717518175191752017521175221752317524175251752617527175281752917530175311753217533175341753517536175371753817539175401754117542175431754417545175461754717548175491755017551175521755317554175551755617557175581755917560175611756217563175641756517566175671756817569175701757117572175731757417575175761757717578175791758017581175821758317584175851758617587175881758917590175911759217593175941759517596175971759817599176001760117602176031760417605176061760717608176091761017611176121761317614176151761617617176181761917620176211762217623176241762517626176271762817629176301763117632176331763417635176361763717638176391764017641176421764317644176451764617647176481764917650176511765217653176541765517656176571765817659176601766117662176631766417665176661766717668176691767017671176721767317674176751767617677176781767917680176811768217683176841768517686176871768817689176901769117692176931769417695176961769717698176991770017701177021770317704177051770617707177081770917710177111771217713177141771517716177171771817719177201772117722177231772417725177261772717728177291773017731177321773317734177351773617737177381773917740177411774217743177441774517746177471774817749177501775117752177531775417755177561775717758177591776017761177621776317764177651776617767177681776917770177711777217773177741777517776177771777817779177801778117782177831778417785177861778717788177891779017791177921779317794177951779617797177981779917800178011780217803178041780517806178071780817809178101781117812178131781417815178161781717818178191782017821178221782317824178251782617827178281782917830178311783217833178341783517836178371783817839178401784117842178431784417845178461784717848178491785017851178521785317854178551785617857178581785917860178611786217863178641786517866178671786817869178701787117872178731787417875178761787717878178791788017881178821788317884178851788617887178881788917890178911789217893178941789517896178971789817899179001790117902179031790417905179061790717908179091791017911179121791317914179151791617917179181791917920179211792217923179241792517926179271792817929179301793117932179331793417935179361793717938179391794017941179421794317944179451794617947179481794917950179511795217953179541795517956179571795817959179601796117962179631796417965179661796717968179691797017971179721797317974179751797617977179781797917980179811798217983179841798517986179871798817989179901799117992179931799417995179961799717998179991800018001180021800318004180051800618007180081800918010180111801218013180141801518016180171801818019180201802118022180231802418025180261802718028180291803018031180321803318034180351803618037180381803918040180411804218043180441804518046180471804818049180501805118052180531805418055180561805718058180591806018061180621806318064180651806618067180681806918070180711807218073180741807518076180771807818079180801808118082180831808418085180861808718088180891809018091180921809318094180951809618097180981809918100181011810218103181041810518106181071810818109181101811118112181131811418115181161811718118181191812018121181221812318124181251812618127181281812918130181311813218133181341813518136181371813818139181401814118142181431814418145181461814718148181491815018151181521815318154181551815618157181581815918160181611816218163181641816518166181671816818169181701817118172181731817418175181761817718178181791818018181181821818318184181851818618187181881818918190181911819218193181941819518196181971819818199182001820118202182031820418205182061820718208182091821018211182121821318214182151821618217182181821918220182211822218223182241822518226182271822818229182301823118232182331823418235182361823718238182391824018241182421824318244182451824618247182481824918250182511825218253182541825518256182571825818259182601826118262182631826418265182661826718268182691827018271182721827318274182751827618277182781827918280182811828218283182841828518286182871828818289182901829118292182931829418295182961829718298182991830018301183021830318304183051830618307183081830918310183111831218313183141831518316183171831818319183201832118322183231832418325183261832718328183291833018331183321833318334183351833618337183381833918340183411834218343183441834518346183471834818349183501835118352183531835418355183561835718358183591836018361183621836318364183651836618367183681836918370183711837218373183741837518376183771837818379183801838118382183831838418385183861838718388183891839018391183921839318394183951839618397183981839918400184011840218403184041840518406184071840818409184101841118412184131841418415184161841718418184191842018421184221842318424184251842618427184281842918430184311843218433184341843518436184371843818439184401844118442184431844418445184461844718448184491845018451184521845318454184551845618457184581845918460184611846218463184641846518466184671846818469184701847118472184731847418475184761847718478184791848018481184821848318484184851848618487184881848918490184911849218493184941849518496184971849818499185001850118502185031850418505185061850718508185091851018511185121851318514185151851618517185181851918520185211852218523185241852518526185271852818529185301853118532185331853418535185361853718538185391854018541185421854318544185451854618547185481854918550185511855218553185541855518556185571855818559185601856118562185631856418565185661856718568185691857018571185721857318574185751857618577185781857918580185811858218583185841858518586185871858818589185901859118592185931859418595185961859718598185991860018601186021860318604186051860618607186081860918610186111861218613186141861518616186171861818619186201862118622186231862418625186261862718628186291863018631186321863318634186351863618637186381863918640186411864218643186441864518646186471864818649186501865118652186531865418655186561865718658186591866018661186621866318664186651866618667186681866918670186711867218673186741867518676186771867818679186801868118682186831868418685186861868718688186891869018691186921869318694186951869618697186981869918700187011870218703187041870518706187071870818709187101871118712187131871418715187161871718718187191872018721187221872318724187251872618727187281872918730187311873218733187341873518736187371873818739187401874118742187431874418745187461874718748187491875018751187521875318754187551875618757187581875918760187611876218763187641876518766187671876818769187701877118772187731877418775187761877718778187791878018781187821878318784187851878618787187881878918790187911879218793187941879518796187971879818799188001880118802188031880418805188061880718808188091881018811188121881318814188151881618817188181881918820188211882218823188241882518826188271882818829188301883118832188331883418835188361883718838188391884018841188421884318844188451884618847188481884918850188511885218853188541885518856188571885818859188601886118862188631886418865188661886718868188691887018871188721887318874188751887618877188781887918880188811888218883188841888518886188871888818889188901889118892188931889418895188961889718898188991890018901189021890318904189051890618907189081890918910189111891218913189141891518916189171891818919189201892118922189231892418925189261892718928189291893018931189321893318934189351893618937189381893918940189411894218943189441894518946189471894818949189501895118952189531895418955189561895718958189591896018961189621896318964189651896618967189681896918970189711897218973189741897518976189771897818979189801898118982189831898418985189861898718988189891899018991189921899318994189951899618997189981899919000190011900219003190041900519006190071900819009190101901119012190131901419015190161901719018190191902019021190221902319024190251902619027190281902919030190311903219033190341903519036190371903819039190401904119042190431904419045190461904719048190491905019051190521905319054190551905619057190581905919060190611906219063190641906519066190671906819069190701907119072190731907419075190761907719078190791908019081190821908319084190851908619087190881908919090190911909219093190941909519096190971909819099191001910119102191031910419105191061910719108191091911019111191121911319114191151911619117191181911919120191211912219123191241912519126191271912819129191301913119132191331913419135191361913719138191391914019141191421914319144191451914619147191481914919150191511915219153191541915519156191571915819159191601916119162191631916419165191661916719168191691917019171191721917319174191751917619177191781917919180191811918219183191841918519186191871918819189191901919119192191931919419195191961919719198191991920019201192021920319204192051920619207192081920919210192111921219213192141921519216192171921819219192201922119222192231922419225192261922719228192291923019231192321923319234192351923619237192381923919240192411924219243192441924519246192471924819249192501925119252192531925419255192561925719258192591926019261192621926319264192651926619267192681926919270192711927219273192741927519276192771927819279192801928119282192831928419285192861928719288192891929019291192921929319294192951929619297192981929919300193011930219303193041930519306193071930819309193101931119312193131931419315193161931719318193191932019321193221932319324193251932619327193281932919330193311933219333193341933519336193371933819339193401934119342193431934419345193461934719348193491935019351193521935319354193551935619357193581935919360193611936219363193641936519366193671936819369193701937119372193731937419375193761937719378193791938019381193821938319384193851938619387193881938919390193911939219393193941939519396193971939819399194001940119402194031940419405194061940719408194091941019411194121941319414194151941619417194181941919420194211942219423194241942519426194271942819429194301943119432194331943419435194361943719438194391944019441194421944319444194451944619447194481944919450194511945219453194541945519456194571945819459194601946119462194631946419465194661946719468194691947019471194721947319474194751947619477194781947919480194811948219483194841948519486194871948819489194901949119492194931949419495194961949719498194991950019501195021950319504195051950619507195081950919510195111951219513195141951519516195171951819519195201952119522195231952419525195261952719528195291953019531195321953319534195351953619537195381953919540195411954219543195441954519546195471954819549195501955119552195531955419555195561955719558195591956019561195621956319564195651956619567195681956919570195711957219573195741957519576195771957819579195801958119582195831958419585195861958719588195891959019591195921959319594195951959619597195981959919600196011960219603196041960519606196071960819609196101961119612196131961419615196161961719618196191962019621196221962319624196251962619627196281962919630196311963219633196341963519636196371963819639196401964119642196431964419645196461964719648196491965019651196521965319654196551965619657196581965919660196611966219663196641966519666196671966819669196701967119672196731967419675196761967719678196791968019681196821968319684196851968619687196881968919690196911969219693196941969519696196971969819699197001970119702197031970419705197061970719708197091971019711197121971319714197151971619717197181971919720197211972219723197241972519726197271972819729197301973119732197331973419735197361973719738197391974019741197421974319744197451974619747197481974919750197511975219753197541975519756197571975819759197601976119762197631976419765197661976719768197691977019771197721977319774197751977619777197781977919780197811978219783197841978519786197871978819789197901979119792197931979419795197961979719798197991980019801198021980319804198051980619807198081980919810198111981219813198141981519816198171981819819198201982119822198231982419825198261982719828198291983019831198321983319834198351983619837198381983919840198411984219843198441984519846198471984819849198501985119852198531985419855198561985719858198591986019861198621986319864198651986619867198681986919870198711987219873198741987519876198771987819879198801988119882198831988419885198861988719888198891989019891198921989319894198951989619897198981989919900199011990219903199041990519906199071990819909199101991119912199131991419915199161991719918199191992019921199221992319924199251992619927199281992919930199311993219933199341993519936199371993819939199401994119942199431994419945199461994719948199491995019951199521995319954199551995619957199581995919960199611996219963199641996519966199671996819969199701997119972199731997419975199761997719978199791998019981199821998319984199851998619987199881998919990199911999219993199941999519996199971999819999200002000120002200032000420005200062000720008200092001020011200122001320014200152001620017200182001920020200212002220023200242002520026200272002820029200302003120032200332003420035200362003720038200392004020041200422004320044200452004620047200482004920050200512005220053200542005520056200572005820059200602006120062200632006420065200662006720068200692007020071200722007320074200752007620077200782007920080200812008220083200842008520086200872008820089200902009120092200932009420095200962009720098200992010020101201022010320104201052010620107201082010920110201112011220113201142011520116201172011820119201202012120122201232012420125201262012720128201292013020131201322013320134201352013620137201382013920140201412014220143201442014520146201472014820149201502015120152201532015420155201562015720158201592016020161201622016320164201652016620167201682016920170201712017220173201742017520176201772017820179201802018120182201832018420185201862018720188201892019020191201922019320194201952019620197201982019920200202012020220203202042020520206202072020820209202102021120212202132021420215202162021720218202192022020221202222022320224202252022620227202282022920230202312023220233202342023520236202372023820239202402024120242202432024420245202462024720248202492025020251202522025320254202552025620257202582025920260202612026220263202642026520266202672026820269202702027120272202732027420275202762027720278202792028020281202822028320284202852028620287202882028920290202912029220293202942029520296202972029820299203002030120302203032030420305203062030720308203092031020311203122031320314203152031620317203182031920320203212032220323203242032520326203272032820329203302033120332203332033420335203362033720338203392034020341203422034320344203452034620347203482034920350203512035220353203542035520356203572035820359203602036120362203632036420365203662036720368203692037020371203722037320374203752037620377203782037920380203812038220383203842038520386203872038820389203902039120392203932039420395203962039720398203992040020401204022040320404204052040620407204082040920410204112041220413204142041520416204172041820419204202042120422204232042420425204262042720428204292043020431204322043320434204352043620437204382043920440204412044220443204442044520446204472044820449204502045120452204532045420455204562045720458204592046020461204622046320464204652046620467204682046920470204712047220473204742047520476204772047820479204802048120482204832048420485204862048720488204892049020491204922049320494204952049620497204982049920500205012050220503205042050520506205072050820509205102051120512205132051420515205162051720518205192052020521205222052320524205252052620527205282052920530205312053220533205342053520536205372053820539205402054120542205432054420545205462054720548205492055020551205522055320554205552055620557205582055920560205612056220563205642056520566205672056820569205702057120572205732057420575205762057720578205792058020581205822058320584205852058620587205882058920590205912059220593205942059520596205972059820599206002060120602206032060420605206062060720608206092061020611206122061320614206152061620617206182061920620206212062220623206242062520626206272062820629206302063120632206332063420635206362063720638206392064020641206422064320644206452064620647206482064920650206512065220653206542065520656206572065820659206602066120662206632066420665
  1. From 1353d8feca19f2f84019797942d70864054db1b0 Mon Sep 17 00:00:00 2001
  2. From: Ben Avison <bavison@riscosopen.org>
  3. Date: Mon, 5 Aug 2013 13:12:46 +0100
  4. Subject: [PATCH 01/94] h264_parser: Initialize the h264dsp context in the
  5. parser as well
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. Each AVStream struct for an H.264 elementary stream actually has two
  10. copies of the H264DSPContext struct (and in fact all the other members
  11. of H264Context as well):
  12. ((H264Context *) ((AVStream *)st)->codec->priv_data)->h264dsp
  13. ((H264Context *) ((AVStream *)st)->parser->priv_data)->h264dsp
  14. but only the first of these was actually being initialised. This
  15. prevented the addition of platform-specific implementations of
  16. parser-related functions.
  17. Signed-off-by: Martin Storsjö <martin@martin.st>
  18. ---
  19. lib/ffmpeg/libavcodec/h264_parser.c | 1 +
  20. 1 file changed, 1 insertion(+)
  21. diff --git a/lib/ffmpeg/libavcodec/h264_parser.c b/lib/ffmpeg/libavcodec/h264_parser.c
  22. index aff9ba1..a732f79 100644
  23. --- a/lib/ffmpeg/libavcodec/h264_parser.c
  24. +++ b/lib/ffmpeg/libavcodec/h264_parser.c
  25. @@ -386,6 +386,7 @@ static int init(AVCodecParserContext *s)
  26. H264Context *h = s->priv_data;
  27. h->thread_context[0] = h;
  28. h->slice_context_count = 1;
  29. + ff_h264dsp_init(&h->h264dsp, 8, 1);
  30. return 0;
  31. }
  32. --
  33. 1.9.3
  34. From 7ea2cb68f6fb1149fce70854e36ed6357a267238 Mon Sep 17 00:00:00 2001
  35. From: Ben Avison <bavison@riscosopen.org>
  36. Date: Mon, 5 Aug 2013 13:12:47 +0100
  37. Subject: [PATCH 02/94] h264dsp: Factorize code into a new function,
  38. h264_find_start_code_candidate
  39. MIME-Version: 1.0
  40. Content-Type: text/plain; charset=UTF-8
  41. Content-Transfer-Encoding: 8bit
  42. This performs the start code search which was previously part of
  43. h264_find_frame_end() - the most CPU intensive part of the function.
  44. By itself, this results in a performance regression:
  45. Before After
  46. Mean StdDev Mean StdDev Change
  47. Overall time 2925.6 26.2 3068.5 31.7 -4.7%
  48. but this can more than be made up for by platform-optimised
  49. implementations of the function.
  50. Signed-off-by: Martin Storsjö <martin@martin.st>
  51. ---
  52. lib/ffmpeg/libavcodec/h264_parser.c | 20 +++-----------------
  53. lib/ffmpeg/libavcodec/h264dsp.c | 29 +++++++++++++++++++++++++++++
  54. lib/ffmpeg/libavcodec/h264dsp.h | 9 +++++++++
  55. 3 files changed, 41 insertions(+), 17 deletions(-)
  56. diff --git a/lib/ffmpeg/libavcodec/h264_parser.c b/lib/ffmpeg/libavcodec/h264_parser.c
  57. index a732f79..972aace 100644
  58. --- a/lib/ffmpeg/libavcodec/h264_parser.c
  59. +++ b/lib/ffmpeg/libavcodec/h264_parser.c
  60. @@ -62,23 +62,9 @@ static int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_si
  61. }
  62. if(state==7){
  63. -#if HAVE_FAST_UNALIGNED
  64. - /* we check i<buf_size instead of i+3/7 because its simpler
  65. - * and there should be FF_INPUT_BUFFER_PADDING_SIZE bytes at the end
  66. - */
  67. -# if HAVE_FAST_64BIT
  68. - while(i<next_avc && !((~*(const uint64_t*)(buf+i) & (*(const uint64_t*)(buf+i) - 0x0101010101010101ULL)) & 0x8080808080808080ULL))
  69. - i+=8;
  70. -# else
  71. - while(i<next_avc && !((~*(const uint32_t*)(buf+i) & (*(const uint32_t*)(buf+i) - 0x01010101U)) & 0x80808080U))
  72. - i+=4;
  73. -# endif
  74. -#endif
  75. - for(; i<next_avc; i++){
  76. - if(!buf[i]){
  77. - state=2;
  78. - break;
  79. - }
  80. + i += h->h264dsp.h264_find_start_code_candidate(buf + i, buf_size - i);
  81. + if (i < buf_size)
  82. + state = 2;
  83. }
  84. }else if(state<=2){
  85. if(buf[i]==1) state^= 5; //2->7, 1->4, 0->5
  86. diff --git a/lib/ffmpeg/libavcodec/h264dsp.c b/lib/ffmpeg/libavcodec/h264dsp.c
  87. index da9e417..b7d61cd 100644
  88. --- a/lib/ffmpeg/libavcodec/h264dsp.c
  89. +++ b/lib/ffmpeg/libavcodec/h264dsp.c
  90. @@ -60,6 +60,34 @@
  91. #include "h264addpx_template.c"
  92. #undef BIT_DEPTH
  93. +static int h264_find_start_code_candidate_c(const uint8_t *buf, int size)
  94. +{
  95. + int i = 0;
  96. +#if HAVE_FAST_UNALIGNED
  97. + /* we check i < size instead of i + 3 / 7 because it is
  98. + * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE
  99. + * bytes at the end.
  100. + */
  101. +#if HAVE_FAST_64BIT
  102. + while (i < size &&
  103. + !((~*(const uint64_t *)(buf + i) &
  104. + (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) &
  105. + 0x8080808080808080ULL))
  106. + i += 8;
  107. +#else
  108. + while (i < size &&
  109. + !((~*(const uint32_t *)(buf + i) &
  110. + (*(const uint32_t *)(buf + i) - 0x01010101U)) &
  111. + 0x80808080U))
  112. + i += 4;
  113. +#endif
  114. +#endif
  115. + for (; i < size; i++)
  116. + if (!buf[i])
  117. + break;
  118. + return i;
  119. +}
  120. +
  121. void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_format_idc)
  122. {
  123. #undef FUNC
  124. @@ -146,6 +174,7 @@ void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_fo
  125. H264_DSP(8);
  126. break;
  127. }
  128. + c->h264_find_start_code_candidate = h264_find_start_code_candidate_c;
  129. if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc);
  130. if (HAVE_ALTIVEC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc);
  131. diff --git a/lib/ffmpeg/libavcodec/h264dsp.h b/lib/ffmpeg/libavcodec/h264dsp.h
  132. index 98ea15c..1be4804 100644
  133. --- a/lib/ffmpeg/libavcodec/h264dsp.h
  134. +++ b/lib/ffmpeg/libavcodec/h264dsp.h
  135. @@ -105,6 +105,15 @@ typedef struct H264DSPContext {
  136. /* bypass-transform */
  137. void (*h264_add_pixels8_clear)(uint8_t *dst, int16_t *block, int stride);
  138. void (*h264_add_pixels4_clear)(uint8_t *dst, int16_t *block, int stride);
  139. +
  140. + /**
  141. + * Search buf from the start for up to size bytes. Return the index
  142. + * of a zero byte, or >= size if not found. Ideally, use lookahead
  143. + * to filter out any zero bytes that are known to not be followed by
  144. + * one or more further zero bytes and a one byte. Better still, filter
  145. + * out any bytes that form the trailing_zero_8bits syntax element too.
  146. + */
  147. + int (*h264_find_start_code_candidate)(const uint8_t *buf, int size);
  148. } H264DSPContext;
  149. void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,
  150. --
  151. 1.9.3
  152. From 458ff4b6c1855c529f563dbbd15e35aaab50adae Mon Sep 17 00:00:00 2001
  153. From: Ben Avison <bavison@riscosopen.org>
  154. Date: Mon, 5 Aug 2013 13:12:48 +0100
  155. Subject: [PATCH 03/94] arm: Add assembly version of
  156. h264_find_start_code_candidate
  157. MIME-Version: 1.0
  158. Content-Type: text/plain; charset=UTF-8
  159. Content-Transfer-Encoding: 8bit
  160. Before After
  161. Mean StdDev Mean StdDev Change
  162. This function 508.8 23.4 185.4 9.0 +174.4%
  163. Overall 3068.5 31.7 2752.1 29.4 +11.5%
  164. In combination with the preceding patch:
  165. Before After
  166. Mean StdDev Mean StdDev Change
  167. Overall 2925.6 26.2 2752.1 29.4 +6.3%
  168. Signed-off-by: Martin Storsjö <martin@martin.st>
  169. ---
  170. lib/ffmpeg/libavcodec/arm/Makefile | 1 +
  171. lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S | 253 +++++++++++++++++++++++++++
  172. lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c | 4 +
  173. lib/ffmpeg/libavcodec/h264_parser.c | 1 -
  174. 4 files changed, 258 insertions(+), 1 deletion(-)
  175. create mode 100644 lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  176. diff --git a/lib/ffmpeg/libavcodec/arm/Makefile b/lib/ffmpeg/libavcodec/arm/Makefile
  177. index 7390a8b..480000b71 100644
  178. --- a/lib/ffmpeg/libavcodec/arm/Makefile
  179. +++ b/lib/ffmpeg/libavcodec/arm/Makefile
  180. @@ -9,6 +9,7 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/sbrdsp_init_arm.o \
  181. OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o \
  182. ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o
  183. +ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o
  184. OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \
  185. arm/flacdsp_arm.o \
  186. diff --git a/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S b/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  187. new file mode 100644
  188. index 0000000..c4f12a6
  189. --- /dev/null
  190. +++ b/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  191. @@ -0,0 +1,253 @@
  192. +/*
  193. + * Copyright (c) 2013 RISC OS Open Ltd
  194. + * Author: Ben Avison <bavison@riscosopen.org>
  195. + *
  196. + * This file is part of Libav.
  197. + *
  198. + * Libav is free software; you can redistribute it and/or
  199. + * modify it under the terms of the GNU Lesser General Public
  200. + * License as published by the Free Software Foundation; either
  201. + * version 2.1 of the License, or (at your option) any later version.
  202. + *
  203. + * Libav is distributed in the hope that it will be useful,
  204. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  205. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  206. + * Lesser General Public License for more details.
  207. + *
  208. + * You should have received a copy of the GNU Lesser General Public
  209. + * License along with Libav; if not, write to the Free Software
  210. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  211. + */
  212. +
  213. +#include "libavutil/arm/asm.S"
  214. +
  215. +RESULT .req a1
  216. +BUF .req a1
  217. +SIZE .req a2
  218. +PATTERN .req a3
  219. +PTR .req a4
  220. +DAT0 .req v1
  221. +DAT1 .req v2
  222. +DAT2 .req v3
  223. +DAT3 .req v4
  224. +TMP0 .req v5
  225. +TMP1 .req v6
  226. +TMP2 .req ip
  227. +TMP3 .req lr
  228. +
  229. +#define PRELOAD_DISTANCE 4
  230. +
  231. +.macro innerloop4
  232. + ldr DAT0, [PTR], #4
  233. + subs SIZE, SIZE, #4 @ C flag survives rest of macro
  234. + sub TMP0, DAT0, PATTERN, lsr #14
  235. + bic TMP0, TMP0, DAT0
  236. + ands TMP0, TMP0, PATTERN
  237. +.endm
  238. +
  239. +.macro innerloop16 decrement, do_preload
  240. + ldmia PTR!, {DAT0,DAT1,DAT2,DAT3}
  241. + .ifnc "\do_preload",""
  242. + pld [PTR, #PRELOAD_DISTANCE*32]
  243. + .endif
  244. + .ifnc "\decrement",""
  245. + subs SIZE, SIZE, #\decrement @ C flag survives rest of macro
  246. + .endif
  247. + sub TMP0, DAT0, PATTERN, lsr #14
  248. + sub TMP1, DAT1, PATTERN, lsr #14
  249. + bic TMP0, TMP0, DAT0
  250. + bic TMP1, TMP1, DAT1
  251. + sub TMP2, DAT2, PATTERN, lsr #14
  252. + sub TMP3, DAT3, PATTERN, lsr #14
  253. + ands TMP0, TMP0, PATTERN
  254. + bic TMP2, TMP2, DAT2
  255. + it eq
  256. + andseq TMP1, TMP1, PATTERN
  257. + bic TMP3, TMP3, DAT3
  258. + itt eq
  259. + andseq TMP2, TMP2, PATTERN
  260. + andseq TMP3, TMP3, PATTERN
  261. +.endm
  262. +
  263. +/* int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size) */
  264. +function ff_h264_find_start_code_candidate_armv6, export=1
  265. + push {v1-v6,lr}
  266. + mov PTR, BUF
  267. + @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go
  268. + @ before using code that does preloads
  269. + cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1
  270. + blo 60f
  271. +
  272. + @ Get to word-alignment, 1 byte at a time
  273. + tst PTR, #3
  274. + beq 2f
  275. +1: ldrb DAT0, [PTR], #1
  276. + sub SIZE, SIZE, #1
  277. + teq DAT0, #0
  278. + beq 90f
  279. + tst PTR, #3
  280. + bne 1b
  281. +2: @ Get to 4-word alignment, 1 word at a time
  282. + ldr PATTERN, =0x80008000
  283. + setend be
  284. + tst PTR, #12
  285. + beq 4f
  286. +3: innerloop4
  287. + bne 91f
  288. + tst PTR, #12
  289. + bne 3b
  290. +4: @ Get to cacheline (8-word) alignment
  291. + tst PTR, #16
  292. + beq 5f
  293. + innerloop16 16
  294. + bne 93f
  295. +5: @ Check complete cachelines, with preloading
  296. + @ We need to stop when there are still (PRELOAD_DISTANCE+1)
  297. + @ complete cachelines to go
  298. + sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32
  299. +6: innerloop16 , do_preload
  300. + bne 93f
  301. + innerloop16 32
  302. + bne 93f
  303. + bcs 6b
  304. + @ Preload trailing part-cacheline, if any
  305. + tst SIZE, #31
  306. + beq 7f
  307. + pld [PTR, #(PRELOAD_DISTANCE+1)*32]
  308. + @ Check remaining data without doing any more preloads. First
  309. + @ do in chunks of 4 words:
  310. +7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16
  311. + bmi 9f
  312. +8: innerloop16 16
  313. + bne 93f
  314. + bcs 8b
  315. + @ Then in words:
  316. +9: adds SIZE, SIZE, #16 - 4
  317. + bmi 11f
  318. +10: innerloop4
  319. + bne 91f
  320. + bcs 10b
  321. +11: setend le
  322. + @ Check second byte of final halfword
  323. + ldrb DAT0, [PTR, #-1]
  324. + teq DAT0, #0
  325. + beq 90f
  326. + @ Check any remaining bytes
  327. + tst SIZE, #3
  328. + beq 13f
  329. +12: ldrb DAT0, [PTR], #1
  330. + sub SIZE, SIZE, #1
  331. + teq DAT0, #0
  332. + beq 90f
  333. + tst SIZE, #3
  334. + bne 12b
  335. + @ No candidate found
  336. +13: sub RESULT, PTR, BUF
  337. + b 99f
  338. +
  339. +60: @ Small buffer - simply check by looping over bytes
  340. + subs SIZE, SIZE, #1
  341. + bcc 99f
  342. +61: ldrb DAT0, [PTR], #1
  343. + subs SIZE, SIZE, #1
  344. + teq DAT0, #0
  345. + beq 90f
  346. + bcs 61b
  347. + @ No candidate found
  348. + sub RESULT, PTR, BUF
  349. + b 99f
  350. +
  351. +90: @ Found a candidate at the preceding byte
  352. + sub RESULT, PTR, BUF
  353. + sub RESULT, RESULT, #1
  354. + b 99f
  355. +
  356. +91: @ Found a candidate somewhere in the preceding 4 bytes
  357. + sub RESULT, PTR, BUF
  358. + sub RESULT, RESULT, #4
  359. + sub TMP0, DAT0, #0x20000
  360. + bics TMP0, TMP0, DAT0
  361. + itt pl
  362. + ldrbpl DAT0, [PTR, #-3]
  363. + addpl RESULT, RESULT, #2
  364. + bpl 92f
  365. + teq RESULT, #0
  366. + beq 98f @ don't look back a byte if found at first byte in buffer
  367. + ldrb DAT0, [PTR, #-5]
  368. +92: teq DAT0, #0
  369. + it eq
  370. + subeq RESULT, RESULT, #1
  371. + b 98f
  372. +
  373. +93: @ Found a candidate somewhere in the preceding 16 bytes
  374. + sub RESULT, PTR, BUF
  375. + sub RESULT, RESULT, #16
  376. + teq TMP0, #0
  377. + beq 95f @ not in first 4 bytes
  378. + sub TMP0, DAT0, #0x20000
  379. + bics TMP0, TMP0, DAT0
  380. + itt pl
  381. + ldrbpl DAT0, [PTR, #-15]
  382. + addpl RESULT, RESULT, #2
  383. + bpl 94f
  384. + teq RESULT, #0
  385. + beq 98f @ don't look back a byte if found at first byte in buffer
  386. + ldrb DAT0, [PTR, #-17]
  387. +94: teq DAT0, #0
  388. + it eq
  389. + subeq RESULT, RESULT, #1
  390. + b 98f
  391. +95: add RESULT, RESULT, #4
  392. + teq TMP1, #0
  393. + beq 96f @ not in next 4 bytes
  394. + sub TMP1, DAT1, #0x20000
  395. + bics TMP1, TMP1, DAT1
  396. + itee mi
  397. + ldrbmi DAT0, [PTR, #-13]
  398. + ldrbpl DAT0, [PTR, #-11]
  399. + addpl RESULT, RESULT, #2
  400. + teq DAT0, #0
  401. + it eq
  402. + subeq RESULT, RESULT, #1
  403. + b 98f
  404. +96: add RESULT, RESULT, #4
  405. + teq TMP2, #0
  406. + beq 97f @ not in next 4 bytes
  407. + sub TMP2, DAT2, #0x20000
  408. + bics TMP2, TMP2, DAT2
  409. + itee mi
  410. + ldrbmi DAT0, [PTR, #-9]
  411. + ldrbpl DAT0, [PTR, #-7]
  412. + addpl RESULT, RESULT, #2
  413. + teq DAT0, #0
  414. + it eq
  415. + subeq RESULT, RESULT, #1
  416. + b 98f
  417. +97: add RESULT, RESULT, #4
  418. + sub TMP3, DAT3, #0x20000
  419. + bics TMP3, TMP3, DAT3
  420. + itee mi
  421. + ldrbmi DAT0, [PTR, #-5]
  422. + ldrbpl DAT0, [PTR, #-3]
  423. + addpl RESULT, RESULT, #2
  424. + teq DAT0, #0
  425. + it eq
  426. + subeq RESULT, RESULT, #1
  427. + @ drop through to 98f
  428. +98: setend le
  429. +99: pop {v1-v6,pc}
  430. +.endfunc
  431. +
  432. + .unreq RESULT
  433. + .unreq BUF
  434. + .unreq SIZE
  435. + .unreq PATTERN
  436. + .unreq PTR
  437. + .unreq DAT0
  438. + .unreq DAT1
  439. + .unreq DAT2
  440. + .unreq DAT3
  441. + .unreq TMP0
  442. + .unreq TMP1
  443. + .unreq TMP2
  444. + .unreq TMP3
  445. diff --git a/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  446. index 785b604..2804e56 100644
  447. --- a/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  448. +++ b/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  449. @@ -24,6 +24,8 @@
  450. #include "libavutil/arm/cpu.h"
  451. #include "libavcodec/h264dsp.h"
  452. +int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size);
  453. +
  454. void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha,
  455. int beta, int8_t *tc0);
  456. void ff_h264_h_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha,
  457. @@ -106,6 +108,8 @@ av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth,
  458. {
  459. int cpu_flags = av_get_cpu_flags();
  460. + if (have_armv6(cpu_flags))
  461. + c->h264_find_start_code_candidate = ff_h264_find_start_code_candidate_armv6;
  462. if (have_neon(cpu_flags))
  463. ff_h264dsp_init_neon(c, bit_depth, chroma_format_idc);
  464. }
  465. diff --git a/lib/ffmpeg/libavcodec/h264_parser.c b/lib/ffmpeg/libavcodec/h264_parser.c
  466. index 972aace..363843c 100644
  467. --- a/lib/ffmpeg/libavcodec/h264_parser.c
  468. +++ b/lib/ffmpeg/libavcodec/h264_parser.c
  469. @@ -65,7 +65,6 @@ static int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_si
  470. i += h->h264dsp.h264_find_start_code_candidate(buf + i, buf_size - i);
  471. if (i < buf_size)
  472. state = 2;
  473. - }
  474. }else if(state<=2){
  475. if(buf[i]==1) state^= 5; //2->7, 1->4, 0->5
  476. else if(buf[i]) state = 7;
  477. --
  478. 1.9.3
  479. From 5841d5b69f0df2f286c0a8e419deb16d927e864e Mon Sep 17 00:00:00 2001
  480. From: popcornmix <popcornmix@gmail.com>
  481. Date: Mon, 19 Aug 2013 22:48:05 +0100
  482. Subject: [PATCH 04/94] [ffmpeg] Backport of h264_find_start_code_candidate
  483. optimisation
  484. ---
  485. ...-Initialize-the-h264dsp-context-in-the-pa.patch | 39 +++
  486. ...torize-code-into-a-new-function-h264_find.patch | 134 +++++++++
  487. ...embly-version-of-h264_find_start_code_can.patch | 322 +++++++++++++++++++++
  488. 3 files changed, 495 insertions(+)
  489. create mode 100644 lib/ffmpeg/patches/0056-h264_parser-Initialize-the-h264dsp-context-in-the-pa.patch
  490. create mode 100644 lib/ffmpeg/patches/0057-h264dsp-Factorize-code-into-a-new-function-h264_find.patch
  491. create mode 100644 lib/ffmpeg/patches/0058-arm-Add-assembly-version-of-h264_find_start_code_can.patch
  492. diff --git a/lib/ffmpeg/patches/0056-h264_parser-Initialize-the-h264dsp-context-in-the-pa.patch b/lib/ffmpeg/patches/0056-h264_parser-Initialize-the-h264dsp-context-in-the-pa.patch
  493. new file mode 100644
  494. index 0000000..263578d
  495. --- /dev/null
  496. +++ b/lib/ffmpeg/patches/0056-h264_parser-Initialize-the-h264dsp-context-in-the-pa.patch
  497. @@ -0,0 +1,39 @@
  498. +From 7a82022ee2f9b1fad991ace0936901e7419444be Mon Sep 17 00:00:00 2001
  499. +From: Ben Avison <bavison@riscosopen.org>
  500. +Date: Mon, 5 Aug 2013 13:12:46 +0100
  501. +Subject: [PATCH 1/3] h264_parser: Initialize the h264dsp context in the
  502. + parser as well
  503. +MIME-Version: 1.0
  504. +Content-Type: text/plain; charset=UTF-8
  505. +Content-Transfer-Encoding: 8bit
  506. +
  507. +Each AVStream struct for an H.264 elementary stream actually has two
  508. +copies of the H264DSPContext struct (and in fact all the other members
  509. +of H264Context as well):
  510. +
  511. +((H264Context *) ((AVStream *)st)->codec->priv_data)->h264dsp
  512. +((H264Context *) ((AVStream *)st)->parser->priv_data)->h264dsp
  513. +
  514. +but only the first of these was actually being initialised. This
  515. +prevented the addition of platform-specific implementations of
  516. +parser-related functions.
  517. +
  518. +Signed-off-by: Martin Storsjö <martin@martin.st>
  519. +---
  520. + libavcodec/h264_parser.c | 1 +
  521. + 1 file changed, 1 insertion(+)
  522. +
  523. +diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
  524. +index 2ed155c..da2a5f9 100644
  525. +--- a/libavcodec/h264_parser.c
  526. ++++ b/libavcodec/h264_parser.c
  527. +@@ -417,6 +417,7 @@ static av_cold int init(AVCodecParserContext *s)
  528. + H264Context *h = s->priv_data;
  529. + h->thread_context[0] = h;
  530. + h->slice_context_count = 1;
  531. ++ ff_h264dsp_init(&h->h264dsp, 8, 1);
  532. + return 0;
  533. + }
  534. +
  535. +--
  536. +1.7.9.5
  537. diff --git a/lib/ffmpeg/patches/0057-h264dsp-Factorize-code-into-a-new-function-h264_find.patch b/lib/ffmpeg/patches/0057-h264dsp-Factorize-code-into-a-new-function-h264_find.patch
  538. new file mode 100644
  539. index 0000000..0151d85
  540. --- /dev/null
  541. +++ b/lib/ffmpeg/patches/0057-h264dsp-Factorize-code-into-a-new-function-h264_find.patch
  542. @@ -0,0 +1,134 @@
  543. +From 218d6844b37d339ffbf2044ad07d8be7767e2734 Mon Sep 17 00:00:00 2001
  544. +From: Ben Avison <bavison@riscosopen.org>
  545. +Date: Mon, 5 Aug 2013 13:12:47 +0100
  546. +Subject: [PATCH 2/3] h264dsp: Factorize code into a new function,
  547. + h264_find_start_code_candidate
  548. +MIME-Version: 1.0
  549. +Content-Type: text/plain; charset=UTF-8
  550. +Content-Transfer-Encoding: 8bit
  551. +
  552. +This performs the start code search which was previously part of
  553. +h264_find_frame_end() - the most CPU intensive part of the function.
  554. +
  555. +By itself, this results in a performance regression:
  556. + Before After
  557. + Mean StdDev Mean StdDev Change
  558. +Overall time 2925.6 26.2 3068.5 31.7 -4.7%
  559. +
  560. +but this can more than be made up for by platform-optimised
  561. +implementations of the function.
  562. +
  563. +Signed-off-by: Martin Storsjö <martin@martin.st>
  564. +---
  565. + libavcodec/h264_parser.c | 27 +++------------------------
  566. + libavcodec/h264dsp.c | 29 +++++++++++++++++++++++++++++
  567. + libavcodec/h264dsp.h | 9 +++++++++
  568. + 3 files changed, 41 insertions(+), 24 deletions(-)
  569. +
  570. +diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c
  571. +index da2a5f9..ef5da98 100644
  572. +--- a/libavcodec/h264_parser.c
  573. ++++ b/libavcodec/h264_parser.c
  574. +@@ -47,30 +47,9 @@ static int h264_find_frame_end(H264Context *h, const uint8_t *buf,
  575. +
  576. + for (i = 0; i < buf_size; i++) {
  577. + if (state == 7) {
  578. +-#if HAVE_FAST_UNALIGNED
  579. +- /* we check i < buf_size instead of i + 3 / 7 because it is
  580. +- * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE
  581. +- * bytes at the end.
  582. +- */
  583. +-#if HAVE_FAST_64BIT
  584. +- while (i < buf_size &&
  585. +- !((~*(const uint64_t *)(buf + i) &
  586. +- (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) &
  587. +- 0x8080808080808080ULL))
  588. +- i += 8;
  589. +-#else
  590. +- while (i < buf_size &&
  591. +- !((~*(const uint32_t *)(buf + i) &
  592. +- (*(const uint32_t *)(buf + i) - 0x01010101U)) &
  593. +- 0x80808080U))
  594. +- i += 4;
  595. +-#endif
  596. +-#endif
  597. +- for (; i < buf_size; i++)
  598. +- if (!buf[i]) {
  599. +- state = 2;
  600. +- break;
  601. +- }
  602. ++ i += h->h264dsp.h264_find_start_code_candidate(buf + i, buf_size - i);
  603. ++ if (i < buf_size)
  604. ++ state = 2;
  605. + } else if (state <= 2) {
  606. + if (buf[i] == 1)
  607. + state ^= 5; // 2->7, 1->4, 0->5
  608. +diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c
  609. +index 3ca6abe..a901dbb 100644
  610. +--- a/libavcodec/h264dsp.c
  611. ++++ b/libavcodec/h264dsp.c
  612. +@@ -53,6 +53,34 @@
  613. + #include "h264addpx_template.c"
  614. + #undef BIT_DEPTH
  615. +
  616. ++static int h264_find_start_code_candidate_c(const uint8_t *buf, int size)
  617. ++{
  618. ++ int i = 0;
  619. ++#if HAVE_FAST_UNALIGNED
  620. ++ /* we check i < size instead of i + 3 / 7 because it is
  621. ++ * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE
  622. ++ * bytes at the end.
  623. ++ */
  624. ++#if HAVE_FAST_64BIT
  625. ++ while (i < size &&
  626. ++ !((~*(const uint64_t *)(buf + i) &
  627. ++ (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) &
  628. ++ 0x8080808080808080ULL))
  629. ++ i += 8;
  630. ++#else
  631. ++ while (i < size &&
  632. ++ !((~*(const uint32_t *)(buf + i) &
  633. ++ (*(const uint32_t *)(buf + i) - 0x01010101U)) &
  634. ++ 0x80808080U))
  635. ++ i += 4;
  636. ++#endif
  637. ++#endif
  638. ++ for (; i < size; i++)
  639. ++ if (!buf[i])
  640. ++ break;
  641. ++ return i;
  642. ++}
  643. ++
  644. + av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,
  645. + const int chroma_format_idc)
  646. + {
  647. +@@ -133,6 +161,7 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,
  648. + H264_DSP(8);
  649. + break;
  650. + }
  651. ++ c->h264_find_start_code_candidate = h264_find_start_code_candidate_c;
  652. +
  653. + if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc);
  654. + if (ARCH_PPC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc);
  655. +diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h
  656. +index 1f9f8fe..6249ba7 100644
  657. +--- a/libavcodec/h264dsp.h
  658. ++++ b/libavcodec/h264dsp.h
  659. +@@ -105,6 +105,15 @@ typedef struct H264DSPContext {
  660. + /* bypass-transform */
  661. + void (*h264_add_pixels8_clear)(uint8_t *dst, int16_t *block, int stride);
  662. + void (*h264_add_pixels4_clear)(uint8_t *dst, int16_t *block, int stride);
  663. ++
  664. ++ /**
  665. ++ * Search buf from the start for up to size bytes. Return the index
  666. ++ * of a zero byte, or >= size if not found. Ideally, use lookahead
  667. ++ * to filter out any zero bytes that are known to not be followed by
  668. ++ * one or more further zero bytes and a one byte. Better still, filter
  669. ++ * out any bytes that form the trailing_zero_8bits syntax element too.
  670. ++ */
  671. ++ int (*h264_find_start_code_candidate)(const uint8_t *buf, int size);
  672. + } H264DSPContext;
  673. +
  674. + void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,
  675. +--
  676. +1.7.9.5
  677. diff --git a/lib/ffmpeg/patches/0058-arm-Add-assembly-version-of-h264_find_start_code_can.patch b/lib/ffmpeg/patches/0058-arm-Add-assembly-version-of-h264_find_start_code_can.patch
  678. new file mode 100644
  679. index 0000000..cdc2d1e
  680. --- /dev/null
  681. +++ b/lib/ffmpeg/patches/0058-arm-Add-assembly-version-of-h264_find_start_code_can.patch
  682. @@ -0,0 +1,322 @@
  683. +From 45e10e5c8d3df09c80a4d80483bff2712367f3fa Mon Sep 17 00:00:00 2001
  684. +From: Ben Avison <bavison@riscosopen.org>
  685. +Date: Mon, 5 Aug 2013 13:12:48 +0100
  686. +Subject: [PATCH 3/3] arm: Add assembly version of
  687. + h264_find_start_code_candidate
  688. +MIME-Version: 1.0
  689. +Content-Type: text/plain; charset=UTF-8
  690. +Content-Transfer-Encoding: 8bit
  691. +
  692. + Before After
  693. + Mean StdDev Mean StdDev Change
  694. +This function 508.8 23.4 185.4 9.0 +174.4%
  695. +Overall 3068.5 31.7 2752.1 29.4 +11.5%
  696. +
  697. +In combination with the preceding patch:
  698. + Before After
  699. + Mean StdDev Mean StdDev Change
  700. +Overall 2925.6 26.2 2752.1 29.4 +6.3%
  701. +
  702. +Signed-off-by: Martin Storsjö <martin@martin.st>
  703. +---
  704. + libavcodec/arm/Makefile | 1 +
  705. + libavcodec/arm/h264dsp_armv6.S | 253 +++++++++++++++++++++++++++++++++++++
  706. + libavcodec/arm/h264dsp_init_arm.c | 4 +
  707. + 3 files changed, 258 insertions(+)
  708. + create mode 100644 libavcodec/arm/h264dsp_armv6.S
  709. +
  710. +diff --git a/libavcodec/arm/Makefile b/libavcodec/arm/Makefile
  711. +index e941aaa..9c64b36 100644
  712. +--- a/libavcodec/arm/Makefile
  713. ++++ b/libavcodec/arm/Makefile
  714. +@@ -45,6 +45,7 @@ ARMV6-OBJS-$(CONFIG_DSPUTIL) += arm/dsputil_init_armv6.o \
  715. + arm/simple_idct_armv6.o \
  716. +
  717. + ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o
  718. ++ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o
  719. + ARMV6-OBJS-$(CONFIG_HPELDSP) += arm/hpeldsp_init_armv6.o \
  720. + arm/hpeldsp_armv6.o
  721. + ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o
  722. +diff --git a/libavcodec/arm/h264dsp_armv6.S b/libavcodec/arm/h264dsp_armv6.S
  723. +new file mode 100644
  724. +index 0000000..c4f12a6
  725. +--- /dev/null
  726. ++++ b/libavcodec/arm/h264dsp_armv6.S
  727. +@@ -0,0 +1,253 @@
  728. ++/*
  729. ++ * Copyright (c) 2013 RISC OS Open Ltd
  730. ++ * Author: Ben Avison <bavison@riscosopen.org>
  731. ++ *
  732. ++ * This file is part of Libav.
  733. ++ *
  734. ++ * Libav is free software; you can redistribute it and/or
  735. ++ * modify it under the terms of the GNU Lesser General Public
  736. ++ * License as published by the Free Software Foundation; either
  737. ++ * version 2.1 of the License, or (at your option) any later version.
  738. ++ *
  739. ++ * Libav is distributed in the hope that it will be useful,
  740. ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
  741. ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  742. ++ * Lesser General Public License for more details.
  743. ++ *
  744. ++ * You should have received a copy of the GNU Lesser General Public
  745. ++ * License along with Libav; if not, write to the Free Software
  746. ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  747. ++ */
  748. ++
  749. ++#include "libavutil/arm/asm.S"
  750. ++
  751. ++RESULT .req a1
  752. ++BUF .req a1
  753. ++SIZE .req a2
  754. ++PATTERN .req a3
  755. ++PTR .req a4
  756. ++DAT0 .req v1
  757. ++DAT1 .req v2
  758. ++DAT2 .req v3
  759. ++DAT3 .req v4
  760. ++TMP0 .req v5
  761. ++TMP1 .req v6
  762. ++TMP2 .req ip
  763. ++TMP3 .req lr
  764. ++
  765. ++#define PRELOAD_DISTANCE 4
  766. ++
  767. ++.macro innerloop4
  768. ++ ldr DAT0, [PTR], #4
  769. ++ subs SIZE, SIZE, #4 @ C flag survives rest of macro
  770. ++ sub TMP0, DAT0, PATTERN, lsr #14
  771. ++ bic TMP0, TMP0, DAT0
  772. ++ ands TMP0, TMP0, PATTERN
  773. ++.endm
  774. ++
  775. ++.macro innerloop16 decrement, do_preload
  776. ++ ldmia PTR!, {DAT0,DAT1,DAT2,DAT3}
  777. ++ .ifnc "\do_preload",""
  778. ++ pld [PTR, #PRELOAD_DISTANCE*32]
  779. ++ .endif
  780. ++ .ifnc "\decrement",""
  781. ++ subs SIZE, SIZE, #\decrement @ C flag survives rest of macro
  782. ++ .endif
  783. ++ sub TMP0, DAT0, PATTERN, lsr #14
  784. ++ sub TMP1, DAT1, PATTERN, lsr #14
  785. ++ bic TMP0, TMP0, DAT0
  786. ++ bic TMP1, TMP1, DAT1
  787. ++ sub TMP2, DAT2, PATTERN, lsr #14
  788. ++ sub TMP3, DAT3, PATTERN, lsr #14
  789. ++ ands TMP0, TMP0, PATTERN
  790. ++ bic TMP2, TMP2, DAT2
  791. ++ it eq
  792. ++ andseq TMP1, TMP1, PATTERN
  793. ++ bic TMP3, TMP3, DAT3
  794. ++ itt eq
  795. ++ andseq TMP2, TMP2, PATTERN
  796. ++ andseq TMP3, TMP3, PATTERN
  797. ++.endm
  798. ++
  799. ++/* int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size) */
  800. ++function ff_h264_find_start_code_candidate_armv6, export=1
  801. ++ push {v1-v6,lr}
  802. ++ mov PTR, BUF
  803. ++ @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go
  804. ++ @ before using code that does preloads
  805. ++ cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1
  806. ++ blo 60f
  807. ++
  808. ++ @ Get to word-alignment, 1 byte at a time
  809. ++ tst PTR, #3
  810. ++ beq 2f
  811. ++1: ldrb DAT0, [PTR], #1
  812. ++ sub SIZE, SIZE, #1
  813. ++ teq DAT0, #0
  814. ++ beq 90f
  815. ++ tst PTR, #3
  816. ++ bne 1b
  817. ++2: @ Get to 4-word alignment, 1 word at a time
  818. ++ ldr PATTERN, =0x80008000
  819. ++ setend be
  820. ++ tst PTR, #12
  821. ++ beq 4f
  822. ++3: innerloop4
  823. ++ bne 91f
  824. ++ tst PTR, #12
  825. ++ bne 3b
  826. ++4: @ Get to cacheline (8-word) alignment
  827. ++ tst PTR, #16
  828. ++ beq 5f
  829. ++ innerloop16 16
  830. ++ bne 93f
  831. ++5: @ Check complete cachelines, with preloading
  832. ++ @ We need to stop when there are still (PRELOAD_DISTANCE+1)
  833. ++ @ complete cachelines to go
  834. ++ sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32
  835. ++6: innerloop16 , do_preload
  836. ++ bne 93f
  837. ++ innerloop16 32
  838. ++ bne 93f
  839. ++ bcs 6b
  840. ++ @ Preload trailing part-cacheline, if any
  841. ++ tst SIZE, #31
  842. ++ beq 7f
  843. ++ pld [PTR, #(PRELOAD_DISTANCE+1)*32]
  844. ++ @ Check remaining data without doing any more preloads. First
  845. ++ @ do in chunks of 4 words:
  846. ++7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16
  847. ++ bmi 9f
  848. ++8: innerloop16 16
  849. ++ bne 93f
  850. ++ bcs 8b
  851. ++ @ Then in words:
  852. ++9: adds SIZE, SIZE, #16 - 4
  853. ++ bmi 11f
  854. ++10: innerloop4
  855. ++ bne 91f
  856. ++ bcs 10b
  857. ++11: setend le
  858. ++ @ Check second byte of final halfword
  859. ++ ldrb DAT0, [PTR, #-1]
  860. ++ teq DAT0, #0
  861. ++ beq 90f
  862. ++ @ Check any remaining bytes
  863. ++ tst SIZE, #3
  864. ++ beq 13f
  865. ++12: ldrb DAT0, [PTR], #1
  866. ++ sub SIZE, SIZE, #1
  867. ++ teq DAT0, #0
  868. ++ beq 90f
  869. ++ tst SIZE, #3
  870. ++ bne 12b
  871. ++ @ No candidate found
  872. ++13: sub RESULT, PTR, BUF
  873. ++ b 99f
  874. ++
  875. ++60: @ Small buffer - simply check by looping over bytes
  876. ++ subs SIZE, SIZE, #1
  877. ++ bcc 99f
  878. ++61: ldrb DAT0, [PTR], #1
  879. ++ subs SIZE, SIZE, #1
  880. ++ teq DAT0, #0
  881. ++ beq 90f
  882. ++ bcs 61b
  883. ++ @ No candidate found
  884. ++ sub RESULT, PTR, BUF
  885. ++ b 99f
  886. ++
  887. ++90: @ Found a candidate at the preceding byte
  888. ++ sub RESULT, PTR, BUF
  889. ++ sub RESULT, RESULT, #1
  890. ++ b 99f
  891. ++
  892. ++91: @ Found a candidate somewhere in the preceding 4 bytes
  893. ++ sub RESULT, PTR, BUF
  894. ++ sub RESULT, RESULT, #4
  895. ++ sub TMP0, DAT0, #0x20000
  896. ++ bics TMP0, TMP0, DAT0
  897. ++ itt pl
  898. ++ ldrbpl DAT0, [PTR, #-3]
  899. ++ addpl RESULT, RESULT, #2
  900. ++ bpl 92f
  901. ++ teq RESULT, #0
  902. ++ beq 98f @ don't look back a byte if found at first byte in buffer
  903. ++ ldrb DAT0, [PTR, #-5]
  904. ++92: teq DAT0, #0
  905. ++ it eq
  906. ++ subeq RESULT, RESULT, #1
  907. ++ b 98f
  908. ++
  909. ++93: @ Found a candidate somewhere in the preceding 16 bytes
  910. ++ sub RESULT, PTR, BUF
  911. ++ sub RESULT, RESULT, #16
  912. ++ teq TMP0, #0
  913. ++ beq 95f @ not in first 4 bytes
  914. ++ sub TMP0, DAT0, #0x20000
  915. ++ bics TMP0, TMP0, DAT0
  916. ++ itt pl
  917. ++ ldrbpl DAT0, [PTR, #-15]
  918. ++ addpl RESULT, RESULT, #2
  919. ++ bpl 94f
  920. ++ teq RESULT, #0
  921. ++ beq 98f @ don't look back a byte if found at first byte in buffer
  922. ++ ldrb DAT0, [PTR, #-17]
  923. ++94: teq DAT0, #0
  924. ++ it eq
  925. ++ subeq RESULT, RESULT, #1
  926. ++ b 98f
  927. ++95: add RESULT, RESULT, #4
  928. ++ teq TMP1, #0
  929. ++ beq 96f @ not in next 4 bytes
  930. ++ sub TMP1, DAT1, #0x20000
  931. ++ bics TMP1, TMP1, DAT1
  932. ++ itee mi
  933. ++ ldrbmi DAT0, [PTR, #-13]
  934. ++ ldrbpl DAT0, [PTR, #-11]
  935. ++ addpl RESULT, RESULT, #2
  936. ++ teq DAT0, #0
  937. ++ it eq
  938. ++ subeq RESULT, RESULT, #1
  939. ++ b 98f
  940. ++96: add RESULT, RESULT, #4
  941. ++ teq TMP2, #0
  942. ++ beq 97f @ not in next 4 bytes
  943. ++ sub TMP2, DAT2, #0x20000
  944. ++ bics TMP2, TMP2, DAT2
  945. ++ itee mi
  946. ++ ldrbmi DAT0, [PTR, #-9]
  947. ++ ldrbpl DAT0, [PTR, #-7]
  948. ++ addpl RESULT, RESULT, #2
  949. ++ teq DAT0, #0
  950. ++ it eq
  951. ++ subeq RESULT, RESULT, #1
  952. ++ b 98f
  953. ++97: add RESULT, RESULT, #4
  954. ++ sub TMP3, DAT3, #0x20000
  955. ++ bics TMP3, TMP3, DAT3
  956. ++ itee mi
  957. ++ ldrbmi DAT0, [PTR, #-5]
  958. ++ ldrbpl DAT0, [PTR, #-3]
  959. ++ addpl RESULT, RESULT, #2
  960. ++ teq DAT0, #0
  961. ++ it eq
  962. ++ subeq RESULT, RESULT, #1
  963. ++ @ drop through to 98f
  964. ++98: setend le
  965. ++99: pop {v1-v6,pc}
  966. ++.endfunc
  967. ++
  968. ++ .unreq RESULT
  969. ++ .unreq BUF
  970. ++ .unreq SIZE
  971. ++ .unreq PATTERN
  972. ++ .unreq PTR
  973. ++ .unreq DAT0
  974. ++ .unreq DAT1
  975. ++ .unreq DAT2
  976. ++ .unreq DAT3
  977. ++ .unreq TMP0
  978. ++ .unreq TMP1
  979. ++ .unreq TMP2
  980. ++ .unreq TMP3
  981. +diff --git a/libavcodec/arm/h264dsp_init_arm.c b/libavcodec/arm/h264dsp_init_arm.c
  982. +index bb8b3b9..b206a1b 100644
  983. +--- a/libavcodec/arm/h264dsp_init_arm.c
  984. ++++ b/libavcodec/arm/h264dsp_init_arm.c
  985. +@@ -24,6 +24,8 @@
  986. + #include "libavutil/arm/cpu.h"
  987. + #include "libavcodec/h264dsp.h"
  988. +
  989. ++int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size);
  990. ++
  991. + void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha,
  992. + int beta, int8_t *tc0);
  993. + void ff_h264_h_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha,
  994. +@@ -102,6 +104,8 @@ av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth,
  995. + {
  996. + int cpu_flags = av_get_cpu_flags();
  997. +
  998. ++ if (have_armv6(cpu_flags))
  999. ++ c->h264_find_start_code_candidate = ff_h264_find_start_code_candidate_armv6;
  1000. + if (have_neon(cpu_flags))
  1001. + h264dsp_init_neon(c, bit_depth, chroma_format_idc);
  1002. + }
  1003. +--
  1004. +1.7.9.5
  1005. --
  1006. 1.9.3
  1007. From db098a580259625bb7b7385a48cb0756aea5cafe Mon Sep 17 00:00:00 2001
  1008. From: Ben Avison <bavison@riscosopen.org>
  1009. Date: Wed, 16 Apr 2014 01:51:31 +0100
  1010. Subject: [PATCH 05/94] h264: Move search code search functions into separate
  1011. source files.
  1012. This permits re-use with parsers for codecs which use similar start codes.
  1013. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
  1014. ---
  1015. lib/ffmpeg/libavcodec/Makefile | 2 +-
  1016. lib/ffmpeg/libavcodec/arm/Makefile | 2 +-
  1017. lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S | 253 ---------------------------
  1018. lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c | 4 +-
  1019. lib/ffmpeg/libavcodec/arm/startcode_armv6.S | 253 +++++++++++++++++++++++++++
  1020. lib/ffmpeg/libavcodec/h264dsp.c | 31 +---
  1021. lib/ffmpeg/libavcodec/startcode.c | 57 ++++++
  1022. lib/ffmpeg/libavcodec/startcode.h | 35 ++++
  1023. 8 files changed, 351 insertions(+), 286 deletions(-)
  1024. delete mode 100644 lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  1025. create mode 100644 lib/ffmpeg/libavcodec/arm/startcode_armv6.S
  1026. create mode 100644 lib/ffmpeg/libavcodec/startcode.c
  1027. create mode 100644 lib/ffmpeg/libavcodec/startcode.h
  1028. diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile
  1029. index dc065a5..460f42c 100644
  1030. --- a/lib/ffmpeg/libavcodec/Makefile
  1031. +++ b/lib/ffmpeg/libavcodec/Makefile
  1032. @@ -49,7 +49,7 @@ OBJS-$(CONFIG_FFT) += avfft.o fft_fixed.o fft_float.o \
  1033. $(FFT-OBJS-yes)
  1034. OBJS-$(CONFIG_GOLOMB) += golomb.o
  1035. OBJS-$(CONFIG_H264CHROMA) += h264chroma.o
  1036. -OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o
  1037. +OBJS-$(CONFIG_H264DSP) += h264dsp.o h264idct.o startcode.o
  1038. OBJS-$(CONFIG_H264PRED) += h264pred.o
  1039. OBJS-$(CONFIG_H264QPEL) += h264qpel.o
  1040. OBJS-$(CONFIG_HUFFMAN) += huffman.o
  1041. diff --git a/lib/ffmpeg/libavcodec/arm/Makefile b/lib/ffmpeg/libavcodec/arm/Makefile
  1042. index 480000b71..0b432e3 100644
  1043. --- a/lib/ffmpeg/libavcodec/arm/Makefile
  1044. +++ b/lib/ffmpeg/libavcodec/arm/Makefile
  1045. @@ -9,7 +9,7 @@ OBJS-$(CONFIG_AAC_DECODER) += arm/sbrdsp_init_arm.o \
  1046. OBJS-$(CONFIG_DCA_DECODER) += arm/dcadsp_init_arm.o \
  1047. ARMV6-OBJS-$(CONFIG_AC3DSP) += arm/ac3dsp_armv6.o
  1048. -ARMV6-OBJS-$(CONFIG_H264DSP) += arm/h264dsp_armv6.o
  1049. +ARMV6-OBJS-$(CONFIG_H264DSP) += arm/startcode_armv6.o
  1050. OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \
  1051. arm/flacdsp_arm.o \
  1052. diff --git a/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S b/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  1053. deleted file mode 100644
  1054. index c4f12a6..0000000
  1055. --- a/lib/ffmpeg/libavcodec/arm/h264dsp_armv6.S
  1056. +++ /dev/null
  1057. @@ -1,253 +0,0 @@
  1058. -/*
  1059. - * Copyright (c) 2013 RISC OS Open Ltd
  1060. - * Author: Ben Avison <bavison@riscosopen.org>
  1061. - *
  1062. - * This file is part of Libav.
  1063. - *
  1064. - * Libav is free software; you can redistribute it and/or
  1065. - * modify it under the terms of the GNU Lesser General Public
  1066. - * License as published by the Free Software Foundation; either
  1067. - * version 2.1 of the License, or (at your option) any later version.
  1068. - *
  1069. - * Libav is distributed in the hope that it will be useful,
  1070. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1071. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1072. - * Lesser General Public License for more details.
  1073. - *
  1074. - * You should have received a copy of the GNU Lesser General Public
  1075. - * License along with Libav; if not, write to the Free Software
  1076. - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  1077. - */
  1078. -
  1079. -#include "libavutil/arm/asm.S"
  1080. -
  1081. -RESULT .req a1
  1082. -BUF .req a1
  1083. -SIZE .req a2
  1084. -PATTERN .req a3
  1085. -PTR .req a4
  1086. -DAT0 .req v1
  1087. -DAT1 .req v2
  1088. -DAT2 .req v3
  1089. -DAT3 .req v4
  1090. -TMP0 .req v5
  1091. -TMP1 .req v6
  1092. -TMP2 .req ip
  1093. -TMP3 .req lr
  1094. -
  1095. -#define PRELOAD_DISTANCE 4
  1096. -
  1097. -.macro innerloop4
  1098. - ldr DAT0, [PTR], #4
  1099. - subs SIZE, SIZE, #4 @ C flag survives rest of macro
  1100. - sub TMP0, DAT0, PATTERN, lsr #14
  1101. - bic TMP0, TMP0, DAT0
  1102. - ands TMP0, TMP0, PATTERN
  1103. -.endm
  1104. -
  1105. -.macro innerloop16 decrement, do_preload
  1106. - ldmia PTR!, {DAT0,DAT1,DAT2,DAT3}
  1107. - .ifnc "\do_preload",""
  1108. - pld [PTR, #PRELOAD_DISTANCE*32]
  1109. - .endif
  1110. - .ifnc "\decrement",""
  1111. - subs SIZE, SIZE, #\decrement @ C flag survives rest of macro
  1112. - .endif
  1113. - sub TMP0, DAT0, PATTERN, lsr #14
  1114. - sub TMP1, DAT1, PATTERN, lsr #14
  1115. - bic TMP0, TMP0, DAT0
  1116. - bic TMP1, TMP1, DAT1
  1117. - sub TMP2, DAT2, PATTERN, lsr #14
  1118. - sub TMP3, DAT3, PATTERN, lsr #14
  1119. - ands TMP0, TMP0, PATTERN
  1120. - bic TMP2, TMP2, DAT2
  1121. - it eq
  1122. - andseq TMP1, TMP1, PATTERN
  1123. - bic TMP3, TMP3, DAT3
  1124. - itt eq
  1125. - andseq TMP2, TMP2, PATTERN
  1126. - andseq TMP3, TMP3, PATTERN
  1127. -.endm
  1128. -
  1129. -/* int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size) */
  1130. -function ff_h264_find_start_code_candidate_armv6, export=1
  1131. - push {v1-v6,lr}
  1132. - mov PTR, BUF
  1133. - @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go
  1134. - @ before using code that does preloads
  1135. - cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1
  1136. - blo 60f
  1137. -
  1138. - @ Get to word-alignment, 1 byte at a time
  1139. - tst PTR, #3
  1140. - beq 2f
  1141. -1: ldrb DAT0, [PTR], #1
  1142. - sub SIZE, SIZE, #1
  1143. - teq DAT0, #0
  1144. - beq 90f
  1145. - tst PTR, #3
  1146. - bne 1b
  1147. -2: @ Get to 4-word alignment, 1 word at a time
  1148. - ldr PATTERN, =0x80008000
  1149. - setend be
  1150. - tst PTR, #12
  1151. - beq 4f
  1152. -3: innerloop4
  1153. - bne 91f
  1154. - tst PTR, #12
  1155. - bne 3b
  1156. -4: @ Get to cacheline (8-word) alignment
  1157. - tst PTR, #16
  1158. - beq 5f
  1159. - innerloop16 16
  1160. - bne 93f
  1161. -5: @ Check complete cachelines, with preloading
  1162. - @ We need to stop when there are still (PRELOAD_DISTANCE+1)
  1163. - @ complete cachelines to go
  1164. - sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32
  1165. -6: innerloop16 , do_preload
  1166. - bne 93f
  1167. - innerloop16 32
  1168. - bne 93f
  1169. - bcs 6b
  1170. - @ Preload trailing part-cacheline, if any
  1171. - tst SIZE, #31
  1172. - beq 7f
  1173. - pld [PTR, #(PRELOAD_DISTANCE+1)*32]
  1174. - @ Check remaining data without doing any more preloads. First
  1175. - @ do in chunks of 4 words:
  1176. -7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16
  1177. - bmi 9f
  1178. -8: innerloop16 16
  1179. - bne 93f
  1180. - bcs 8b
  1181. - @ Then in words:
  1182. -9: adds SIZE, SIZE, #16 - 4
  1183. - bmi 11f
  1184. -10: innerloop4
  1185. - bne 91f
  1186. - bcs 10b
  1187. -11: setend le
  1188. - @ Check second byte of final halfword
  1189. - ldrb DAT0, [PTR, #-1]
  1190. - teq DAT0, #0
  1191. - beq 90f
  1192. - @ Check any remaining bytes
  1193. - tst SIZE, #3
  1194. - beq 13f
  1195. -12: ldrb DAT0, [PTR], #1
  1196. - sub SIZE, SIZE, #1
  1197. - teq DAT0, #0
  1198. - beq 90f
  1199. - tst SIZE, #3
  1200. - bne 12b
  1201. - @ No candidate found
  1202. -13: sub RESULT, PTR, BUF
  1203. - b 99f
  1204. -
  1205. -60: @ Small buffer - simply check by looping over bytes
  1206. - subs SIZE, SIZE, #1
  1207. - bcc 99f
  1208. -61: ldrb DAT0, [PTR], #1
  1209. - subs SIZE, SIZE, #1
  1210. - teq DAT0, #0
  1211. - beq 90f
  1212. - bcs 61b
  1213. - @ No candidate found
  1214. - sub RESULT, PTR, BUF
  1215. - b 99f
  1216. -
  1217. -90: @ Found a candidate at the preceding byte
  1218. - sub RESULT, PTR, BUF
  1219. - sub RESULT, RESULT, #1
  1220. - b 99f
  1221. -
  1222. -91: @ Found a candidate somewhere in the preceding 4 bytes
  1223. - sub RESULT, PTR, BUF
  1224. - sub RESULT, RESULT, #4
  1225. - sub TMP0, DAT0, #0x20000
  1226. - bics TMP0, TMP0, DAT0
  1227. - itt pl
  1228. - ldrbpl DAT0, [PTR, #-3]
  1229. - addpl RESULT, RESULT, #2
  1230. - bpl 92f
  1231. - teq RESULT, #0
  1232. - beq 98f @ don't look back a byte if found at first byte in buffer
  1233. - ldrb DAT0, [PTR, #-5]
  1234. -92: teq DAT0, #0
  1235. - it eq
  1236. - subeq RESULT, RESULT, #1
  1237. - b 98f
  1238. -
  1239. -93: @ Found a candidate somewhere in the preceding 16 bytes
  1240. - sub RESULT, PTR, BUF
  1241. - sub RESULT, RESULT, #16
  1242. - teq TMP0, #0
  1243. - beq 95f @ not in first 4 bytes
  1244. - sub TMP0, DAT0, #0x20000
  1245. - bics TMP0, TMP0, DAT0
  1246. - itt pl
  1247. - ldrbpl DAT0, [PTR, #-15]
  1248. - addpl RESULT, RESULT, #2
  1249. - bpl 94f
  1250. - teq RESULT, #0
  1251. - beq 98f @ don't look back a byte if found at first byte in buffer
  1252. - ldrb DAT0, [PTR, #-17]
  1253. -94: teq DAT0, #0
  1254. - it eq
  1255. - subeq RESULT, RESULT, #1
  1256. - b 98f
  1257. -95: add RESULT, RESULT, #4
  1258. - teq TMP1, #0
  1259. - beq 96f @ not in next 4 bytes
  1260. - sub TMP1, DAT1, #0x20000
  1261. - bics TMP1, TMP1, DAT1
  1262. - itee mi
  1263. - ldrbmi DAT0, [PTR, #-13]
  1264. - ldrbpl DAT0, [PTR, #-11]
  1265. - addpl RESULT, RESULT, #2
  1266. - teq DAT0, #0
  1267. - it eq
  1268. - subeq RESULT, RESULT, #1
  1269. - b 98f
  1270. -96: add RESULT, RESULT, #4
  1271. - teq TMP2, #0
  1272. - beq 97f @ not in next 4 bytes
  1273. - sub TMP2, DAT2, #0x20000
  1274. - bics TMP2, TMP2, DAT2
  1275. - itee mi
  1276. - ldrbmi DAT0, [PTR, #-9]
  1277. - ldrbpl DAT0, [PTR, #-7]
  1278. - addpl RESULT, RESULT, #2
  1279. - teq DAT0, #0
  1280. - it eq
  1281. - subeq RESULT, RESULT, #1
  1282. - b 98f
  1283. -97: add RESULT, RESULT, #4
  1284. - sub TMP3, DAT3, #0x20000
  1285. - bics TMP3, TMP3, DAT3
  1286. - itee mi
  1287. - ldrbmi DAT0, [PTR, #-5]
  1288. - ldrbpl DAT0, [PTR, #-3]
  1289. - addpl RESULT, RESULT, #2
  1290. - teq DAT0, #0
  1291. - it eq
  1292. - subeq RESULT, RESULT, #1
  1293. - @ drop through to 98f
  1294. -98: setend le
  1295. -99: pop {v1-v6,pc}
  1296. -.endfunc
  1297. -
  1298. - .unreq RESULT
  1299. - .unreq BUF
  1300. - .unreq SIZE
  1301. - .unreq PATTERN
  1302. - .unreq PTR
  1303. - .unreq DAT0
  1304. - .unreq DAT1
  1305. - .unreq DAT2
  1306. - .unreq DAT3
  1307. - .unreq TMP0
  1308. - .unreq TMP1
  1309. - .unreq TMP2
  1310. - .unreq TMP3
  1311. diff --git a/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  1312. index 2804e56..842fb9f 100644
  1313. --- a/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  1314. +++ b/lib/ffmpeg/libavcodec/arm/h264dsp_init_arm.c
  1315. @@ -24,7 +24,7 @@
  1316. #include "libavutil/arm/cpu.h"
  1317. #include "libavcodec/h264dsp.h"
  1318. -int ff_h264_find_start_code_candidate_armv6(const uint8_t *buf, int size);
  1319. +int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size);
  1320. void ff_h264_v_loop_filter_luma_neon(uint8_t *pix, int stride, int alpha,
  1321. int beta, int8_t *tc0);
  1322. @@ -109,7 +109,7 @@ av_cold void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth,
  1323. int cpu_flags = av_get_cpu_flags();
  1324. if (have_armv6(cpu_flags))
  1325. - c->h264_find_start_code_candidate = ff_h264_find_start_code_candidate_armv6;
  1326. + c->h264_find_start_code_candidate = ff_startcode_find_candidate_armv6;
  1327. if (have_neon(cpu_flags))
  1328. ff_h264dsp_init_neon(c, bit_depth, chroma_format_idc);
  1329. }
  1330. diff --git a/lib/ffmpeg/libavcodec/arm/startcode_armv6.S b/lib/ffmpeg/libavcodec/arm/startcode_armv6.S
  1331. new file mode 100644
  1332. index 0000000..a46f009
  1333. --- /dev/null
  1334. +++ b/lib/ffmpeg/libavcodec/arm/startcode_armv6.S
  1335. @@ -0,0 +1,253 @@
  1336. +/*
  1337. + * Copyright (c) 2013 RISC OS Open Ltd
  1338. + * Author: Ben Avison <bavison@riscosopen.org>
  1339. + *
  1340. + * This file is part of FFmpeg.
  1341. + *
  1342. + * FFmpeg is free software; you can redistribute it and/or
  1343. + * modify it under the terms of the GNU Lesser General Public
  1344. + * License as published by the Free Software Foundation; either
  1345. + * version 2.1 of the License, or (at your option) any later version.
  1346. + *
  1347. + * FFmpeg is distributed in the hope that it will be useful,
  1348. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1349. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1350. + * Lesser General Public License for more details.
  1351. + *
  1352. + * You should have received a copy of the GNU Lesser General Public
  1353. + * License along with FFmpeg; if not, write to the Free Software
  1354. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  1355. + */
  1356. +
  1357. +#include "libavutil/arm/asm.S"
  1358. +
  1359. +RESULT .req a1
  1360. +BUF .req a1
  1361. +SIZE .req a2
  1362. +PATTERN .req a3
  1363. +PTR .req a4
  1364. +DAT0 .req v1
  1365. +DAT1 .req v2
  1366. +DAT2 .req v3
  1367. +DAT3 .req v4
  1368. +TMP0 .req v5
  1369. +TMP1 .req v6
  1370. +TMP2 .req ip
  1371. +TMP3 .req lr
  1372. +
  1373. +#define PRELOAD_DISTANCE 4
  1374. +
  1375. +.macro innerloop4
  1376. + ldr DAT0, [PTR], #4
  1377. + subs SIZE, SIZE, #4 @ C flag survives rest of macro
  1378. + sub TMP0, DAT0, PATTERN, lsr #14
  1379. + bic TMP0, TMP0, DAT0
  1380. + ands TMP0, TMP0, PATTERN
  1381. +.endm
  1382. +
  1383. +.macro innerloop16 decrement, do_preload
  1384. + ldmia PTR!, {DAT0,DAT1,DAT2,DAT3}
  1385. + .ifnc "\do_preload",""
  1386. + pld [PTR, #PRELOAD_DISTANCE*32]
  1387. + .endif
  1388. + .ifnc "\decrement",""
  1389. + subs SIZE, SIZE, #\decrement @ C flag survives rest of macro
  1390. + .endif
  1391. + sub TMP0, DAT0, PATTERN, lsr #14
  1392. + sub TMP1, DAT1, PATTERN, lsr #14
  1393. + bic TMP0, TMP0, DAT0
  1394. + bic TMP1, TMP1, DAT1
  1395. + sub TMP2, DAT2, PATTERN, lsr #14
  1396. + sub TMP3, DAT3, PATTERN, lsr #14
  1397. + ands TMP0, TMP0, PATTERN
  1398. + bic TMP2, TMP2, DAT2
  1399. + it eq
  1400. + andseq TMP1, TMP1, PATTERN
  1401. + bic TMP3, TMP3, DAT3
  1402. + itt eq
  1403. + andseq TMP2, TMP2, PATTERN
  1404. + andseq TMP3, TMP3, PATTERN
  1405. +.endm
  1406. +
  1407. +/* int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size) */
  1408. +function ff_startcode_find_candidate_armv6, export=1
  1409. + push {v1-v6,lr}
  1410. + mov PTR, BUF
  1411. + @ Ensure there are at least (PRELOAD_DISTANCE+2) complete cachelines to go
  1412. + @ before using code that does preloads
  1413. + cmp SIZE, #(PRELOAD_DISTANCE+3)*32 - 1
  1414. + blo 60f
  1415. +
  1416. + @ Get to word-alignment, 1 byte at a time
  1417. + tst PTR, #3
  1418. + beq 2f
  1419. +1: ldrb DAT0, [PTR], #1
  1420. + sub SIZE, SIZE, #1
  1421. + teq DAT0, #0
  1422. + beq 90f
  1423. + tst PTR, #3
  1424. + bne 1b
  1425. +2: @ Get to 4-word alignment, 1 word at a time
  1426. + ldr PATTERN, =0x80008000
  1427. + setend be
  1428. + tst PTR, #12
  1429. + beq 4f
  1430. +3: innerloop4
  1431. + bne 91f
  1432. + tst PTR, #12
  1433. + bne 3b
  1434. +4: @ Get to cacheline (8-word) alignment
  1435. + tst PTR, #16
  1436. + beq 5f
  1437. + innerloop16 16
  1438. + bne 93f
  1439. +5: @ Check complete cachelines, with preloading
  1440. + @ We need to stop when there are still (PRELOAD_DISTANCE+1)
  1441. + @ complete cachelines to go
  1442. + sub SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32
  1443. +6: innerloop16 , do_preload
  1444. + bne 93f
  1445. + innerloop16 32
  1446. + bne 93f
  1447. + bcs 6b
  1448. + @ Preload trailing part-cacheline, if any
  1449. + tst SIZE, #31
  1450. + beq 7f
  1451. + pld [PTR, #(PRELOAD_DISTANCE+1)*32]
  1452. + @ Check remaining data without doing any more preloads. First
  1453. + @ do in chunks of 4 words:
  1454. +7: adds SIZE, SIZE, #(PRELOAD_DISTANCE+2)*32 - 16
  1455. + bmi 9f
  1456. +8: innerloop16 16
  1457. + bne 93f
  1458. + bcs 8b
  1459. + @ Then in words:
  1460. +9: adds SIZE, SIZE, #16 - 4
  1461. + bmi 11f
  1462. +10: innerloop4
  1463. + bne 91f
  1464. + bcs 10b
  1465. +11: setend le
  1466. + @ Check second byte of final halfword
  1467. + ldrb DAT0, [PTR, #-1]
  1468. + teq DAT0, #0
  1469. + beq 90f
  1470. + @ Check any remaining bytes
  1471. + tst SIZE, #3
  1472. + beq 13f
  1473. +12: ldrb DAT0, [PTR], #1
  1474. + sub SIZE, SIZE, #1
  1475. + teq DAT0, #0
  1476. + beq 90f
  1477. + tst SIZE, #3
  1478. + bne 12b
  1479. + @ No candidate found
  1480. +13: sub RESULT, PTR, BUF
  1481. + b 99f
  1482. +
  1483. +60: @ Small buffer - simply check by looping over bytes
  1484. + subs SIZE, SIZE, #1
  1485. + bcc 99f
  1486. +61: ldrb DAT0, [PTR], #1
  1487. + subs SIZE, SIZE, #1
  1488. + teq DAT0, #0
  1489. + beq 90f
  1490. + bcs 61b
  1491. + @ No candidate found
  1492. + sub RESULT, PTR, BUF
  1493. + b 99f
  1494. +
  1495. +90: @ Found a candidate at the preceding byte
  1496. + sub RESULT, PTR, BUF
  1497. + sub RESULT, RESULT, #1
  1498. + b 99f
  1499. +
  1500. +91: @ Found a candidate somewhere in the preceding 4 bytes
  1501. + sub RESULT, PTR, BUF
  1502. + sub RESULT, RESULT, #4
  1503. + sub TMP0, DAT0, #0x20000
  1504. + bics TMP0, TMP0, DAT0
  1505. + itt pl
  1506. + ldrbpl DAT0, [PTR, #-3]
  1507. + addpl RESULT, RESULT, #2
  1508. + bpl 92f
  1509. + teq RESULT, #0
  1510. + beq 98f @ don't look back a byte if found at first byte in buffer
  1511. + ldrb DAT0, [PTR, #-5]
  1512. +92: teq DAT0, #0
  1513. + it eq
  1514. + subeq RESULT, RESULT, #1
  1515. + b 98f
  1516. +
  1517. +93: @ Found a candidate somewhere in the preceding 16 bytes
  1518. + sub RESULT, PTR, BUF
  1519. + sub RESULT, RESULT, #16
  1520. + teq TMP0, #0
  1521. + beq 95f @ not in first 4 bytes
  1522. + sub TMP0, DAT0, #0x20000
  1523. + bics TMP0, TMP0, DAT0
  1524. + itt pl
  1525. + ldrbpl DAT0, [PTR, #-15]
  1526. + addpl RESULT, RESULT, #2
  1527. + bpl 94f
  1528. + teq RESULT, #0
  1529. + beq 98f @ don't look back a byte if found at first byte in buffer
  1530. + ldrb DAT0, [PTR, #-17]
  1531. +94: teq DAT0, #0
  1532. + it eq
  1533. + subeq RESULT, RESULT, #1
  1534. + b 98f
  1535. +95: add RESULT, RESULT, #4
  1536. + teq TMP1, #0
  1537. + beq 96f @ not in next 4 bytes
  1538. + sub TMP1, DAT1, #0x20000
  1539. + bics TMP1, TMP1, DAT1
  1540. + itee mi
  1541. + ldrbmi DAT0, [PTR, #-13]
  1542. + ldrbpl DAT0, [PTR, #-11]
  1543. + addpl RESULT, RESULT, #2
  1544. + teq DAT0, #0
  1545. + it eq
  1546. + subeq RESULT, RESULT, #1
  1547. + b 98f
  1548. +96: add RESULT, RESULT, #4
  1549. + teq TMP2, #0
  1550. + beq 97f @ not in next 4 bytes
  1551. + sub TMP2, DAT2, #0x20000
  1552. + bics TMP2, TMP2, DAT2
  1553. + itee mi
  1554. + ldrbmi DAT0, [PTR, #-9]
  1555. + ldrbpl DAT0, [PTR, #-7]
  1556. + addpl RESULT, RESULT, #2
  1557. + teq DAT0, #0
  1558. + it eq
  1559. + subeq RESULT, RESULT, #1
  1560. + b 98f
  1561. +97: add RESULT, RESULT, #4
  1562. + sub TMP3, DAT3, #0x20000
  1563. + bics TMP3, TMP3, DAT3
  1564. + itee mi
  1565. + ldrbmi DAT0, [PTR, #-5]
  1566. + ldrbpl DAT0, [PTR, #-3]
  1567. + addpl RESULT, RESULT, #2
  1568. + teq DAT0, #0
  1569. + it eq
  1570. + subeq RESULT, RESULT, #1
  1571. + @ drop through to 98f
  1572. +98: setend le
  1573. +99: pop {v1-v6,pc}
  1574. +endfunc
  1575. +
  1576. + .unreq RESULT
  1577. + .unreq BUF
  1578. + .unreq SIZE
  1579. + .unreq PATTERN
  1580. + .unreq PTR
  1581. + .unreq DAT0
  1582. + .unreq DAT1
  1583. + .unreq DAT2
  1584. + .unreq DAT3
  1585. + .unreq TMP0
  1586. + .unreq TMP1
  1587. + .unreq TMP2
  1588. + .unreq TMP3
  1589. diff --git a/lib/ffmpeg/libavcodec/h264dsp.c b/lib/ffmpeg/libavcodec/h264dsp.c
  1590. index b7d61cd..a84ae59 100644
  1591. --- a/lib/ffmpeg/libavcodec/h264dsp.c
  1592. +++ b/lib/ffmpeg/libavcodec/h264dsp.c
  1593. @@ -30,6 +30,7 @@
  1594. #include "avcodec.h"
  1595. #include "h264dsp.h"
  1596. #include "h264idct.h"
  1597. +#include "startcode.h"
  1598. #include "libavutil/common.h"
  1599. #define BIT_DEPTH 8
  1600. @@ -60,34 +61,6 @@
  1601. #include "h264addpx_template.c"
  1602. #undef BIT_DEPTH
  1603. -static int h264_find_start_code_candidate_c(const uint8_t *buf, int size)
  1604. -{
  1605. - int i = 0;
  1606. -#if HAVE_FAST_UNALIGNED
  1607. - /* we check i < size instead of i + 3 / 7 because it is
  1608. - * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE
  1609. - * bytes at the end.
  1610. - */
  1611. -#if HAVE_FAST_64BIT
  1612. - while (i < size &&
  1613. - !((~*(const uint64_t *)(buf + i) &
  1614. - (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) &
  1615. - 0x8080808080808080ULL))
  1616. - i += 8;
  1617. -#else
  1618. - while (i < size &&
  1619. - !((~*(const uint32_t *)(buf + i) &
  1620. - (*(const uint32_t *)(buf + i) - 0x01010101U)) &
  1621. - 0x80808080U))
  1622. - i += 4;
  1623. -#endif
  1624. -#endif
  1625. - for (; i < size; i++)
  1626. - if (!buf[i])
  1627. - break;
  1628. - return i;
  1629. -}
  1630. -
  1631. void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_format_idc)
  1632. {
  1633. #undef FUNC
  1634. @@ -174,7 +147,7 @@ void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_fo
  1635. H264_DSP(8);
  1636. break;
  1637. }
  1638. - c->h264_find_start_code_candidate = h264_find_start_code_candidate_c;
  1639. + c->h264_find_start_code_candidate = ff_startcode_find_candidate_c;
  1640. if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc);
  1641. if (HAVE_ALTIVEC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc);
  1642. diff --git a/lib/ffmpeg/libavcodec/startcode.c b/lib/ffmpeg/libavcodec/startcode.c
  1643. new file mode 100644
  1644. index 0000000..5df7695
  1645. --- /dev/null
  1646. +++ b/lib/ffmpeg/libavcodec/startcode.c
  1647. @@ -0,0 +1,57 @@
  1648. +/*
  1649. + * Copyright (c) 2003-2010 Michael Niedermayer <michaelni@gmx.at>
  1650. + *
  1651. + * This file is part of FFmpeg.
  1652. + *
  1653. + * FFmpeg is free software; you can redistribute it and/or
  1654. + * modify it under the terms of the GNU Lesser General Public
  1655. + * License as published by the Free Software Foundation; either
  1656. + * version 2.1 of the License, or (at your option) any later version.
  1657. + *
  1658. + * FFmpeg is distributed in the hope that it will be useful,
  1659. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1660. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1661. + * Lesser General Public License for more details.
  1662. + *
  1663. + * You should have received a copy of the GNU Lesser General Public
  1664. + * License along with FFmpeg; if not, write to the Free Software
  1665. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  1666. + */
  1667. +
  1668. +/**
  1669. + * @file
  1670. + * Accelerated start code search function for start codes common to
  1671. + * MPEG-1/2/4 video, VC-1, H.264/5
  1672. + * @author Michael Niedermayer <michaelni@gmx.at>
  1673. + */
  1674. +
  1675. +#include "startcode.h"
  1676. +#include "config.h"
  1677. +
  1678. +int ff_startcode_find_candidate_c(const uint8_t *buf, int size)
  1679. +{
  1680. + int i = 0;
  1681. +#if HAVE_FAST_UNALIGNED
  1682. + /* we check i < size instead of i + 3 / 7 because it is
  1683. + * simpler and there must be FF_INPUT_BUFFER_PADDING_SIZE
  1684. + * bytes at the end.
  1685. + */
  1686. +# if HAVE_FAST_64BIT
  1687. + while (i < size &&
  1688. + !((~*(const uint64_t *)(buf + i) &
  1689. + (*(const uint64_t *)(buf + i) - 0x0101010101010101ULL)) &
  1690. + 0x8080808080808080ULL))
  1691. + i += 8;
  1692. +# else
  1693. + while (i < size &&
  1694. + !((~*(const uint32_t *)(buf + i) &
  1695. + (*(const uint32_t *)(buf + i) - 0x01010101U)) &
  1696. + 0x80808080U))
  1697. + i += 4;
  1698. +# endif
  1699. +#endif
  1700. + for (; i < size; i++)
  1701. + if (!buf[i])
  1702. + break;
  1703. + return i;
  1704. +}
  1705. diff --git a/lib/ffmpeg/libavcodec/startcode.h b/lib/ffmpeg/libavcodec/startcode.h
  1706. new file mode 100644
  1707. index 0000000..cc55d5f
  1708. --- /dev/null
  1709. +++ b/lib/ffmpeg/libavcodec/startcode.h
  1710. @@ -0,0 +1,35 @@
  1711. +/*
  1712. + * Copyright (c) 2003-2010 Michael Niedermayer <michaelni@gmx.at>
  1713. + *
  1714. + * This file is part of FFmpeg.
  1715. + *
  1716. + * FFmpeg is free software; you can redistribute it and/or
  1717. + * modify it under the terms of the GNU Lesser General Public
  1718. + * License as published by the Free Software Foundation; either
  1719. + * version 2.1 of the License, or (at your option) any later version.
  1720. + *
  1721. + * FFmpeg is distributed in the hope that it will be useful,
  1722. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1723. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1724. + * Lesser General Public License for more details.
  1725. + *
  1726. + * You should have received a copy of the GNU Lesser General Public
  1727. + * License along with FFmpeg; if not, write to the Free Software
  1728. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  1729. + */
  1730. +
  1731. +/**
  1732. + * @file
  1733. + * Accelerated start code search function for start codes common to
  1734. + * MPEG-1/2/4 video, VC-1, H.264/5
  1735. + * @author Michael Niedermayer <michaelni@gmx.at>
  1736. + */
  1737. +
  1738. +#ifndef AVCODEC_STARTCODE_H
  1739. +#define AVCODEC_STARTCODE_H
  1740. +
  1741. +#include <stdint.h>
  1742. +
  1743. +int ff_startcode_find_candidate_c(const uint8_t *buf, int size);
  1744. +
  1745. +#endif /* AVCODEC_STARTCODE_H */
  1746. --
  1747. 1.9.3
  1748. From 7d95eb8e026582e5446e7e11d75ba999286a34d0 Mon Sep 17 00:00:00 2001
  1749. From: Ben Avison <bavison@riscosopen.org>
  1750. Date: Wed, 16 Apr 2014 01:51:32 +0100
  1751. Subject: [PATCH 06/94] vc-1: Add platform-specific start code search routine
  1752. to VC1DSPContext.
  1753. Initialise VC1DSPContext for parser as well as for decoder.
  1754. Note, the VC-1 code doesn't actually use the function pointer yet.
  1755. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
  1756. ---
  1757. lib/ffmpeg/libavcodec/Makefile | 7 +++---
  1758. lib/ffmpeg/libavcodec/arm/Makefile | 3 +++
  1759. lib/ffmpeg/libavcodec/arm/vc1dsp_init_arm.c | 33 +++++++++++++++++++++++++++++
  1760. lib/ffmpeg/libavcodec/vc1.c | 2 ++
  1761. lib/ffmpeg/libavcodec/vc1dec.c | 1 -
  1762. lib/ffmpeg/libavcodec/vc1dsp.c | 5 +++++
  1763. lib/ffmpeg/libavcodec/vc1dsp.h | 9 ++++++++
  1764. 7 files changed, 56 insertions(+), 4 deletions(-)
  1765. create mode 100644 lib/ffmpeg/libavcodec/arm/vc1dsp_init_arm.c
  1766. diff --git a/lib/ffmpeg/libavcodec/Makefile b/lib/ffmpeg/libavcodec/Makefile
  1767. index 460f42c..8d8a548 100644
  1768. --- a/lib/ffmpeg/libavcodec/Makefile
  1769. +++ b/lib/ffmpeg/libavcodec/Makefile
  1770. @@ -455,7 +455,7 @@ OBJS-$(CONFIG_VB_DECODER) += vb.o
  1771. OBJS-$(CONFIG_VBLE_DECODER) += vble.o
  1772. OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1.o vc1data.o vc1dsp.o \
  1773. msmpeg4.o msmpeg4data.o \
  1774. - intrax8.o intrax8dsp.o
  1775. + intrax8.o intrax8dsp.o startcode.o
  1776. OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
  1777. OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
  1778. OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
  1779. @@ -487,6 +487,7 @@ OBJS-$(CONFIG_WMAVOICE_DECODER) += wmavoice.o \
  1780. celp_filters.o \
  1781. acelp_vectors.o acelp_filters.o
  1782. OBJS-$(CONFIG_WMV1_DECODER) += msmpeg4.o msmpeg4data.o
  1783. +
  1784. OBJS-$(CONFIG_WMV2_DECODER) += wmv2dec.o wmv2.o wmv2dsp.o \
  1785. msmpeg4.o msmpeg4data.o \
  1786. intrax8.o intrax8dsp.o
  1787. @@ -746,9 +747,9 @@ OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
  1788. OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o
  1789. OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o
  1790. OBJS-$(CONFIG_TAK_PARSER) += tak_parser.o tak.o
  1791. -OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \
  1792. +OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o vc1dsp.o \
  1793. msmpeg4.o msmpeg4data.o mpeg4video.o \
  1794. - h263.o
  1795. + h263.o startcode.o
  1796. OBJS-$(CONFIG_VORBIS_PARSER) += vorbis_parser.o xiph.o
  1797. OBJS-$(CONFIG_VP3_PARSER) += vp3_parser.o
  1798. OBJS-$(CONFIG_VP8_PARSER) += vp8_parser.o
  1799. diff --git a/lib/ffmpeg/libavcodec/arm/Makefile b/lib/ffmpeg/libavcodec/arm/Makefile
  1800. index 0b432e3..715eed7 100644
  1801. --- a/lib/ffmpeg/libavcodec/arm/Makefile
  1802. +++ b/lib/ffmpeg/libavcodec/arm/Makefile
  1803. @@ -16,6 +16,9 @@ OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \
  1804. OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_init_arm.o
  1805. ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o
  1806. +ARMV6-OBJS-$(CONFIG_VC1_DECODER) += arm/startcode_armv6.o
  1807. +OBJS-$(CONFIG_VC1_DECODER) += arm/vc1dsp_init_arm.o
  1808. +ARMV6-OBJS-$(CONFIG_VC1_PARSER) += arm/startcode_armv6.o
  1809. OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_arm.o
  1810. OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o
  1811. diff --git a/lib/ffmpeg/libavcodec/arm/vc1dsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/vc1dsp_init_arm.c
  1812. new file mode 100644
  1813. index 0000000..fec5e78
  1814. --- /dev/null
  1815. +++ b/lib/ffmpeg/libavcodec/arm/vc1dsp_init_arm.c
  1816. @@ -0,0 +1,33 @@
  1817. +/*
  1818. + * This file is part of Libav.
  1819. + *
  1820. + * Libav is free software; you can redistribute it and/or
  1821. + * modify it under the terms of the GNU Lesser General Public
  1822. + * License as published by the Free Software Foundation; either
  1823. + * version 2.1 of the License, or (at your option) any later version.
  1824. + *
  1825. + * Libav is distributed in the hope that it will be useful,
  1826. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1827. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  1828. + * Lesser General Public License for more details.
  1829. + *
  1830. + * You should have received a copy of the GNU Lesser General Public
  1831. + * License along with Libav; if not, write to the Free Software
  1832. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  1833. + */
  1834. +
  1835. +#include <stdint.h>
  1836. +
  1837. +#include "libavutil/attributes.h"
  1838. +#include "libavutil/arm/cpu.h"
  1839. +#include "libavcodec/vc1dsp.h"
  1840. +
  1841. +int ff_startcode_find_candidate_armv6(const uint8_t *buf, int size);
  1842. +
  1843. +av_cold void ff_vc1dsp_init_arm(VC1DSPContext *dsp)
  1844. +{
  1845. + int cpu_flags = av_get_cpu_flags();
  1846. +
  1847. + if (have_armv6(cpu_flags))
  1848. + dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_armv6;
  1849. +}
  1850. diff --git a/lib/ffmpeg/libavcodec/vc1.c b/lib/ffmpeg/libavcodec/vc1.c
  1851. index e2e90a8..9b15809 100644
  1852. --- a/lib/ffmpeg/libavcodec/vc1.c
  1853. +++ b/lib/ffmpeg/libavcodec/vc1.c
  1854. @@ -1663,5 +1663,7 @@ int ff_vc1_init_common(VC1Context *v)
  1855. v->pq = -1;
  1856. v->mvrange = 0; /* 7.1.1.18, p80 */
  1857. + ff_vc1dsp_init(&v->vc1dsp);
  1858. +
  1859. return 0;
  1860. }
  1861. diff --git a/lib/ffmpeg/libavcodec/vc1dec.c b/lib/ffmpeg/libavcodec/vc1dec.c
  1862. index 2130c74..9fd3cae 100644
  1863. --- a/lib/ffmpeg/libavcodec/vc1dec.c
  1864. +++ b/lib/ffmpeg/libavcodec/vc1dec.c
  1865. @@ -5193,7 +5193,6 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx)
  1866. ff_vc1_decode_end(avctx);
  1867. ff_h264chroma_init(&v->h264chroma, 8);
  1868. - ff_vc1dsp_init(&v->vc1dsp);
  1869. if (avctx->codec_id == AV_CODEC_ID_WMV3 || avctx->codec_id == AV_CODEC_ID_WMV3IMAGE) {
  1870. int count = 0;
  1871. diff --git a/lib/ffmpeg/libavcodec/vc1dsp.c b/lib/ffmpeg/libavcodec/vc1dsp.c
  1872. index 260eda4..3e3f00e 100644
  1873. --- a/lib/ffmpeg/libavcodec/vc1dsp.c
  1874. +++ b/lib/ffmpeg/libavcodec/vc1dsp.c
  1875. @@ -30,6 +30,7 @@
  1876. #include "h264chroma.h"
  1877. #include "rnd_avg.h"
  1878. #include "vc1dsp.h"
  1879. +#include "startcode.h"
  1880. /** Apply overlap transform to horizontal edge
  1881. @@ -861,8 +862,12 @@ av_cold void ff_vc1dsp_init(VC1DSPContext* dsp) {
  1882. dsp->sprite_v_double_twoscale = sprite_v_double_twoscale_c;
  1883. #endif
  1884. + dsp->vc1_find_start_code_candidate = ff_startcode_find_candidate_c;
  1885. +
  1886. if (HAVE_ALTIVEC)
  1887. ff_vc1dsp_init_altivec(dsp);
  1888. + if (ARCH_ARM)
  1889. + ff_vc1dsp_init_arm(dsp);
  1890. if (ARCH_X86)
  1891. ff_vc1dsp_init_x86(dsp);
  1892. }
  1893. diff --git a/lib/ffmpeg/libavcodec/vc1dsp.h b/lib/ffmpeg/libavcodec/vc1dsp.h
  1894. index 6540eff..302e4a8 100644
  1895. --- a/lib/ffmpeg/libavcodec/vc1dsp.h
  1896. +++ b/lib/ffmpeg/libavcodec/vc1dsp.h
  1897. @@ -73,10 +73,19 @@ typedef struct VC1DSPContext {
  1898. void (*sprite_v_double_twoscale)(uint8_t *dst, const uint8_t *src1a, const uint8_t *src1b, int offset1,
  1899. const uint8_t *src2a, const uint8_t *src2b, int offset2,
  1900. int alpha, int width);
  1901. +
  1902. + /**
  1903. + * Search buf from the start for up to size bytes. Return the index
  1904. + * of a zero byte, or >= size if not found. Ideally, use lookahead
  1905. + * to filter out any zero bytes that are known to not be followed by
  1906. + * one or more further zero bytes and a one byte.
  1907. + */
  1908. + int (*vc1_find_start_code_candidate)(const uint8_t *buf, int size);
  1909. } VC1DSPContext;
  1910. void ff_vc1dsp_init(VC1DSPContext* c);
  1911. void ff_vc1dsp_init_altivec(VC1DSPContext* c);
  1912. +void ff_vc1dsp_init_arm(VC1DSPContext* dsp);
  1913. void ff_vc1dsp_init_x86(VC1DSPContext* dsp);
  1914. #endif /* AVCODEC_VC1DSP_H */
  1915. --
  1916. 1.9.3
  1917. From 9b459c3c4130299099b2e5aca5bff3d6f8d60e72 Mon Sep 17 00:00:00 2001
  1918. From: Ben Avison <bavison@riscosopen.org>
  1919. Date: Wed, 23 Apr 2014 01:41:04 +0100
  1920. Subject: [PATCH 07/94] vc-1: Optimise parser (with special attention to ARM)
  1921. The previous implementation of the parser made four passes over each input
  1922. buffer (reduced to two if the container format already guaranteed the input
  1923. buffer corresponded to frames, such as with MKV). But these buffers are
  1924. often 200K in size, certainly enough to flush the data out of L1 cache, and
  1925. for many CPUs, all the way out to main memory. The passes were:
  1926. 1) locate frame boundaries (not needed for MKV etc)
  1927. 2) copy the data into a contiguous block (not needed for MKV etc)
  1928. 3) locate the start codes within each frame
  1929. 4) unescape the data between start codes
  1930. After this, the unescaped data was parsed to extract certain header fields,
  1931. but because the unescape operation was so large, this was usually also
  1932. effectively operating on uncached memory. Most of the unescaped data was
  1933. simply thrown away and never processed further. Only step 2 - because it
  1934. used memcpy - was using prefetch, making things even worse.
  1935. This patch reorganises these steps so that, aside from the copying, the
  1936. operations are performed in parallel, maximising cache utilisation. No more
  1937. than the worst-case number of bytes needed for header parsing is unescaped.
  1938. Most of the data is, in practice, only read in order to search for a start
  1939. code, for which optimised implementations already existed in the H264 codec
  1940. (notably the ARM version uses prefetch, so we end up doing both remaining
  1941. passes at maximum speed). For MKV files, we know when we've found the last
  1942. start code of interest in a given frame, so we are able to avoid doing even
  1943. that one remaining pass for most of the buffer.
  1944. In some use-cases (such as the Raspberry Pi) video decode is handled by the
  1945. GPU, but the entire elementary stream is still fed through the parser to
  1946. pick out certain elements of the header which are necessary to manage the
  1947. decode process. As you might expect, in these cases, the performance of the
  1948. parser is significant.
  1949. To measure parser performance, I used the same VC-1 elementary stream in
  1950. either an MPEG-2 transport stream or a MKV file, and fed it through ffmpeg
  1951. with -c:v copy -c:a copy -f null. These are the gperftools counts for
  1952. those streams, both filtered to only include vc1_parse() and its callees,
  1953. and unfiltered (to include the whole binary). Lower numbers are better:
  1954. Before After
  1955. File Filtered Mean StdDev Mean StdDev Confidence Change
  1956. M2TS No 861.7 8.2 650.5 8.1 100.0% +32.5%
  1957. MKV No 868.9 7.4 731.7 9.0 100.0% +18.8%
  1958. M2TS Yes 250.0 11.2 27.2 3.4 100.0% +817.9%
  1959. MKV Yes 149.0 12.8 1.7 0.8 100.0% +8526.3%
  1960. Yes, that last case shows vc1_parse() running 86 times faster! The M2TS
  1961. case does show a larger absolute improvement though, since it was worse
  1962. to begin with.
  1963. This patch has been tested with the FATE suite (albeit on x86 for speed).
  1964. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
  1965. ---
  1966. lib/ffmpeg/libavcodec/vc1_parser.c | 269 ++++++++++++++++++++++++-------------
  1967. 1 file changed, 175 insertions(+), 94 deletions(-)
  1968. diff --git a/lib/ffmpeg/libavcodec/vc1_parser.c b/lib/ffmpeg/libavcodec/vc1_parser.c
  1969. index 53af61c..af601ad 100644
  1970. --- a/lib/ffmpeg/libavcodec/vc1_parser.c
  1971. +++ b/lib/ffmpeg/libavcodec/vc1_parser.c
  1972. @@ -29,112 +29,83 @@
  1973. #include "vc1.h"
  1974. #include "get_bits.h"
  1975. +/** The maximum number of bytes of a sequence, entry point or
  1976. + * frame header whose values we pay any attention to */
  1977. +#define UNESCAPED_THRESHOLD 37
  1978. +
  1979. +/** The maximum number of bytes of a sequence, entry point or
  1980. + * frame header which must be valid memory (because they are
  1981. + * used to update the bitstream cache in skip_bits() calls)
  1982. + */
  1983. +#define UNESCAPED_LIMIT 144
  1984. +
  1985. +typedef enum {
  1986. + NO_MATCH,
  1987. + ONE_ZERO,
  1988. + TWO_ZEROS,
  1989. + ONE
  1990. +} VC1ParseSearchState;
  1991. +
  1992. typedef struct {
  1993. ParseContext pc;
  1994. VC1Context v;
  1995. + uint8_t prev_start_code;
  1996. + size_t bytes_to_skip;
  1997. + uint8_t unesc_buffer[UNESCAPED_LIMIT];
  1998. + size_t unesc_index;
  1999. + VC1ParseSearchState search_state;
  2000. } VC1ParseContext;
  2001. -static void vc1_extract_headers(AVCodecParserContext *s, AVCodecContext *avctx,
  2002. - const uint8_t *buf, int buf_size)
  2003. +static void vc1_extract_header(AVCodecParserContext *s, AVCodecContext *avctx,
  2004. + const uint8_t *buf, int buf_size)
  2005. {
  2006. + /* Parse the header we just finished unescaping */
  2007. VC1ParseContext *vpc = s->priv_data;
  2008. GetBitContext gb;
  2009. - const uint8_t *start, *end, *next;
  2010. - uint8_t *buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
  2011. -
  2012. + int ret;
  2013. vpc->v.s.avctx = avctx;
  2014. vpc->v.parse_only = 1;
  2015. - next = buf;
  2016. - s->repeat_pict = 0;
  2017. -
  2018. - for(start = buf, end = buf + buf_size; next < end; start = next){
  2019. - int buf2_size, size;
  2020. -
  2021. - next = find_next_marker(start + 4, end);
  2022. - size = next - start - 4;
  2023. - buf2_size = vc1_unescape_buffer(start + 4, size, buf2);
  2024. - init_get_bits(&gb, buf2, buf2_size * 8);
  2025. - if(size <= 0) continue;
  2026. - switch(AV_RB32(start)){
  2027. - case VC1_CODE_SEQHDR:
  2028. - ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb);
  2029. - break;
  2030. - case VC1_CODE_ENTRYPOINT:
  2031. - ff_vc1_decode_entry_point(avctx, &vpc->v, &gb);
  2032. - break;
  2033. - case VC1_CODE_FRAME:
  2034. - if(vpc->v.profile < PROFILE_ADVANCED)
  2035. - ff_vc1_parse_frame_header (&vpc->v, &gb);
  2036. - else
  2037. - ff_vc1_parse_frame_header_adv(&vpc->v, &gb);
  2038. -
  2039. - /* keep AV_PICTURE_TYPE_BI internal to VC1 */
  2040. - if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI)
  2041. - s->pict_type = AV_PICTURE_TYPE_B;
  2042. - else
  2043. - s->pict_type = vpc->v.s.pict_type;
  2044. -
  2045. - if (avctx->ticks_per_frame > 1){
  2046. - // process pulldown flags
  2047. - s->repeat_pict = 1;
  2048. - // Pulldown flags are only valid when 'broadcast' has been set.
  2049. - // So ticks_per_frame will be 2
  2050. - if (vpc->v.rff){
  2051. - // repeat field
  2052. - s->repeat_pict = 2;
  2053. - }else if (vpc->v.rptfrm){
  2054. - // repeat frames
  2055. - s->repeat_pict = vpc->v.rptfrm * 2 + 1;
  2056. - }
  2057. - }
  2058. + init_get_bits(&gb, buf, buf_size * 8);
  2059. + switch (vpc->prev_start_code) {
  2060. + case VC1_CODE_SEQHDR & 0xFF:
  2061. + ff_vc1_decode_sequence_header(avctx, &vpc->v, &gb);
  2062. + break;
  2063. + case VC1_CODE_ENTRYPOINT & 0xFF:
  2064. + ff_vc1_decode_entry_point(avctx, &vpc->v, &gb);
  2065. + break;
  2066. + case VC1_CODE_FRAME & 0xFF:
  2067. + if(vpc->v.profile < PROFILE_ADVANCED)
  2068. + ret = ff_vc1_parse_frame_header (&vpc->v, &gb);
  2069. + else
  2070. + ret = ff_vc1_parse_frame_header_adv(&vpc->v, &gb);
  2071. + if (ret < 0)
  2072. break;
  2073. - }
  2074. - }
  2075. - av_free(buf2);
  2076. -}
  2077. + /* keep AV_PICTURE_TYPE_BI internal to VC1 */
  2078. + if (vpc->v.s.pict_type == AV_PICTURE_TYPE_BI)
  2079. + s->pict_type = AV_PICTURE_TYPE_B;
  2080. + else
  2081. + s->pict_type = vpc->v.s.pict_type;
  2082. -/**
  2083. - * Find the end of the current frame in the bitstream.
  2084. - * @return the position of the first byte of the next frame, or -1
  2085. - */
  2086. -static int vc1_find_frame_end(ParseContext *pc, const uint8_t *buf,
  2087. - int buf_size) {
  2088. - int pic_found, i;
  2089. - uint32_t state;
  2090. -
  2091. - pic_found= pc->frame_start_found;
  2092. - state= pc->state;
  2093. -
  2094. - i=0;
  2095. - if(!pic_found){
  2096. - for(i=0; i<buf_size; i++){
  2097. - state= (state<<8) | buf[i];
  2098. - if(state == VC1_CODE_FRAME || state == VC1_CODE_FIELD){
  2099. - i++;
  2100. - pic_found=1;
  2101. - break;
  2102. + if (avctx->ticks_per_frame > 1){
  2103. + // process pulldown flags
  2104. + s->repeat_pict = 1;
  2105. + // Pulldown flags are only valid when 'broadcast' has been set.
  2106. + // So ticks_per_frame will be 2
  2107. + if (vpc->v.rff){
  2108. + // repeat field
  2109. + s->repeat_pict = 2;
  2110. + }else if (vpc->v.rptfrm){
  2111. + // repeat frames
  2112. + s->repeat_pict = vpc->v.rptfrm * 2 + 1;
  2113. }
  2114. + }else{
  2115. + s->repeat_pict = 0;
  2116. }
  2117. - }
  2118. - if(pic_found){
  2119. - /* EOF considered as end of frame */
  2120. - if (buf_size == 0)
  2121. - return 0;
  2122. - for(; i<buf_size; i++){
  2123. - state= (state<<8) | buf[i];
  2124. - if(IS_MARKER(state) && state != VC1_CODE_FIELD && state != VC1_CODE_SLICE){
  2125. - pc->frame_start_found=0;
  2126. - pc->state=-1;
  2127. - return i-3;
  2128. - }
  2129. - }
  2130. + break;
  2131. }
  2132. - pc->frame_start_found= pic_found;
  2133. - pc->state= state;
  2134. - return END_NOT_FOUND;
  2135. }
  2136. static int vc1_parse(AVCodecParserContext *s,
  2137. @@ -142,22 +113,127 @@ static int vc1_parse(AVCodecParserContext *s,
  2138. const uint8_t **poutbuf, int *poutbuf_size,
  2139. const uint8_t *buf, int buf_size)
  2140. {
  2141. + /* Here we do the searching for frame boundaries and headers at
  2142. + * the same time. Only a minimal amount at the start of each
  2143. + * header is unescaped. */
  2144. VC1ParseContext *vpc = s->priv_data;
  2145. - int next;
  2146. + int pic_found = vpc->pc.frame_start_found;
  2147. + uint8_t *unesc_buffer = vpc->unesc_buffer;
  2148. + size_t unesc_index = vpc->unesc_index;
  2149. + VC1ParseSearchState search_state = vpc->search_state;
  2150. + int next = END_NOT_FOUND;
  2151. + int i = vpc->bytes_to_skip;
  2152. - if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
  2153. - next= buf_size;
  2154. - }else{
  2155. - next= vc1_find_frame_end(&vpc->pc, buf, buf_size);
  2156. + if (pic_found && buf_size == 0) {
  2157. + /* EOF considered as end of frame */
  2158. + memset(unesc_buffer + unesc_index, 0, UNESCAPED_THRESHOLD - unesc_index);
  2159. + vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
  2160. + next = 0;
  2161. + }
  2162. + while (i < buf_size) {
  2163. + int start_code_found = 0;
  2164. + uint8_t b;
  2165. + while (i < buf_size && unesc_index < UNESCAPED_THRESHOLD) {
  2166. + b = buf[i++];
  2167. + unesc_buffer[unesc_index++] = b;
  2168. + if (search_state <= ONE_ZERO)
  2169. + search_state = b ? NO_MATCH : search_state + 1;
  2170. + else if (search_state == TWO_ZEROS) {
  2171. + if (b == 1)
  2172. + search_state = ONE;
  2173. + else if (b > 1) {
  2174. + if (b == 3)
  2175. + unesc_index--; // swallow emulation prevention byte
  2176. + search_state = NO_MATCH;
  2177. + }
  2178. + }
  2179. + else { // search_state == ONE
  2180. + // Header unescaping terminates early due to detection of next start code
  2181. + search_state = NO_MATCH;
  2182. + start_code_found = 1;
  2183. + break;
  2184. + }
  2185. + }
  2186. + if ((s->flags & PARSER_FLAG_COMPLETE_FRAMES) &&
  2187. + unesc_index >= UNESCAPED_THRESHOLD &&
  2188. + vpc->prev_start_code == (VC1_CODE_FRAME & 0xFF))
  2189. + {
  2190. + // No need to keep scanning the rest of the buffer for
  2191. + // start codes if we know it contains a complete frame and
  2192. + // we've already unescaped all we need of the frame header
  2193. + vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
  2194. + break;
  2195. + }
  2196. + if (unesc_index >= UNESCAPED_THRESHOLD && !start_code_found) {
  2197. + while (i < buf_size) {
  2198. + if (search_state == NO_MATCH) {
  2199. + i += vpc->v.vc1dsp.vc1_find_start_code_candidate(buf + i, buf_size - i);
  2200. + if (i < buf_size) {
  2201. + search_state = ONE_ZERO;
  2202. + }
  2203. + i++;
  2204. + } else {
  2205. + b = buf[i++];
  2206. + if (search_state == ONE_ZERO)
  2207. + search_state = b ? NO_MATCH : TWO_ZEROS;
  2208. + else if (search_state == TWO_ZEROS) {
  2209. + if (b >= 1)
  2210. + search_state = b == 1 ? ONE : NO_MATCH;
  2211. + }
  2212. + else { // search_state == ONE
  2213. + search_state = NO_MATCH;
  2214. + start_code_found = 1;
  2215. + break;
  2216. + }
  2217. + }
  2218. + }
  2219. + }
  2220. + if (start_code_found) {
  2221. + vc1_extract_header(s, avctx, unesc_buffer, unesc_index);
  2222. +
  2223. + vpc->prev_start_code = b;
  2224. + unesc_index = 0;
  2225. +
  2226. + if (!(s->flags & PARSER_FLAG_COMPLETE_FRAMES)) {
  2227. + if (!pic_found && (b == (VC1_CODE_FRAME & 0xFF) || b == (VC1_CODE_FIELD & 0xFF))) {
  2228. + pic_found = 1;
  2229. + }
  2230. + else if (pic_found && b != (VC1_CODE_FIELD & 0xFF) && b != (VC1_CODE_SLICE & 0xFF)) {
  2231. + next = i - 4;
  2232. + pic_found = b == (VC1_CODE_FRAME & 0xFF);
  2233. + break;
  2234. + }
  2235. + }
  2236. + }
  2237. + }
  2238. + vpc->pc.frame_start_found = pic_found;
  2239. + vpc->unesc_index = unesc_index;
  2240. + vpc->search_state = search_state;
  2241. +
  2242. + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
  2243. + next = buf_size;
  2244. + } else {
  2245. if (ff_combine_frame(&vpc->pc, next, &buf, &buf_size) < 0) {
  2246. + vpc->bytes_to_skip = 0;
  2247. *poutbuf = NULL;
  2248. *poutbuf_size = 0;
  2249. return buf_size;
  2250. }
  2251. }
  2252. - vc1_extract_headers(s, avctx, buf, buf_size);
  2253. + vpc->v.first_pic_header_flag = 1;
  2254. +
  2255. + /* If we return with a valid pointer to a combined frame buffer
  2256. + * then on the next call then we'll have been unhelpfully rewound
  2257. + * by up to 4 bytes (depending upon whether the start code
  2258. + * overlapped the input buffer, and if so by how much). We don't
  2259. + * want this: it will either cause spurious second detections of
  2260. + * the start code we've already seen, or cause extra bytes to be
  2261. + * inserted at the start of the unescaped buffer. */
  2262. + vpc->bytes_to_skip = 4;
  2263. + if (next < 0)
  2264. + vpc->bytes_to_skip += next;
  2265. *poutbuf = buf;
  2266. *poutbuf_size = buf_size;
  2267. @@ -188,6 +264,11 @@ static int vc1_parse_init(AVCodecParserContext *s)
  2268. {
  2269. VC1ParseContext *vpc = s->priv_data;
  2270. vpc->v.s.slice_context_count = 1;
  2271. + vpc->v.first_pic_header_flag = 1;
  2272. + vpc->prev_start_code = 0;
  2273. + vpc->bytes_to_skip = 0;
  2274. + vpc->unesc_index = 0;
  2275. + vpc->search_state = NO_MATCH;
  2276. return ff_vc1_init_common(&vpc->v);
  2277. }
  2278. --
  2279. 1.9.3
  2280. From c2ebe54fe1d7c7a6cee7282bcf2668a826006ade Mon Sep 17 00:00:00 2001
  2281. From: Ben Avison <bavison@riscosopen.org>
  2282. Date: Wed, 19 Mar 2014 17:44:59 +0000
  2283. Subject: [PATCH 08/94] truehd: add hand-scheduled ARM asm version of
  2284. mlp_filter_channel.
  2285. Profiling results for overall audio decode and the mlp_filter_channel(_arm)
  2286. function in particular are as follows:
  2287. Before After
  2288. Mean StdDev Mean StdDev Confidence Change
  2289. 6:2 total 380.4 22.0 370.8 17.0 87.4% +2.6% (insignificant)
  2290. 6:2 function 60.7 7.2 36.6 8.1 100.0% +65.8%
  2291. 8:2 total 357.0 17.5 343.2 19.0 97.8% +4.0% (insignificant)
  2292. 8:2 function 60.3 8.8 37.3 3.8 100.0% +61.8%
  2293. 6:6 total 717.2 23.2 658.4 15.7 100.0% +8.9%
  2294. 6:6 function 140.4 12.9 81.5 9.2 100.0% +72.4%
  2295. 8:8 total 981.9 16.2 896.2 24.5 100.0% +9.6%
  2296. 8:8 function 193.4 15.0 103.3 11.5 100.0% +87.2%
  2297. Experiments with adding preload instructions to this function yielded no
  2298. useful benefit, so these have not been included.
  2299. The assembly version has also been tested with a fuzz tester to ensure that
  2300. any combinations of inputs not exercised by my available test streams still
  2301. generate mathematically identical results to the C version.
  2302. ---
  2303. lib/ffmpeg/libavcodec/arm/Makefile | 5 +-
  2304. lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S | 430 ++++++++++++++++++++++++++++
  2305. lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c | 36 +++
  2306. lib/ffmpeg/libavcodec/mlpdsp.h | 1 +
  2307. 4 files changed, 471 insertions(+), 1 deletion(-)
  2308. create mode 100644 lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  2309. create mode 100644 lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  2310. diff --git a/lib/ffmpeg/libavcodec/arm/Makefile b/lib/ffmpeg/libavcodec/arm/Makefile
  2311. index 715eed7..5b0edf0 100644
  2312. --- a/lib/ffmpeg/libavcodec/arm/Makefile
  2313. +++ b/lib/ffmpeg/libavcodec/arm/Makefile
  2314. @@ -14,6 +14,8 @@ ARMV6-OBJS-$(CONFIG_H264DSP) += arm/startcode_armv6.o
  2315. OBJS-$(CONFIG_FLAC_DECODER) += arm/flacdsp_init_arm.o \
  2316. arm/flacdsp_arm.o \
  2317. +OBJS-$(CONFIG_MLP_DECODER) += arm/mlpdsp_init_arm.o \
  2318. + arm/mlpdsp_arm.o
  2319. OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_init_arm.o
  2320. ARMV6-OBJS-$(CONFIG_MPEGAUDIODSP) += arm/mpegaudiodsp_fixed_armv6.o
  2321. ARMV6-OBJS-$(CONFIG_VC1_DECODER) += arm/startcode_armv6.o
  2322. @@ -21,6 +23,8 @@ OBJS-$(CONFIG_VC1_DECODER) += arm/vc1dsp_init_arm.o
  2323. ARMV6-OBJS-$(CONFIG_VC1_PARSER) += arm/startcode_armv6.o
  2324. OBJS-$(CONFIG_MPEGVIDEO) += arm/mpegvideo_arm.o
  2325. +OBJS-$(CONFIG_TRUEHD_DECODER) += arm/mlpdsp_init_arm.o \
  2326. + arm/mlpdsp_arm.o
  2327. OBJS-$(CONFIG_VORBIS_DECODER) += arm/vorbisdsp_init_arm.o
  2328. OBJS-$(CONFIG_VP3DSP) += arm/vp3dsp_init_arm.o
  2329. OBJS-$(CONFIG_VP5_DECODER) += arm/vp56dsp_init_arm.o
  2330. @@ -34,7 +38,6 @@ OBJS-$(CONFIG_H264CHROMA) += arm/h264chroma_init_arm.o
  2331. OBJS-$(CONFIG_H264DSP) += arm/h264dsp_init_arm.o
  2332. OBJS-$(CONFIG_H264PRED) += arm/h264pred_init_arm.o
  2333. OBJS-$(CONFIG_H264QPEL) += arm/h264qpel_init_arm.o
  2334. -
  2335. OBJS-$(CONFIG_RV30_DECODER) += arm/rv34dsp_init_arm.o
  2336. OBJS-$(CONFIG_RV40_DECODER) += arm/rv34dsp_init_arm.o \
  2337. arm/rv40dsp_init_arm.o \
  2338. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  2339. new file mode 100644
  2340. index 0000000..114496f
  2341. --- /dev/null
  2342. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  2343. @@ -0,0 +1,430 @@
  2344. +/*
  2345. + * Copyright (c) 2014 RISC OS Open Ltd
  2346. + * Author: Ben Avison <bavison@riscosopen.org>
  2347. + *
  2348. + * This file is part of Libav.
  2349. + *
  2350. + * Libav is free software; you can redistribute it and/or
  2351. + * modify it under the terms of the GNU Lesser General Public
  2352. + * License as published by the Free Software Foundation; either
  2353. + * version 2.1 of the License, or (at your option) any later version.
  2354. + *
  2355. + * Libav is distributed in the hope that it will be useful,
  2356. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2357. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2358. + * Lesser General Public License for more details.
  2359. + *
  2360. + * You should have received a copy of the GNU Lesser General Public
  2361. + * License along with Libav; if not, write to the Free Software
  2362. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  2363. + */
  2364. +
  2365. +// This code uses too many ARM-only tricks to easily assemble as Thumb
  2366. +.arm
  2367. +#undef CONFIG_THUMB
  2368. +#define CONFIG_THUMB 0
  2369. +
  2370. +#include "libavutil/arm/asm.S"
  2371. +
  2372. +#define MAX_CHANNELS 8
  2373. +#define MAX_FIR_ORDER 8
  2374. +#define MAX_IIR_ORDER 4
  2375. +#define MAX_RATEFACTOR 4
  2376. +#define MAX_BLOCKSIZE (40 * MAX_RATEFACTOR)
  2377. +
  2378. +PST .req a1
  2379. +PCO .req a2
  2380. +AC0 .req a3
  2381. +AC1 .req a4
  2382. +CO0 .req v1
  2383. +CO1 .req v2
  2384. +CO2 .req v3
  2385. +CO3 .req v4
  2386. +ST0 .req v5
  2387. +ST1 .req v6
  2388. +ST2 .req sl
  2389. +ST3 .req fp
  2390. +I .req ip
  2391. +PSAMP .req lr
  2392. +
  2393. +
  2394. +// Some macros that do loads/multiplies where the register number is determined
  2395. +// from an assembly-time expression. Boy is GNU assembler's syntax ugly...
  2396. +
  2397. +.macro load group, index, base, offset
  2398. + .altmacro
  2399. + load_ \group, %(\index), \base, \offset
  2400. + .noaltmacro
  2401. +.endm
  2402. +
  2403. +.macro load_ group, index, base, offset
  2404. + ldr \group\index, [\base, #\offset]
  2405. +.endm
  2406. +
  2407. +.macro loadd group, index, base, offset
  2408. + .altmacro
  2409. + loadd_ \group, %(\index), %(\index+1), \base, \offset
  2410. + .noaltmacro
  2411. +.endm
  2412. +
  2413. +.macro loadd_ group, index0, index1, base, offset
  2414. +A .if offset >= 256
  2415. +A ldr \group\index0, [\base, #\offset]
  2416. +A ldr \group\index1, [\base, #(\offset) + 4]
  2417. +A .else
  2418. + ldrd \group\index0, \group\index1, [\base, #\offset]
  2419. +A .endif
  2420. +.endm
  2421. +
  2422. +.macro multiply index, accumulate, long
  2423. + .altmacro
  2424. + multiply_ %(\index), \accumulate, \long
  2425. + .noaltmacro
  2426. +.endm
  2427. +
  2428. +.macro multiply_ index, accumulate, long
  2429. + .if \long
  2430. + .if \accumulate
  2431. + smlal AC0, AC1, CO\index, ST\index
  2432. + .else
  2433. + smull AC0, AC1, CO\index, ST\index
  2434. + .endif
  2435. + .else
  2436. + .if \accumulate
  2437. + mla AC0, CO\index, ST\index, AC0
  2438. + .else
  2439. + mul AC0, CO\index, ST\index
  2440. + .endif
  2441. + .endif
  2442. +.endm
  2443. +
  2444. +// A macro to update the load register number and load offsets
  2445. +
  2446. +.macro inc howmany
  2447. + .set LOAD_REG, (LOAD_REG + \howmany) & 3
  2448. + .set OFFSET_CO, OFFSET_CO + 4 * \howmany
  2449. + .set OFFSET_ST, OFFSET_ST + 4 * \howmany
  2450. + .if FIR_REMAIN > 0
  2451. + .set FIR_REMAIN, FIR_REMAIN - \howmany
  2452. + .if FIR_REMAIN == 0
  2453. + .set OFFSET_CO, 4 * MAX_FIR_ORDER
  2454. + .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)
  2455. + .endif
  2456. + .elseif IIR_REMAIN > 0
  2457. + .set IIR_REMAIN, IIR_REMAIN - \howmany
  2458. + .endif
  2459. +.endm
  2460. +
  2461. +// Macro to implement the inner loop for one specific combination of parameters
  2462. +
  2463. +.macro implement_filter mask_minus1, shift_0, shift_8, iir_taps, fir_taps
  2464. + .set TOTAL_TAPS, \iir_taps + \fir_taps
  2465. +
  2466. + // Deal with register allocation...
  2467. + .set DEFINED_SHIFT, 0
  2468. + .set DEFINED_MASK, 0
  2469. + .set SHUFFLE_SHIFT, 0
  2470. + .set SHUFFLE_MASK, 0
  2471. + .set SPILL_SHIFT, 0
  2472. + .set SPILL_MASK, 0
  2473. + .if TOTAL_TAPS == 0
  2474. + // Little register pressure in this case - just keep MASK where it was
  2475. + .if !\mask_minus1
  2476. + MASK .req ST1
  2477. + .set DEFINED_MASK, 1
  2478. + .endif
  2479. + .else
  2480. + .if \shift_0
  2481. + .if !\mask_minus1
  2482. + // AC1 is unused with shift 0
  2483. + MASK .req AC1
  2484. + .set DEFINED_MASK, 1
  2485. + .set SHUFFLE_MASK, 1
  2486. + .endif
  2487. + .elseif \shift_8
  2488. + .if !\mask_minus1
  2489. + .if TOTAL_TAPS <= 4
  2490. + // All coefficients are preloaded (so pointer not needed)
  2491. + MASK .req PCO
  2492. + .set DEFINED_MASK, 1
  2493. + .set SHUFFLE_MASK, 1
  2494. + .else
  2495. + .set SPILL_MASK, 1
  2496. + .endif
  2497. + .endif
  2498. + .else // shift not 0 or 8
  2499. + .if TOTAL_TAPS <= 3
  2500. + // All coefficients are preloaded, and at least one CO register is unused
  2501. + .if \fir_taps & 1
  2502. + SHIFT .req CO0
  2503. + .set DEFINED_SHIFT, 1
  2504. + .set SHUFFLE_SHIFT, 1
  2505. + .else
  2506. + SHIFT .req CO3
  2507. + .set DEFINED_SHIFT, 1
  2508. + .set SHUFFLE_SHIFT, 1
  2509. + .endif
  2510. + .if !\mask_minus1
  2511. + MASK .req PCO
  2512. + .set DEFINED_MASK, 1
  2513. + .set SHUFFLE_MASK, 1
  2514. + .endif
  2515. + .elseif TOTAL_TAPS == 4
  2516. + // All coefficients are preloaded
  2517. + SHIFT .req PCO
  2518. + .set DEFINED_SHIFT, 1
  2519. + .set SHUFFLE_SHIFT, 1
  2520. + .if !\mask_minus1
  2521. + .set SPILL_MASK, 1
  2522. + .endif
  2523. + .else
  2524. + .set SPILL_SHIFT, 1
  2525. + .if !\mask_minus1
  2526. + .set SPILL_MASK, 1
  2527. + .endif
  2528. + .endif
  2529. + .endif
  2530. + .endif
  2531. + .if SPILL_SHIFT
  2532. + SHIFT .req ST0
  2533. + .set DEFINED_SHIFT, 1
  2534. + .endif
  2535. + .if SPILL_MASK
  2536. + MASK .req ST1
  2537. + .set DEFINED_MASK, 1
  2538. + .endif
  2539. +
  2540. + // Preload coefficients if possible
  2541. + .if TOTAL_TAPS <= 4
  2542. + .set OFFSET_CO, 0
  2543. + .if \fir_taps & 1
  2544. + .set LOAD_REG, 1
  2545. + .else
  2546. + .set LOAD_REG, 0
  2547. + .endif
  2548. + .rept \fir_taps
  2549. + load CO, LOAD_REG, PCO, OFFSET_CO
  2550. + .set LOAD_REG, (LOAD_REG + 1) & 3
  2551. + .set OFFSET_CO, OFFSET_CO + 4
  2552. + .endr
  2553. + .set OFFSET_CO, 4 * MAX_FIR_ORDER
  2554. + .rept \iir_taps
  2555. + load CO, LOAD_REG, PCO, OFFSET_CO
  2556. + .set LOAD_REG, (LOAD_REG + 1) & 3
  2557. + .set OFFSET_CO, OFFSET_CO + 4
  2558. + .endr
  2559. + .endif
  2560. +
  2561. + // Move mask/shift to final positions if necessary
  2562. + // Need to do this after preloading, because in some cases we
  2563. + // reuse the coefficient pointer register
  2564. + .if SHUFFLE_SHIFT
  2565. + mov SHIFT, ST0
  2566. + .endif
  2567. + .if SHUFFLE_MASK
  2568. + mov MASK, ST1
  2569. + .endif
  2570. +
  2571. + // Begin loop
  2572. +01:
  2573. + .if TOTAL_TAPS == 0
  2574. + // Things simplify a lot in this case
  2575. + // In fact this could be pipelined further if it's worth it...
  2576. + ldr ST0, [PSAMP]
  2577. + subs I, I, #1
  2578. + .if !\mask_minus1
  2579. + and ST0, ST0, MASK
  2580. + .endif
  2581. + str ST0, [PST, #-4]!
  2582. + str ST0, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)]
  2583. + str ST0, [PSAMP], #4 * MAX_CHANNELS
  2584. + bne 01b
  2585. + .else
  2586. + .if \fir_taps & 1
  2587. + .set LOAD_REG, 1
  2588. + .else
  2589. + .set LOAD_REG, 0
  2590. + .endif
  2591. + .set LOAD_BANK, 0
  2592. + .set FIR_REMAIN, \fir_taps
  2593. + .set IIR_REMAIN, \iir_taps
  2594. + .if FIR_REMAIN == 0 // only IIR terms
  2595. + .set OFFSET_CO, 4 * MAX_FIR_ORDER
  2596. + .set OFFSET_ST, 4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)
  2597. + .else
  2598. + .set OFFSET_CO, 0
  2599. + .set OFFSET_ST, 0
  2600. + .endif
  2601. + .set MUL_REG, LOAD_REG
  2602. + .set COUNTER, 0
  2603. + .rept TOTAL_TAPS + 2
  2604. + // Do load(s)
  2605. + .if FIR_REMAIN != 0 || IIR_REMAIN != 0
  2606. + .if COUNTER == 0
  2607. + .if TOTAL_TAPS > 4
  2608. + load CO, LOAD_REG, PCO, OFFSET_CO
  2609. + .endif
  2610. + load ST, LOAD_REG, PST, OFFSET_ST
  2611. + inc 1
  2612. + .elseif COUNTER == 1 && (\fir_taps & 1) == 0
  2613. + .if TOTAL_TAPS > 4
  2614. + load CO, LOAD_REG, PCO, OFFSET_CO
  2615. + .endif
  2616. + load ST, LOAD_REG, PST, OFFSET_ST
  2617. + inc 1
  2618. + .elseif LOAD_BANK == 0
  2619. + .if TOTAL_TAPS > 4
  2620. + .if FIR_REMAIN == 0 && IIR_REMAIN == 1
  2621. + load CO, LOAD_REG, PCO, OFFSET_CO
  2622. + .else
  2623. + loadd CO, LOAD_REG, PCO, OFFSET_CO
  2624. + .endif
  2625. + .endif
  2626. + .set LOAD_BANK, 1
  2627. + .else
  2628. + .if FIR_REMAIN == 0 && IIR_REMAIN == 1
  2629. + load ST, LOAD_REG, PST, OFFSET_ST
  2630. + inc 1
  2631. + .else
  2632. + loadd ST, LOAD_REG, PST, OFFSET_ST
  2633. + inc 2
  2634. + .endif
  2635. + .set LOAD_BANK, 0
  2636. + .endif
  2637. + .endif
  2638. +
  2639. + // Do interleaved multiplies, slightly delayed
  2640. + .if COUNTER >= 2
  2641. + multiply MUL_REG, COUNTER > 2, !\shift_0
  2642. + .set MUL_REG, (MUL_REG + 1) & 3
  2643. + .endif
  2644. + .set COUNTER, COUNTER + 1
  2645. + .endr
  2646. +
  2647. + // Post-process the result of the multiplies
  2648. + .if SPILL_SHIFT
  2649. + ldr SHIFT, [sp, #9*4 + 0*4]
  2650. + .endif
  2651. + .if SPILL_MASK
  2652. + ldr MASK, [sp, #9*4 + 1*4]
  2653. + .endif
  2654. + ldr ST2, [PSAMP]
  2655. + subs I, I, #1
  2656. + .if \shift_8
  2657. + mov AC0, AC0, lsr #8
  2658. + orr AC0, AC0, AC1, lsl #24
  2659. + .elseif !\shift_0
  2660. + rsb ST3, SHIFT, #32
  2661. + mov AC0, AC0, lsr SHIFT
  2662. + orr AC0, AC0, AC1, lsl ST3
  2663. + .endif
  2664. + .if \mask_minus1
  2665. + add ST3, ST2, AC0
  2666. + .else
  2667. + add ST2, ST2, AC0
  2668. + and ST3, ST2, MASK
  2669. + sub ST2, ST3, AC0
  2670. + .endif
  2671. + str ST3, [PST, #-4]!
  2672. + str ST2, [PST, #4 * (MAX_BLOCKSIZE + MAX_FIR_ORDER)]
  2673. + str ST3, [PSAMP], #4 * MAX_CHANNELS
  2674. + bne 01b
  2675. + .endif
  2676. + b 99f
  2677. +
  2678. + .if DEFINED_SHIFT
  2679. + .unreq SHIFT
  2680. + .endif
  2681. + .if DEFINED_MASK
  2682. + .unreq MASK
  2683. + .endif
  2684. +.endm
  2685. +
  2686. +.macro switch_on_fir_taps mask_minus1, shift_0, shift_8, iir_taps
  2687. + ldr pc, [pc, a3, LSL #2] // firorder is in range 0-(8-iir_taps)
  2688. + .word 0
  2689. + .word 70f
  2690. + .word 71f
  2691. + .word 72f
  2692. + .word 73f
  2693. + .word 74f
  2694. + .word 75f
  2695. + .if \iir_taps <= 2
  2696. + .word 76f
  2697. + .if \iir_taps <= 1
  2698. + .word 77f
  2699. + .if \iir_taps == 0
  2700. + .word 78f
  2701. + .endif
  2702. + .endif
  2703. + .endif
  2704. +70: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 0
  2705. +71: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 1
  2706. +72: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 2
  2707. +73: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 3
  2708. +74: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 4
  2709. +75: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 5
  2710. + .if \iir_taps <= 2
  2711. +76: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 6
  2712. + .if \iir_taps <= 1
  2713. +77: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 7
  2714. + .if \iir_taps == 0
  2715. +78: implement_filter \mask_minus1, \shift_0, \shift_8, \iir_taps, 8
  2716. + .endif
  2717. + .endif
  2718. + .endif
  2719. +.endm
  2720. +
  2721. +.macro switch_on_iir_taps mask_minus1, shift_0, shift_8
  2722. + ldr pc, [pc, a4, LSL #2] // irorder is in range 0-3
  2723. + .word 0
  2724. + .word 60f
  2725. + .word 61f
  2726. + .word 62f
  2727. + .word 63f
  2728. +60: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 0
  2729. +61: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 1
  2730. +62: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 2
  2731. +63: switch_on_fir_taps \mask_minus1, \shift_0, \shift_8, 3
  2732. +.endm
  2733. +
  2734. +/* void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff,
  2735. + * int firorder, int iirorder,
  2736. + * unsigned int filter_shift, int32_t mask,
  2737. + * int blocksize, int32_t *sample_buffer);
  2738. + */
  2739. +function ff_mlp_filter_channel_arm, export=1
  2740. + push {v1-fp,lr}
  2741. + add v1, sp, #9*4 // point at arguments on stack
  2742. + ldm v1, {ST0,ST1,I,PSAMP}
  2743. + cmp ST1, #-1
  2744. + bne 30f
  2745. + movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8
  2746. + bne 20f
  2747. + bcs 10f
  2748. + switch_on_iir_taps 1, 1, 0
  2749. +10: switch_on_iir_taps 1, 0, 1
  2750. +20: switch_on_iir_taps 1, 0, 0
  2751. +30: movs ST2, ST0, lsl #29 // shift is in range 0-15; we want to special-case 0 and 8
  2752. + bne 50f
  2753. + bcs 40f
  2754. + switch_on_iir_taps 0, 1, 0
  2755. +40: switch_on_iir_taps 0, 0, 1
  2756. +50: switch_on_iir_taps 0, 0, 0
  2757. +99: pop {v1-fp,pc}
  2758. +endfunc
  2759. +
  2760. + .unreq PST
  2761. + .unreq PCO
  2762. + .unreq AC0
  2763. + .unreq AC1
  2764. + .unreq CO0
  2765. + .unreq CO1
  2766. + .unreq CO2
  2767. + .unreq CO3
  2768. + .unreq ST0
  2769. + .unreq ST1
  2770. + .unreq ST2
  2771. + .unreq ST3
  2772. + .unreq I
  2773. + .unreq PSAMP
  2774. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  2775. new file mode 100644
  2776. index 0000000..f0ea285
  2777. --- /dev/null
  2778. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  2779. @@ -0,0 +1,36 @@
  2780. +/*
  2781. + * Copyright (c) 2014 RISC OS Open Ltd
  2782. + * Author: Ben Avison <bavison@riscosopen.org>
  2783. + *
  2784. + * This file is part of Libav.
  2785. + *
  2786. + * Libav is free software; you can redistribute it and/or
  2787. + * modify it under the terms of the GNU Lesser General Public
  2788. + * License as published by the Free Software Foundation; either
  2789. + * version 2.1 of the License, or (at your option) any later version.
  2790. + *
  2791. + * Libav is distributed in the hope that it will be useful,
  2792. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2793. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  2794. + * Lesser General Public License for more details.
  2795. + *
  2796. + * You should have received a copy of the GNU Lesser General Public
  2797. + * License along with Libav; if not, write to the Free Software
  2798. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  2799. + */
  2800. +
  2801. +#include <stdint.h>
  2802. +
  2803. +#include "libavutil/arm/cpu.h"
  2804. +#include "libavutil/attributes.h"
  2805. +#include "libavcodec/mlpdsp.h"
  2806. +
  2807. +void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff,
  2808. + int firorder, int iirorder,
  2809. + unsigned int filter_shift, int32_t mask,
  2810. + int blocksize, int32_t *sample_buffer);
  2811. +
  2812. +av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c)
  2813. +{
  2814. + c->mlp_filter_channel = ff_mlp_filter_channel_arm;
  2815. +}
  2816. diff --git a/lib/ffmpeg/libavcodec/mlpdsp.h b/lib/ffmpeg/libavcodec/mlpdsp.h
  2817. index 84a8aa3..129bcfe 100644
  2818. --- a/lib/ffmpeg/libavcodec/mlpdsp.h
  2819. +++ b/lib/ffmpeg/libavcodec/mlpdsp.h
  2820. @@ -32,6 +32,7 @@ typedef struct MLPDSPContext {
  2821. } MLPDSPContext;
  2822. void ff_mlpdsp_init(MLPDSPContext *c);
  2823. +void ff_mlpdsp_init_arm(MLPDSPContext *c);
  2824. void ff_mlpdsp_init_x86(MLPDSPContext *c);
  2825. #endif /* AVCODEC_MLPDSP_H */
  2826. --
  2827. 1.9.3
  2828. From 904cb11e58484c5d0bca17b8c209916d106d2079 Mon Sep 17 00:00:00 2001
  2829. From: Ben Avison <bavison@riscosopen.org>
  2830. Date: Wed, 19 Mar 2014 17:48:54 +0000
  2831. Subject: [PATCH 09/94] truehd: break out part of rematrix_channels into
  2832. platform-specific callback.
  2833. Verified with profiling that this doesn't have a measurable effect upon
  2834. overall performance.
  2835. ---
  2836. lib/ffmpeg/libavcodec/mlpdec.c | 37 ++++++++++++-------------------------
  2837. lib/ffmpeg/libavcodec/mlpdsp.c | 35 ++++++++++++++++++++++++++++++++++-
  2838. lib/ffmpeg/libavcodec/mlpdsp.h | 23 +++++++++++++++++++++++
  2839. 3 files changed, 69 insertions(+), 26 deletions(-)
  2840. diff --git a/lib/ffmpeg/libavcodec/mlpdec.c b/lib/ffmpeg/libavcodec/mlpdec.c
  2841. index c763624..e9343a5 100644
  2842. --- a/lib/ffmpeg/libavcodec/mlpdec.c
  2843. +++ b/lib/ffmpeg/libavcodec/mlpdec.c
  2844. @@ -958,7 +958,7 @@ static void fill_noise_buffer(MLPDecodeContext *m, unsigned int substr)
  2845. static void rematrix_channels(MLPDecodeContext *m, unsigned int substr)
  2846. {
  2847. SubStream *s = &m->substream[substr];
  2848. - unsigned int mat, src_ch, i;
  2849. + unsigned int mat;
  2850. unsigned int maxchan;
  2851. maxchan = s->max_matrix_channel;
  2852. @@ -970,31 +970,18 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr)
  2853. }
  2854. for (mat = 0; mat < s->num_primitive_matrices; mat++) {
  2855. - int matrix_noise_shift = s->matrix_noise_shift[mat];
  2856. unsigned int dest_ch = s->matrix_out_ch[mat];
  2857. - int32_t mask = MSB_MASK(s->quant_step_size[dest_ch]);
  2858. - int32_t *coeffs = s->matrix_coeff[mat];
  2859. - int index = s->num_primitive_matrices - mat;
  2860. - int index2 = 2 * index + 1;
  2861. -
  2862. - /* TODO: DSPContext? */
  2863. -
  2864. - for (i = 0; i < s->blockpos; i++) {
  2865. - int32_t bypassed_lsb = m->bypassed_lsbs[i][mat];
  2866. - int32_t *samples = m->sample_buffer[i];
  2867. - int64_t accum = 0;
  2868. -
  2869. - for (src_ch = 0; src_ch <= maxchan; src_ch++)
  2870. - accum += (int64_t) samples[src_ch] * coeffs[src_ch];
  2871. -
  2872. - if (matrix_noise_shift) {
  2873. - index &= m->access_unit_size_pow2 - 1;
  2874. - accum += m->noise_buffer[index] << (matrix_noise_shift + 7);
  2875. - index += index2;
  2876. - }
  2877. -
  2878. - samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb;
  2879. - }
  2880. + m->dsp.mlp_rematrix_channel(&m->sample_buffer[0][0],
  2881. + s->matrix_coeff[mat],
  2882. + &m->bypassed_lsbs[0][mat],
  2883. + m->noise_buffer,
  2884. + s->num_primitive_matrices - mat,
  2885. + dest_ch,
  2886. + s->blockpos,
  2887. + maxchan,
  2888. + s->matrix_noise_shift[mat],
  2889. + m->access_unit_size_pow2,
  2890. + MSB_MASK(s->quant_step_size[dest_ch]));
  2891. }
  2892. }
  2893. diff --git a/lib/ffmpeg/libavcodec/mlpdsp.c b/lib/ffmpeg/libavcodec/mlpdsp.c
  2894. index 9a376e2..1f912fb 100644
  2895. --- a/lib/ffmpeg/libavcodec/mlpdsp.c
  2896. +++ b/lib/ffmpeg/libavcodec/mlpdsp.c
  2897. @@ -56,9 +56,42 @@ static void ff_mlp_filter_channel(int32_t *state, const int32_t *coeff,
  2898. }
  2899. }
  2900. -void ff_mlpdsp_init(MLPDSPContext *c)
  2901. +void ff_mlp_rematrix_channel(int32_t *samples,
  2902. + const int32_t *coeffs,
  2903. + const uint8_t *bypassed_lsbs,
  2904. + const int8_t *noise_buffer,
  2905. + int index,
  2906. + unsigned int dest_ch,
  2907. + uint16_t blockpos,
  2908. + unsigned int maxchan,
  2909. + int matrix_noise_shift,
  2910. + int access_unit_size_pow2,
  2911. + int32_t mask)
  2912. +{
  2913. + unsigned int src_ch, i;
  2914. + int index2 = 2 * index + 1;
  2915. + for (i = 0; i < blockpos; i++) {
  2916. + int64_t accum = 0;
  2917. +
  2918. + for (src_ch = 0; src_ch <= maxchan; src_ch++)
  2919. + accum += (int64_t) samples[src_ch] * coeffs[src_ch];
  2920. +
  2921. + if (matrix_noise_shift) {
  2922. + index &= access_unit_size_pow2 - 1;
  2923. + accum += noise_buffer[index] << (matrix_noise_shift + 7);
  2924. + index += index2;
  2925. + }
  2926. +
  2927. + samples[dest_ch] = ((accum >> 14) & mask) + *bypassed_lsbs;
  2928. + bypassed_lsbs += MAX_CHANNELS;
  2929. + samples += MAX_CHANNELS;
  2930. + }
  2931. +}
  2932. +
  2933. +av_cold void ff_mlpdsp_init(MLPDSPContext *c)
  2934. {
  2935. c->mlp_filter_channel = ff_mlp_filter_channel;
  2936. + c->mlp_rematrix_channel = ff_mlp_rematrix_channel;
  2937. if (ARCH_X86)
  2938. ff_mlpdsp_init_x86(c);
  2939. }
  2940. diff --git a/lib/ffmpeg/libavcodec/mlpdsp.h b/lib/ffmpeg/libavcodec/mlpdsp.h
  2941. index 129bcfe..f98e9be 100644
  2942. --- a/lib/ffmpeg/libavcodec/mlpdsp.h
  2943. +++ b/lib/ffmpeg/libavcodec/mlpdsp.h
  2944. @@ -24,11 +24,34 @@
  2945. #include <stdint.h>
  2946. +void ff_mlp_rematrix_channel(int32_t *samples,
  2947. + const int32_t *coeffs,
  2948. + const uint8_t *bypassed_lsbs,
  2949. + const int8_t *noise_buffer,
  2950. + int index,
  2951. + unsigned int dest_ch,
  2952. + uint16_t blockpos,
  2953. + unsigned int maxchan,
  2954. + int matrix_noise_shift,
  2955. + int access_unit_size_pow2,
  2956. + int32_t mask);
  2957. +
  2958. typedef struct MLPDSPContext {
  2959. void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff,
  2960. int firorder, int iirorder,
  2961. unsigned int filter_shift, int32_t mask,
  2962. int blocksize, int32_t *sample_buffer);
  2963. + void (*mlp_rematrix_channel)(int32_t *samples,
  2964. + const int32_t *coeffs,
  2965. + const uint8_t *bypassed_lsbs,
  2966. + const int8_t *noise_buffer,
  2967. + int index,
  2968. + unsigned int dest_ch,
  2969. + uint16_t blockpos,
  2970. + unsigned int maxchan,
  2971. + int matrix_noise_shift,
  2972. + int access_unit_size_pow2,
  2973. + int32_t mask);
  2974. } MLPDSPContext;
  2975. void ff_mlpdsp_init(MLPDSPContext *c);
  2976. --
  2977. 1.9.3
  2978. From 0bb8daacca4b35d716addbc591fec43fd4fe6467 Mon Sep 17 00:00:00 2001
  2979. From: Ben Avison <bavison@riscosopen.org>
  2980. Date: Wed, 19 Mar 2014 17:49:48 +0000
  2981. Subject: [PATCH 10/94] truehd: add hand-scheduled ARM asm version of
  2982. ff_mlp_rematrix_channel.
  2983. Profiling results for overall audio decode and the rematrix_channels function
  2984. in particular are as follows:
  2985. Before After
  2986. Mean StdDev Mean StdDev Confidence Change
  2987. 6:2 total 370.8 17.0 348.8 20.1 99.9% +6.3%
  2988. 6:2 function 46.4 8.4 45.8 6.6 18.0% +1.2% (insignificant)
  2989. 8:2 total 343.2 19.0 339.1 15.4 54.7% +1.2% (insignificant)
  2990. 8:2 function 38.9 3.9 40.2 6.9 52.4% -3.2% (insignificant)
  2991. 6:6 total 658.4 15.7 604.6 20.8 100.0% +8.9%
  2992. 6:6 function 109.0 8.7 59.5 5.4 100.0% +83.3%
  2993. 8:8 total 896.2 24.5 766.4 17.6 100.0% +16.9%
  2994. 8:8 function 223.4 12.8 93.8 5.0 100.0% +138.3%
  2995. The assembly version has also been tested with a fuzz tester to ensure that
  2996. any combinations of inputs not exercised by my available test streams still
  2997. generate mathematically identical results to the C version.
  2998. ---
  2999. lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S | 231 ++++++++++++++++++++++++++++
  3000. lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c | 12 ++
  3001. 2 files changed, 243 insertions(+)
  3002. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3003. index 114496f..10008fe 100644
  3004. --- a/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3005. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3006. @@ -428,3 +428,234 @@ endfunc
  3007. .unreq ST3
  3008. .unreq I
  3009. .unreq PSAMP
  3010. +
  3011. +/********************************************************************/
  3012. +
  3013. +PSA .req a1 // samples
  3014. +PCO .req a2 // coeffs
  3015. +PBL .req a3 // bypassed_lsbs
  3016. +INDEX .req a4
  3017. +CO0 .req v1
  3018. +CO1 .req v2
  3019. +CO2 .req v3
  3020. +CO3 .req v4
  3021. +SA0 .req v5
  3022. +SA1 .req v6
  3023. +SA2 .req sl
  3024. +SA3 .req fp
  3025. +AC0 .req ip
  3026. +AC1 .req lr
  3027. +NOISE .req SA0
  3028. +LSB .req SA1
  3029. +DCH .req SA2 // dest_ch
  3030. +MASK .req SA3
  3031. +
  3032. + // INDEX is used as follows:
  3033. + // bits 0..6 index2 (values up to 17, but wider so that we can
  3034. + // add to index field without needing to mask)
  3035. + // bits 7..14 i (values up to 160)
  3036. + // bit 15 underflow detect for i
  3037. + // bits 25..31 (if access_unit_size_pow2 == 128) \ index
  3038. + // bits 26..31 (if access_unit_size_pow2 == 64) /
  3039. +
  3040. +.macro implement_rematrix shift, index_mask, mask_minus1, maxchan
  3041. + .if \maxchan == 1
  3042. + // We can just leave the coefficients in registers in this case
  3043. + ldrd CO0, CO1, [PCO]
  3044. + .endif
  3045. +1:
  3046. + .if \maxchan == 1
  3047. + ldrd SA0, SA1, [PSA]
  3048. + smull AC0, AC1, CO0, SA0
  3049. + .elseif \maxchan == 5
  3050. + ldr CO0, [PCO, #0]
  3051. + ldr SA0, [PSA, #0]
  3052. + ldr CO1, [PCO, #4]
  3053. + ldr SA1, [PSA, #4]
  3054. + ldrd CO2, CO3, [PCO, #8]
  3055. + smull AC0, AC1, CO0, SA0
  3056. + ldrd SA2, SA3, [PSA, #8]
  3057. + smlal AC0, AC1, CO1, SA1
  3058. + ldrd CO0, CO1, [PCO, #16]
  3059. + smlal AC0, AC1, CO2, SA2
  3060. + ldrd SA0, SA1, [PSA, #16]
  3061. + smlal AC0, AC1, CO3, SA3
  3062. + smlal AC0, AC1, CO0, SA0
  3063. + .else // \maxchan == 7
  3064. + ldr CO2, [PCO, #0]
  3065. + ldr SA2, [PSA, #0]
  3066. + ldr CO3, [PCO, #4]
  3067. + ldr SA3, [PSA, #4]
  3068. + ldrd CO0, CO1, [PCO, #8]
  3069. + smull AC0, AC1, CO2, SA2
  3070. + ldrd SA0, SA1, [PSA, #8]
  3071. + smlal AC0, AC1, CO3, SA3
  3072. + ldrd CO2, CO3, [PCO, #16]
  3073. + smlal AC0, AC1, CO0, SA0
  3074. + ldrd SA2, SA3, [PSA, #16]
  3075. + smlal AC0, AC1, CO1, SA1
  3076. + ldrd CO0, CO1, [PCO, #24]
  3077. + smlal AC0, AC1, CO2, SA2
  3078. + ldrd SA0, SA1, [PSA, #24]
  3079. + smlal AC0, AC1, CO3, SA3
  3080. + smlal AC0, AC1, CO0, SA0
  3081. + .endif
  3082. + ldm sp, {NOISE, DCH, MASK}
  3083. + smlal AC0, AC1, CO1, SA1
  3084. + .if \shift != 0
  3085. + .if \index_mask == 63
  3086. + add NOISE, NOISE, INDEX, lsr #32-6
  3087. + ldrb LSB, [PBL], #MAX_CHANNELS
  3088. + ldrsb NOISE, [NOISE]
  3089. + add INDEX, INDEX, INDEX, lsl #32-6
  3090. + .else // \index_mask == 127
  3091. + add NOISE, NOISE, INDEX, lsr #32-7
  3092. + ldrb LSB, [PBL], #MAX_CHANNELS
  3093. + ldrsb NOISE, [NOISE]
  3094. + add INDEX, INDEX, INDEX, lsl #32-7
  3095. + .endif
  3096. + sub INDEX, INDEX, #1<<7
  3097. + adds AC0, AC0, NOISE, lsl #\shift + 7
  3098. + adc AC1, AC1, NOISE, asr #31
  3099. + .else
  3100. + ldrb LSB, [PBL], #MAX_CHANNELS
  3101. + sub INDEX, INDEX, #1<<7
  3102. + .endif
  3103. + add PSA, PSA, #MAX_CHANNELS*4
  3104. + mov AC0, AC0, lsr #14
  3105. + orr AC0, AC0, AC1, lsl #18
  3106. + .if !\mask_minus1
  3107. + and AC0, AC0, MASK
  3108. + .endif
  3109. + add AC0, AC0, LSB
  3110. + tst INDEX, #1<<15
  3111. + str AC0, [PSA, DCH, lsl #2] // DCH is precompensated for the early increment of PSA
  3112. + beq 1b
  3113. + b 98f
  3114. +.endm
  3115. +
  3116. +.macro switch_on_maxchan shift, index_mask, mask_minus1
  3117. + cmp v4, #5
  3118. + blo 51f
  3119. + beq 50f
  3120. + implement_rematrix \shift, \index_mask, \mask_minus1, 7
  3121. +50: implement_rematrix \shift, \index_mask, \mask_minus1, 5
  3122. +51: implement_rematrix \shift, \index_mask, \mask_minus1, 1
  3123. +.endm
  3124. +
  3125. +.macro switch_on_mask shift, index_mask
  3126. + cmp sl, #-1
  3127. + bne 40f
  3128. + switch_on_maxchan \shift, \index_mask, 1
  3129. +40: switch_on_maxchan \shift, \index_mask, 0
  3130. +.endm
  3131. +
  3132. +.macro switch_on_au_size shift
  3133. + .if \shift == 0
  3134. + switch_on_mask \shift, undefined
  3135. + .else
  3136. + teq v6, #64
  3137. + bne 30f
  3138. + orr INDEX, INDEX, v1, lsl #32-6
  3139. + switch_on_mask \shift, 63
  3140. +30: orr INDEX, INDEX, v1, lsl #32-7
  3141. + switch_on_mask \shift, 127
  3142. + .endif
  3143. +.endm
  3144. +
  3145. +/* void ff_mlp_rematrix_channel_arm(int32_t *samples,
  3146. + * const int32_t *coeffs,
  3147. + * const uint8_t *bypassed_lsbs,
  3148. + * const int8_t *noise_buffer,
  3149. + * int index,
  3150. + * unsigned int dest_ch,
  3151. + * uint16_t blockpos,
  3152. + * unsigned int maxchan,
  3153. + * int matrix_noise_shift,
  3154. + * int access_unit_size_pow2,
  3155. + * int32_t mask);
  3156. + */
  3157. +function ff_mlp_rematrix_channel_arm, export=1
  3158. + push {v1-fp,lr}
  3159. + add v1, sp, #9*4 // point at arguments on stack
  3160. + ldm v1, {v1-sl}
  3161. + teq v4, #1
  3162. + teqne v4, #5
  3163. + teqne v4, #7
  3164. + bne 99f
  3165. + teq v6, #64
  3166. + teqne v6, #128
  3167. + bne 99f
  3168. + sub v2, v2, #MAX_CHANNELS
  3169. + push {a4,v2,sl} // initialise NOISE,DCH,MASK; make sp dword-aligned
  3170. + movs INDEX, v3, lsl #7
  3171. + beq 98f // just in case, do nothing if blockpos = 0
  3172. + subs INDEX, INDEX, #1<<7 // offset by 1 so we borrow at the right time
  3173. + adc lr, v1, v1 // calculate index2 (C was set by preceding subs)
  3174. + orr INDEX, INDEX, lr
  3175. + // Switch on matrix_noise_shift: values 0 and 1 are
  3176. + // disproportionately common so do those in a form the branch
  3177. + // predictor can accelerate. Values can only go up to 15.
  3178. + cmp v5, #1
  3179. + beq 11f
  3180. + blo 10f
  3181. + ldr pc, [pc, v5, lsl #2]
  3182. + .word 0
  3183. + .word 0
  3184. + .word 0
  3185. + .word 12f
  3186. + .word 13f
  3187. + .word 14f
  3188. + .word 15f
  3189. + .word 16f
  3190. + .word 17f
  3191. + .word 18f
  3192. + .word 19f
  3193. + .word 20f
  3194. + .word 21f
  3195. + .word 22f
  3196. + .word 23f
  3197. + .word 24f
  3198. + .word 25f
  3199. +10: switch_on_au_size 0
  3200. +11: switch_on_au_size 1
  3201. +12: switch_on_au_size 2
  3202. +13: switch_on_au_size 3
  3203. +14: switch_on_au_size 4
  3204. +15: switch_on_au_size 5
  3205. +16: switch_on_au_size 6
  3206. +17: switch_on_au_size 7
  3207. +18: switch_on_au_size 8
  3208. +19: switch_on_au_size 9
  3209. +20: switch_on_au_size 10
  3210. +21: switch_on_au_size 11
  3211. +22: switch_on_au_size 12
  3212. +23: switch_on_au_size 13
  3213. +24: switch_on_au_size 14
  3214. +25: switch_on_au_size 15
  3215. +
  3216. +98: add sp, sp, #3*4
  3217. + pop {v1-fp,pc}
  3218. +99: // Can't handle these parameters, drop back to C
  3219. + pop {v1-fp,lr}
  3220. + b X(ff_mlp_rematrix_channel)
  3221. +endfunc
  3222. +
  3223. + .unreq PSA
  3224. + .unreq PCO
  3225. + .unreq PBL
  3226. + .unreq INDEX
  3227. + .unreq CO0
  3228. + .unreq CO1
  3229. + .unreq CO2
  3230. + .unreq CO3
  3231. + .unreq SA0
  3232. + .unreq SA1
  3233. + .unreq SA2
  3234. + .unreq SA3
  3235. + .unreq AC0
  3236. + .unreq AC1
  3237. + .unreq NOISE
  3238. + .unreq LSB
  3239. + .unreq DCH
  3240. + .unreq MASK
  3241. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  3242. index f0ea285..268dfdd 100644
  3243. --- a/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  3244. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  3245. @@ -29,8 +29,20 @@ void ff_mlp_filter_channel_arm(int32_t *state, const int32_t *coeff,
  3246. int firorder, int iirorder,
  3247. unsigned int filter_shift, int32_t mask,
  3248. int blocksize, int32_t *sample_buffer);
  3249. +void ff_mlp_rematrix_channel_arm(int32_t *samples,
  3250. + const int32_t *coeffs,
  3251. + const uint8_t *bypassed_lsbs,
  3252. + const int8_t *noise_buffer,
  3253. + int index,
  3254. + unsigned int dest_ch,
  3255. + uint16_t blockpos,
  3256. + unsigned int maxchan,
  3257. + int matrix_noise_shift,
  3258. + int access_unit_size_pow2,
  3259. + int32_t mask);
  3260. av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c)
  3261. {
  3262. c->mlp_filter_channel = ff_mlp_filter_channel_arm;
  3263. + c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm;
  3264. }
  3265. --
  3266. 1.9.3
  3267. From 034e1a8920aec0fa36ffc7da8f63e48c68364e15 Mon Sep 17 00:00:00 2001
  3268. From: Ben Avison <bavison@riscosopen.org>
  3269. Date: Wed, 19 Mar 2014 17:50:36 +0000
  3270. Subject: [PATCH 11/94] truehd: tune VLC decoding for ARM.
  3271. Profiling on a Raspberry Pi revealed the best performance to correspond
  3272. with VLC_BITS = 5. Results for overall audio decode and the get_vlc2 function
  3273. in particular are as follows:
  3274. Before After
  3275. Mean StdDev Mean StdDev Confidence Change
  3276. 6:2 total 348.8 20.1 339.6 15.1 88.8% +2.7% (insignificant)
  3277. 6:2 function 38.1 8.1 26.4 4.1 100.0% +44.5%
  3278. 8:2 total 339.1 15.4 324.5 15.5 99.4% +4.5%
  3279. 8:2 function 33.8 7.0 27.3 5.6 99.7% +23.6%
  3280. 6:6 total 604.6 20.8 572.8 20.6 100.0% +5.6%
  3281. 6:6 function 95.8 8.4 68.9 8.2 100.0% +39.1%
  3282. 8:8 total 766.4 17.6 741.5 21.2 100.0% +3.4%
  3283. 8:8 function 106.0 11.4 86.1 9.9 100.0% +23.1%
  3284. ---
  3285. lib/ffmpeg/libavcodec/mlpdec.c | 13 ++++++++++---
  3286. 1 file changed, 10 insertions(+), 3 deletions(-)
  3287. diff --git a/lib/ffmpeg/libavcodec/mlpdec.c b/lib/ffmpeg/libavcodec/mlpdec.c
  3288. index e9343a5..a998dac 100644
  3289. --- a/lib/ffmpeg/libavcodec/mlpdec.c
  3290. +++ b/lib/ffmpeg/libavcodec/mlpdec.c
  3291. @@ -36,9 +36,16 @@
  3292. #include "mlp_parser.h"
  3293. #include "mlpdsp.h"
  3294. #include "mlp.h"
  3295. +#include "config.h"
  3296. /** number of bits used for VLC lookup - longest Huffman code is 9 */
  3297. +#if ARCH_ARM == 1
  3298. +#define VLC_BITS 5
  3299. +#define VLC_STATIC_SIZE 64
  3300. +#else
  3301. #define VLC_BITS 9
  3302. +#define VLC_STATIC_SIZE 512
  3303. +#endif
  3304. typedef struct SubStream {
  3305. /// Set if a valid restart header has been read. Otherwise the substream cannot be decoded.
  3306. @@ -190,13 +197,13 @@ static av_cold void init_static(void)
  3307. if (!huff_vlc[0].bits) {
  3308. INIT_VLC_STATIC(&huff_vlc[0], VLC_BITS, 18,
  3309. &ff_mlp_huffman_tables[0][0][1], 2, 1,
  3310. - &ff_mlp_huffman_tables[0][0][0], 2, 1, 512);
  3311. + &ff_mlp_huffman_tables[0][0][0], 2, 1, VLC_STATIC_SIZE);
  3312. INIT_VLC_STATIC(&huff_vlc[1], VLC_BITS, 16,
  3313. &ff_mlp_huffman_tables[1][0][1], 2, 1,
  3314. - &ff_mlp_huffman_tables[1][0][0], 2, 1, 512);
  3315. + &ff_mlp_huffman_tables[1][0][0], 2, 1, VLC_STATIC_SIZE);
  3316. INIT_VLC_STATIC(&huff_vlc[2], VLC_BITS, 15,
  3317. &ff_mlp_huffman_tables[2][0][1], 2, 1,
  3318. - &ff_mlp_huffman_tables[2][0][0], 2, 1, 512);
  3319. + &ff_mlp_huffman_tables[2][0][0], 2, 1, VLC_STATIC_SIZE);
  3320. }
  3321. ff_mlp_init_crc();
  3322. --
  3323. 1.9.3
  3324. From 25ab0401ebb7f035bcf7291452e6772a9c7b233a Mon Sep 17 00:00:00 2001
  3325. From: Ben Avison <bavison@riscosopen.org>
  3326. Date: Wed, 19 Mar 2014 17:54:07 +0000
  3327. Subject: [PATCH 12/94] truehd: break out part of output_data into
  3328. platform-specific callback.
  3329. Verified with profiling that this doesn't have a measurable effect upon
  3330. overall performance.
  3331. ---
  3332. lib/ffmpeg/libavcodec/mlpdec.c | 40 +++++++++++++++++++++++-----------------
  3333. lib/ffmpeg/libavcodec/mlpdsp.c | 36 ++++++++++++++++++++++++++++++++++++
  3334. lib/ffmpeg/libavcodec/mlpdsp.h | 22 ++++++++++++++++++++++
  3335. 3 files changed, 81 insertions(+), 17 deletions(-)
  3336. diff --git a/lib/ffmpeg/libavcodec/mlpdec.c b/lib/ffmpeg/libavcodec/mlpdec.c
  3337. index a998dac..6d7c803 100644
  3338. --- a/lib/ffmpeg/libavcodec/mlpdec.c
  3339. +++ b/lib/ffmpeg/libavcodec/mlpdec.c
  3340. @@ -359,6 +359,10 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb)
  3341. m->avctx->sample_fmt = AV_SAMPLE_FMT_S32;
  3342. else
  3343. m->avctx->sample_fmt = AV_SAMPLE_FMT_S16;
  3344. + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(m->substream[m->max_decoded_substream].max_matrix_channel,
  3345. + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32,
  3346. + m->substream[m->max_decoded_substream].ch_assign,
  3347. + m->substream[m->max_decoded_substream].output_shift);
  3348. m->params_valid = 1;
  3349. for (substr = 0; substr < MAX_SUBSTREAMS; substr++)
  3350. @@ -553,6 +557,10 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
  3351. if (substr == m->max_decoded_substream) {
  3352. m->avctx->channels = s->max_matrix_channel + 1;
  3353. m->avctx->channel_layout = s->ch_layout;
  3354. + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->max_matrix_channel,
  3355. + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32,
  3356. + s->ch_assign,
  3357. + s->output_shift);
  3358. if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) {
  3359. if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) ||
  3360. @@ -798,9 +806,15 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp,
  3361. return ret;
  3362. if (s->param_presence_flags & PARAM_OUTSHIFT)
  3363. - if (get_bits1(gbp))
  3364. + if (get_bits1(gbp)) {
  3365. for (ch = 0; ch <= s->max_matrix_channel; ch++)
  3366. s->output_shift[ch] = get_sbits(gbp, 4);
  3367. + if (substr == m->max_decoded_substream)
  3368. + m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->max_matrix_channel,
  3369. + m->avctx->sample_fmt == AV_SAMPLE_FMT_S32,
  3370. + s->ch_assign,
  3371. + s->output_shift);
  3372. + }
  3373. if (s->param_presence_flags & PARAM_QUANTSTEP)
  3374. if (get_bits1(gbp))
  3375. @@ -999,9 +1013,6 @@ static int output_data(MLPDecodeContext *m, unsigned int substr,
  3376. {
  3377. AVCodecContext *avctx = m->avctx;
  3378. SubStream *s = &m->substream[substr];
  3379. - unsigned int i, out_ch = 0;
  3380. - int32_t *data_32;
  3381. - int16_t *data_16;
  3382. int ret;
  3383. int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32);
  3384. @@ -1021,19 +1032,14 @@ static int output_data(MLPDecodeContext *m, unsigned int substr,
  3385. av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
  3386. return ret;
  3387. }
  3388. - data_32 = (int32_t *)frame->data[0];
  3389. - data_16 = (int16_t *)frame->data[0];
  3390. -
  3391. - for (i = 0; i < s->blockpos; i++) {
  3392. - for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) {
  3393. - int mat_ch = s->ch_assign[out_ch];
  3394. - int32_t sample = m->sample_buffer[i][mat_ch]
  3395. - << s->output_shift[mat_ch];
  3396. - s->lossless_check_data ^= (sample & 0xffffff) << mat_ch;
  3397. - if (is32) *data_32++ = sample << 8;
  3398. - else *data_16++ = sample >> 8;
  3399. - }
  3400. - }
  3401. + s->lossless_check_data = m->dsp.mlp_pack_output(s->lossless_check_data,
  3402. + m->sample_buffer,
  3403. + frame->data[0],
  3404. + s->blockpos,
  3405. + s->max_matrix_channel,
  3406. + is32,
  3407. + s->ch_assign,
  3408. + s->output_shift);
  3409. *got_frame_ptr = 1;
  3410. diff --git a/lib/ffmpeg/libavcodec/mlpdsp.c b/lib/ffmpeg/libavcodec/mlpdsp.c
  3411. index 1f912fb..2bb5cec 100644
  3412. --- a/lib/ffmpeg/libavcodec/mlpdsp.c
  3413. +++ b/lib/ffmpeg/libavcodec/mlpdsp.c
  3414. @@ -88,10 +88,46 @@ void ff_mlp_rematrix_channel(int32_t *samples,
  3415. }
  3416. }
  3417. +static int32_t (*mlp_select_pack_output(uint8_t max_matrix_channel,
  3418. + int is32,
  3419. + uint8_t *ch_assign,
  3420. + int8_t *output_shift))(int32_t, int32_t (*)[], void *, uint16_t, uint8_t, int, uint8_t*, int8_t *)
  3421. +{
  3422. + return ff_mlp_pack_output;
  3423. +}
  3424. +
  3425. +int32_t ff_mlp_pack_output(int32_t lossless_check_data,
  3426. + int32_t (*sample_buffer)[MAX_CHANNELS],
  3427. + void *data,
  3428. + uint16_t blockpos,
  3429. + uint8_t max_matrix_channel,
  3430. + int is32,
  3431. + uint8_t *ch_assign,
  3432. + int8_t *output_shift)
  3433. +{
  3434. + unsigned int i, out_ch = 0;
  3435. + int32_t *data_32 = (int32_t *)data;
  3436. + int16_t *data_16 = (int16_t *)data;
  3437. +
  3438. + for (i = 0; i < blockpos; i++) {
  3439. + for (out_ch = 0; out_ch <= max_matrix_channel; out_ch++) {
  3440. + int mat_ch = ch_assign[out_ch];
  3441. + int32_t sample = sample_buffer[i][mat_ch]
  3442. + << output_shift[mat_ch];
  3443. + lossless_check_data ^= (sample & 0xffffff) << mat_ch;
  3444. + if (is32) *data_32++ = sample << 8;
  3445. + else *data_16++ = sample >> 8;
  3446. + }
  3447. + }
  3448. + return lossless_check_data;
  3449. +}
  3450. +
  3451. av_cold void ff_mlpdsp_init(MLPDSPContext *c)
  3452. {
  3453. c->mlp_filter_channel = ff_mlp_filter_channel;
  3454. c->mlp_rematrix_channel = ff_mlp_rematrix_channel;
  3455. + c->mlp_select_pack_output = mlp_select_pack_output;
  3456. + c->mlp_pack_output = ff_mlp_pack_output;
  3457. if (ARCH_X86)
  3458. ff_mlpdsp_init_x86(c);
  3459. }
  3460. diff --git a/lib/ffmpeg/libavcodec/mlpdsp.h b/lib/ffmpeg/libavcodec/mlpdsp.h
  3461. index f98e9be..5bc901f 100644
  3462. --- a/lib/ffmpeg/libavcodec/mlpdsp.h
  3463. +++ b/lib/ffmpeg/libavcodec/mlpdsp.h
  3464. @@ -23,6 +23,7 @@
  3465. #define AVCODEC_MLPDSP_H
  3466. #include <stdint.h>
  3467. +#include "mlp.h"
  3468. void ff_mlp_rematrix_channel(int32_t *samples,
  3469. const int32_t *coeffs,
  3470. @@ -36,6 +37,15 @@ void ff_mlp_rematrix_channel(int32_t *samples,
  3471. int access_unit_size_pow2,
  3472. int32_t mask);
  3473. +int32_t ff_mlp_pack_output(int32_t lossless_check_data,
  3474. + int32_t (*sample_buffer)[MAX_CHANNELS],
  3475. + void *data,
  3476. + uint16_t blockpos,
  3477. + uint8_t max_matrix_channel,
  3478. + int is32,
  3479. + uint8_t *ch_assign,
  3480. + int8_t *output_shift);
  3481. +
  3482. typedef struct MLPDSPContext {
  3483. void (*mlp_filter_channel)(int32_t *state, const int32_t *coeff,
  3484. int firorder, int iirorder,
  3485. @@ -52,6 +62,18 @@ typedef struct MLPDSPContext {
  3486. int matrix_noise_shift,
  3487. int access_unit_size_pow2,
  3488. int32_t mask);
  3489. + int32_t (*(*mlp_select_pack_output)(uint8_t max_matrix_channel,
  3490. + int is32,
  3491. + uint8_t *ch_assign,
  3492. + int8_t *output_shift))(int32_t, int32_t (*)[], void *, uint16_t, uint8_t, int, uint8_t*, int8_t *);
  3493. + int32_t (*mlp_pack_output)(int32_t lossless_check_data,
  3494. + int32_t (*sample_buffer)[MAX_CHANNELS],
  3495. + void *data,
  3496. + uint16_t blockpos,
  3497. + uint8_t max_matrix_channel,
  3498. + int is32,
  3499. + uint8_t *ch_assign,
  3500. + int8_t *output_shift);
  3501. } MLPDSPContext;
  3502. void ff_mlpdsp_init(MLPDSPContext *c);
  3503. --
  3504. 1.9.3
  3505. From bdefac00779c5601816f949353d9bbeb3b199611 Mon Sep 17 00:00:00 2001
  3506. From: Ben Avison <bavison@riscosopen.org>
  3507. Date: Wed, 19 Mar 2014 17:54:59 +0000
  3508. Subject: [PATCH 13/94] truehd: add hand-scheduled ARM asm version of
  3509. ff_mlp_pack_output.
  3510. Profiling results for overall decode and the output_data function in
  3511. particular are as follows:
  3512. Before After
  3513. Mean StdDev Mean StdDev Confidence Change
  3514. 6:2 total 339.6 15.1 329.3 16.0 95.8% +3.1% (insignificant)
  3515. 6:2 function 24.6 6.0 9.9 3.1 100.0% +148.5%
  3516. 8:2 total 324.5 15.5 323.6 14.3 15.2% +0.3% (insignificant)
  3517. 8:2 function 20.4 3.9 9.9 3.4 100.0% +104.7%
  3518. 6:6 total 572.8 20.6 539.9 24.2 100.0% +6.1%
  3519. 6:6 function 54.5 5.6 16.0 3.8 100.0% +240.9%
  3520. 8:8 total 741.5 21.2 702.5 18.5 100.0% +5.6%
  3521. 8:8 function 63.9 7.6 18.4 4.8 100.0% +247.3%
  3522. The assembly version has also been tested with a fuzz tester to ensure that
  3523. any combinations of inputs not exercised by my available test streams still
  3524. generate mathematically identical results to the C version.
  3525. ---
  3526. lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S | 503 ++++++++++++++++++++++++++++
  3527. lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c | 64 ++++
  3528. 2 files changed, 567 insertions(+)
  3529. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3530. index 10008fe..338d323 100644
  3531. --- a/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3532. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_arm.S
  3533. @@ -98,6 +98,26 @@ A .endif
  3534. .endif
  3535. .endm
  3536. +.macro loadregoffsh2 group, index, base, offgroup, offindex
  3537. + .altmacro
  3538. + loadregoffsh2_ \group, %(\index), \base, \offgroup, %(\offindex)
  3539. + .noaltmacro
  3540. +.endm
  3541. +
  3542. +.macro loadregoffsh2_ group, index, base, offgroup, offindex
  3543. + ldr \group\index, [\base, \offgroup\offindex, lsl #2]
  3544. +.endm
  3545. +
  3546. +.macro eorlslreg check, data, group, index
  3547. + .altmacro
  3548. + eorlslreg_ \check, \data, \group, %(\index)
  3549. + .noaltmacro
  3550. +.endm
  3551. +
  3552. +.macro eorlslreg_ check, data, group, index
  3553. + eor \check, \check, \data, lsl \group\index
  3554. +.endm
  3555. +
  3556. // A macro to update the load register number and load offsets
  3557. .macro inc howmany
  3558. @@ -659,3 +679,486 @@ endfunc
  3559. .unreq LSB
  3560. .unreq DCH
  3561. .unreq MASK
  3562. +
  3563. +/********************************************************************/
  3564. +
  3565. +.macro decr_modulo var, by, modulus
  3566. + .set \var, \var - \by
  3567. + .if \var == 0
  3568. + .set \var, \modulus
  3569. + .endif
  3570. +.endm
  3571. +
  3572. + .macro load_group1 size, channels, r0, r1, r2, r3, pointer_dead=0
  3573. + .if \size == 2
  3574. + ldrd \r0, \r1, [IN], #(\size + 8 - \channels) * 4
  3575. + .else // size == 4
  3576. + .if IDX1 > 4 || \channels==8
  3577. + ldm IN!, {\r0, \r1, \r2, \r3}
  3578. + .else
  3579. + ldm IN, {\r0, \r1, \r2, \r3}
  3580. + .if !\pointer_dead
  3581. + add IN, IN, #(4 + 8 - \channels) * 4
  3582. + .endif
  3583. + .endif
  3584. + .endif
  3585. + decr_modulo IDX1, \size, \channels
  3586. + .endm
  3587. +
  3588. + .macro load_group2 size, channels, r0, r1, r2, r3, pointer_dead=0
  3589. + .if \size == 2
  3590. + .if IDX1 > 2
  3591. + ldm IN!, {\r2, \r3}
  3592. + .else
  3593. +//A .ifc \r2, ip
  3594. +//A .if \pointer_dead
  3595. +//A ldm IN, {\r2, \r3}
  3596. +//A .else
  3597. +//A ldr \r2, [IN], #4
  3598. +//A ldr \r3, [IN], #(\size - 1 + 8 - \channels) * 4
  3599. +//A .endif
  3600. +//A .else
  3601. + ldrd \r2, \r3, [IN], #(\size + 8 - \channels) * 4
  3602. +//A .endif
  3603. + .endif
  3604. + .endif
  3605. + decr_modulo IDX1, \size, \channels
  3606. + .endm
  3607. +
  3608. +.macro implement_pack inorder, channels, shift
  3609. +.if \inorder
  3610. +.ifc \shift, mixed
  3611. +
  3612. +CHECK .req a1
  3613. +IN .req a2
  3614. +OUT .req a3
  3615. +COUNT .req a4
  3616. +DAT0 .req v1
  3617. +DAT1 .req v2
  3618. +DAT2 .req v3
  3619. +DAT3 .req v4
  3620. +SHIFT0 .req v5
  3621. +SHIFT1 .req v6
  3622. +SHIFT2 .req sl
  3623. +SHIFT3 .req fp
  3624. +SHIFT4 .req ip
  3625. +SHIFT5 .req lr
  3626. +
  3627. + .macro output4words
  3628. + .set SIZE_GROUP1, IDX1
  3629. + .if SIZE_GROUP1 > 4
  3630. + .set SIZE_GROUP1, 4
  3631. + .endif
  3632. + .set SIZE_GROUP2, 4 - SIZE_GROUP1
  3633. + load_group1 SIZE_GROUP1, \channels, DAT0, DAT1, DAT2, DAT3
  3634. + load_group2 SIZE_GROUP2, \channels, DAT0, DAT1, DAT2, DAT3
  3635. + .if \channels == 2
  3636. + lsl DAT0, SHIFT0
  3637. + lsl DAT1, SHIFT1
  3638. + lsl DAT2, SHIFT0
  3639. + lsl DAT3, SHIFT1
  3640. + .elseif \channels == 6
  3641. + .if IDX2 == 6
  3642. + lsl DAT0, SHIFT0
  3643. + lsl DAT1, SHIFT1
  3644. + lsl DAT2, SHIFT2
  3645. + lsl DAT3, SHIFT3
  3646. + .elseif IDX2 == 2
  3647. + lsl DAT0, SHIFT4
  3648. + lsl DAT1, SHIFT5
  3649. + lsl DAT2, SHIFT0
  3650. + lsl DAT3, SHIFT1
  3651. + .else // IDX2 == 4
  3652. + lsl DAT0, SHIFT2
  3653. + lsl DAT1, SHIFT3
  3654. + lsl DAT2, SHIFT4
  3655. + lsl DAT3, SHIFT5
  3656. + .endif
  3657. + .elseif \channels == 8
  3658. + .if IDX2 == 8
  3659. + uxtb SHIFT0, SHIFT4, ror #0
  3660. + uxtb SHIFT1, SHIFT4, ror #8
  3661. + uxtb SHIFT2, SHIFT4, ror #16
  3662. + uxtb SHIFT3, SHIFT4, ror #24
  3663. + .else
  3664. + uxtb SHIFT0, SHIFT5, ror #0
  3665. + uxtb SHIFT1, SHIFT5, ror #8
  3666. + uxtb SHIFT2, SHIFT5, ror #16
  3667. + uxtb SHIFT3, SHIFT5, ror #24
  3668. + .endif
  3669. + lsl DAT0, SHIFT0
  3670. + lsl DAT1, SHIFT1
  3671. + lsl DAT2, SHIFT2
  3672. + lsl DAT3, SHIFT3
  3673. + .endif
  3674. + eor CHECK, CHECK, DAT0, lsr #8 - (\channels - IDX2)
  3675. + eor CHECK, CHECK, DAT1, lsr #7 - (\channels - IDX2)
  3676. + decr_modulo IDX2, 2, \channels
  3677. + eor CHECK, CHECK, DAT2, lsr #8 - (\channels - IDX2)
  3678. + eor CHECK, CHECK, DAT3, lsr #7 - (\channels - IDX2)
  3679. + decr_modulo IDX2, 2, \channels
  3680. + stm OUT!, {DAT0 - DAT3}
  3681. + .endm
  3682. +
  3683. + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4)
  3684. + .if (WORDS_PER_LOOP % 2) == 0
  3685. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3686. + .endif
  3687. + .if (WORDS_PER_LOOP % 2) == 0
  3688. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3689. + .endif
  3690. + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4
  3691. + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels
  3692. +
  3693. +function ff_mlp_pack_output_inorder_\channels\()ch_mixedshift_arm, export=1
  3694. + .if SAMPLES_PER_LOOP > 1
  3695. + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice
  3696. + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not
  3697. + .endif
  3698. + teq COUNT, #0
  3699. + bxeq lr
  3700. + push {v1-v6,sl,fp,lr}
  3701. + ldr SHIFT0, [sp, #(9+3)*4] // get output_shift from stack
  3702. + ldr SHIFT1, =0x08080808
  3703. + ldr SHIFT4, [SHIFT0]
  3704. + .if \channels == 2
  3705. + uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8
  3706. + uxtb SHIFT0, SHIFT4, ror #0
  3707. + uxtb SHIFT1, SHIFT4, ror #8
  3708. + .else
  3709. + ldr SHIFT5, [SHIFT0, #4]
  3710. + uadd8 SHIFT4, SHIFT4, SHIFT1 // increase all shifts by 8
  3711. + uadd8 SHIFT5, SHIFT5, SHIFT1
  3712. + .if \channels == 6
  3713. + uxtb SHIFT0, SHIFT4, ror #0
  3714. + uxtb SHIFT1, SHIFT4, ror #8
  3715. + uxtb SHIFT2, SHIFT4, ror #16
  3716. + uxtb SHIFT3, SHIFT4, ror #24
  3717. + uxtb SHIFT4, SHIFT5, ror #0
  3718. + uxtb SHIFT5, SHIFT5, ror #8
  3719. + .endif
  3720. + .endif
  3721. + .set IDX1, \channels
  3722. + .set IDX2, \channels
  3723. +0:
  3724. + .rept WORDS_PER_LOOP / 4
  3725. + output4words
  3726. + .endr
  3727. + subs COUNT, COUNT, #SAMPLES_PER_LOOP
  3728. + bne 0b
  3729. + pop {v1-v6,sl,fp,pc}
  3730. + .ltorg
  3731. +endfunc
  3732. + .purgem output4words
  3733. +
  3734. + .unreq CHECK
  3735. + .unreq IN
  3736. + .unreq OUT
  3737. + .unreq COUNT
  3738. + .unreq DAT0
  3739. + .unreq DAT1
  3740. + .unreq DAT2
  3741. + .unreq DAT3
  3742. + .unreq SHIFT0
  3743. + .unreq SHIFT1
  3744. + .unreq SHIFT2
  3745. + .unreq SHIFT3
  3746. + .unreq SHIFT4
  3747. + .unreq SHIFT5
  3748. +
  3749. +.else // not mixed
  3750. +
  3751. +CHECK .req a1
  3752. +IN .req a2
  3753. +OUT .req a3
  3754. +COUNT .req a4
  3755. +DAT0 .req v1
  3756. +DAT1 .req v2
  3757. +DAT2 .req v3
  3758. +DAT3 .req v4
  3759. +DAT4 .req v5
  3760. +DAT5 .req v6
  3761. +DAT6 .req sl // use these rather than the otherwise unused
  3762. +DAT7 .req fp // ip and lr so that we can load them usinf LDRD
  3763. +
  3764. + .macro output4words tail, head, r0, r1, r2, r3, r4, r5, r6, r7, pointer_dead=0
  3765. + .if \head
  3766. + .set SIZE_GROUP1, IDX1
  3767. + .if SIZE_GROUP1 > 4
  3768. + .set SIZE_GROUP1, 4
  3769. + .endif
  3770. + .set SIZE_GROUP2, 4 - SIZE_GROUP1
  3771. + load_group1 SIZE_GROUP1, \channels, \r0, \r1, \r2, \r3, \pointer_dead
  3772. + .endif
  3773. + .if \tail
  3774. + eor CHECK, CHECK, \r4, lsr #8 - (\channels - IDX2)
  3775. + eor CHECK, CHECK, \r5, lsr #7 - (\channels - IDX2)
  3776. + decr_modulo IDX2, 2, \channels
  3777. + .endif
  3778. + .if \head
  3779. + load_group2 SIZE_GROUP2, \channels, \r0, \r1, \r2, \r3, \pointer_dead
  3780. + .endif
  3781. + .if \tail
  3782. + eor CHECK, CHECK, \r6, lsr #8 - (\channels - IDX2)
  3783. + eor CHECK, CHECK, \r7, lsr #7 - (\channels - IDX2)
  3784. + decr_modulo IDX2, 2, \channels
  3785. + stm OUT!, {\r4, \r5, \r6, \r7}
  3786. + .endif
  3787. + .if \head
  3788. + lsl \r0, #8 + \shift
  3789. + lsl \r1, #8 + \shift
  3790. + lsl \r2, #8 + \shift
  3791. + lsl \r3, #8 + \shift
  3792. + .endif
  3793. + .endm
  3794. +
  3795. + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 8)
  3796. + .if (WORDS_PER_LOOP % 2) == 0
  3797. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3798. + .endif
  3799. + .if (WORDS_PER_LOOP % 2) == 0
  3800. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3801. + .endif
  3802. + .if (WORDS_PER_LOOP % 2) == 0
  3803. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3804. + .endif
  3805. + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 8
  3806. + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels
  3807. +
  3808. +function ff_mlp_pack_output_inorder_\channels\()ch_\shift\()shift_arm, export=1
  3809. + .if SAMPLES_PER_LOOP > 1
  3810. + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice
  3811. + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not
  3812. + .endif
  3813. + subs COUNT, COUNT, #SAMPLES_PER_LOOP
  3814. + bxlo lr
  3815. + push {v1-v6,sl,fp,lr}
  3816. + .set IDX1, \channels
  3817. + .set IDX2, \channels
  3818. + output4words 0, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7
  3819. +0: beq 1f
  3820. + .rept WORDS_PER_LOOP / 8
  3821. + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3
  3822. + output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7
  3823. + .endr
  3824. + subs COUNT, COUNT, #SAMPLES_PER_LOOP
  3825. + bne 0b
  3826. +1:
  3827. + .rept WORDS_PER_LOOP / 8 - 1
  3828. + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3
  3829. + output4words 1, 1, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7
  3830. + .endr
  3831. + output4words 1, 1, DAT4, DAT5, DAT6, DAT7, DAT0, DAT1, DAT2, DAT3, pointer_dead=1
  3832. + output4words 1, 0, DAT0, DAT1, DAT2, DAT3, DAT4, DAT5, DAT6, DAT7
  3833. + pop {v1-v6,sl,fp,pc}
  3834. +endfunc
  3835. + .purgem output4words
  3836. +
  3837. + .unreq CHECK
  3838. + .unreq IN
  3839. + .unreq OUT
  3840. + .unreq COUNT
  3841. + .unreq DAT0
  3842. + .unreq DAT1
  3843. + .unreq DAT2
  3844. + .unreq DAT3
  3845. + .unreq DAT4
  3846. + .unreq DAT5
  3847. + .unreq DAT6
  3848. + .unreq DAT7
  3849. +
  3850. +.endif // mixed
  3851. +.else // not inorder
  3852. +.ifc \shift, mixed
  3853. +
  3854. +// This case not currently handled
  3855. +
  3856. +.else // not mixed
  3857. +
  3858. +CHECK .req a1
  3859. +IN .req a2
  3860. +OUT .req a3
  3861. +COUNT .req a4
  3862. +DAT0 .req v1
  3863. +DAT1 .req v2
  3864. +DAT2 .req v3
  3865. +DAT3 .req v4
  3866. +CHAN0 .req v5
  3867. +CHAN1 .req v6
  3868. +CHAN2 .req sl
  3869. +CHAN3 .req fp
  3870. +CHAN4 .req ip
  3871. +CHAN5 .req lr
  3872. +
  3873. + .macro output4words
  3874. + .if \channels == 8
  3875. + .if IDX1 == 8
  3876. + uxtb CHAN0, CHAN4, ror #0
  3877. + uxtb CHAN1, CHAN4, ror #8
  3878. + uxtb CHAN2, CHAN4, ror #16
  3879. + uxtb CHAN3, CHAN4, ror #24
  3880. + .else
  3881. + uxtb CHAN0, CHAN5, ror #0
  3882. + uxtb CHAN1, CHAN5, ror #8
  3883. + uxtb CHAN2, CHAN5, ror #16
  3884. + uxtb CHAN3, CHAN5, ror #24
  3885. + .endif
  3886. + ldr DAT0, [IN, CHAN0, lsl #2]
  3887. + ldr DAT1, [IN, CHAN1, lsl #2]
  3888. + ldr DAT2, [IN, CHAN2, lsl #2]
  3889. + ldr DAT3, [IN, CHAN3, lsl #2]
  3890. + .if IDX1 == 4
  3891. + add IN, IN, #8*4
  3892. + .endif
  3893. + decr_modulo IDX1, 4, \channels
  3894. + .else
  3895. + .set SIZE_GROUP1, IDX1
  3896. + .if SIZE_GROUP1 > 4
  3897. + .set SIZE_GROUP1, 4
  3898. + .endif
  3899. + .set SIZE_GROUP2, 4 - SIZE_GROUP1
  3900. + .if SIZE_GROUP1 == 2
  3901. + loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1)
  3902. + loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1)
  3903. + add IN, IN, #8*4
  3904. + .else // SIZE_GROUP1 == 4
  3905. + loadregoffsh2 DAT, 0, IN, CHAN, 0 + (\channels - IDX1)
  3906. + loadregoffsh2 DAT, 1, IN, CHAN, 1 + (\channels - IDX1)
  3907. + loadregoffsh2 DAT, 2, IN, CHAN, 2 + (\channels - IDX1)
  3908. + loadregoffsh2 DAT, 3, IN, CHAN, 3 + (\channels - IDX1)
  3909. + .if IDX1 == 4
  3910. + add IN, IN, #8*4
  3911. + .endif
  3912. + .endif
  3913. + decr_modulo IDX1, SIZE_GROUP1, \channels
  3914. + .if SIZE_GROUP2 == 2
  3915. + loadregoffsh2 DAT, 2, IN, CHAN, 0 + (\channels - IDX1)
  3916. + loadregoffsh2 DAT, 3, IN, CHAN, 1 + (\channels - IDX1)
  3917. + .if IDX1 == 2
  3918. + add IN, IN, #8*4
  3919. + .endif
  3920. + .endif
  3921. + decr_modulo IDX1, SIZE_GROUP2, \channels
  3922. + .endif
  3923. + .if \channels == 8 // in this case we can corrupt CHAN0-3
  3924. + rsb CHAN0, CHAN0, #8
  3925. + rsb CHAN1, CHAN1, #8
  3926. + rsb CHAN2, CHAN2, #8
  3927. + rsb CHAN3, CHAN3, #8
  3928. + lsl DAT0, #8 + \shift
  3929. + lsl DAT1, #8 + \shift
  3930. + lsl DAT2, #8 + \shift
  3931. + lsl DAT3, #8 + \shift
  3932. + eor CHECK, CHECK, DAT0, lsr CHAN0
  3933. + eor CHECK, CHECK, DAT1, lsr CHAN1
  3934. + eor CHECK, CHECK, DAT2, lsr CHAN2
  3935. + eor CHECK, CHECK, DAT3, lsr CHAN3
  3936. + .else
  3937. + .if \shift != 0
  3938. + lsl DAT0, #\shift
  3939. + lsl DAT1, #\shift
  3940. + lsl DAT2, #\shift
  3941. + lsl DAT3, #\shift
  3942. + .endif
  3943. + bic DAT0, DAT0, #0xff000000
  3944. + bic DAT1, DAT1, #0xff000000
  3945. + bic DAT2, DAT2, #0xff000000
  3946. + bic DAT3, DAT3, #0xff000000
  3947. + eorlslreg CHECK, DAT0, CHAN, 0 + (\channels - IDX2)
  3948. + eorlslreg CHECK, DAT1, CHAN, 1 + (\channels - IDX2)
  3949. + decr_modulo IDX2, 2, \channels
  3950. + eorlslreg CHECK, DAT2, CHAN, 0 + (\channels - IDX2)
  3951. + eorlslreg CHECK, DAT3, CHAN, 1 + (\channels - IDX2)
  3952. + decr_modulo IDX2, 2, \channels
  3953. + lsl DAT0, #8
  3954. + lsl DAT1, #8
  3955. + lsl DAT2, #8
  3956. + lsl DAT3, #8
  3957. + .endif
  3958. + stm OUT!, {DAT0 - DAT3}
  3959. + .endm
  3960. +
  3961. + .set WORDS_PER_LOOP, \channels // calculate LCM (channels, 4)
  3962. + .if (WORDS_PER_LOOP % 2) == 0
  3963. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3964. + .endif
  3965. + .if (WORDS_PER_LOOP % 2) == 0
  3966. + .set WORDS_PER_LOOP, WORDS_PER_LOOP / 2
  3967. + .endif
  3968. + .set WORDS_PER_LOOP, WORDS_PER_LOOP * 4
  3969. + .set SAMPLES_PER_LOOP, WORDS_PER_LOOP / \channels
  3970. +
  3971. +function ff_mlp_pack_output_outoforder_\channels\()ch_\shift\()shift_arm, export=1
  3972. + .if SAMPLES_PER_LOOP > 1
  3973. + tst COUNT, #SAMPLES_PER_LOOP - 1 // always seems to be in practice
  3974. + bne X(ff_mlp_pack_output) // but just in case, branch to C implementation if not
  3975. + .endif
  3976. + teq COUNT, #0
  3977. + bxeq lr
  3978. + push {v1-v6,sl,fp,lr}
  3979. + ldr CHAN0, [sp, #(9+2)*4] // get ch_assign from stack
  3980. + ldr CHAN4, [CHAN0]
  3981. + .if \channels == 2
  3982. + uxtb CHAN0, CHAN4, ror #0
  3983. + uxtb CHAN1, CHAN4, ror #8
  3984. + .else
  3985. + ldr CHAN5, [CHAN0, #4]
  3986. + .if \channels == 6
  3987. + uxtb CHAN0, CHAN4, ror #0
  3988. + uxtb CHAN1, CHAN4, ror #8
  3989. + uxtb CHAN2, CHAN4, ror #16
  3990. + uxtb CHAN3, CHAN4, ror #24
  3991. + uxtb CHAN4, CHAN5, ror #0
  3992. + uxtb CHAN5, CHAN5, ror #8
  3993. + .endif
  3994. + .endif
  3995. + .set IDX1, \channels
  3996. + .set IDX2, \channels
  3997. +0:
  3998. + .rept WORDS_PER_LOOP / 4
  3999. + output4words
  4000. + .endr
  4001. + subs COUNT, COUNT, #SAMPLES_PER_LOOP
  4002. + bne 0b
  4003. + pop {v1-v6,sl,fp,pc}
  4004. + .ltorg
  4005. +endfunc
  4006. + .purgem output4words
  4007. +
  4008. + .unreq CHECK
  4009. + .unreq IN
  4010. + .unreq OUT
  4011. + .unreq COUNT
  4012. + .unreq DAT0
  4013. + .unreq DAT1
  4014. + .unreq DAT2
  4015. + .unreq DAT3
  4016. + .unreq CHAN0
  4017. + .unreq CHAN1
  4018. + .unreq CHAN2
  4019. + .unreq CHAN3
  4020. + .unreq CHAN4
  4021. + .unreq CHAN5
  4022. +
  4023. +.endif // mixed
  4024. +.endif // inorder
  4025. +.endm // implement_pack
  4026. +
  4027. +.macro pack_channels inorder, channels
  4028. + implement_pack \inorder, \channels, 0
  4029. + implement_pack \inorder, \channels, 1
  4030. + implement_pack \inorder, \channels, 2
  4031. + implement_pack \inorder, \channels, 3
  4032. + implement_pack \inorder, \channels, 4
  4033. + implement_pack \inorder, \channels, 5
  4034. + implement_pack \inorder, \channels, mixed
  4035. +.endm
  4036. +
  4037. +.macro pack_order inorder
  4038. + pack_channels \inorder, 2
  4039. + pack_channels \inorder, 6
  4040. + pack_channels \inorder, 8
  4041. +.endm
  4042. +
  4043. + pack_order 0
  4044. + pack_order 1
  4045. diff --git a/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  4046. index 268dfdd..2d8b98d 100644
  4047. --- a/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  4048. +++ b/lib/ffmpeg/libavcodec/arm/mlpdsp_init_arm.c
  4049. @@ -41,8 +41,72 @@ void ff_mlp_rematrix_channel_arm(int32_t *samples,
  4050. int access_unit_size_pow2,
  4051. int32_t mask);
  4052. +#define DECLARE_PACK(order,channels,shift) \
  4053. + int32_t ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_arm(int32_t, int32_t (*)[], void *, uint16_t, uint8_t, int, uint8_t*, int8_t *);
  4054. +#define ENUMERATE_PACK(order,channels,shift) \
  4055. + ff_mlp_pack_output_##order##order_##channels##ch_##shift##shift_arm,
  4056. +#define PACK_CHANNELS(macro,order,channels) \
  4057. + macro(order,channels,0) \
  4058. + macro(order,channels,1) \
  4059. + macro(order,channels,2) \
  4060. + macro(order,channels,3) \
  4061. + macro(order,channels,4) \
  4062. + macro(order,channels,5) \
  4063. + macro(order,channels,mixed)
  4064. +#define PACK_ORDER(macro,order) \
  4065. + PACK_CHANNELS(macro,order,2) \
  4066. + PACK_CHANNELS(macro,order,6) \
  4067. + PACK_CHANNELS(macro,order,8)
  4068. +#define PACK_ALL(macro) \
  4069. + PACK_ORDER(macro,outof) \
  4070. + PACK_ORDER(macro,in)
  4071. +PACK_ALL(DECLARE_PACK)
  4072. +
  4073. +#define ff_mlp_pack_output_outoforder_2ch_mixedshift_arm 0
  4074. +#define ff_mlp_pack_output_outoforder_6ch_mixedshift_arm 0
  4075. +#define ff_mlp_pack_output_outoforder_8ch_mixedshift_arm 0
  4076. +
  4077. +static int32_t (*mlp_select_pack_output_arm(uint8_t max_matrix_channel,
  4078. + int is32,
  4079. + uint8_t *ch_assign,
  4080. + int8_t *output_shift))(int32_t, int32_t (*)[], void *, uint16_t, uint8_t, int, uint8_t*, int8_t *)
  4081. +{
  4082. + int ch_index;
  4083. + int shift = output_shift[0] < 0 || output_shift[0] > 5 ? 6 : output_shift[0];
  4084. + int inorder = 1;
  4085. + static int32_t (*const routine[2*3*7])(int32_t, int32_t (*)[], void *, uint16_t, uint8_t, int, uint8_t*, int8_t *) = {
  4086. + PACK_ALL(ENUMERATE_PACK)
  4087. + };
  4088. + int i;
  4089. +
  4090. + if (!is32) // don't support 16-bit output (it's not used by TrueHD)
  4091. + return ff_mlp_pack_output;
  4092. +
  4093. + switch (max_matrix_channel) {
  4094. + case 1: ch_index = 0; break;
  4095. + case 5: ch_index = 1; break;
  4096. + case 7: ch_index = 2; break;
  4097. + default: return ff_mlp_pack_output;
  4098. + }
  4099. +
  4100. + for (i = 0; i <= max_matrix_channel; i++) {
  4101. + if (shift != 6 && output_shift[i] != shift)
  4102. + shift = 6; // indicate mixed shifts
  4103. + if (ch_assign[i] != i)
  4104. + inorder = 0;
  4105. + }
  4106. + if (shift == 6 && !inorder)
  4107. + return ff_mlp_pack_output; // can't currently handle both an order array and a shift array
  4108. +
  4109. + return routine[(inorder*3+ch_index)*7+shift];
  4110. +}
  4111. +
  4112. av_cold void ff_mlpdsp_init_arm(MLPDSPContext *c)
  4113. {
  4114. + int cpu_flags = av_get_cpu_flags();
  4115. +
  4116. c->mlp_filter_channel = ff_mlp_filter_channel_arm;
  4117. c->mlp_rematrix_channel = ff_mlp_rematrix_channel_arm;
  4118. + if (cpu_flags & AV_CPU_FLAG_ARMV6)
  4119. + c->mlp_select_pack_output = mlp_select_pack_output_arm;
  4120. }
  4121. --
  4122. 1.9.3
  4123. From 9af15bf0b7bc7940bd8bcc9ddae23178c9723bd6 Mon Sep 17 00:00:00 2001
  4124. From: Ben Avison <bavison@riscosopen.org>
  4125. Date: Thu, 14 Nov 2013 19:48:41 +0000
  4126. Subject: [PATCH 14/94] More efficient infobool expression evaluator
  4127. Expession infobools are evaluated at runtime from one or more single infobools
  4128. and a combination of boolean NOT, AND and OR operators. Previously, parsing
  4129. produced a vector of operands (leaf nodes) and operators in postfix
  4130. (reverse-Polish) form, and evaluated all leaf nodes every time the expression
  4131. was evaluated. But this ignores the fact that in many cases, once one operand
  4132. of an AND or OR operation has been evaluated, there is no need to evaluate the
  4133. other operand because its value can have no effect on the ultimate result. It
  4134. is also worth noting that AND and OR operations are associative, meaning they
  4135. can be rearranged at runtime to better suit the selected skin.
  4136. This patch rewrites the expression parsing and evaluation code. Now the
  4137. internal repreentation is in the form of a tree where leaf nodes represent a
  4138. single infobool, and branch nodes represent either an AND or an OR operation
  4139. on two or more child nodes.
  4140. Expressions are rewritten at parse time into a form which favours the
  4141. formation of groups of associative nodes. These groups are then reordered at
  4142. evaluation time such that nodes whose value renders the evaluation of the
  4143. remainder of the group unnecessary tend to be evaluated first (these are
  4144. true nodes for OR subexpressions, or false nodes for AND subexpressions).
  4145. The end effect is to minimise the number of leaf nodes that need to be
  4146. evaluated in order to determine the value of the expression. The runtime
  4147. adaptability has the advantage of not being customised for any particular skin.
  4148. The modifications to the expression at parse time fall into two groups:
  4149. 1) Moving logical NOTs so that they are only applied to leaf nodes.
  4150. For example, rewriting ![A+B]|C as !A|!B|C allows reordering such that
  4151. any of the three leaves can be evaluated first.
  4152. 2) Combining adjacent AND or OR operations such that each path from the root
  4153. to a leaf encounters a strictly alternating pattern of AND and OR
  4154. operations. So [A|B]|[C|D+[[E|F]|G] becomes A|B|C|[D+[E|F|G]].
  4155. I measured the effect while the Videos window of the default skin was open
  4156. (but idle) on a Raspberry Pi, and this reduced the CPU usage by 2.8% from
  4157. 41.9% to 39.1%:
  4158. Before After
  4159. Mean StdDev Mean StdDev Confidence Change
  4160. IdleCPU% 41.9 0.5 39.1 0.9 100.0% +7.0%
  4161. ---
  4162. xbmc/interfaces/info/InfoExpression.cpp | 313 +++++++++++++++++++++-----------
  4163. xbmc/interfaces/info/InfoExpression.h | 63 ++++++-
  4164. 2 files changed, 269 insertions(+), 107 deletions(-)
  4165. diff --git a/xbmc/interfaces/info/InfoExpression.cpp b/xbmc/interfaces/info/InfoExpression.cpp
  4166. index f4d32c1..db461dd 100644
  4167. --- a/xbmc/interfaces/info/InfoExpression.cpp
  4168. +++ b/xbmc/interfaces/info/InfoExpression.cpp
  4169. @@ -22,6 +22,9 @@
  4170. #include <stack>
  4171. #include "utils/log.h"
  4172. #include "GUIInfoManager.h"
  4173. +#include <list>
  4174. +#include <boost/shared_ptr.hpp>
  4175. +#include <boost/make_shared.hpp>
  4176. using namespace std;
  4177. using namespace INFO;
  4178. @@ -40,21 +43,89 @@ void InfoSingle::Update(const CGUIListItem *item)
  4179. InfoExpression::InfoExpression(const std::string &expression, int context)
  4180. : InfoBool(expression, context)
  4181. {
  4182. - Parse(expression);
  4183. + if (!Parse(expression))
  4184. + CLog::Log(LOGERROR, "Error parsing boolean expression %s", expression.c_str());
  4185. }
  4186. void InfoExpression::Update(const CGUIListItem *item)
  4187. {
  4188. - Evaluate(item, m_value);
  4189. + m_value = m_expression_tree->Evaluate(item);
  4190. }
  4191. -#define OPERATOR_LB 5
  4192. -#define OPERATOR_RB 4
  4193. -#define OPERATOR_NOT 3
  4194. -#define OPERATOR_AND 2
  4195. -#define OPERATOR_OR 1
  4196. +/* Expressions are rewritten at parse time into a form which favours the
  4197. + * formation of groups of associative nodes. These groups are then reordered at
  4198. + * evaluation time such that nodes whose value renders the evaluation of the
  4199. + * remainder of the group unnecessary tend to be evaluated first (these are
  4200. + * true nodes for OR subexpressions, or false nodes for AND subexpressions).
  4201. + * The end effect is to minimise the number of leaf nodes that need to be
  4202. + * evaluated in order to determine the value of the expression. The runtime
  4203. + * adaptability has the advantage of not being customised for any particular skin.
  4204. + *
  4205. + * The modifications to the expression at parse time fall into two groups:
  4206. + * 1) Moving logical NOTs so that they are only applied to leaf nodes.
  4207. + * For example, rewriting ![A+B]|C as !A|!B|C allows reordering such that
  4208. + * any of the three leaves can be evaluated first.
  4209. + * 2) Combining adjacent AND or OR operations such that each path from the root
  4210. + * to a leaf encounters a strictly alternating pattern of AND and OR
  4211. + * operations. So [A|B]|[C|D+[[E|F]|G] becomes A|B|C|[D+[E|F|G]].
  4212. + */
  4213. +
  4214. +bool InfoExpression::InfoLeaf::Evaluate(const CGUIListItem *item)
  4215. +{
  4216. + return m_invert ^ m_info->Get(item);
  4217. +}
  4218. -short InfoExpression::GetOperator(const char ch) const
  4219. +InfoExpression::InfoAssociativeGroup::InfoAssociativeGroup(
  4220. + bool and_not_or,
  4221. + const InfoSubexpressionPtr &left,
  4222. + const InfoSubexpressionPtr &right)
  4223. + : m_and_not_or(and_not_or)
  4224. +{
  4225. + AddChild(right);
  4226. + AddChild(left);
  4227. +}
  4228. +
  4229. +void InfoExpression::InfoAssociativeGroup::AddChild(const InfoSubexpressionPtr &child)
  4230. +{
  4231. + m_children.push_front(child); // largely undoes the effect of parsing right-associative
  4232. +}
  4233. +
  4234. +void InfoExpression::InfoAssociativeGroup::Merge(InfoAssociativeGroup *other)
  4235. +{
  4236. + m_children.splice(m_children.end(), other->m_children);
  4237. +}
  4238. +
  4239. +bool InfoExpression::InfoAssociativeGroup::Evaluate(const CGUIListItem *item)
  4240. +{
  4241. + /* Handle either AND or OR by using the relation
  4242. + * A AND B == !(!A OR !B)
  4243. + * to convert ANDs into ORs
  4244. + */
  4245. + std::list<InfoSubexpressionPtr>::iterator last = m_children.end();
  4246. + std::list<InfoSubexpressionPtr>::iterator it = m_children.begin();
  4247. + bool result = m_and_not_or ^ (*it)->Evaluate(item);
  4248. + while (!result && ++it != last)
  4249. + {
  4250. + result = m_and_not_or ^ (*it)->Evaluate(item);
  4251. + if (result)
  4252. + {
  4253. + /* Move this child to the head of the list so we evaluate faster next time */
  4254. + InfoSubexpressionPtr p = *it;
  4255. + m_children.erase(it);
  4256. + m_children.push_front(p);
  4257. + }
  4258. + }
  4259. + return m_and_not_or ^ result;
  4260. +}
  4261. +
  4262. +/* Expressions are parsed using the shunting-yard algorithm. Binary operators
  4263. + * (AND/OR) are treated as right-associative so that we don't need to make a
  4264. + * special case for the unary NOT operator. This has no effect upon the answers
  4265. + * generated, though the initial sequence of evaluation of leaves may be
  4266. + * different from what you might expect.
  4267. + */
  4268. +
  4269. +InfoExpression::operator_t InfoExpression::GetOperator(char ch)
  4270. {
  4271. if (ch == '[')
  4272. return OPERATOR_LB;
  4273. @@ -67,122 +138,160 @@ short InfoExpression::GetOperator(const char ch) const
  4274. else if (ch == '|')
  4275. return OPERATOR_OR;
  4276. else
  4277. - return 0;
  4278. + return OPERATOR_NONE;
  4279. }
  4280. -void InfoExpression::Parse(const std::string &expression)
  4281. +void InfoExpression::OperatorPop(std::stack<operator_t> &operator_stack, bool &invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes)
  4282. {
  4283. - stack<char> operators;
  4284. - std::string operand;
  4285. - for (unsigned int i = 0; i < expression.size(); i++)
  4286. + operator_t op2 = operator_stack.top();
  4287. + operator_stack.pop();
  4288. + if (op2 == OPERATOR_NOT)
  4289. {
  4290. - if (GetOperator(expression[i]))
  4291. + invert = !invert;
  4292. + }
  4293. + else
  4294. + {
  4295. + // At this point, it can only be OPERATOR_AND or OPERATOR_OR
  4296. + if (invert)
  4297. + op2 = (operator_t) (OPERATOR_AND ^ OPERATOR_OR ^ op2);
  4298. + node_type_t new_type = op2 == OPERATOR_AND ? NODE_AND : NODE_OR;
  4299. +
  4300. + InfoSubexpressionPtr right = nodes.top();
  4301. + nodes.pop();
  4302. + InfoSubexpressionPtr left = nodes.top();
  4303. +
  4304. + node_type_t right_type = node_types.top();
  4305. + node_types.pop();
  4306. + node_type_t left_type = node_types.top();
  4307. +
  4308. + // Combine associative operations into the same node where possible
  4309. + if (left_type == new_type && right_type == new_type)
  4310. + (static_cast<InfoAssociativeGroup *>(left.get()))->Merge(static_cast<InfoAssociativeGroup *>(right.get()));
  4311. + else if (left_type == new_type)
  4312. + (static_cast<InfoAssociativeGroup *>(left.get()))->AddChild(right);
  4313. + else
  4314. {
  4315. - // cleanup any operand, translate and put into our expression list
  4316. - if (!operand.empty())
  4317. + nodes.pop();
  4318. + node_types.pop();
  4319. + if (right_type == new_type)
  4320. {
  4321. - InfoPtr info = g_infoManager.Register(operand, m_context);
  4322. - if (info)
  4323. - {
  4324. - m_listItemDependent |= info->ListItemDependent();
  4325. - m_postfix.push_back(m_operands.size());
  4326. - m_operands.push_back(info);
  4327. - }
  4328. - operand.clear();
  4329. + (static_cast<InfoAssociativeGroup *>(right.get()))->AddChild(left);
  4330. + nodes.push(right);
  4331. }
  4332. - // handle closing parenthesis
  4333. - if (expression[i] == ']')
  4334. - {
  4335. - while (!operators.empty())
  4336. - {
  4337. - char oper = operators.top();
  4338. - operators.pop();
  4339. + else
  4340. + nodes.push(boost::make_shared<InfoAssociativeGroup>(new_type == NODE_AND, left, right));
  4341. + node_types.push(new_type);
  4342. + }
  4343. + }
  4344. +}
  4345. +
  4346. +void InfoExpression::ProcessOperator(operator_t op, std::stack<operator_t> &operator_stack, bool &invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes)
  4347. +{
  4348. + // Handle any higher-priority stacked operators, except when the new operator is left-bracket.
  4349. + // For a right-bracket, this will stop with the matching left-bracket at the top of the operator stack.
  4350. + if (op != OPERATOR_LB)
  4351. + {
  4352. + while (operator_stack.size() > 0 && operator_stack.top() > op)
  4353. + OperatorPop(operator_stack, invert, node_types, nodes);
  4354. + }
  4355. + if (op == OPERATOR_RB)
  4356. + operator_stack.pop(); // remove the matching left-bracket
  4357. + else
  4358. + operator_stack.push(op);
  4359. + if (op == OPERATOR_NOT)
  4360. + invert = !invert;
  4361. +}
  4362. - if (oper == '[')
  4363. - break;
  4364. +bool InfoExpression::ProcessOperand(std::string &operand, bool invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes)
  4365. +{
  4366. + InfoPtr info = g_infoManager.Register(operand, m_context);
  4367. + if (!info)
  4368. + return false;
  4369. + m_listItemDependent |= info->ListItemDependent();
  4370. + nodes.push(boost::make_shared<InfoLeaf>(info, invert));
  4371. + node_types.push(NODE_LEAF);
  4372. + operand.clear();
  4373. + return true;
  4374. +}
  4375. - m_postfix.push_back(-GetOperator(oper)); // negative denotes operator
  4376. - }
  4377. +bool InfoExpression::Parse(const std::string &expression)
  4378. +{
  4379. + const char *s = expression.c_str();
  4380. + std::string operand;
  4381. + std::stack<operator_t> operator_stack;
  4382. + bool invert = false;
  4383. + std::stack<node_type_t> node_types;
  4384. + std::stack<InfoSubexpressionPtr> nodes;
  4385. + // The next two are for syntax-checking purposes
  4386. + bool after_binaryoperator = true;
  4387. + int bracket_count = 0;
  4388. +
  4389. + char c;
  4390. + // Skip leading whitespace - don't want it to count as an operand if that's all there is
  4391. + do
  4392. + {
  4393. + c = *s++;
  4394. + } while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
  4395. + s--;
  4396. + while ((c = *s++) != '\0')
  4397. + {
  4398. + operator_t op;
  4399. + if ((op = GetOperator(c)) != OPERATOR_NONE)
  4400. + {
  4401. + // Character is an operator
  4402. + if ((!after_binaryoperator && (c == '!' || c == '[')) ||
  4403. + (after_binaryoperator && (c == ']' || c == '+' || c == '|')))
  4404. + {
  4405. + CLog::Log(LOGERROR, "Misplaced %c", c);
  4406. + return false;
  4407. }
  4408. - else
  4409. + if (c == '[')
  4410. + bracket_count++;
  4411. + else if (c == ']' && bracket_count-- == 0)
  4412. + {
  4413. + CLog::Log(LOGERROR, "Unmatched ]");
  4414. + return false;
  4415. + }
  4416. + if (operand.size() > 0 && !ProcessOperand(operand, invert, node_types, nodes))
  4417. {
  4418. - // all other operators we pop off the stack any operator
  4419. - // that has a higher priority than the one we have.
  4420. - while (!operators.empty() && GetOperator(operators.top()) > GetOperator(expression[i]))
  4421. - {
  4422. - // only handle parenthesis once they're closed.
  4423. - if (operators.top() == '[' && expression[i] != ']')
  4424. - break;
  4425. -
  4426. - m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator
  4427. - operators.pop();
  4428. - }
  4429. - operators.push(expression[i]);
  4430. + CLog::Log(LOGERROR, "Bad operand '%s'", operand.c_str());
  4431. + return false;
  4432. }
  4433. + ProcessOperator(op, operator_stack, invert, node_types, nodes);
  4434. + if (c == '+' || c == '|')
  4435. + after_binaryoperator = true;
  4436. + // Skip trailing whitespace - don't want it to count as an operand if that's all there is
  4437. + do
  4438. + {
  4439. + c = *s++;
  4440. + } while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
  4441. + s--;
  4442. }
  4443. else
  4444. {
  4445. - operand += expression[i];
  4446. + // Character is part of operand
  4447. + operand += c;
  4448. + after_binaryoperator = false;
  4449. }
  4450. }
  4451. -
  4452. - if (!operand.empty())
  4453. + if (bracket_count > 0)
  4454. {
  4455. - InfoPtr info = g_infoManager.Register(operand, m_context);
  4456. - if (info)
  4457. - {
  4458. - m_listItemDependent |= info->ListItemDependent();
  4459. - m_postfix.push_back(m_operands.size());
  4460. - m_operands.push_back(info);
  4461. - }
  4462. + CLog::Log(LOGERROR, "Unmatched [");
  4463. + return false;
  4464. }
  4465. -
  4466. - // finish up by adding any operators
  4467. - while (!operators.empty())
  4468. + if (after_binaryoperator)
  4469. {
  4470. - m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator
  4471. - operators.pop();
  4472. + CLog::Log(LOGERROR, "Missing operand");
  4473. + return false;
  4474. }
  4475. -
  4476. - // test evaluate
  4477. - bool test;
  4478. - if (!Evaluate(NULL, test))
  4479. - CLog::Log(LOGERROR, "Error evaluating boolean expression %s", expression.c_str());
  4480. -}
  4481. -
  4482. -bool InfoExpression::Evaluate(const CGUIListItem *item, bool &result)
  4483. -{
  4484. - stack<bool> save;
  4485. - for (vector<short>::const_iterator it = m_postfix.begin(); it != m_postfix.end(); ++it)
  4486. + if (operand.size() > 0 && !ProcessOperand(operand, invert, node_types, nodes))
  4487. {
  4488. - short expr = *it;
  4489. - if (expr == -OPERATOR_NOT)
  4490. - { // NOT the top item on the stack
  4491. - if (save.empty()) return false;
  4492. - bool expr = save.top();
  4493. - save.pop();
  4494. - save.push(!expr);
  4495. - }
  4496. - else if (expr == -OPERATOR_AND)
  4497. - { // AND the top two items on the stack
  4498. - if (save.size() < 2) return false;
  4499. - bool right = save.top(); save.pop();
  4500. - bool left = save.top(); save.pop();
  4501. - save.push(left && right);
  4502. - }
  4503. - else if (expr == -OPERATOR_OR)
  4504. - { // OR the top two items on the stack
  4505. - if (save.size() < 2) return false;
  4506. - bool right = save.top(); save.pop();
  4507. - bool left = save.top(); save.pop();
  4508. - save.push(left || right);
  4509. - }
  4510. - else if (expr >= 0) // operand
  4511. - save.push(m_operands[expr]->Get(item));
  4512. - }
  4513. - if (save.size() != 1)
  4514. + CLog::Log(LOGERROR, "Bad operand '%s'", operand.c_str());
  4515. return false;
  4516. - result = save.top();
  4517. + }
  4518. + while (operator_stack.size() > 0)
  4519. + OperatorPop(operator_stack, invert, node_types, nodes);
  4520. +
  4521. + m_expression_tree = nodes.top();
  4522. return true;
  4523. }
  4524. -
  4525. diff --git a/xbmc/interfaces/info/InfoExpression.h b/xbmc/interfaces/info/InfoExpression.h
  4526. index 4e0faee..0a91399 100644
  4527. --- a/xbmc/interfaces/info/InfoExpression.h
  4528. +++ b/xbmc/interfaces/info/InfoExpression.h
  4529. @@ -21,6 +21,8 @@
  4530. #pragma once
  4531. #include <vector>
  4532. +#include <list>
  4533. +#include <stack>
  4534. #include "InfoBool.h"
  4535. class CGUIListItem;
  4536. @@ -50,12 +52,63 @@ class InfoExpression : public InfoBool
  4537. virtual void Update(const CGUIListItem *item);
  4538. private:
  4539. - void Parse(const std::string &expression);
  4540. - bool Evaluate(const CGUIListItem *item, bool &result);
  4541. - short GetOperator(const char ch) const;
  4542. + typedef enum
  4543. + {
  4544. + OPERATOR_NONE = 0,
  4545. + OPERATOR_LB, // 1
  4546. + OPERATOR_RB, // 2
  4547. + OPERATOR_OR, // 3
  4548. + OPERATOR_AND, // 4
  4549. + OPERATOR_NOT, // 5
  4550. + } operator_t;
  4551. - std::vector<short> m_postfix; ///< the postfix form of the expression (operators and operand indicies)
  4552. - std::vector<InfoPtr> m_operands; ///< the operands in the expression
  4553. + typedef enum
  4554. + {
  4555. + NODE_LEAF,
  4556. + NODE_AND,
  4557. + NODE_OR,
  4558. + } node_type_t;
  4559. +
  4560. + // An abstract base class for nodes in the expression tree
  4561. + class InfoSubexpression
  4562. + {
  4563. + public:
  4564. + virtual ~InfoSubexpression(void) {}; // so we can destruct derived classes using a pointer to their base class
  4565. + virtual bool Evaluate(const CGUIListItem *item) = 0;
  4566. + };
  4567. +
  4568. + typedef boost::shared_ptr<InfoSubexpression> InfoSubexpressionPtr;
  4569. +
  4570. + // A leaf node in the expression tree
  4571. + class InfoLeaf : public InfoSubexpression
  4572. + {
  4573. + public:
  4574. + InfoLeaf(InfoPtr info, bool invert) : m_info(info), m_invert(invert) {};
  4575. + virtual bool Evaluate(const CGUIListItem *item);
  4576. + private:
  4577. + InfoPtr m_info;
  4578. + bool m_invert;
  4579. + };
  4580. +
  4581. + // A branch node in the expression tree
  4582. + class InfoAssociativeGroup : public InfoSubexpression
  4583. + {
  4584. + public:
  4585. + InfoAssociativeGroup(bool and_not_or, const InfoSubexpressionPtr &left, const InfoSubexpressionPtr &right);
  4586. + void AddChild(const InfoSubexpressionPtr &child);
  4587. + void Merge(InfoAssociativeGroup *other);
  4588. + virtual bool Evaluate(const CGUIListItem *item);
  4589. + private:
  4590. + bool m_and_not_or;
  4591. + std::list<InfoSubexpressionPtr> m_children;
  4592. + };
  4593. +
  4594. + static operator_t GetOperator(char ch);
  4595. + static void OperatorPop(std::stack<operator_t> &operator_stack, bool &invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes);
  4596. + static void ProcessOperator(operator_t op, std::stack<operator_t> &operator_stack, bool &invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes);
  4597. + bool ProcessOperand(std::string &operand, bool invert, std::stack<node_type_t> &node_types, std::stack<InfoSubexpressionPtr> &nodes);
  4598. + bool Parse(const std::string &expression);
  4599. + InfoSubexpressionPtr m_expression_tree;
  4600. };
  4601. };
  4602. --
  4603. 1.9.3
  4604. From 36067cf823d539a00eea75d561ac78a4b1431a66 Mon Sep 17 00:00:00 2001
  4605. From: Ben Avison <bavison@riscosopen.org>
  4606. Date: Mon, 24 Mar 2014 22:26:21 +0000
  4607. Subject: [PATCH 15/94] Where an infobool expression failed to parse, evaluate
  4608. the infobool as false. Previously, this would result in a segfault due to the
  4609. dereferencing of an uninitialised pointer to the head of the expression tree.
  4610. ---
  4611. xbmc/interfaces/info/InfoExpression.cpp | 3 +++
  4612. 1 file changed, 3 insertions(+)
  4613. diff --git a/xbmc/interfaces/info/InfoExpression.cpp b/xbmc/interfaces/info/InfoExpression.cpp
  4614. index db461dd..7c54064 100644
  4615. --- a/xbmc/interfaces/info/InfoExpression.cpp
  4616. +++ b/xbmc/interfaces/info/InfoExpression.cpp
  4617. @@ -44,7 +44,10 @@ InfoExpression::InfoExpression(const std::string &expression, int context)
  4618. : InfoBool(expression, context)
  4619. {
  4620. if (!Parse(expression))
  4621. + {
  4622. CLog::Log(LOGERROR, "Error parsing boolean expression %s", expression.c_str());
  4623. + m_expression_tree = boost::make_shared<InfoLeaf>(g_infoManager.Register("false", 0), false);
  4624. + }
  4625. }
  4626. void InfoExpression::Update(const CGUIListItem *item)
  4627. --
  4628. 1.9.3
  4629. From 7f2870606f1e183d70b1dc2dbc07fa8bc437d0cc Mon Sep 17 00:00:00 2001
  4630. From: Ben Avison <bavison@riscosopen.org>
  4631. Date: Tue, 26 Nov 2013 20:09:48 +0000
  4632. Subject: [PATCH 16/94] Add caching of infolabels
  4633. The functions CGUIInfoLabel::GetLabel and CGUIInfoLabel::GetItemLabel take
  4634. a number of strings returned from CGUIInfoManager::GetImage or
  4635. CGUIInfoManager::GetLabel, and combine them with various constant strings
  4636. which were determined during CGUIInfoLabel::Parse.
  4637. Rather than perform all the string operations on every call, this patch
  4638. changes to use a two-pass process: first it queries all the GetImage/GetLabel
  4639. strings, and then only if at least one of them has changed does it bother
  4640. rebuilding the resultant string - otherwise it re-uses the copy built on a
  4641. preceding call.
  4642. CGUIInfoLabel::GetLabel/GetItemLabel are also changed to return string
  4643. references, rather than forcing an additional string copy.
  4644. I have measured the effect while the Videos window of the default skin was
  4645. open (but idle) on a Raspberry Pi, and this reduced the CPU usage by 0.8%
  4646. from 36.2% to 35.4%:
  4647. Before After
  4648. Mean StdDev Mean StdDev Confidence Change
  4649. IdleCPU% 36.2 0.5 35.4 0.5 99.9% +2.2%
  4650. ---
  4651. xbmc/guilib/GUIInfoTypes.cpp | 102 +++++++++++++++++++++++++++++++++----------
  4652. xbmc/guilib/GUIInfoTypes.h | 11 ++++-
  4653. 2 files changed, 87 insertions(+), 26 deletions(-)
  4654. diff --git a/xbmc/guilib/GUIInfoTypes.cpp b/xbmc/guilib/GUIInfoTypes.cpp
  4655. index 6977e0f..d78c26a 100644
  4656. --- a/xbmc/guilib/GUIInfoTypes.cpp
  4657. +++ b/xbmc/guilib/GUIInfoTypes.cpp
  4658. @@ -136,37 +136,64 @@ void CGUIInfoLabel::SetLabel(const CStdString &label, const CStdString &fallback
  4659. Parse(label, context);
  4660. }
  4661. -CStdString CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback /*= NULL*/) const
  4662. +const std::string &CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage, CStdString *fallback /*= NULL*/) const
  4663. {
  4664. - CStdString label;
  4665. - for (unsigned int i = 0; i < m_info.size(); i++)
  4666. + for (unsigned int i = 0, j = 0; i < m_info.size(); i++)
  4667. {
  4668. const CInfoPortion &portion = m_info[i];
  4669. if (portion.m_info)
  4670. {
  4671. - CStdString infoLabel;
  4672. + std::string infoLabel;
  4673. if (preferImage)
  4674. infoLabel = g_infoManager.GetImage(portion.m_info, contextWindow, fallback);
  4675. if (infoLabel.empty())
  4676. infoLabel = g_infoManager.GetLabel(portion.m_info, contextWindow, fallback);
  4677. - if (!infoLabel.empty())
  4678. - label += portion.GetLabel(infoLabel);
  4679. + if (j == m_labelPortions.size())
  4680. + m_labelPortions.push_back(infoLabel);
  4681. + else if (infoLabel != m_labelPortions[j])
  4682. + {
  4683. + m_labelPortions[j] = infoLabel;
  4684. + m_labelDirty = true;
  4685. + }
  4686. + j++;
  4687. }
  4688. - else
  4689. - { // no info, so just append the prefix
  4690. - label += portion.m_prefix;
  4691. + }
  4692. + if (m_labelDirty)
  4693. + {
  4694. + m_label.clear();
  4695. + for (unsigned int i = 0, j= 0; i < m_info.size(); i++)
  4696. + {
  4697. + const CInfoPortion &portion = m_info[i];
  4698. + if (portion.m_info)
  4699. + {
  4700. + if (!m_labelPortions[j].empty())
  4701. + m_label += portion.GetLabel(m_labelPortions[j]);
  4702. + j++;
  4703. + }
  4704. + else
  4705. + { // no info, so just append the prefix
  4706. + m_label += portion.m_prefix;
  4707. + }
  4708. }
  4709. + if (m_label.empty()) // empty label, use the fallback
  4710. + m_label = m_fallback;
  4711. + m_labelDirty = false;
  4712. }
  4713. - if (label.empty()) // empty label, use the fallback
  4714. - return m_fallback;
  4715. - return label;
  4716. + return m_label;
  4717. }
  4718. -CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback /*= NULL*/) const
  4719. +const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImages, CStdString *fallback /*= NULL*/) const
  4720. {
  4721. - if (!item->IsFileItem()) return "";
  4722. - CStdString label;
  4723. - for (unsigned int i = 0; i < m_info.size(); i++)
  4724. + if (!item->IsFileItem())
  4725. + {
  4726. + if (m_itemLabelDirty)
  4727. + {
  4728. + m_itemLabel = "";
  4729. + m_itemLabelDirty = false;
  4730. + }
  4731. + return m_itemLabel;
  4732. + }
  4733. + for (unsigned int i = 0, j = 0; i < m_info.size(); i++)
  4734. {
  4735. const CInfoPortion &portion = m_info[i];
  4736. if (portion.m_info)
  4737. @@ -176,17 +203,38 @@ CStdString CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool preferImag
  4738. infoLabel = g_infoManager.GetItemImage((const CFileItem *)item, portion.m_info, fallback);
  4739. else
  4740. infoLabel = g_infoManager.GetItemLabel((const CFileItem *)item, portion.m_info, fallback);
  4741. - if (!infoLabel.empty())
  4742. - label += portion.GetLabel(infoLabel);
  4743. + if (j == m_itemLabelPortions.size())
  4744. + m_itemLabelPortions.push_back(infoLabel);
  4745. + else if (infoLabel != m_itemLabelPortions[j])
  4746. + {
  4747. + m_itemLabelPortions[j] = infoLabel;
  4748. + m_itemLabelDirty = true;
  4749. + }
  4750. + j++;
  4751. }
  4752. - else
  4753. - { // no info, so just append the prefix
  4754. - label += portion.m_prefix;
  4755. + }
  4756. + if (m_itemLabelDirty)
  4757. + {
  4758. + m_itemLabel.clear();
  4759. + for (unsigned int i = 0, j = 0; i < m_info.size(); i++)
  4760. + {
  4761. + const CInfoPortion &portion = m_info[i];
  4762. + if (portion.m_info)
  4763. + {
  4764. + if (!m_itemLabelPortions[j].empty())
  4765. + m_itemLabel += portion.GetLabel(m_itemLabelPortions[j]);
  4766. + j++;
  4767. + }
  4768. + else
  4769. + { // no info, so just append the prefix
  4770. + m_itemLabel += portion.m_prefix;
  4771. + }
  4772. }
  4773. + if (m_itemLabel.empty())
  4774. + m_itemLabel = m_fallback;
  4775. + m_itemLabelDirty = false;
  4776. }
  4777. - if (label.empty())
  4778. - return m_fallback;
  4779. - return label;
  4780. + return m_itemLabel;
  4781. }
  4782. bool CGUIInfoLabel::IsEmpty() const
  4783. @@ -277,6 +325,12 @@ const static infoformat infoformatmap[] = {{ "$INFO[", FORMATINFO },
  4784. void CGUIInfoLabel::Parse(const CStdString &label, int context)
  4785. {
  4786. m_info.clear();
  4787. + m_labelDirty = true;
  4788. + m_label.clear();
  4789. + m_labelPortions.clear();
  4790. + m_itemLabelDirty = true;
  4791. + m_itemLabel.clear();
  4792. + m_itemLabelPortions.clear();
  4793. // Step 1: Replace all $LOCALIZE[number] with the real string
  4794. CStdString work = ReplaceLocalize(label);
  4795. // Step 2: Replace all $ADDON[id number] with the real string
  4796. diff --git a/xbmc/guilib/GUIInfoTypes.h b/xbmc/guilib/GUIInfoTypes.h
  4797. index 8c1c1dc..418b2c4 100644
  4798. --- a/xbmc/guilib/GUIInfoTypes.h
  4799. +++ b/xbmc/guilib/GUIInfoTypes.h
  4800. @@ -83,7 +83,7 @@ class CGUIInfoLabel
  4801. \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL.
  4802. \return label (or image).
  4803. */
  4804. - CStdString GetLabel(int contextWindow, bool preferImage = false, CStdString *fallback = NULL) const;
  4805. + const std::string &GetLabel(int contextWindow, bool preferImage = false, CStdString *fallback = NULL) const;
  4806. /*!
  4807. \brief Gets a label (or image) for a given listitem from the info manager.
  4808. @@ -92,7 +92,7 @@ class CGUIInfoLabel
  4809. \param fallback if non-NULL, is set to an alternate value to use should the actual value be not appropriate. Defaults to NULL.
  4810. \return label (or image).
  4811. */
  4812. - CStdString GetItemLabel(const CGUIListItem *item, bool preferImage = false, CStdString *fallback = NULL) const;
  4813. + const std::string &GetItemLabel(const CGUIListItem *item, bool preferImage = false, CStdString *fallback = NULL) const;
  4814. bool IsConstant() const;
  4815. bool IsEmpty() const;
  4816. @@ -132,6 +132,13 @@ class CGUIInfoLabel
  4817. CStdString m_fallback;
  4818. std::vector<CInfoPortion> m_info;
  4819. +
  4820. + mutable bool m_labelDirty;
  4821. + mutable std::string m_label;
  4822. + mutable std::vector<std::string> m_labelPortions;
  4823. + mutable bool m_itemLabelDirty;
  4824. + mutable std::string m_itemLabel;
  4825. + mutable std::vector<std::string> m_itemLabelPortions;
  4826. };
  4827. #endif
  4828. --
  4829. 1.9.3
  4830. From 3d5a1912ffd4556ec09208fea50d2a2919775c9f Mon Sep 17 00:00:00 2001
  4831. From: Ben Avison <bavison@riscosopen.org>
  4832. Date: Tue, 10 Dec 2013 01:12:31 +0000
  4833. Subject: [PATCH 17/94] De-duplication of string cache for non-item and item
  4834. labels
  4835. ---
  4836. xbmc/guilib/GUIInfoTypes.cpp | 50 +++++++++++++++++++++++++-------------------
  4837. xbmc/guilib/GUIInfoTypes.h | 4 +---
  4838. 2 files changed, 29 insertions(+), 25 deletions(-)
  4839. diff --git a/xbmc/guilib/GUIInfoTypes.cpp b/xbmc/guilib/GUIInfoTypes.cpp
  4840. index d78c26a..8bd131f 100644
  4841. --- a/xbmc/guilib/GUIInfoTypes.cpp
  4842. +++ b/xbmc/guilib/GUIInfoTypes.cpp
  4843. @@ -121,7 +121,7 @@ void CGUIInfoColor::Parse(const CStdString &label, int context)
  4844. m_color = g_colorManager.GetColor(label);
  4845. }
  4846. -CGUIInfoLabel::CGUIInfoLabel()
  4847. +CGUIInfoLabel::CGUIInfoLabel() : m_labelDirty(true)
  4848. {
  4849. }
  4850. @@ -178,7 +178,10 @@ const std::string &CGUIInfoLabel::GetLabel(int contextWindow, bool preferImage,
  4851. if (m_label.empty()) // empty label, use the fallback
  4852. m_label = m_fallback;
  4853. m_labelDirty = false;
  4854. + m_isLabelOfListItem = false;
  4855. }
  4856. + else
  4857. + assert(m_isLabelOfListItem == false);
  4858. return m_label;
  4859. }
  4860. @@ -186,12 +189,15 @@ const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool pr
  4861. {
  4862. if (!item->IsFileItem())
  4863. {
  4864. - if (m_itemLabelDirty)
  4865. + if (m_labelDirty)
  4866. {
  4867. - m_itemLabel = "";
  4868. - m_itemLabelDirty = false;
  4869. + m_label = "";
  4870. + m_labelDirty = false;
  4871. + m_isLabelOfListItem = true;
  4872. }
  4873. - return m_itemLabel;
  4874. + else
  4875. + assert(m_isLabelOfListItem == true);
  4876. + return m_label;
  4877. }
  4878. for (unsigned int i = 0, j = 0; i < m_info.size(); i++)
  4879. {
  4880. @@ -203,38 +209,41 @@ const std::string &CGUIInfoLabel::GetItemLabel(const CGUIListItem *item, bool pr
  4881. infoLabel = g_infoManager.GetItemImage((const CFileItem *)item, portion.m_info, fallback);
  4882. else
  4883. infoLabel = g_infoManager.GetItemLabel((const CFileItem *)item, portion.m_info, fallback);
  4884. - if (j == m_itemLabelPortions.size())
  4885. - m_itemLabelPortions.push_back(infoLabel);
  4886. - else if (infoLabel != m_itemLabelPortions[j])
  4887. + if (j == m_labelPortions.size())
  4888. + m_labelPortions.push_back(infoLabel);
  4889. + else if (infoLabel != m_labelPortions[j])
  4890. {
  4891. - m_itemLabelPortions[j] = infoLabel;
  4892. - m_itemLabelDirty = true;
  4893. + m_labelPortions[j] = infoLabel;
  4894. + m_labelDirty = true;
  4895. }
  4896. j++;
  4897. }
  4898. }
  4899. - if (m_itemLabelDirty)
  4900. + if (m_labelDirty)
  4901. {
  4902. - m_itemLabel.clear();
  4903. + m_label.clear();
  4904. for (unsigned int i = 0, j = 0; i < m_info.size(); i++)
  4905. {
  4906. const CInfoPortion &portion = m_info[i];
  4907. if (portion.m_info)
  4908. {
  4909. - if (!m_itemLabelPortions[j].empty())
  4910. - m_itemLabel += portion.GetLabel(m_itemLabelPortions[j]);
  4911. + if (!m_labelPortions[j].empty())
  4912. + m_label += portion.GetLabel(m_labelPortions[j]);
  4913. j++;
  4914. }
  4915. else
  4916. { // no info, so just append the prefix
  4917. - m_itemLabel += portion.m_prefix;
  4918. + m_label += portion.m_prefix;
  4919. }
  4920. }
  4921. - if (m_itemLabel.empty())
  4922. - m_itemLabel = m_fallback;
  4923. - m_itemLabelDirty = false;
  4924. + if (m_label.empty())
  4925. + m_label = m_fallback;
  4926. + m_labelDirty = false;
  4927. + m_isLabelOfListItem = true;
  4928. }
  4929. - return m_itemLabel;
  4930. + else
  4931. + assert(m_isLabelOfListItem == true);
  4932. + return m_label;
  4933. }
  4934. bool CGUIInfoLabel::IsEmpty() const
  4935. @@ -328,9 +337,6 @@ void CGUIInfoLabel::Parse(const CStdString &label, int context)
  4936. m_labelDirty = true;
  4937. m_label.clear();
  4938. m_labelPortions.clear();
  4939. - m_itemLabelDirty = true;
  4940. - m_itemLabel.clear();
  4941. - m_itemLabelPortions.clear();
  4942. // Step 1: Replace all $LOCALIZE[number] with the real string
  4943. CStdString work = ReplaceLocalize(label);
  4944. // Step 2: Replace all $ADDON[id number] with the real string
  4945. diff --git a/xbmc/guilib/GUIInfoTypes.h b/xbmc/guilib/GUIInfoTypes.h
  4946. index 418b2c4..6d9ebf7 100644
  4947. --- a/xbmc/guilib/GUIInfoTypes.h
  4948. +++ b/xbmc/guilib/GUIInfoTypes.h
  4949. @@ -133,12 +133,10 @@ class CGUIInfoLabel
  4950. CStdString m_fallback;
  4951. std::vector<CInfoPortion> m_info;
  4952. + mutable bool m_isLabelOfListItem;
  4953. mutable bool m_labelDirty;
  4954. mutable std::string m_label;
  4955. mutable std::vector<std::string> m_labelPortions;
  4956. - mutable bool m_itemLabelDirty;
  4957. - mutable std::string m_itemLabel;
  4958. - mutable std::vector<std::string> m_itemLabelPortions;
  4959. };
  4960. #endif
  4961. --
  4962. 1.9.3
  4963. From 1427baf4395b760227afbef8e17956ba251f2fbe Mon Sep 17 00:00:00 2001
  4964. From: popcornmix <popcornmix@gmail.com>
  4965. Date: Fri, 21 Feb 2014 15:16:13 +0000
  4966. Subject: [PATCH 18/94] Faster and simpler portable implementation of
  4967. MathUtils::round_int().
  4968. Much as I like a bit of inline assembler, I have also removed the ARM versions
  4969. of MathUtils::truncate_int() and MathUtils::round_int(). The former was just
  4970. how any sane compiler should have assembled a cast from double to signed int
  4971. anyway. The latter was a much too complicated way to achieve the desired
  4972. effect, and was switched out in most ARM builds anyway in favour of the old
  4973. portable implementation that used floor().
  4974. Verified that MathUtils::test() still passes, and that GCC is now able to
  4975. inline MathUtils::round_int(), where it didn't previously.
  4976. I tested on a Raspberry Pi with the default theme, displaying the front page
  4977. with the RSS ticker enabled. This saturates the CPU, so I'm measuring the
  4978. improvement using the debug window's FPS figure. This patch improves this from
  4979. ~50.8 FPS to ~52.6 FPS.
  4980. ---
  4981. xbmc/utils/MathUtils.h | 129 +++++++++++++++++++++++--------------------------
  4982. 1 file changed, 61 insertions(+), 68 deletions(-)
  4983. diff --git a/xbmc/utils/MathUtils.h b/xbmc/utils/MathUtils.h
  4984. index 96af9f4..0dae77d 100644
  4985. --- a/xbmc/utils/MathUtils.h
  4986. +++ b/xbmc/utils/MathUtils.h
  4987. @@ -34,17 +34,13 @@
  4988. #if defined(__ppc__) || \
  4989. defined(__powerpc__) || \
  4990. - (defined(TARGET_DARWIN_IOS) && defined(__llvm__)) || \
  4991. - (defined(TARGET_ANDROID) && defined(__arm__)) || \
  4992. - defined(TARGET_RASPBERRY_PI)
  4993. + defined(__arm__)
  4994. #define DISABLE_MATHUTILS_ASM_ROUND_INT
  4995. #endif
  4996. #if defined(__ppc__) || \
  4997. defined(__powerpc__) || \
  4998. - (defined(TARGET_DARWIN) && defined(__llvm__)) || \
  4999. - (defined(TARGET_ANDROID) && defined(__arm__)) || \
  5000. - defined(TARGET_RASPBERRY_PI)
  5001. + defined(__arm__)
  5002. #define DISABLE_MATHUTILS_ASM_TRUNCATE_INT
  5003. #endif
  5004. @@ -73,60 +69,63 @@ namespace MathUtils
  5005. {
  5006. assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
  5007. assert(x < static_cast<double>(INT_MAX / 2) + 1.0);
  5008. - const float round_to_nearest = 0.5f;
  5009. - int i;
  5010. #if defined(DISABLE_MATHUTILS_ASM_ROUND_INT)
  5011. - i = floor(x + round_to_nearest);
  5012. -
  5013. -#elif defined(__arm__)
  5014. - // From 'ARM-v7-M Architecture Reference Manual' page A7-569:
  5015. - // "The floating-point to integer operation (vcvt) [normally] uses the Round towards Zero rounding mode"
  5016. - // Because of this...we must use some less-than-straightforward logic to perform this operation without
  5017. - // changing the rounding mode flags
  5018. -
  5019. - /* The assembly below implements the following logic:
  5020. - if (x < 0)
  5021. - inc = -0.5f
  5022. - else
  5023. - inc = 0.5f
  5024. - int_val = trunc(x+inc);
  5025. - err = x - int_val;
  5026. - if (err == 0.5f)
  5027. - int_val++;
  5028. - return int_val;
  5029. - */
  5030. + /* This implementation warrants some further explanation.
  5031. + *
  5032. + * First, a couple of notes on rounding:
  5033. + * 1) C casts from float/double to integer round towards zero.
  5034. + * 2) Float/double additions are rounded according to the normal rules,
  5035. + * in other words: on some architectures, it's fixed at compile-time,
  5036. + * and on others it can be set using fesetround()). The following
  5037. + * analysis assumes round-to-nearest with ties rounding to even. This
  5038. + * is a fairly sensible choice, and is the default with ARM VFP.
  5039. + *
  5040. + * What this function wants is round-to-nearest with ties rounding to
  5041. + * +infinity. This isn't an IEEE rounding mode, even if we could guarantee
  5042. + * that all architectures supported fesetround(), which they don't. Instead,
  5043. + * this adds an offset of 2147483648.5 (= 0x80000000.8p0), then casts to
  5044. + * an unsigned int (crucially, all possible inputs are now in a range where
  5045. + * round to zero acts the same as round to -infinity) and then subtracts
  5046. + * 0x80000000 in the integer domain. The 0.5 component of the offset
  5047. + * converts what is effectively a round down into a round to nearest, with
  5048. + * ties rounding up, as desired.
  5049. + *
  5050. + * There is a catch, that because there is a double rounding, there is a
  5051. + * small region where the input falls just *below* a tie, where the addition
  5052. + * of the offset causes a round *up* to an exact integer, due to the finite
  5053. + * level of precision available in floating point. You need to be aware of
  5054. + * this when calling this function, although at present it is not believed
  5055. + * that XBMC ever attempts to round numbers in this window.
  5056. + *
  5057. + * It is worth proving the size of the affected window. Recall that double
  5058. + * precision employs a mantissa of 52 bits.
  5059. + * 1) For all inputs -0.5 <= x <= INT_MAX
  5060. + * Once the offset is applied, the most significant binary digit in the
  5061. + * floating-point representation is +2^31.
  5062. + * At this magnitude, the smallest step representable in double precision
  5063. + * is 2^31 / 2^52 = 0.000000476837158203125
  5064. + * So the size of the range which is rounded up due to the addition is
  5065. + * half the size of this step, or 0.0000002384185791015625
  5066. + *
  5067. + * 2) For all inputs INT_MIN/2 < x < -0.5
  5068. + * Once the offset is applied, the most significant binary digit in the
  5069. + * floating-point representation is +2^30.
  5070. + * At this magnitude, the smallest step representable in double precision
  5071. + * is 2^30 / 2^52 = 0.0000002384185791015625
  5072. + * So the size of the range which is rounded up due to the addition is
  5073. + * half the size of this step, or 0.00000011920928955078125
  5074. + *
  5075. + * 3) For all inputs INT_MIN <= x <= INT_MIN/2
  5076. + * The representation once the offset is applied has equal or greater
  5077. + * precision than the input, so the addition does not cause rounding.
  5078. + */
  5079. + return ((unsigned int) (x + 0x80000000.8p0)) - 0x80000000;
  5080. - __asm__ __volatile__ (
  5081. -#if defined(__ARM_PCS_VFP)
  5082. - "fconstd d1,#%G[rnd_val] \n\t" // Copy round_to_nearest into a working register (d1 = 0.5)
  5083. #else
  5084. - "vmov.F64 d1,%[rnd_val] \n\t"
  5085. -#endif
  5086. - "fcmpezd %P[value] \n\t" // Check value against zero (value == 0?)
  5087. - "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
  5088. - "it mi \n\t"
  5089. - "vnegmi.F64 d1, d1 \n\t" // if N-flag is set, negate round_to_nearest (if (value < 0) d1 = -1 * d1)
  5090. - "vadd.F64 d1,%P[value],d1 \n\t" // Add round_to_nearest to value, store result in working register (d1 += value)
  5091. - "vcvt.S32.F64 s3,d1 \n\t" // Truncate(round towards zero) (s3 = (int)d1)
  5092. - "vmov %[result],s3 \n\t" // Store the integer result in a general-purpose register (result = s3)
  5093. - "vcvt.F64.S32 d1,s3 \n\t" // Convert back to floating-point (d1 = (double)s3)
  5094. - "vsub.F64 d1,%P[value],d1 \n\t" // Calculate the error (d1 = value - d1)
  5095. -#if defined(__ARM_PCS_VFP)
  5096. - "fconstd d2,#%G[rnd_val] \n\t" // d2 = 0.5;
  5097. -#else
  5098. - "vmov.F64 d2,%[rnd_val] \n\t"
  5099. -#endif
  5100. - "fcmped d1, d2 \n\t" // (d1 == 0.5?)
  5101. - "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
  5102. - "it eq \n\t"
  5103. - "addeq %[result],#1 \n\t" // (if (d1 == d2) result++;)
  5104. - : [result] "=r"(i) // Outputs
  5105. - : [rnd_val] "Dv" (round_to_nearest), [value] "w"(x) // Inputs
  5106. - : "d1", "d2", "s3" // Clobbers
  5107. - );
  5108. -
  5109. -#elif defined(__SSE2__)
  5110. + const float round_to_nearest = 0.5f;
  5111. + int i;
  5112. +#if defined(__SSE2__)
  5113. const float round_dn_to_nearest = 0.4999999f;
  5114. i = (x > 0) ? _mm_cvttsd_si32(_mm_set_sd(x + round_to_nearest)) : _mm_cvttsd_si32(_mm_set_sd(x - round_dn_to_nearest));
  5115. @@ -150,8 +149,8 @@ namespace MathUtils
  5116. );
  5117. #endif
  5118. -
  5119. return i;
  5120. +#endif
  5121. }
  5122. /*! \brief Truncate to nearest integer.
  5123. @@ -165,20 +164,13 @@ namespace MathUtils
  5124. {
  5125. assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
  5126. assert(x < static_cast<double>(INT_MAX / 2) + 1.0);
  5127. - int i;
  5128. #if defined(DISABLE_MATHUTILS_ASM_TRUNCATE_INT)
  5129. - return i = (int)x;
  5130. -
  5131. -#elif defined(__arm__)
  5132. - __asm__ __volatile__ (
  5133. - "vcvt.S32.F64 %[result],%P[value] \n\t" // Truncate(round towards zero) and store the result
  5134. - : [result] "=w"(i) // Outputs
  5135. - : [value] "w"(x) // Inputs
  5136. - );
  5137. - return i;
  5138. + return x;
  5139. -#elif defined(TARGET_WINDOWS)
  5140. +#else
  5141. + int i;
  5142. +#if defined(TARGET_WINDOWS)
  5143. const float round_towards_m_i = -0.5f;
  5144. __asm
  5145. {
  5146. @@ -204,6 +196,7 @@ namespace MathUtils
  5147. if (x < 0)
  5148. i = -i;
  5149. return (i);
  5150. +#endif
  5151. }
  5152. inline int64_t abs(int64_t a)
  5153. --
  5154. 1.9.3
  5155. From 0ad4df440ea225cc951a65bf9553b1f00f416d85 Mon Sep 17 00:00:00 2001
  5156. From: Ben Avison <bavison@riscosopen.org>
  5157. Date: Wed, 11 Dec 2013 17:21:54 +0000
  5158. Subject: [PATCH 19/94] Move the reference-counting of Begin and End calls from
  5159. DX and GL source files into GUIFontTTF.cpp.
  5160. ---
  5161. xbmc/guilib/GUIFontTTF.cpp | 21 ++++++++
  5162. xbmc/guilib/GUIFontTTF.h | 6 ++-
  5163. xbmc/guilib/GUIFontTTFDX.cpp | 79 +++++++++++++----------------
  5164. xbmc/guilib/GUIFontTTFDX.h | 4 +-
  5165. xbmc/guilib/GUIFontTTFGL.cpp | 118 +++++++++++++++++++------------------------
  5166. xbmc/guilib/GUIFontTTFGL.h | 4 +-
  5167. 6 files changed, 117 insertions(+), 115 deletions(-)
  5168. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  5169. index 9c8e516..90b9c4a 100644
  5170. --- a/xbmc/guilib/GUIFontTTF.cpp
  5171. +++ b/xbmc/guilib/GUIFontTTF.cpp
  5172. @@ -309,6 +309,27 @@ bool CGUIFontTTFBase::Load(const CStdString& strFilename, float height, float as
  5173. return true;
  5174. }
  5175. +void CGUIFontTTFBase::Begin()
  5176. +{
  5177. + if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
  5178. + {
  5179. + m_vertex_count = 0;
  5180. + }
  5181. + // Keep track of the nested begin/end calls.
  5182. + m_nestedBeginCount++;
  5183. +}
  5184. +
  5185. +void CGUIFontTTFBase::End()
  5186. +{
  5187. + if (m_nestedBeginCount == 0)
  5188. + return;
  5189. +
  5190. + if (--m_nestedBeginCount > 0)
  5191. + return;
  5192. +
  5193. + LastEnd();
  5194. +}
  5195. +
  5196. void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors, const vecText &text, uint32_t alignment, float maxPixelWidth, bool scrolling)
  5197. {
  5198. Begin();
  5199. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  5200. index 9723a43..c1c4507 100644
  5201. --- a/xbmc/guilib/GUIFontTTF.h
  5202. +++ b/xbmc/guilib/GUIFontTTF.h
  5203. @@ -77,8 +77,8 @@ class CGUIFontTTFBase
  5204. bool Load(const CStdString& strFilename, float height = 20.0f, float aspect = 1.0f, float lineSpacing = 1.0f, bool border = false);
  5205. - virtual void Begin() = 0;
  5206. - virtual void End() = 0;
  5207. + void Begin();
  5208. + void End();
  5209. const CStdString& GetFileName() const { return m_strFileName; };
  5210. @@ -169,6 +169,8 @@ class CGUIFontTTFBase
  5211. CStdString m_strFileName;
  5212. private:
  5213. + virtual bool FirstBegin() = 0;
  5214. + virtual void LastEnd() = 0;
  5215. CGUIFontTTFBase(const CGUIFontTTFBase&);
  5216. CGUIFontTTFBase& operator=(const CGUIFontTTFBase&);
  5217. int m_referenceCount;
  5218. diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp
  5219. index e3eba24..2f90668 100644
  5220. --- a/xbmc/guilib/GUIFontTTFDX.cpp
  5221. +++ b/xbmc/guilib/GUIFontTTFDX.cpp
  5222. @@ -51,65 +51,56 @@ CGUIFontTTFDX::~CGUIFontTTFDX(void)
  5223. free(m_index);
  5224. }
  5225. -void CGUIFontTTFDX::Begin()
  5226. +bool CGUIFontTTFDX::FirstBegin()
  5227. {
  5228. LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
  5229. if (pD3DDevice == NULL)
  5230. + {
  5231. CLog::Log(LOGERROR, __FUNCTION__" - failed to get Direct3D device");
  5232. + return false;
  5233. + }
  5234. - if (m_nestedBeginCount == 0 && pD3DDevice != NULL && m_texture != NULL)
  5235. + int unit = 0;
  5236. + // just have to blit from our texture.
  5237. + m_texture->BindToUnit(unit);
  5238. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse
  5239. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  5240. + pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  5241. + pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  5242. + pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  5243. + unit++;
  5244. +
  5245. + if(g_Windowing.UseLimitedColor())
  5246. {
  5247. - int unit = 0;
  5248. - // just have to blit from our texture.
  5249. - m_texture->BindToUnit(unit);
  5250. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); // only use diffuse
  5251. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
  5252. - pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  5253. - pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  5254. - pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
  5255. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD );
  5256. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ;
  5257. + pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) );
  5258. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR );
  5259. unit++;
  5260. -
  5261. - if(g_Windowing.UseLimitedColor())
  5262. - {
  5263. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP , D3DTOP_ADD );
  5264. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG1, D3DTA_CURRENT) ;
  5265. - pD3DDevice->SetRenderState( D3DRS_TEXTUREFACTOR, D3DCOLOR_RGBA(16,16,16,0) );
  5266. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLORARG2, D3DTA_TFACTOR );
  5267. - unit++;
  5268. - }
  5269. -
  5270. - // no other texture stages needed
  5271. - pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE);
  5272. - pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  5273. -
  5274. - pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  5275. - pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
  5276. - pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  5277. - pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  5278. - pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  5279. - pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  5280. - pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  5281. - pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE);
  5282. -
  5283. - pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
  5284. - m_vertex_count = 0;
  5285. }
  5286. - // Keep track of the nested begin/end calls.
  5287. - m_nestedBeginCount++;
  5288. + // no other texture stages needed
  5289. + pD3DDevice->SetTextureStageState( unit, D3DTSS_COLOROP, D3DTOP_DISABLE);
  5290. + pD3DDevice->SetTextureStageState( unit, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  5291. +
  5292. + pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
  5293. + pD3DDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
  5294. + pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
  5295. + pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
  5296. + pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  5297. + pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
  5298. + pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  5299. + pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE);
  5300. +
  5301. + pD3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
  5302. + return true;
  5303. }
  5304. -void CGUIFontTTFDX::End()
  5305. +void CGUIFontTTFDX::LastEnd()
  5306. {
  5307. LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
  5308. - if (m_nestedBeginCount == 0)
  5309. - return;
  5310. -
  5311. - if (--m_nestedBeginCount > 0)
  5312. - return;
  5313. -
  5314. if (m_vertex_count == 0)
  5315. return;
  5316. diff --git a/xbmc/guilib/GUIFontTTFDX.h b/xbmc/guilib/GUIFontTTFDX.h
  5317. index 0431085..17dfefe 100644
  5318. --- a/xbmc/guilib/GUIFontTTFDX.h
  5319. +++ b/xbmc/guilib/GUIFontTTFDX.h
  5320. @@ -41,8 +41,8 @@ class CGUIFontTTFDX : public CGUIFontTTFBase
  5321. CGUIFontTTFDX(const CStdString& strFileName);
  5322. virtual ~CGUIFontTTFDX(void);
  5323. - virtual void Begin();
  5324. - virtual void End();
  5325. + virtual bool FirstBegin();
  5326. + virtual void LastEnd();
  5327. protected:
  5328. virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
  5329. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  5330. index 3358a5a..93b7ea6 100644
  5331. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  5332. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  5333. @@ -50,90 +50,78 @@ CGUIFontTTFGL::~CGUIFontTTFGL(void)
  5334. {
  5335. }
  5336. -void CGUIFontTTFGL::Begin()
  5337. +bool CGUIFontTTFGL::FirstBegin()
  5338. {
  5339. - if (m_nestedBeginCount == 0 && m_texture != NULL)
  5340. + if (!m_bTextureLoaded)
  5341. {
  5342. - if (!m_bTextureLoaded)
  5343. - {
  5344. - // Have OpenGL generate a texture object handle for us
  5345. - glGenTextures(1, (GLuint*) &m_nTexture);
  5346. + // Have OpenGL generate a texture object handle for us
  5347. + glGenTextures(1, (GLuint*) &m_nTexture);
  5348. - // Bind the texture object
  5349. - glBindTexture(GL_TEXTURE_2D, m_nTexture);
  5350. + // Bind the texture object
  5351. + glBindTexture(GL_TEXTURE_2D, m_nTexture);
  5352. #ifdef HAS_GL
  5353. - glEnable(GL_TEXTURE_2D);
  5354. + glEnable(GL_TEXTURE_2D);
  5355. #endif
  5356. - // Set the texture's stretching properties
  5357. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  5358. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  5359. + // Set the texture's stretching properties
  5360. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  5361. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  5362. - // Set the texture image -- THIS WORKS, so the pixels must be wrong.
  5363. - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0,
  5364. - GL_ALPHA, GL_UNSIGNED_BYTE, m_texture->GetPixels());
  5365. + // Set the texture image -- THIS WORKS, so the pixels must be wrong.
  5366. + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, m_texture->GetWidth(), m_texture->GetHeight(), 0,
  5367. + GL_ALPHA, GL_UNSIGNED_BYTE, m_texture->GetPixels());
  5368. - VerifyGLState();
  5369. - m_bTextureLoaded = true;
  5370. - }
  5371. + VerifyGLState();
  5372. + m_bTextureLoaded = true;
  5373. + }
  5374. - // Turn Blending On
  5375. - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  5376. - glEnable(GL_BLEND);
  5377. + // Turn Blending On
  5378. + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
  5379. + glEnable(GL_BLEND);
  5380. #ifdef HAS_GL
  5381. - glEnable(GL_TEXTURE_2D);
  5382. + glEnable(GL_TEXTURE_2D);
  5383. #endif
  5384. - glBindTexture(GL_TEXTURE_2D, m_nTexture);
  5385. + glBindTexture(GL_TEXTURE_2D, m_nTexture);
  5386. #ifdef HAS_GL
  5387. - glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
  5388. - glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
  5389. - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
  5390. - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
  5391. - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
  5392. - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
  5393. - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
  5394. - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
  5395. - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
  5396. - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  5397. - VerifyGLState();
  5398. + glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE);
  5399. + glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB,GL_REPLACE);
  5400. + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
  5401. + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
  5402. + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
  5403. + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE0);
  5404. + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
  5405. + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
  5406. + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
  5407. + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  5408. + VerifyGLState();
  5409. +
  5410. + if(g_Windowing.UseLimitedColor())
  5411. + {
  5412. + glActiveTexture(GL_TEXTURE1);
  5413. + glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind
  5414. + glEnable(GL_TEXTURE_2D);
  5415. - if(g_Windowing.UseLimitedColor())
  5416. - {
  5417. - glActiveTexture(GL_TEXTURE1);
  5418. - glBindTexture(GL_TEXTURE_2D, m_nTexture); // dummy bind
  5419. - glEnable(GL_TEXTURE_2D);
  5420. -
  5421. - const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f};
  5422. - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE);
  5423. - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
  5424. - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD);
  5425. - glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS);
  5426. - glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT);
  5427. - glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR);
  5428. - glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR);
  5429. - glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE);
  5430. - glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS);
  5431. - VerifyGLState();
  5432. - }
  5433. + const GLfloat rgba[4] = {16.0f / 255.0f, 16.0f / 255.0f, 16.0f / 255.0f, 0.0f};
  5434. + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE , GL_COMBINE);
  5435. + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, rgba);
  5436. + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB , GL_ADD);
  5437. + glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB , GL_PREVIOUS);
  5438. + glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB , GL_CONSTANT);
  5439. + glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB , GL_SRC_COLOR);
  5440. + glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB , GL_SRC_COLOR);
  5441. + glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA , GL_REPLACE);
  5442. + glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA , GL_PREVIOUS);
  5443. + VerifyGLState();
  5444. + }
  5445. #else
  5446. - g_Windowing.EnableGUIShader(SM_FONTS);
  5447. + g_Windowing.EnableGUIShader(SM_FONTS);
  5448. #endif
  5449. -
  5450. - m_vertex_count = 0;
  5451. - }
  5452. - // Keep track of the nested begin/end calls.
  5453. - m_nestedBeginCount++;
  5454. + return true;
  5455. }
  5456. -void CGUIFontTTFGL::End()
  5457. +void CGUIFontTTFGL::LastEnd()
  5458. {
  5459. - if (m_nestedBeginCount == 0)
  5460. - return;
  5461. -
  5462. - if (--m_nestedBeginCount > 0)
  5463. - return;
  5464. -
  5465. #ifdef HAS_GL
  5466. glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
  5467. diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
  5468. index a0dacba..6736cf7 100644
  5469. --- a/xbmc/guilib/GUIFontTTFGL.h
  5470. +++ b/xbmc/guilib/GUIFontTTFGL.h
  5471. @@ -41,8 +41,8 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
  5472. CGUIFontTTFGL(const CStdString& strFileName);
  5473. virtual ~CGUIFontTTFGL(void);
  5474. - virtual void Begin();
  5475. - virtual void End();
  5476. + virtual bool FirstBegin();
  5477. + virtual void LastEnd();
  5478. protected:
  5479. virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
  5480. --
  5481. 1.9.3
  5482. From 427373ae5bb96489afb22529714c16e8f82c2195 Mon Sep 17 00:00:00 2001
  5483. From: Ben Avison <bavison@riscosopen.org>
  5484. Date: Wed, 11 Dec 2013 18:47:54 +0000
  5485. Subject: [PATCH 20/94] Convert CGUIFontTTFBase::m_vertex to be managed as a
  5486. std::vector. Also retired CGUIFontTTFBase::m_vertex_count and
  5487. CGUIFontTTFBase::m_vertex_size because these can be derived from vector
  5488. member functions.
  5489. ---
  5490. xbmc/guilib/GUIFontTTF.cpp | 29 +++++------------------------
  5491. xbmc/guilib/GUIFontTTF.h | 4 +---
  5492. xbmc/guilib/GUIFontTTFDX.cpp | 12 ++++++------
  5493. xbmc/guilib/GUIFontTTFGL.cpp | 12 ++++++------
  5494. 4 files changed, 18 insertions(+), 39 deletions(-)
  5495. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  5496. index 90b9c4a..3f219d9 100644
  5497. --- a/xbmc/guilib/GUIFontTTF.cpp
  5498. +++ b/xbmc/guilib/GUIFontTTF.cpp
  5499. @@ -139,8 +139,7 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
  5500. m_nestedBeginCount = 0;
  5501. m_bTextureLoaded = false;
  5502. - m_vertex_size = 4*1024;
  5503. - m_vertex = (SVertex*)malloc(m_vertex_size * sizeof(SVertex));
  5504. + m_vertex.reserve(4*1024);
  5505. m_face = NULL;
  5506. m_stroker = NULL;
  5507. @@ -155,7 +154,6 @@ CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
  5508. m_textureScaleX = m_textureScaleY = 0.0;
  5509. m_ellipsesWidth = m_height = 0.0f;
  5510. m_color = 0;
  5511. - m_vertex_count = 0;
  5512. m_nTexture = 0;
  5513. }
  5514. @@ -216,9 +214,7 @@ void CGUIFontTTFBase::Clear()
  5515. g_freeTypeLibrary.ReleaseStroker(m_stroker);
  5516. m_stroker = NULL;
  5517. - free(m_vertex);
  5518. - m_vertex = NULL;
  5519. - m_vertex_count = 0;
  5520. + m_vertex.clear();
  5521. }
  5522. bool CGUIFontTTFBase::Load(const CStdString& strFilename, float height, float aspect, float lineSpacing, bool border)
  5523. @@ -313,7 +309,7 @@ void CGUIFontTTFBase::Begin()
  5524. {
  5525. if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
  5526. {
  5527. - m_vertex_count = 0;
  5528. + m_vertex.clear();
  5529. }
  5530. // Keep track of the nested begin/end calls.
  5531. m_nestedBeginCount++;
  5532. @@ -746,22 +742,9 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
  5533. float tt = texture.y1 * m_textureScaleY;
  5534. float tb = texture.y2 * m_textureScaleY;
  5535. - // grow the vertex buffer if required
  5536. - if(m_vertex_count >= m_vertex_size)
  5537. - {
  5538. - m_vertex_size *= 2;
  5539. - void* old = m_vertex;
  5540. - m_vertex = (SVertex*)realloc(m_vertex, m_vertex_size * sizeof(SVertex));
  5541. - if (!m_vertex)
  5542. - {
  5543. - free(old);
  5544. - CLog::Log(LOGSEVERE, "%s: can't allocate %"PRIdS" bytes for texture", __FUNCTION__ , m_vertex_size * sizeof(SVertex));
  5545. - return;
  5546. - }
  5547. - }
  5548. -
  5549. + m_vertex.resize(m_vertex.size() + 4);
  5550. + SVertex* v = &m_vertex[m_vertex.size() - 4];
  5551. m_color = color;
  5552. - SVertex* v = m_vertex + m_vertex_count;
  5553. unsigned char r = GET_R(color)
  5554. , g = GET_G(color)
  5555. @@ -828,8 +811,6 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
  5556. v[3].y = y[2];
  5557. v[3].z = z[2];
  5558. #endif
  5559. -
  5560. - m_vertex_count+=4;
  5561. }
  5562. // Oblique code - original taken from freetype2 (ftsynth.c)
  5563. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  5564. index c1c4507..35e3cf9 100644
  5565. --- a/xbmc/guilib/GUIFontTTF.h
  5566. +++ b/xbmc/guilib/GUIFontTTF.h
  5567. @@ -157,9 +157,7 @@ class CGUIFontTTFBase
  5568. bool m_bTextureLoaded;
  5569. unsigned int m_nTexture;
  5570. - SVertex* m_vertex;
  5571. - int m_vertex_count;
  5572. - int m_vertex_size;
  5573. + std::vector<SVertex> m_vertex;
  5574. float m_textureScaleX;
  5575. float m_textureScaleY;
  5576. diff --git a/xbmc/guilib/GUIFontTTFDX.cpp b/xbmc/guilib/GUIFontTTFDX.cpp
  5577. index 2f90668..6ef8984 100644
  5578. --- a/xbmc/guilib/GUIFontTTFDX.cpp
  5579. +++ b/xbmc/guilib/GUIFontTTFDX.cpp
  5580. @@ -101,17 +101,17 @@ void CGUIFontTTFDX::LastEnd()
  5581. {
  5582. LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
  5583. - if (m_vertex_count == 0)
  5584. + if (m_vertex.size() == 0)
  5585. return;
  5586. - unsigned index_size = m_vertex_size * 6 / 4;
  5587. + unsigned index_size = m_vertex.capacity() * 6 / 4;
  5588. if(m_index_size < index_size)
  5589. {
  5590. uint16_t* id = (uint16_t*)calloc(index_size, sizeof(uint16_t));
  5591. if(id == NULL)
  5592. return;
  5593. - for(int i = 0, b = 0; i < m_vertex_size; i += 4, b += 6)
  5594. + for(int i = 0, b = 0; i < m_vertex.capacity(); i += 4, b += 6)
  5595. {
  5596. id[b+0] = i + 0;
  5597. id[b+1] = i + 1;
  5598. @@ -140,11 +140,11 @@ void CGUIFontTTFDX::LastEnd()
  5599. pD3DDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST
  5600. , 0
  5601. - , m_vertex_count
  5602. - , m_vertex_count / 2
  5603. + , m_vertex.size()
  5604. + , m_vertex.size() / 2
  5605. , m_index
  5606. , D3DFMT_INDEX16
  5607. - , m_vertex
  5608. + , &m_vertex[0]
  5609. , sizeof(SVertex));
  5610. pD3DDevice->SetTransform(D3DTS_WORLD, &orig);
  5611. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  5612. index 93b7ea6..a4e8571 100644
  5613. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  5614. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  5615. @@ -125,13 +125,13 @@ void CGUIFontTTFGL::LastEnd()
  5616. #ifdef HAS_GL
  5617. glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
  5618. - glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, r));
  5619. - glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, x));
  5620. - glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)m_vertex + offsetof(SVertex, u));
  5621. + glColorPointer (4, GL_UNSIGNED_BYTE, sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, r));
  5622. + glVertexPointer (3, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, x));
  5623. + glTexCoordPointer(2, GL_FLOAT , sizeof(SVertex), (char*)&m_vertex[0] + offsetof(SVertex, u));
  5624. glEnableClientState(GL_COLOR_ARRAY);
  5625. glEnableClientState(GL_VERTEX_ARRAY);
  5626. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  5627. - glDrawArrays(GL_QUADS, 0, m_vertex_count);
  5628. + glDrawArrays(GL_QUADS, 0, m_vertex.size());
  5629. glPopClientAttrib();
  5630. glActiveTexture(GL_TEXTURE1);
  5631. @@ -147,10 +147,10 @@ void CGUIFontTTFGL::LastEnd()
  5632. GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
  5633. // stack object until VBOs will be used
  5634. - std::vector<SVertex> vecVertices( 6 * (m_vertex_count / 4) );
  5635. + std::vector<SVertex> vecVertices( 6 * (m_vertex.size() / 4) );
  5636. SVertex *vertices = &vecVertices[0];
  5637. - for (int i=0; i<m_vertex_count; i+=4)
  5638. + for (size_t i=0; i<m_vertex.size(); i+=4)
  5639. {
  5640. *vertices++ = m_vertex[i];
  5641. *vertices++ = m_vertex[i+1];
  5642. --
  5643. 1.9.3
  5644. From a3e8e7f1055726a050e04d1e4ab61a5355cdbd6a Mon Sep 17 00:00:00 2001
  5645. From: Ben Avison <bavison@riscosopen.org>
  5646. Date: Mon, 16 Dec 2013 18:58:12 +0000
  5647. Subject: [PATCH 21/94] CGUIFontTTFBase::RenderCharacter can now append to
  5648. arbitrary vectors of vertices rather than only CGUIFontTTFBase::m_vertex
  5649. ---
  5650. xbmc/guilib/GUIFontTTF.cpp | 12 +++++++-----
  5651. xbmc/guilib/GUIFontTTF.h | 2 +-
  5652. 2 files changed, 8 insertions(+), 6 deletions(-)
  5653. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  5654. index 3f219d9..1aaf68b 100644
  5655. --- a/xbmc/guilib/GUIFontTTF.cpp
  5656. +++ b/xbmc/guilib/GUIFontTTF.cpp
  5657. @@ -330,6 +330,8 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  5658. {
  5659. Begin();
  5660. + std::vector<SVertex> &vertices = m_vertex;
  5661. +
  5662. // save the origin, which is scaled separately
  5663. m_originX = x;
  5664. m_originY = y;
  5665. @@ -410,7 +412,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  5666. for (int i = 0; i < 3; i++)
  5667. {
  5668. - RenderCharacter(startX + cursorX, startY, period, color, !scrolling);
  5669. + RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
  5670. cursorX += period->advance;
  5671. }
  5672. break;
  5673. @@ -419,7 +421,7 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  5674. else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
  5675. break; // exceeded max allowed width - stop rendering
  5676. - RenderCharacter(startX + cursorX, startY, ch, color, !scrolling);
  5677. + RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
  5678. if ( alignment & XBFONT_JUSTIFIED )
  5679. {
  5680. if ((*pos & 0xffff) == L' ')
  5681. @@ -676,7 +678,7 @@ bool CGUIFontTTFBase::CacheCharacter(wchar_t letter, uint32_t style, Character *
  5682. return true;
  5683. }
  5684. -void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX)
  5685. +void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector<SVertex> &vertices)
  5686. {
  5687. // actual image width isn't same as the character width as that is
  5688. // just baseline width and height should include the descent
  5689. @@ -742,8 +744,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
  5690. float tt = texture.y1 * m_textureScaleY;
  5691. float tb = texture.y2 * m_textureScaleY;
  5692. - m_vertex.resize(m_vertex.size() + 4);
  5693. - SVertex* v = &m_vertex[m_vertex.size() - 4];
  5694. + vertices.resize(vertices.size() + 4);
  5695. + SVertex* v = &vertices[vertices.size() - 4];
  5696. m_color = color;
  5697. unsigned char r = GET_R(color)
  5698. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  5699. index 35e3cf9..4a6a696 100644
  5700. --- a/xbmc/guilib/GUIFontTTF.h
  5701. +++ b/xbmc/guilib/GUIFontTTF.h
  5702. @@ -109,7 +109,7 @@ class CGUIFontTTFBase
  5703. // Stuff for pre-rendering for speed
  5704. inline Character *GetCharacter(character_t letter);
  5705. bool CacheCharacter(wchar_t letter, uint32_t style, Character *ch);
  5706. - void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX);
  5707. + void RenderCharacter(float posX, float posY, const Character *ch, color_t color, bool roundX, std::vector<SVertex> &vertices);
  5708. void ClearCharacterCache();
  5709. virtual CBaseTexture* ReallocTexture(unsigned int& newHeight) = 0;
  5710. --
  5711. 1.9.3
  5712. From 79263f02e56ef10410984c98a844aaa9bf43199e Mon Sep 17 00:00:00 2001
  5713. From: Ben Avison <bavison@riscosopen.org>
  5714. Date: Wed, 15 Jan 2014 17:18:38 +0000
  5715. Subject: [PATCH 22/94] Add a cache of font glyph bounding box vertices. This
  5716. is implemented as a template because ultimately we will key on different
  5717. parameters and store values of different types, depending upon whether we
  5718. have a GLES or non-GLES backend, and for GLES, whether or not the currently
  5719. applicable transformation matrices permit the use of hardware clipping.
  5720. ---
  5721. xbmc/guilib/GUIFontCache.cpp | 105 ++++++++++++++++++++
  5722. xbmc/guilib/GUIFontCache.h | 217 ++++++++++++++++++++++++++++++++++++++++++
  5723. xbmc/guilib/GUIFontTTF.cpp | 181 +++++++++++++++++++----------------
  5724. xbmc/guilib/GUIFontTTF.h | 5 +
  5725. xbmc/guilib/GUIFontTTFGL.cpp | 1 +
  5726. xbmc/guilib/GraphicContext.h | 1 +
  5727. xbmc/guilib/Makefile.in | 1 +
  5728. xbmc/guilib/TransformMatrix.h | 11 +++
  5729. 8 files changed, 438 insertions(+), 84 deletions(-)
  5730. create mode 100644 xbmc/guilib/GUIFontCache.cpp
  5731. create mode 100644 xbmc/guilib/GUIFontCache.h
  5732. diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
  5733. new file mode 100644
  5734. index 0000000..c029713
  5735. --- /dev/null
  5736. +++ b/xbmc/guilib/GUIFontCache.cpp
  5737. @@ -0,0 +1,105 @@
  5738. +/*
  5739. + * Copyright (C) 2005-2013 Team XBMC
  5740. + * http://xbmc.org
  5741. + *
  5742. + * This Program is free software; you can redistribute it and/or modify
  5743. + * it under the terms of the GNU General Public License as published by
  5744. + * the Free Software Foundation; either version 2, or (at your option)
  5745. + * any later version.
  5746. + *
  5747. + * This Program is distributed in the hope that it will be useful,
  5748. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5749. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5750. + * GNU General Public License for more details.
  5751. + *
  5752. + * You should have received a copy of the GNU General Public License
  5753. + * along with XBMC; see the file COPYING. If not, see
  5754. + * <http://www.gnu.org/licenses/>.
  5755. + *
  5756. + */
  5757. +
  5758. +#include <stdint.h>
  5759. +#include <vector>
  5760. +#include "utils/StdString.h" // required by GUIFontTTF.h
  5761. +#include "GUIFontTTF.h"
  5762. +#include "GraphicContext.h"
  5763. +
  5764. +template<class Position, class Value>
  5765. +void CGUIFontCacheEntry<Position, Value>::Reassign::operator()(CGUIFontCacheEntry<Position, Value> &entry)
  5766. +{
  5767. + entry.m_key.m_pos = m_key.m_pos;
  5768. + entry.m_key.m_colors.assign(m_key.m_colors.begin(), m_key.m_colors.end());
  5769. + entry.m_key.m_text.assign(m_key.m_text.begin(), m_key.m_text.end());
  5770. + entry.m_key.m_alignment = m_key.m_alignment;
  5771. + entry.m_key.m_maxPixelWidth = m_key.m_maxPixelWidth;
  5772. + entry.m_key.m_scrolling = m_key.m_scrolling;
  5773. + entry.m_matrix = m_key.m_matrix;
  5774. + entry.m_key.m_scaleX = m_key.m_scaleX;
  5775. + entry.m_key.m_scaleY = m_key.m_scaleY;
  5776. +
  5777. + entry.m_lastUsedMillis = m_nowMillis;
  5778. + entry.m_value.clear();
  5779. +}
  5780. +
  5781. +template<class Position, class Value>
  5782. +CGUIFontCacheEntry<Position, Value>::~CGUIFontCacheEntry()
  5783. +{
  5784. + delete &m_key.m_colors;
  5785. + delete &m_key.m_text;
  5786. + m_value.clear();
  5787. +}
  5788. +
  5789. +template<class Position, class Value>
  5790. +Value &CGUIFontCache<Position, Value>::Lookup(Position &pos,
  5791. + const vecColors &colors, const vecText &text,
  5792. + uint32_t alignment, float maxPixelWidth,
  5793. + bool scrolling,
  5794. + unsigned int nowMillis, bool &dirtyCache)
  5795. +{
  5796. + const CGUIFontCacheKey<Position> key(pos,
  5797. + const_cast<vecColors &>(colors), const_cast<vecText &>(text),
  5798. + alignment, maxPixelWidth,
  5799. + scrolling, g_graphicsContext.GetGUIMatrix(),
  5800. + g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY());
  5801. + EntryHashIterator i = m_list.get<Hash>().find(key);
  5802. + if (i == m_list.get<Hash>().end())
  5803. + {
  5804. + /* Cache miss */
  5805. + EntryAgeIterator oldest = m_list.get<Age>().begin();
  5806. + if (!m_list.get<Age>().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT)
  5807. + {
  5808. + /* The oldest existing entry is old enough to expire and reuse */
  5809. + m_list.get<Hash>().modify(m_list.project<Hash>(oldest), typename CGUIFontCacheEntry<Position, Value>::Reassign(key, nowMillis));
  5810. + m_list.get<Age>().relocate(m_list.get<Age>().end(), oldest);
  5811. + }
  5812. + else
  5813. + {
  5814. + /* We need a new entry instead */
  5815. + /* Yes, this causes the creation an destruction of a temporary entry, but
  5816. + * this code ought to only be used infrequently, when the cache needs to grow */
  5817. + m_list.get<Age>().push_back(CGUIFontCacheEntry<Position, Value>(*this, key, nowMillis));
  5818. + }
  5819. + dirtyCache = true;
  5820. + return (--m_list.get<Age>().end())->m_value;
  5821. + }
  5822. + else
  5823. + {
  5824. + /* Cache hit */
  5825. + /* Update time in entry and move to the back of the list */
  5826. + i->m_lastUsedMillis = nowMillis;
  5827. + m_list.get<Age>().relocate(m_list.get<Age>().end(), m_list.project<Age>(i));
  5828. + dirtyCache = false;
  5829. + return i->m_value;
  5830. + }
  5831. +}
  5832. +
  5833. +template<class Position, class Value>
  5834. +void CGUIFontCache<Position, Value>::Flush()
  5835. +{
  5836. + m_list.get<Age>().clear();
  5837. +}
  5838. +
  5839. +template void CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Reassign::operator()(CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue> &entry);
  5840. +template CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::~CGUIFontCacheEntry();
  5841. +template CGUIFontCacheStaticValue &CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
  5842. +template void CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Flush();
  5843. diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
  5844. new file mode 100644
  5845. index 0000000..ef65845
  5846. --- /dev/null
  5847. +++ b/xbmc/guilib/GUIFontCache.h
  5848. @@ -0,0 +1,217 @@
  5849. +/*!
  5850. +\file GUIFontCache.h
  5851. +\brief
  5852. +*/
  5853. +
  5854. +#ifndef CGUILIB_GUIFONTCACHE_H
  5855. +#define CGUILIB_GUIFONTCACHE_H
  5856. +#pragma once
  5857. +
  5858. +/*
  5859. + * Copyright (C) 2005-2013 Team XBMC
  5860. + * http://xbmc.org
  5861. + *
  5862. + * This Program is free software; you can redistribute it and/or modify
  5863. + * it under the terms of the GNU General Public License as published by
  5864. + * the Free Software Foundation; either version 2, or (at your option)
  5865. + * any later version.
  5866. + *
  5867. + * This Program is distributed in the hope that it will be useful,
  5868. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  5869. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  5870. + * GNU General Public License for more details.
  5871. + *
  5872. + * You should have received a copy of the GNU General Public License
  5873. + * along with XBMC; see the file COPYING. If not, see
  5874. + * <http://www.gnu.org/licenses/>.
  5875. + *
  5876. + */
  5877. +
  5878. +#include <cstddef>
  5879. +#include <cstring>
  5880. +#include <stdint.h>
  5881. +
  5882. +#include <algorithm>
  5883. +#include <vector>
  5884. +
  5885. +#include "boost/multi_index_container.hpp"
  5886. +#include "boost/multi_index/sequenced_index.hpp"
  5887. +#include "boost/multi_index/hashed_index.hpp"
  5888. +#include "boost/multi_index/member.hpp"
  5889. +
  5890. +#include "TransformMatrix.h"
  5891. +
  5892. +using namespace boost::multi_index;
  5893. +
  5894. +#define FONT_CACHE_TIME_LIMIT (1000)
  5895. +
  5896. +template<class Position, class Value> class CGUIFontCache;
  5897. +class CGUIFontTTFBase;
  5898. +
  5899. +template<class Position>
  5900. +struct CGUIFontCacheKey
  5901. +{
  5902. + Position m_pos;
  5903. + vecColors &m_colors;
  5904. + vecText &m_text;
  5905. + uint32_t m_alignment;
  5906. + float m_maxPixelWidth;
  5907. + bool m_scrolling;
  5908. + const TransformMatrix &m_matrix;
  5909. + float m_scaleX;
  5910. + float m_scaleY;
  5911. +
  5912. + CGUIFontCacheKey(Position pos,
  5913. + vecColors &colors, vecText &text,
  5914. + uint32_t alignment, float maxPixelWidth,
  5915. + bool scrolling, const TransformMatrix &matrix,
  5916. + float scaleX, float scaleY) :
  5917. + m_pos(pos),
  5918. + m_colors(colors), m_text(text),
  5919. + m_alignment(alignment), m_maxPixelWidth(maxPixelWidth),
  5920. + m_scrolling(scrolling), m_matrix(matrix),
  5921. + m_scaleX(scaleX), m_scaleY(scaleY)
  5922. + {}
  5923. +};
  5924. +
  5925. +template<class Position, class Value>
  5926. +struct CGUIFontCacheEntry
  5927. +{
  5928. + const CGUIFontCache<Position, Value> &m_cache;
  5929. + CGUIFontCacheKey<Position> m_key;
  5930. + TransformMatrix m_matrix;
  5931. +
  5932. + /* These need to be declared as mutable to get round the fact that only
  5933. + * const iterators are available. These fields do not affect comparison or
  5934. + * hash functors, so from the container's point of view, they are mutable. */
  5935. + mutable unsigned int m_lastUsedMillis;
  5936. + mutable Value m_value;
  5937. +
  5938. + CGUIFontCacheEntry(const CGUIFontCache<Position, Value> &cache, const CGUIFontCacheKey<Position> &key, unsigned int nowMillis) :
  5939. + m_cache(cache),
  5940. + m_key(key.m_pos,
  5941. + *new vecColors, *new vecText,
  5942. + key.m_alignment, key.m_maxPixelWidth,
  5943. + key.m_scrolling, m_matrix,
  5944. + key.m_scaleX, key.m_scaleY),
  5945. + m_lastUsedMillis(nowMillis)
  5946. + {
  5947. + m_key.m_colors.assign(key.m_colors.begin(), key.m_colors.end());
  5948. + m_key.m_text.assign(key.m_text.begin(), key.m_text.end());
  5949. + m_matrix = key.m_matrix;
  5950. + }
  5951. +
  5952. + CGUIFontCacheEntry(const CGUIFontCacheEntry &other) :
  5953. + m_cache(other.m_cache),
  5954. + m_key(other.m_key.m_pos,
  5955. + *new vecColors, *new vecText,
  5956. + other.m_key.m_alignment, other.m_key.m_maxPixelWidth,
  5957. + other.m_key.m_scrolling, m_matrix,
  5958. + other.m_key.m_scaleX, other.m_key.m_scaleY),
  5959. + m_lastUsedMillis(other.m_lastUsedMillis),
  5960. + m_value(other.m_value)
  5961. + {
  5962. + m_key.m_colors.assign(other.m_key.m_colors.begin(), other.m_key.m_colors.end());
  5963. + m_key.m_text.assign(other.m_key.m_text.begin(), other.m_key.m_text.end());
  5964. + m_matrix = other.m_key.m_matrix;
  5965. + }
  5966. +
  5967. + struct Reassign
  5968. + {
  5969. + Reassign(const CGUIFontCacheKey<Position> &key, unsigned int nowMillis) : m_key(key), m_nowMillis(nowMillis) {}
  5970. + void operator()(CGUIFontCacheEntry &entry);
  5971. + private:
  5972. + const CGUIFontCacheKey<Position> &m_key;
  5973. + unsigned int m_nowMillis;
  5974. + };
  5975. +
  5976. + ~CGUIFontCacheEntry();
  5977. +};
  5978. +
  5979. +template<class Position>
  5980. +struct CGUIFontCacheHash
  5981. +{
  5982. + size_t operator()(const CGUIFontCacheKey<Position> &key) const
  5983. + {
  5984. + /* Not much effort has gone into choosing this hash function */
  5985. + size_t hash = 0, i;
  5986. + for (i = 0; i < 3 && i < key.m_text.size(); ++i)
  5987. + hash += key.m_text[i];
  5988. + if (key.m_colors.size())
  5989. + hash += key.m_colors[0];
  5990. + hash += MatrixHashContribution(key);
  5991. + return hash;
  5992. + }
  5993. +};
  5994. +
  5995. +template<class Position>
  5996. +struct CGUIFontCacheKeysMatch
  5997. +{
  5998. + bool operator()(const CGUIFontCacheKey<Position> &a, const CGUIFontCacheKey<Position> &b) const
  5999. + {
  6000. + return a.m_text == b.m_text &&
  6001. + a.m_colors == b.m_colors &&
  6002. + a.m_alignment == b.m_alignment &&
  6003. + a.m_scrolling == b.m_scrolling &&
  6004. + a.m_maxPixelWidth == b.m_maxPixelWidth &&
  6005. + Match(a.m_pos, a.m_matrix, b.m_pos, b.m_matrix, a.m_scrolling) &&
  6006. + a.m_scaleX == b.m_scaleX &&
  6007. + a.m_scaleY == b.m_scaleY;
  6008. + }
  6009. +};
  6010. +
  6011. +template<class Position, class Value>
  6012. +class CGUIFontCache
  6013. +{
  6014. + /* Empty structs used as tags to identify indexes */
  6015. + struct Age {};
  6016. + struct Hash {};
  6017. +
  6018. + typedef multi_index_container<
  6019. + CGUIFontCacheEntry<Position, Value>,
  6020. + indexed_by<
  6021. + sequenced<tag<Age> >,
  6022. + hashed_unique<tag<Hash>, member<CGUIFontCacheEntry<Position, Value>, CGUIFontCacheKey<Position>, &CGUIFontCacheEntry<Position, Value>::m_key>, CGUIFontCacheHash<Position>, CGUIFontCacheKeysMatch<Position> >
  6023. + >
  6024. + > EntryList;
  6025. +
  6026. + typedef typename EntryList::template index<Age>::type::iterator EntryAgeIterator;
  6027. + typedef typename EntryList::template index<Hash>::type::iterator EntryHashIterator;
  6028. +
  6029. + EntryList m_list;
  6030. +
  6031. +public:
  6032. + const CGUIFontTTFBase &m_font;
  6033. +
  6034. + CGUIFontCache(CGUIFontTTFBase &font) : m_font(font) {}
  6035. + Value &Lookup(Position &pos,
  6036. + const vecColors &colors, const vecText &text,
  6037. + uint32_t alignment, float maxPixelWidth,
  6038. + bool scrolling,
  6039. + unsigned int nowMillis, bool &dirtyCache);
  6040. + void Flush();
  6041. +};
  6042. +
  6043. +struct CGUIFontCacheStaticPosition
  6044. +{
  6045. + float m_x;
  6046. + float m_y;
  6047. + CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {}
  6048. +};
  6049. +
  6050. +typedef std::vector<SVertex> CGUIFontCacheStaticValue;
  6051. +
  6052. +inline bool Match(const CGUIFontCacheStaticPosition &a, const TransformMatrix &a_m,
  6053. + const CGUIFontCacheStaticPosition &b, const TransformMatrix &b_m,
  6054. + bool scrolling)
  6055. +{
  6056. + return a.m_x == b.m_x && a.m_y == b.m_y && a_m == b_m;
  6057. +}
  6058. +
  6059. +inline float MatrixHashContribution(const CGUIFontCacheKey<CGUIFontCacheStaticPosition> &a)
  6060. +{
  6061. + /* Ensure horizontally translated versions end up in different buckets */
  6062. + return a.m_matrix.m[0][3];
  6063. +}
  6064. +
  6065. +#endif
  6066. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  6067. index 1aaf68b..288e61a 100644
  6068. --- a/xbmc/guilib/GUIFontTTF.cpp
  6069. +++ b/xbmc/guilib/GUIFontTTF.cpp
  6070. @@ -27,6 +27,7 @@
  6071. #include "utils/MathUtils.h"
  6072. #include "utils/log.h"
  6073. #include "windowing/WindowingFactory.h"
  6074. +#include "threads/SystemClock.h"
  6075. #include <math.h>
  6076. @@ -131,7 +132,7 @@ class CFreeTypeLibrary
  6077. XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library
  6078. #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary)
  6079. -CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName)
  6080. +CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this)
  6081. {
  6082. m_texture = NULL;
  6083. m_char = NULL;
  6084. @@ -330,108 +331,120 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  6085. {
  6086. Begin();
  6087. - std::vector<SVertex> &vertices = m_vertex;
  6088. -
  6089. - // save the origin, which is scaled separately
  6090. - m_originX = x;
  6091. - m_originY = y;
  6092. -
  6093. - // Check if we will really need to truncate or justify the text
  6094. - if ( alignment & XBFONT_TRUNCATED )
  6095. + bool dirtyCache;
  6096. + CGUIFontCacheStaticPosition staticPos(x, y);
  6097. + std::vector<SVertex> &vertices = m_staticCache.Lookup(staticPos,
  6098. + colors, text,
  6099. + alignment, maxPixelWidth,
  6100. + scrolling,
  6101. + XbmcThreads::SystemClockMillis(),
  6102. + dirtyCache);
  6103. + if (dirtyCache)
  6104. {
  6105. - if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
  6106. - alignment &= ~XBFONT_TRUNCATED;
  6107. - }
  6108. - else if ( alignment & XBFONT_JUSTIFIED )
  6109. - {
  6110. - if ( maxPixelWidth <= 0.0f )
  6111. - alignment &= ~XBFONT_JUSTIFIED;
  6112. - }
  6113. + // save the origin, which is scaled separately
  6114. + m_originX = x;
  6115. + m_originY = y;
  6116. - // calculate sizing information
  6117. - float startX = 0;
  6118. - float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering
  6119. + // Check if we will really need to truncate or justify the text
  6120. + if ( alignment & XBFONT_TRUNCATED )
  6121. + {
  6122. + if ( maxPixelWidth <= 0.0f || GetTextWidthInternal(text.begin(), text.end()) <= maxPixelWidth)
  6123. + alignment &= ~XBFONT_TRUNCATED;
  6124. + }
  6125. + else if ( alignment & XBFONT_JUSTIFIED )
  6126. + {
  6127. + if ( maxPixelWidth <= 0.0f )
  6128. + alignment &= ~XBFONT_JUSTIFIED;
  6129. + }
  6130. - if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
  6131. - {
  6132. - // Get the extent of this line
  6133. - float w = GetTextWidthInternal( text.begin(), text.end() );
  6134. + // calculate sizing information
  6135. + float startX = 0;
  6136. + float startY = (alignment & XBFONT_CENTER_Y) ? -0.5f*m_cellHeight : 0; // vertical centering
  6137. - if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
  6138. - w = maxPixelWidth;
  6139. + if ( alignment & (XBFONT_RIGHT | XBFONT_CENTER_X) )
  6140. + {
  6141. + // Get the extent of this line
  6142. + float w = GetTextWidthInternal( text.begin(), text.end() );
  6143. - if ( alignment & XBFONT_CENTER_X)
  6144. - w *= 0.5f;
  6145. - // Offset this line's starting position
  6146. - startX -= w;
  6147. - }
  6148. + if ( alignment & XBFONT_TRUNCATED && w > maxPixelWidth + 0.5f ) // + 0.5f due to rounding issues
  6149. + w = maxPixelWidth;
  6150. - float spacePerLetter = 0; // for justification effects
  6151. - if ( alignment & XBFONT_JUSTIFIED )
  6152. - {
  6153. - // first compute the size of the text to render in both characters and pixels
  6154. - unsigned int lineChars = 0;
  6155. - float linePixels = 0;
  6156. - for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
  6157. + if ( alignment & XBFONT_CENTER_X)
  6158. + w *= 0.5f;
  6159. + // Offset this line's starting position
  6160. + startX -= w;
  6161. + }
  6162. +
  6163. + float spacePerLetter = 0; // for justification effects
  6164. + if ( alignment & XBFONT_JUSTIFIED )
  6165. {
  6166. - Character *ch = GetCharacter(*pos);
  6167. - if (ch)
  6168. - { // spaces have multiple times the justification spacing of normal letters
  6169. - lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
  6170. - linePixels += ch->advance;
  6171. + // first compute the size of the text to render in both characters and pixels
  6172. + unsigned int lineChars = 0;
  6173. + float linePixels = 0;
  6174. + for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
  6175. + {
  6176. + Character *ch = GetCharacter(*pos);
  6177. + if (ch)
  6178. + { // spaces have multiple times the justification spacing of normal letters
  6179. + lineChars += ((*pos & 0xffff) == L' ') ? justification_word_weight : 1;
  6180. + linePixels += ch->advance;
  6181. + }
  6182. }
  6183. + if (lineChars > 1)
  6184. + spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
  6185. }
  6186. - if (lineChars > 1)
  6187. - spacePerLetter = (maxPixelWidth - linePixels) / (lineChars - 1);
  6188. - }
  6189. - float cursorX = 0; // current position along the line
  6190. -
  6191. - for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
  6192. - {
  6193. - // If starting text on a new line, determine justification effects
  6194. - // Get the current letter in the CStdString
  6195. - color_t color = (*pos & 0xff0000) >> 16;
  6196. - if (color >= colors.size())
  6197. - color = 0;
  6198. - color = colors[color];
  6199. + float cursorX = 0; // current position along the line
  6200. - // grab the next character
  6201. - Character *ch = GetCharacter(*pos);
  6202. - if (!ch) continue;
  6203. -
  6204. - if ( alignment & XBFONT_TRUNCATED )
  6205. + for (vecText::const_iterator pos = text.begin(); pos != text.end(); ++pos)
  6206. {
  6207. - // Check if we will be exceeded the max allowed width
  6208. - if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
  6209. - {
  6210. - // Yup. Let's draw the ellipses, then bail
  6211. - // Perhaps we should really bail to the next line in this case??
  6212. - Character *period = GetCharacter(L'.');
  6213. - if (!period)
  6214. - break;
  6215. + // If starting text on a new line, determine justification effects
  6216. + // Get the current letter in the CStdString
  6217. + color_t color = (*pos & 0xff0000) >> 16;
  6218. + if (color >= colors.size())
  6219. + color = 0;
  6220. + color = colors[color];
  6221. +
  6222. + // grab the next character
  6223. + Character *ch = GetCharacter(*pos);
  6224. + if (!ch) continue;
  6225. - for (int i = 0; i < 3; i++)
  6226. + if ( alignment & XBFONT_TRUNCATED )
  6227. + {
  6228. + // Check if we will be exceeded the max allowed width
  6229. + if ( cursorX + ch->advance + 3 * m_ellipsesWidth > maxPixelWidth )
  6230. {
  6231. - RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
  6232. - cursorX += period->advance;
  6233. + // Yup. Let's draw the ellipses, then bail
  6234. + // Perhaps we should really bail to the next line in this case??
  6235. + Character *period = GetCharacter(L'.');
  6236. + if (!period)
  6237. + break;
  6238. +
  6239. + for (int i = 0; i < 3; i++)
  6240. + {
  6241. + RenderCharacter(startX + cursorX, startY, period, color, !scrolling, vertices);
  6242. + cursorX += period->advance;
  6243. + }
  6244. + break;
  6245. }
  6246. - break;
  6247. }
  6248. - }
  6249. - else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
  6250. - break; // exceeded max allowed width - stop rendering
  6251. + else if (maxPixelWidth > 0 && cursorX > maxPixelWidth)
  6252. + break; // exceeded max allowed width - stop rendering
  6253. - RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
  6254. - if ( alignment & XBFONT_JUSTIFIED )
  6255. - {
  6256. - if ((*pos & 0xffff) == L' ')
  6257. - cursorX += ch->advance + spacePerLetter * justification_word_weight;
  6258. + RenderCharacter(startX + cursorX, startY, ch, color, !scrolling, vertices);
  6259. + if ( alignment & XBFONT_JUSTIFIED )
  6260. + {
  6261. + if ((*pos & 0xffff) == L' ')
  6262. + cursorX += ch->advance + spacePerLetter * justification_word_weight;
  6263. + else
  6264. + cursorX += ch->advance + spacePerLetter;
  6265. + }
  6266. else
  6267. - cursorX += ch->advance + spacePerLetter;
  6268. + cursorX += ch->advance;
  6269. }
  6270. - else
  6271. - cursorX += ch->advance;
  6272. }
  6273. + /* Append the new vertices (from the cache or otherwise) to the set collected
  6274. + * since the first Begin() call */
  6275. + m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  6276. End();
  6277. }
  6278. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  6279. index 4a6a696..7cb4669 100644
  6280. --- a/xbmc/guilib/GUIFontTTF.h
  6281. +++ b/xbmc/guilib/GUIFontTTF.h
  6282. @@ -64,6 +64,9 @@ struct SVertex
  6283. };
  6284. +#include "GUIFontCache.h"
  6285. +
  6286. +
  6287. class CGUIFontTTFBase
  6288. {
  6289. friend class CGUIFont;
  6290. @@ -166,6 +169,8 @@ class CGUIFontTTFBase
  6291. CStdString m_strFileName;
  6292. + CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue> m_staticCache;
  6293. +
  6294. private:
  6295. virtual bool FirstBegin() = 0;
  6296. virtual void LastEnd() = 0;
  6297. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  6298. index a4e8571..cb56987 100644
  6299. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  6300. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  6301. @@ -200,6 +200,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
  6302. m_textureScaleX = 1.0f / m_textureWidth;
  6303. if (m_textureHeight < newHeight)
  6304. CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight);
  6305. + m_staticCache.Flush();
  6306. memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch());
  6307. if (m_texture)
  6308. diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
  6309. index 6c2dcd4..bab2457 100644
  6310. --- a/xbmc/guilib/GraphicContext.h
  6311. +++ b/xbmc/guilib/GraphicContext.h
  6312. @@ -146,6 +146,7 @@ class CGraphicContext : public CCriticalSection,
  6313. inline void ScaleFinalCoords(float &x, float &y, float &z) const XBMC_FORCE_INLINE { m_finalTransform.matrix.TransformPosition(x, y, z); }
  6314. bool RectIsAngled(float x1, float y1, float x2, float y2) const;
  6315. + inline const TransformMatrix &GetGUIMatrix() const XBMC_FORCE_INLINE { return m_finalTransform.matrix; }
  6316. inline float GetGUIScaleX() const XBMC_FORCE_INLINE { return m_finalTransform.scaleX; }
  6317. inline float GetGUIScaleY() const XBMC_FORCE_INLINE { return m_finalTransform.scaleY; }
  6318. inline color_t MergeAlpha(color_t color) const XBMC_FORCE_INLINE
  6319. diff --git a/xbmc/guilib/Makefile.in b/xbmc/guilib/Makefile.in
  6320. index 086fb0d..af82979 100644
  6321. --- a/xbmc/guilib/Makefile.in
  6322. +++ b/xbmc/guilib/Makefile.in
  6323. @@ -23,6 +23,7 @@ SRCS += GUIEditControl.cpp
  6324. SRCS += GUIFadeLabelControl.cpp
  6325. SRCS += GUIFixedListContainer.cpp
  6326. SRCS += GUIFont.cpp
  6327. +SRCS += GUIFontCache.cpp
  6328. SRCS += GUIFontManager.cpp
  6329. SRCS += GUIFontTTF.cpp
  6330. SRCS += GUIImage.cpp
  6331. diff --git a/xbmc/guilib/TransformMatrix.h b/xbmc/guilib/TransformMatrix.h
  6332. index f351c99..9036ba9 100644
  6333. --- a/xbmc/guilib/TransformMatrix.h
  6334. +++ b/xbmc/guilib/TransformMatrix.h
  6335. @@ -245,3 +245,14 @@ class TransformMatrix
  6336. float alpha;
  6337. bool identity;
  6338. };
  6339. +
  6340. +inline bool operator==(const TransformMatrix &a, const TransformMatrix &b)
  6341. +{
  6342. + return a.alpha == b.alpha && ((a.identity && b.identity) ||
  6343. + (!a.identity && !b.identity && std::equal(&a.m[0][0], &a.m[0][0] + sizeof a.m / sizeof a.m[0][0], &b.m[0][0])));
  6344. +}
  6345. +
  6346. +inline bool operator!=(const TransformMatrix &a, const TransformMatrix &b)
  6347. +{
  6348. + return !operator==(a, b);
  6349. +}
  6350. --
  6351. 1.9.3
  6352. From 65d2b7f112b400f75140de44579e6cdf98378b67 Mon Sep 17 00:00:00 2001
  6353. From: Ben Avison <bavison@riscosopen.org>
  6354. Date: Thu, 23 Jan 2014 22:24:17 +0000
  6355. Subject: [PATCH 23/94] Lay the groundwork for hardware clipping.
  6356. For glScissor() to replace CGraphicContext::ClipRect, a necessary condition
  6357. is that no shear or rotation is introduced between the coordinate systems
  6358. they use; this depends upon the settings of the GUI matrix m_finalTransform
  6359. as well as the OpenGL model-view and projection matrices. These all remain
  6360. unchanged between paired calls of CGUIShader::OnEnabled and
  6361. CGUIShader::OnDisabled, so we scan the matrices in CGUIShader::OnEnabled to
  6362. see whether hardware clipping is possible.
  6363. Then, in CGUIFontTTFBase::RenderCharacter, we don't apply software clipping
  6364. in such cases. However, because vertices arising from multiple
  6365. CGUIFontTTFBase::DrawTextInternal calls (each of which often uses a different
  6366. clip rectangle) get lumped into the same vector, which only at the end is
  6367. passed to OpenGL for rendering, we need to wait a few commits before we can
  6368. actually apply hardware clipping. In the meantime, expect to see rendering
  6369. errors.
  6370. ---
  6371. xbmc/guilib/GUIFontTTF.cpp | 3 +-
  6372. xbmc/guilib/GUIShader.cpp | 80 +++++++++++++++++++++++++++++++-
  6373. xbmc/guilib/GUIShader.h | 11 +++++
  6374. xbmc/guilib/GraphicContext.cpp | 10 ++++
  6375. xbmc/guilib/GraphicContext.h | 1 +
  6376. xbmc/rendering/RenderSystem.h | 2 +
  6377. xbmc/rendering/gles/RenderSystemGLES.cpp | 22 +++++++++
  6378. xbmc/rendering/gles/RenderSystemGLES.h | 2 +
  6379. 8 files changed, 128 insertions(+), 3 deletions(-)
  6380. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  6381. index 288e61a..19c7ff4 100644
  6382. --- a/xbmc/guilib/GUIFontTTF.cpp
  6383. +++ b/xbmc/guilib/GUIFontTTF.cpp
  6384. @@ -710,7 +710,8 @@ void CGUIFontTTFBase::RenderCharacter(float posX, float posY, const Character *c
  6385. (posY + ch->offsetY + height) * g_graphicsContext.GetGUIScaleY());
  6386. vertex += CPoint(m_originX, m_originY);
  6387. CRect texture(ch->left, ch->top, ch->right, ch->bottom);
  6388. - g_graphicsContext.ClipRect(vertex, texture);
  6389. + if (!g_Windowing.ScissorsCanEffectClipping())
  6390. + g_graphicsContext.ClipRect(vertex, texture);
  6391. // transform our positions - note, no scaling due to GUI calibration/resolution occurs
  6392. float x[4], y[4], z[4];
  6393. diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp
  6394. index 11089b8..53bce09 100644
  6395. --- a/xbmc/guilib/GUIShader.cpp
  6396. +++ b/xbmc/guilib/GUIShader.cpp
  6397. @@ -26,6 +26,8 @@
  6398. #include "GUIShader.h"
  6399. #include "MatrixGLES.h"
  6400. #include "utils/log.h"
  6401. +#include "windowing/egl/WinSystemEGL.h"
  6402. +#include "guilib/GraphicContext.h"
  6403. CGUIShader::CGUIShader( const char *shader ) : CGLSLShaderProgram("guishader_vert.glsl", shader)
  6404. {
  6405. @@ -86,8 +88,82 @@ bool CGUIShader::OnEnabled()
  6406. {
  6407. // This is called after glUseProgram()
  6408. - glUniformMatrix4fv(m_hProj, 1, GL_FALSE, g_matrices.GetMatrix(MM_PROJECTION));
  6409. - glUniformMatrix4fv(m_hModel, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  6410. + GLfloat *projMatrix = g_matrices.GetMatrix(MM_PROJECTION);
  6411. + GLfloat *modelMatrix = g_matrices.GetMatrix(MM_MODELVIEW);
  6412. + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, projMatrix);
  6413. + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, modelMatrix);
  6414. +
  6415. + const TransformMatrix &guiMatrix = g_graphicsContext.GetGUIMatrix();
  6416. + CRect viewPort; // absolute positions of corners
  6417. + g_Windowing.GetViewPort(viewPort);
  6418. +
  6419. + /* glScissor operates in window coordinates. In order that we can use it to
  6420. + * perform clipping, we must ensure that there is an independent linear
  6421. + * transformation from the coordinate system used by CGraphicContext::ClipRect
  6422. + * to window coordinates, separately for X and Y (in other words, no
  6423. + * rotation or shear is introduced at any stage). To do, this, we need to
  6424. + * check that zeros are present in the following locations:
  6425. + *
  6426. + * GUI matrix:
  6427. + * / * 0 * * \
  6428. + * | 0 * * * |
  6429. + * \ 0 0 * * /
  6430. + * ^ TransformMatrix::TransformX/Y/ZCoord are only ever called with
  6431. + * input z = 0, so this column doesn't matter
  6432. + * Model-view matrix:
  6433. + * / * 0 0 * \
  6434. + * | 0 * 0 * |
  6435. + * | 0 0 * * |
  6436. + * \ * * * * / <- eye w has no influence on window x/y (last column below
  6437. + * is either 0 or ignored)
  6438. + * Projection matrix:
  6439. + * / * 0 0 0 \
  6440. + * | 0 * 0 0 |
  6441. + * | * * * * | <- normalised device coordinate z has no influence on window x/y
  6442. + * \ 0 0 * 0 /
  6443. + *
  6444. + * Some of these zeros are not strictly required to ensure this, but they tend
  6445. + * to be zeroed in the common case, so by checking for zeros here, we simplify
  6446. + * the calculation of the window x/y coordinates further down the line.
  6447. + *
  6448. + * (Minor detail: we don't quite deal in window coordinates as defined by
  6449. + * OpenGL, because CRenderSystemGLES::SetScissors flips the Y axis. But all
  6450. + * that's needed to handle that is an effective negation at the stage where
  6451. + * Y is in normalised device coordinates.)
  6452. + */
  6453. + m_clipPossible = guiMatrix.m[0][1] == 0 &&
  6454. + guiMatrix.m[1][0] == 0 &&
  6455. + guiMatrix.m[2][0] == 0 &&
  6456. + guiMatrix.m[2][1] == 0 &&
  6457. + modelMatrix[0+1*4] == 0 &&
  6458. + modelMatrix[0+2*4] == 0 &&
  6459. + modelMatrix[1+0*4] == 0 &&
  6460. + modelMatrix[1+2*4] == 0 &&
  6461. + modelMatrix[2+0*4] == 0 &&
  6462. + modelMatrix[2+1*4] == 0 &&
  6463. + projMatrix[0+1*4] == 0 &&
  6464. + projMatrix[0+2*4] == 0 &&
  6465. + projMatrix[0+3*4] == 0 &&
  6466. + projMatrix[1+0*4] == 0 &&
  6467. + projMatrix[1+2*4] == 0 &&
  6468. + projMatrix[1+3*4] == 0 &&
  6469. + projMatrix[3+0*4] == 0 &&
  6470. + projMatrix[3+1*4] == 0 &&
  6471. + projMatrix[3+3*4] == 0;
  6472. + if (m_clipPossible)
  6473. + {
  6474. + m_clipXFactor = guiMatrix.m[0][0] * modelMatrix[0+0*4] * projMatrix[0+0*4];
  6475. + m_clipXOffset = (guiMatrix.m[0][3] * modelMatrix[0+0*4] + modelMatrix[0+3*4]) * projMatrix[0+0*4];
  6476. + m_clipYFactor = guiMatrix.m[1][1] * modelMatrix[1+1*4] * projMatrix[1+1*4];
  6477. + m_clipYOffset = (guiMatrix.m[1][3] * modelMatrix[1+1*4] + modelMatrix[1+3*4]) * projMatrix[1+1*4];
  6478. + float clipW = (guiMatrix.m[2][3] * modelMatrix[2+2*4] + modelMatrix[2+3*4]) * projMatrix[3+2*4];
  6479. + float xMult = (viewPort.x2 - viewPort.x1) / (2 * clipW);
  6480. + float yMult = (viewPort.y1 - viewPort.y2) / (2 * clipW); // correct for inverted window coordinate scheme
  6481. + m_clipXFactor = m_clipXFactor * xMult;
  6482. + m_clipXOffset = m_clipXOffset * xMult + (viewPort.x2 + viewPort.x1) / 2;
  6483. + m_clipYFactor = m_clipYFactor * yMult;
  6484. + m_clipYOffset = m_clipYOffset * yMult + (viewPort.y2 + viewPort.y1) / 2;
  6485. + }
  6486. return true;
  6487. }
  6488. diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h
  6489. index c7e95aa..86ce4cc 100644
  6490. --- a/xbmc/guilib/GUIShader.h
  6491. +++ b/xbmc/guilib/GUIShader.h
  6492. @@ -41,6 +41,11 @@ class CGUIShader : public CGLSLShaderProgram
  6493. GLint GetCord1Loc() { return m_hCord1; }
  6494. GLint GetUniColLoc() { return m_hUniCol; }
  6495. GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; }
  6496. + bool HardwareClipIsPossible() { return m_clipPossible; }
  6497. + GLfloat GetClipXFactor() { return m_clipXFactor; }
  6498. + GLfloat GetClipXOffset() { return m_clipXOffset; }
  6499. + GLfloat GetClipYFactor() { return m_clipYFactor; }
  6500. + GLfloat GetClipYOffset() { return m_clipYOffset; }
  6501. protected:
  6502. GLint m_hTex0;
  6503. @@ -56,6 +61,12 @@ class CGUIShader : public CGLSLShaderProgram
  6504. GLfloat *m_proj;
  6505. GLfloat *m_model;
  6506. +
  6507. + bool m_clipPossible;
  6508. + GLfloat m_clipXFactor;
  6509. + GLfloat m_clipXOffset;
  6510. + GLfloat m_clipYFactor;
  6511. + GLfloat m_clipYOffset;
  6512. };
  6513. #endif // GUI_SHADER_H
  6514. diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
  6515. index 38f17a7..5bffdf5 100644
  6516. --- a/xbmc/guilib/GraphicContext.cpp
  6517. +++ b/xbmc/guilib/GraphicContext.cpp
  6518. @@ -167,6 +167,16 @@ void CGraphicContext::ClipRect(CRect &vertex, CRect &texture, CRect *texture2)
  6519. }
  6520. }
  6521. +CRect CGraphicContext::GetClipRegion()
  6522. +{
  6523. + if (m_clipRegions.empty())
  6524. + return CRect(0, 0, m_iScreenWidth, m_iScreenHeight);
  6525. + CRect clipRegion(m_clipRegions.top());
  6526. + if (!m_origins.empty())
  6527. + clipRegion -= m_origins.top();
  6528. + return clipRegion;
  6529. +}
  6530. +
  6531. bool CGraphicContext::SetViewPort(float fx, float fy, float fwidth, float fheight, bool intersectPrevious /* = false */)
  6532. {
  6533. // transform coordinates - we may have a rotation which changes the positioning of the
  6534. diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
  6535. index bab2457..0a27643 100644
  6536. --- a/xbmc/guilib/GraphicContext.h
  6537. +++ b/xbmc/guilib/GraphicContext.h
  6538. @@ -199,6 +199,7 @@ class CGraphicContext : public CCriticalSection,
  6539. void ApplyHardwareTransform();
  6540. void RestoreHardwareTransform();
  6541. void ClipRect(CRect &vertex, CRect &texture, CRect *diffuse = NULL);
  6542. + CRect GetClipRegion();
  6543. inline void AddGUITransform()
  6544. {
  6545. m_transforms.push(m_finalTransform);
  6546. diff --git a/xbmc/rendering/RenderSystem.h b/xbmc/rendering/RenderSystem.h
  6547. index fa64eba..c1dfb93 100644
  6548. --- a/xbmc/rendering/RenderSystem.h
  6549. +++ b/xbmc/rendering/RenderSystem.h
  6550. @@ -110,6 +110,8 @@ class CRenderSystemBase
  6551. virtual void GetViewPort(CRect& viewPort) = 0;
  6552. virtual void RestoreViewPort() {};
  6553. + virtual bool ScissorsCanEffectClipping() { return false; }
  6554. + virtual CRect ClipRectToScissorRect(const CRect &rect) { return CRect(); }
  6555. virtual void SetScissors(const CRect &rect) = 0;
  6556. virtual void ResetScissors() = 0;
  6557. diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp
  6558. index 653c9ec..deb3afc 100644
  6559. --- a/xbmc/rendering/gles/RenderSystemGLES.cpp
  6560. +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp
  6561. @@ -533,6 +533,28 @@ void CRenderSystemGLES::SetViewPort(CRect& viewPort)
  6562. m_viewPort[3] = viewPort.Height();
  6563. }
  6564. +bool CRenderSystemGLES::ScissorsCanEffectClipping()
  6565. +{
  6566. + if (m_pGUIshader[m_method])
  6567. + return m_pGUIshader[m_method]->HardwareClipIsPossible();
  6568. +
  6569. + return false;
  6570. +}
  6571. +
  6572. +CRect CRenderSystemGLES::ClipRectToScissorRect(const CRect &rect)
  6573. +{
  6574. + if (!m_pGUIshader[m_method])
  6575. + return CRect();
  6576. + float xFactor = m_pGUIshader[m_method]->GetClipXFactor();
  6577. + float xOffset = m_pGUIshader[m_method]->GetClipXOffset();
  6578. + float yFactor = m_pGUIshader[m_method]->GetClipYFactor();
  6579. + float yOffset = m_pGUIshader[m_method]->GetClipYOffset();
  6580. + return CRect(rect.x1 * xFactor + xOffset,
  6581. + rect.y1 * yFactor + yOffset,
  6582. + rect.x2 * xFactor + xOffset,
  6583. + rect.y2 * yFactor + yOffset);
  6584. +}
  6585. +
  6586. void CRenderSystemGLES::SetScissors(const CRect &rect)
  6587. {
  6588. if (!m_bRenderCreated)
  6589. diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h
  6590. index 98e398a..81ee49e 100644
  6591. --- a/xbmc/rendering/gles/RenderSystemGLES.h
  6592. +++ b/xbmc/rendering/gles/RenderSystemGLES.h
  6593. @@ -63,6 +63,8 @@ class CRenderSystemGLES : public CRenderSystemBase
  6594. virtual void SetViewPort(CRect& viewPort);
  6595. virtual void GetViewPort(CRect& viewPort);
  6596. + virtual bool ScissorsCanEffectClipping();
  6597. + virtual CRect ClipRectToScissorRect(const CRect &rect);
  6598. virtual void SetScissors(const CRect& rect);
  6599. virtual void ResetScissors();
  6600. --
  6601. 1.9.3
  6602. From e372121bc53da1b0353b51f5e9897011c5f54033 Mon Sep 17 00:00:00 2001
  6603. From: Ben Avison <bavison@riscosopen.org>
  6604. Date: Thu, 23 Jan 2014 16:42:22 +0000
  6605. Subject: [PATCH 24/94] Increase font cache hit rate by keying on the
  6606. fractional part of m_originX and m_originY *after* they have been through the
  6607. graphics context's transformation matrix, plus the scale/rotation elements of
  6608. the matrix, rather than the origin in the original frame of reference plus
  6609. the complete transformation matrix. All vertices of individual glyph bounding
  6610. boxes are a constant offset from this position, and when the fractional part
  6611. of the translation is a match, the rounding of each vertex will be in the
  6612. same direction; this permits us to calculate the desired vertices from the
  6613. cached ones simply by adding the integer parts of the translations with no
  6614. additional rounding steps.
  6615. Note that this requires that software clipping is *not* performed.
  6616. ---
  6617. xbmc/guilib/GUIFontCache.cpp | 8 +++++++
  6618. xbmc/guilib/GUIFontCache.h | 43 +++++++++++++++++++++++++++++++++++
  6619. xbmc/guilib/GUIFontTTF.cpp | 53 +++++++++++++++++++++++++++++++++++---------
  6620. xbmc/guilib/GUIFontTTF.h | 1 +
  6621. 4 files changed, 95 insertions(+), 10 deletions(-)
  6622. diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
  6623. index c029713..b66c00b 100644
  6624. --- a/xbmc/guilib/GUIFontCache.cpp
  6625. +++ b/xbmc/guilib/GUIFontCache.cpp
  6626. @@ -85,6 +85,9 @@ Value &CGUIFontCache<Position, Value>::Lookup(Position &pos,
  6627. else
  6628. {
  6629. /* Cache hit */
  6630. + /* Update the translation arguments so that they hold the offset to apply
  6631. + * to the cached values (but only in the dynamic case) */
  6632. + pos.UpdateWithOffsets(i->m_key.m_pos, scrolling);
  6633. /* Update time in entry and move to the back of the list */
  6634. i->m_lastUsedMillis = nowMillis;
  6635. m_list.get<Age>().relocate(m_list.get<Age>().end(), m_list.project<Age>(i));
  6636. @@ -103,3 +106,8 @@ template void CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStati
  6637. template CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::~CGUIFontCacheEntry();
  6638. template CGUIFontCacheStaticValue &CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Lookup(CGUIFontCacheStaticPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
  6639. template void CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Flush();
  6640. +
  6641. +template void CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Reassign::operator()(CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue> &entry);
  6642. +template CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::~CGUIFontCacheEntry();
  6643. +template CGUIFontCacheDynamicValue &CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
  6644. +template void CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Flush();
  6645. diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
  6646. index ef65845..d913dee 100644
  6647. --- a/xbmc/guilib/GUIFontCache.h
  6648. +++ b/xbmc/guilib/GUIFontCache.h
  6649. @@ -44,6 +44,7 @@
  6650. using namespace boost::multi_index;
  6651. #define FONT_CACHE_TIME_LIMIT (1000)
  6652. +#define FONT_CACHE_DIST_LIMIT (0.01)
  6653. template<class Position, class Value> class CGUIFontCache;
  6654. class CGUIFontTTFBase;
  6655. @@ -197,6 +198,7 @@ struct CGUIFontCacheStaticPosition
  6656. float m_x;
  6657. float m_y;
  6658. CGUIFontCacheStaticPosition(float x, float y) : m_x(x), m_y(y) {}
  6659. + void UpdateWithOffsets(const CGUIFontCacheStaticPosition &cached, bool scrolling) {}
  6660. };
  6661. typedef std::vector<SVertex> CGUIFontCacheStaticValue;
  6662. @@ -214,4 +216,45 @@ inline float MatrixHashContribution(const CGUIFontCacheKey<CGUIFontCacheStaticPo
  6663. return a.m_matrix.m[0][3];
  6664. }
  6665. +struct CGUIFontCacheDynamicPosition
  6666. +{
  6667. + float m_x;
  6668. + float m_y;
  6669. + float m_z;
  6670. + CGUIFontCacheDynamicPosition() {}
  6671. + CGUIFontCacheDynamicPosition(float x, float y, float z) : m_x(x), m_y(y), m_z(z) {}
  6672. + void UpdateWithOffsets(const CGUIFontCacheDynamicPosition &cached, bool scrolling)
  6673. + {
  6674. + if (scrolling)
  6675. + m_x = m_x - cached.m_x;
  6676. + else
  6677. + m_x = floorf(m_x - cached.m_x + FONT_CACHE_DIST_LIMIT);
  6678. + m_y = floorf(m_y - cached.m_y + FONT_CACHE_DIST_LIMIT);
  6679. + m_z = floorf(m_z - cached.m_z + FONT_CACHE_DIST_LIMIT);
  6680. + }
  6681. +};
  6682. +
  6683. +typedef std::vector<SVertex> CGUIFontCacheDynamicValue;
  6684. +
  6685. +inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m,
  6686. + const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m,
  6687. + bool scrolling)
  6688. +{
  6689. + float diffX = a.m_x - b.m_x + FONT_CACHE_DIST_LIMIT;
  6690. + float diffY = a.m_y - b.m_y + FONT_CACHE_DIST_LIMIT;
  6691. + float diffZ = a.m_z - b.m_z + FONT_CACHE_DIST_LIMIT;
  6692. + return (scrolling || diffX - floorf(diffX) < 2 * FONT_CACHE_DIST_LIMIT) &&
  6693. + diffY - floorf(diffY) < 2 * FONT_CACHE_DIST_LIMIT &&
  6694. + diffZ - floorf(diffZ) < 2 * FONT_CACHE_DIST_LIMIT &&
  6695. + a_m.m[0][0] == b_m.m[0][0] &&
  6696. + a_m.m[1][1] == b_m.m[1][1] &&
  6697. + a_m.m[2][2] == b_m.m[2][2];
  6698. + // We already know the first 3 columns of both matrices are diagonal, so no need to check the other elements
  6699. +}
  6700. +
  6701. +inline float MatrixHashContribution(const CGUIFontCacheKey<CGUIFontCacheDynamicPosition> &a)
  6702. +{
  6703. + return 0;
  6704. +}
  6705. +
  6706. #endif
  6707. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  6708. index 19c7ff4..73f0e50 100644
  6709. --- a/xbmc/guilib/GUIFontTTF.cpp
  6710. +++ b/xbmc/guilib/GUIFontTTF.cpp
  6711. @@ -132,7 +132,7 @@ class CFreeTypeLibrary
  6712. XBMC_GLOBAL_REF(CFreeTypeLibrary, g_freeTypeLibrary); // our freetype library
  6713. #define g_freeTypeLibrary XBMC_GLOBAL_USE(CFreeTypeLibrary)
  6714. -CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this)
  6715. +CGUIFontTTFBase::CGUIFontTTFBase(const CStdString& strFileName) : m_staticCache(*this), m_dynamicCache(*this)
  6716. {
  6717. m_texture = NULL;
  6718. m_char = NULL;
  6719. @@ -332,13 +332,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  6720. Begin();
  6721. bool dirtyCache;
  6722. + bool hardwareClipping = g_Windowing.ScissorsCanEffectClipping();
  6723. CGUIFontCacheStaticPosition staticPos(x, y);
  6724. - std::vector<SVertex> &vertices = m_staticCache.Lookup(staticPos,
  6725. - colors, text,
  6726. - alignment, maxPixelWidth,
  6727. - scrolling,
  6728. - XbmcThreads::SystemClockMillis(),
  6729. - dirtyCache);
  6730. + CGUIFontCacheDynamicPosition dynamicPos;
  6731. + if (hardwareClipping)
  6732. + {
  6733. + dynamicPos = CGUIFontCacheDynamicPosition(g_graphicsContext.ScaleFinalXCoord(x, y),
  6734. + g_graphicsContext.ScaleFinalYCoord(x, y),
  6735. + g_graphicsContext.ScaleFinalZCoord(x, y));
  6736. + }
  6737. + std::vector<SVertex> &vertices = hardwareClipping ?
  6738. + m_dynamicCache.Lookup(dynamicPos,
  6739. + colors, text,
  6740. + alignment, maxPixelWidth,
  6741. + scrolling,
  6742. + XbmcThreads::SystemClockMillis(),
  6743. + dirtyCache) :
  6744. + m_staticCache.Lookup(staticPos,
  6745. + colors, text,
  6746. + alignment, maxPixelWidth,
  6747. + scrolling,
  6748. + XbmcThreads::SystemClockMillis(),
  6749. + dirtyCache);
  6750. if (dirtyCache)
  6751. {
  6752. // save the origin, which is scaled separately
  6753. @@ -441,10 +456,28 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  6754. else
  6755. cursorX += ch->advance;
  6756. }
  6757. + if (hardwareClipping)
  6758. + /* Append the new vertices (which we have just constructed in the cache)
  6759. + * to the set collected since the first Begin() call */
  6760. + m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  6761. + }
  6762. + else if (hardwareClipping)
  6763. + {
  6764. + /* Apply the translation offset to the vertices from the cache after
  6765. + * appending them to the set collected since the first Begin() call */
  6766. + m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  6767. + SVertex *v;
  6768. + for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++)
  6769. + {
  6770. + v->x += dynamicPos.m_x;
  6771. + v->y += dynamicPos.m_y;
  6772. + v->z += dynamicPos.m_z;
  6773. + }
  6774. }
  6775. - /* Append the new vertices (from the cache or otherwise) to the set collected
  6776. - * since the first Begin() call */
  6777. - m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  6778. + if (!hardwareClipping)
  6779. + /* Append the new vertices (from the cache or otherwise) to the set collected
  6780. + * since the first Begin() call */
  6781. + m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  6782. End();
  6783. }
  6784. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  6785. index 7cb4669..78445ab 100644
  6786. --- a/xbmc/guilib/GUIFontTTF.h
  6787. +++ b/xbmc/guilib/GUIFontTTF.h
  6788. @@ -170,6 +170,7 @@ class CGUIFontTTFBase
  6789. CStdString m_strFileName;
  6790. CGUIFontCache<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue> m_staticCache;
  6791. + CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue> m_dynamicCache;
  6792. private:
  6793. virtual bool FirstBegin() = 0;
  6794. --
  6795. 1.9.3
  6796. From 10eeb73ca15798de26abd5f8846214c8938f8b42 Mon Sep 17 00:00:00 2001
  6797. From: Ben Avison <bavison@riscosopen.org>
  6798. Date: Wed, 8 Jan 2014 12:16:33 +0000
  6799. Subject: [PATCH 25/94] Rewrite of scrolling text code.
  6800. No longer shuffles the string round to minimise the number of characters
  6801. before the clipping rectangle; this doesn't save much on rendering time but
  6802. does harm the effectiveness of the cache. Now uses a pixel offset into the
  6803. string rather than a character + pixel offset, and plots the entire string
  6804. every time (execpt when the wrap point is visible, in which case the entire
  6805. string is plotted twice).
  6806. It also makes motion smoother, because (possibly unintentionally) the
  6807. previous code preferred to align the scroll offset with character boundaries.
  6808. This would lead to uneven changes of position, especially when the width of
  6809. the character currently being scrolled off the edge was only slightly more
  6810. than an integral multiple of the scroll increment.
  6811. ---
  6812. xbmc/guilib/GUIFadeLabelControl.cpp | 8 +--
  6813. xbmc/guilib/GUIFont.cpp | 123 +++++++++++++-----------------------
  6814. xbmc/guilib/GUIFont.h | 17 ++---
  6815. xbmc/guilib/GUIRSSControl.cpp | 6 +-
  6816. xbmc/utils/RssReader.cpp | 2 +-
  6817. xbmc/utils/RssReader.h | 2 +-
  6818. 6 files changed, 58 insertions(+), 100 deletions(-)
  6819. diff --git a/xbmc/guilib/GUIFadeLabelControl.cpp b/xbmc/guilib/GUIFadeLabelControl.cpp
  6820. index d594c04..86ee73a 100644
  6821. --- a/xbmc/guilib/GUIFadeLabelControl.cpp
  6822. +++ b/xbmc/guilib/GUIFadeLabelControl.cpp
  6823. @@ -109,18 +109,14 @@ void CGUIFadeLabelControl::Process(unsigned int currentTime, CDirtyRegionList &d
  6824. bool moveToNextLabel = false;
  6825. if (!m_scrollOut)
  6826. {
  6827. - vecText text;
  6828. - m_textLayout.GetFirstText(text);
  6829. - if (m_scrollInfo.characterPos && m_scrollInfo.characterPos < text.size())
  6830. - text.erase(text.begin(), text.begin() + min((int)m_scrollInfo.characterPos - 1, (int)text.size()));
  6831. - if (m_label.font->GetTextWidth(text) < m_width)
  6832. + if (m_scrollInfo.pixelPos + m_width > m_scrollInfo.m_textWidth)
  6833. {
  6834. if (m_fadeAnim.GetProcess() != ANIM_PROCESS_NORMAL)
  6835. m_fadeAnim.QueueAnimation(ANIM_PROCESS_NORMAL);
  6836. moveToNextLabel = true;
  6837. }
  6838. }
  6839. - else if (m_scrollInfo.characterPos > m_textLayout.GetTextLength())
  6840. + else if (m_scrollInfo.pixelPos > m_scrollInfo.m_textWidth)
  6841. moveToNextLabel = true;
  6842. // apply the fading animation
  6843. diff --git a/xbmc/guilib/GUIFont.cpp b/xbmc/guilib/GUIFont.cpp
  6844. index a7ee668..eb8efdb 100644
  6845. --- a/xbmc/guilib/GUIFont.cpp
  6846. +++ b/xbmc/guilib/GUIFont.cpp
  6847. @@ -36,7 +36,12 @@ CScrollInfo::CScrollInfo(unsigned int wait /* = 50 */, float pos /* = 0 */,
  6848. initialWait = wait;
  6849. initialPos = pos;
  6850. SetSpeed(speed ? speed : defaultSpeed);
  6851. - g_charsetConverter.utf8ToW(scrollSuffix, suffix);
  6852. + CStdStringW wsuffix;
  6853. + g_charsetConverter.utf8ToW(scrollSuffix, wsuffix);
  6854. + suffix.clear();
  6855. + suffix.reserve(wsuffix.size());
  6856. + for (vecText::size_type i = 0; i < wsuffix.size(); i++)
  6857. + suffix.push_back(wsuffix[i]);
  6858. Reset();
  6859. }
  6860. @@ -115,11 +120,12 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo)
  6861. {
  6862. // draw at our scroll position
  6863. // we handle the scrolling as follows:
  6864. - // We scroll on a per-pixel basis up until we have scrolled the first character outside
  6865. - // of our viewport, whereby we cycle the string around, and reset the scroll position.
  6866. - //
  6867. - // pixelPos is the amount in pixels to move the string by.
  6868. - // characterPos is the amount in characters to rotate the string by.
  6869. + // We scroll on a per-pixel basis (eschewing the use of character indices
  6870. + // which were also in use previously). The complete string, including suffix,
  6871. + // is plotted to achieve the desired effect - normally just the one time, but
  6872. + // if there is a wrap point within the viewport then it will be plotted twice.
  6873. + // If the string is smaller than the viewport, then it may be plotted even
  6874. + // more times than that.
  6875. //
  6876. if (scrollInfo.waitTime)
  6877. {
  6878. @@ -135,54 +141,19 @@ bool CGUIFont::UpdateScrollInfo(const vecText &text, CScrollInfo &scrollInfo)
  6879. // move along by the appropriate scroll amount
  6880. float scrollAmount = fabs(scrollInfo.GetPixelsPerFrame() * g_graphicsContext.GetGUIScaleX());
  6881. - if (scrollInfo.pixelSpeed > 0)
  6882. + if (!scrollInfo.m_widthValid)
  6883. {
  6884. - // we want to move scrollAmount, grab the next character
  6885. - float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
  6886. - if (scrollInfo.pixelPos + scrollAmount < charWidth)
  6887. - scrollInfo.pixelPos += scrollAmount; // within the current character
  6888. - else
  6889. - { // past the current character, decrement scrollAmount by the charWidth and move to the next character
  6890. - while (scrollInfo.pixelPos + scrollAmount >= charWidth)
  6891. - {
  6892. - scrollAmount -= (charWidth - scrollInfo.pixelPos);
  6893. - scrollInfo.pixelPos = 0;
  6894. - scrollInfo.characterPos++;
  6895. - if (scrollInfo.characterPos >= text.size() + scrollInfo.suffix.size())
  6896. - {
  6897. - scrollInfo.Reset();
  6898. - break;
  6899. - }
  6900. - charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
  6901. - }
  6902. - }
  6903. - }
  6904. - else if (scrollInfo.pixelSpeed < 0)
  6905. - { // scrolling backwards
  6906. - // we want to move scrollAmount, grab the next character
  6907. - float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
  6908. - if (scrollInfo.pixelPos + scrollAmount < charWidth)
  6909. - scrollInfo.pixelPos += scrollAmount; // within the current character
  6910. - else
  6911. - { // past the current character, decrement scrollAmount by the charWidth and move to the next character
  6912. - while (scrollInfo.pixelPos + scrollAmount >= charWidth)
  6913. - {
  6914. - scrollAmount -= (charWidth - scrollInfo.pixelPos);
  6915. - scrollInfo.pixelPos = 0;
  6916. - if (scrollInfo.characterPos == 0)
  6917. - {
  6918. - scrollInfo.Reset();
  6919. - scrollInfo.characterPos = text.size() + scrollInfo.suffix.size() - 1;
  6920. - break;
  6921. - }
  6922. - scrollInfo.characterPos--;
  6923. - charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
  6924. - }
  6925. - }
  6926. + /* Calculate the pixel width of the complete string */
  6927. + scrollInfo.m_textWidth = GetTextWidth(text);
  6928. + scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix);
  6929. + scrollInfo.m_widthValid = true;
  6930. }
  6931. + scrollInfo.pixelPos += scrollAmount;
  6932. + assert(scrollInfo.m_totalWidth != 0);
  6933. + while (scrollInfo.pixelPos >= scrollInfo.m_totalWidth)
  6934. + scrollInfo.pixelPos -= scrollInfo.m_totalWidth;
  6935. - if(scrollInfo.characterPos != old.characterPos
  6936. - || scrollInfo.pixelPos != old.pixelPos)
  6937. + if (scrollInfo.pixelPos != old.pixelPos)
  6938. return true;
  6939. else
  6940. return false;
  6941. @@ -194,39 +165,27 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo
  6942. if (!m_font) return;
  6943. if (!shadowColor) shadowColor = m_shadowColor;
  6944. - float spaceWidth = GetCharWidth(L' ');
  6945. - // max chars on screen + extra margin chars
  6946. - vecText::size_type maxChars =
  6947. - std::min<vecText::size_type>(
  6948. - (text.size() + (vecText::size_type)scrollInfo.suffix.size()),
  6949. - (vecText::size_type)((maxWidth * 1.05f) / spaceWidth));
  6950. -
  6951. if (!text.size() || ClippedRegionIsEmpty(x, y, maxWidth, alignment))
  6952. return; // nothing to render
  6953. - maxWidth = ROUND((maxWidth + scrollInfo.pixelPos) / g_graphicsContext.GetGUIScaleX());
  6954. + if (!scrollInfo.m_widthValid)
  6955. + {
  6956. + /* Calculate the pixel width of the complete string */
  6957. + scrollInfo.m_textWidth = GetTextWidth(text);
  6958. + scrollInfo.m_totalWidth = scrollInfo.m_textWidth + GetTextWidth(scrollInfo.suffix);
  6959. + scrollInfo.m_widthValid = true;
  6960. + }
  6961. +
  6962. + assert(scrollInfo.m_totalWidth != 0);
  6963. +
  6964. + float textPixelWidth = ROUND(scrollInfo.m_textWidth / g_graphicsContext.GetGUIScaleX());
  6965. + float suffixPixelWidth = ROUND((scrollInfo.m_totalWidth - scrollInfo.m_textWidth) / g_graphicsContext.GetGUIScaleX());
  6966. - float charWidth = GetCharWidth(scrollInfo.GetCurrentChar(text));
  6967. float offset;
  6968. if(scrollInfo.pixelSpeed >= 0)
  6969. offset = scrollInfo.pixelPos;
  6970. else
  6971. - offset = charWidth - scrollInfo.pixelPos;
  6972. -
  6973. - // Now rotate our string as needed, only take a slightly larger then visible part of the text.
  6974. - unsigned int pos = scrollInfo.characterPos;
  6975. - vecText renderText;
  6976. - renderText.reserve(maxChars);
  6977. - for (vecText::size_type i = 0; i < maxChars; i++)
  6978. - {
  6979. - if (pos >= text.size() + scrollInfo.suffix.size())
  6980. - pos = 0;
  6981. - if (pos < text.size())
  6982. - renderText.push_back(text[pos]);
  6983. - else
  6984. - renderText.push_back(scrollInfo.suffix[pos - text.size()]);
  6985. - pos++;
  6986. - }
  6987. + offset = scrollInfo.m_totalWidth - scrollInfo.pixelPos;
  6988. vecColors renderColors;
  6989. for (unsigned int i = 0; i < colors.size(); i++)
  6990. @@ -239,9 +198,17 @@ void CGUIFont::DrawScrollingText(float x, float y, const vecColors &colors, colo
  6991. vecColors shadowColors;
  6992. for (unsigned int i = 0; i < renderColors.size(); i++)
  6993. shadowColors.push_back((renderColors[i] & 0xff000000) != 0 ? shadowColor : 0);
  6994. - m_font->DrawTextInternal(x - offset + 1, y + 1, shadowColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll);
  6995. + for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth)
  6996. + {
  6997. + m_font->DrawTextInternal(x + dx + 1, y + 1, shadowColors, text, alignment, textPixelWidth, scroll);
  6998. + m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth + 1, y + 1, shadowColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll);
  6999. + }
  7000. + }
  7001. + for (float dx = -offset; dx < maxWidth; dx += scrollInfo.m_totalWidth)
  7002. + {
  7003. + m_font->DrawTextInternal(x + dx, y, renderColors, text, alignment, textPixelWidth, scroll);
  7004. + m_font->DrawTextInternal(x + dx + scrollInfo.m_textWidth, y, renderColors, scrollInfo.suffix, alignment, suffixPixelWidth, scroll);
  7005. }
  7006. - m_font->DrawTextInternal(x - offset, y, renderColors, renderText, alignment, maxWidth + m_font->GetLineHeight(2.0f), scroll);
  7007. g_graphicsContext.RestoreClipRegion();
  7008. }
  7009. diff --git a/xbmc/guilib/GUIFont.h b/xbmc/guilib/GUIFont.h
  7010. index c55db48..09cf9b3 100644
  7011. --- a/xbmc/guilib/GUIFont.h
  7012. +++ b/xbmc/guilib/GUIFont.h
  7013. @@ -64,7 +64,6 @@ class CScrollInfo
  7014. void Reset()
  7015. {
  7016. waitTime = initialWait;
  7017. - characterPos = 0;
  7018. // pixelPos is where we start the current letter, so is measured
  7019. // to the left of the text rendering's left edge. Thus, a negative
  7020. // value will mean the text starts to the right
  7021. @@ -72,25 +71,19 @@ class CScrollInfo
  7022. // privates:
  7023. m_averageFrameTime = 1000.f / abs(defaultSpeed);
  7024. m_lastFrameTime = 0;
  7025. - }
  7026. - uint32_t GetCurrentChar(const vecText &text) const
  7027. - {
  7028. - assert(text.size());
  7029. - if (characterPos < text.size())
  7030. - return text[characterPos];
  7031. - else if (characterPos < text.size() + suffix.size())
  7032. - return suffix[characterPos - text.size()];
  7033. - return text[0];
  7034. + m_widthValid = false;
  7035. }
  7036. float GetPixelsPerFrame();
  7037. float pixelPos;
  7038. float pixelSpeed;
  7039. unsigned int waitTime;
  7040. - unsigned int characterPos;
  7041. unsigned int initialWait;
  7042. float initialPos;
  7043. - CStdStringW suffix;
  7044. + vecText suffix;
  7045. + mutable float m_textWidth;
  7046. + mutable float m_totalWidth;
  7047. + mutable bool m_widthValid;
  7048. static const int defaultSpeed = 60;
  7049. private:
  7050. diff --git a/xbmc/guilib/GUIRSSControl.cpp b/xbmc/guilib/GUIRSSControl.cpp
  7051. index 712e118..203c138 100644
  7052. --- a/xbmc/guilib/GUIRSSControl.cpp
  7053. +++ b/xbmc/guilib/GUIRSSControl.cpp
  7054. @@ -119,7 +119,9 @@ void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyre
  7055. dirty = true;
  7056. if (CRssManager::Get().GetReader(GetID(), GetParentID(), this, m_pReader))
  7057. - m_scrollInfo.characterPos = m_pReader->m_SavedScrollPos;
  7058. + {
  7059. + m_scrollInfo.pixelPos = m_pReader->m_savedScrollPixelPos;
  7060. + }
  7061. else
  7062. {
  7063. if (m_strRSSTags != "")
  7064. @@ -177,7 +179,7 @@ void CGUIRSSControl::Render()
  7065. if (m_pReader)
  7066. {
  7067. m_pReader->CheckForUpdates();
  7068. - m_pReader->m_SavedScrollPos = m_scrollInfo.characterPos;
  7069. + m_pReader->m_savedScrollPixelPos = m_scrollInfo.pixelPos;
  7070. }
  7071. }
  7072. CGUIControl::Render();
  7073. diff --git a/xbmc/utils/RssReader.cpp b/xbmc/utils/RssReader.cpp
  7074. index b1e53b7..f68597a 100644
  7075. --- a/xbmc/utils/RssReader.cpp
  7076. +++ b/xbmc/utils/RssReader.cpp
  7077. @@ -54,7 +54,7 @@ CRssReader::CRssReader() : CThread("RSSReader")
  7078. m_pObserver = NULL;
  7079. m_spacesBetweenFeeds = 0;
  7080. m_bIsRunning = false;
  7081. - m_SavedScrollPos = 0;
  7082. + m_savedScrollPixelPos = 0;
  7083. m_rtlText = false;
  7084. m_requestRefresh = false;
  7085. }
  7086. diff --git a/xbmc/utils/RssReader.h b/xbmc/utils/RssReader.h
  7087. index 2c6f366..b74faf2 100644
  7088. --- a/xbmc/utils/RssReader.h
  7089. +++ b/xbmc/utils/RssReader.h
  7090. @@ -43,7 +43,7 @@ class CRssReader : public CThread
  7091. void SetObserver(IRssObserver* observer);
  7092. void CheckForUpdates();
  7093. void requestRefresh();
  7094. - unsigned int m_SavedScrollPos;
  7095. + float m_savedScrollPixelPos;
  7096. private:
  7097. void Process();
  7098. --
  7099. 1.9.3
  7100. From 7064920379f68a7f6114813db8ad40a21c4957cc Mon Sep 17 00:00:00 2001
  7101. From: Ben Avison <bavison@riscosopen.org>
  7102. Date: Mon, 27 Jan 2014 23:21:10 +0000
  7103. Subject: [PATCH 26/94] Move the application of the translation offsets into
  7104. the GLES code. Still all pure software at this stage. Main change is in the
  7105. data types at the interface between CGUIFontTTFBase and CGUIFontTTFGL. The
  7106. old way (array of vertices in m_vertex) are retained in addition, for the
  7107. sake`of cases that need to use software clipping on GLES, as well as for DX
  7108. and GL support where the new scheme is not (yet?) used.
  7109. ---
  7110. xbmc/guilib/GUIFontTTF.cpp | 19 +++---------
  7111. xbmc/guilib/GUIFontTTF.h | 17 +++++++++++
  7112. xbmc/guilib/GUIFontTTFGL.cpp | 72 ++++++++++++++++++++++++++++++++------------
  7113. 3 files changed, 73 insertions(+), 35 deletions(-)
  7114. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  7115. index 73f0e50..ad0a53b 100644
  7116. --- a/xbmc/guilib/GUIFontTTF.cpp
  7117. +++ b/xbmc/guilib/GUIFontTTF.cpp
  7118. @@ -215,6 +215,7 @@ void CGUIFontTTFBase::Clear()
  7119. g_freeTypeLibrary.ReleaseStroker(m_stroker);
  7120. m_stroker = NULL;
  7121. + m_vertexTrans.clear();
  7122. m_vertex.clear();
  7123. }
  7124. @@ -310,6 +311,7 @@ void CGUIFontTTFBase::Begin()
  7125. {
  7126. if (m_nestedBeginCount == 0 && m_texture != NULL && FirstBegin())
  7127. {
  7128. + m_vertexTrans.clear();
  7129. m_vertex.clear();
  7130. }
  7131. // Keep track of the nested begin/end calls.
  7132. @@ -457,23 +459,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  7133. cursorX += ch->advance;
  7134. }
  7135. if (hardwareClipping)
  7136. - /* Append the new vertices (which we have just constructed in the cache)
  7137. - * to the set collected since the first Begin() call */
  7138. - m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  7139. + m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices));
  7140. }
  7141. else if (hardwareClipping)
  7142. - {
  7143. - /* Apply the translation offset to the vertices from the cache after
  7144. - * appending them to the set collected since the first Begin() call */
  7145. - m_vertex.insert(m_vertex.end(), vertices.begin(), vertices.end());
  7146. - SVertex *v;
  7147. - for (v = &*m_vertex.end() - vertices.size(); v != &*m_vertex.end(); v++)
  7148. - {
  7149. - v->x += dynamicPos.m_x;
  7150. - v->y += dynamicPos.m_y;
  7151. - v->z += dynamicPos.m_z;
  7152. - }
  7153. - }
  7154. + m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices));
  7155. if (!hardwareClipping)
  7156. /* Append the new vertices (from the cache or otherwise) to the set collected
  7157. * since the first Begin() call */
  7158. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  7159. index 78445ab..c71f90d 100644
  7160. --- a/xbmc/guilib/GUIFontTTF.h
  7161. +++ b/xbmc/guilib/GUIFontTTF.h
  7162. @@ -61,6 +61,14 @@ struct SVertex
  7163. unsigned char r, g, b, a;
  7164. #endif
  7165. float u, v;
  7166. + struct SVertex Offset(float translate[3]) const
  7167. + {
  7168. + SVertex out = *this;
  7169. + out.x += translate[0];
  7170. + out.y += translate[1];
  7171. + out.z += translate[2];
  7172. + return out;
  7173. + }
  7174. };
  7175. @@ -160,6 +168,15 @@ class CGUIFontTTFBase
  7176. bool m_bTextureLoaded;
  7177. unsigned int m_nTexture;
  7178. + struct CTranslatedVertices
  7179. + {
  7180. + float translateX;
  7181. + float translateY;
  7182. + float translateZ;
  7183. + const std::vector<SVertex> *vertexBuffer;
  7184. + CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector<SVertex> *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {}
  7185. + };
  7186. + std::vector<CTranslatedVertices> m_vertexTrans;
  7187. std::vector<SVertex> m_vertex;
  7188. float m_textureScaleX;
  7189. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7190. index cb56987..f6aa081 100644
  7191. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7192. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7193. @@ -146,34 +146,65 @@ void CGUIFontTTFGL::LastEnd()
  7194. GLint colLoc = g_Windowing.GUIShaderGetCol();
  7195. GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
  7196. - // stack object until VBOs will be used
  7197. - std::vector<SVertex> vecVertices( 6 * (m_vertex.size() / 4) );
  7198. - SVertex *vertices = &vecVertices[0];
  7199. + // Enable the attributes used by this shader
  7200. + glEnableVertexAttribArray(posLoc);
  7201. + glEnableVertexAttribArray(colLoc);
  7202. + glEnableVertexAttribArray(tex0Loc);
  7203. - for (size_t i=0; i<m_vertex.size(); i+=4)
  7204. + if (m_vertex.size() > 0)
  7205. {
  7206. - *vertices++ = m_vertex[i];
  7207. - *vertices++ = m_vertex[i+1];
  7208. - *vertices++ = m_vertex[i+2];
  7209. + // Deal with vertices that had to use software clipping
  7210. + std::vector<SVertex> vecVertices( 6 * (m_vertex.size() / 4) );
  7211. + SVertex *vertices = &vecVertices[0];
  7212. - *vertices++ = m_vertex[i+1];
  7213. - *vertices++ = m_vertex[i+3];
  7214. - *vertices++ = m_vertex[i+2];
  7215. - }
  7216. + for (size_t i=0; i<m_vertex.size(); i+=4)
  7217. + {
  7218. + *vertices++ = m_vertex[i];
  7219. + *vertices++ = m_vertex[i+1];
  7220. + *vertices++ = m_vertex[i+2];
  7221. - vertices = &vecVertices[0];
  7222. + *vertices++ = m_vertex[i+1];
  7223. + *vertices++ = m_vertex[i+3];
  7224. + *vertices++ = m_vertex[i+2];
  7225. + }
  7226. - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7227. - // Normalize color values. Does not affect Performance at all.
  7228. - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7229. - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7230. + vertices = &vecVertices[0];
  7231. - glEnableVertexAttribArray(posLoc);
  7232. - glEnableVertexAttribArray(colLoc);
  7233. - glEnableVertexAttribArray(tex0Loc);
  7234. + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7235. + // Normalize color values. Does not affect Performance at all.
  7236. + glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7237. + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7238. +
  7239. + glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7240. + }
  7241. + if (m_vertexTrans.size() > 0)
  7242. + {
  7243. + // Deal with the vertices that can be hardware clipped and therefore translated
  7244. + std::vector<SVertex> vecVertices;
  7245. + for (size_t i = 0; i < m_vertexTrans.size(); i++)
  7246. + {
  7247. + float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ };
  7248. + for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
  7249. + {
  7250. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate));
  7251. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
  7252. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
  7253. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
  7254. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate));
  7255. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
  7256. + }
  7257. + }
  7258. + SVertex *vertices = &vecVertices[0];
  7259. - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7260. + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7261. + // Normalize color values. Does not affect Performance at all.
  7262. + glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7263. + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7264. +
  7265. + glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7266. + }
  7267. + // Disable the attributes used by this shader
  7268. glDisableVertexAttribArray(posLoc);
  7269. glDisableVertexAttribArray(colLoc);
  7270. glDisableVertexAttribArray(tex0Loc);
  7271. @@ -201,6 +232,7 @@ CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
  7272. if (m_textureHeight < newHeight)
  7273. CLog::Log(LOGWARNING, "%s: allocated new texture with height of %d, requested %d", __FUNCTION__, m_textureHeight, newHeight);
  7274. m_staticCache.Flush();
  7275. + m_dynamicCache.Flush();
  7276. memset(newTexture->GetPixels(), 0, m_textureHeight * newTexture->GetPitch());
  7277. if (m_texture)
  7278. --
  7279. 1.9.3
  7280. From 476fce7bc2897e8898f4392809d934b0d5f46518 Mon Sep 17 00:00:00 2001
  7281. From: Ben Avison <bavison@riscosopen.org>
  7282. Date: Wed, 15 Jan 2014 15:28:06 +0000
  7283. Subject: [PATCH 27/94] Rather than applying the translation offsets to the
  7284. vertices, now applies them to the model view matrix from the top of the
  7285. matrix stack and pushes it over to OpenGL. The vertices themselves are still
  7286. all held client-side.
  7287. ---
  7288. xbmc/guilib/GUIFontTTF.h | 8 -------
  7289. xbmc/guilib/GUIFontTTFGL.cpp | 40 +++++++++++++++++++++-----------
  7290. xbmc/guilib/GUIShader.h | 1 +
  7291. xbmc/rendering/gles/RenderSystemGLES.cpp | 8 +++++++
  7292. xbmc/rendering/gles/RenderSystemGLES.h | 1 +
  7293. 5 files changed, 36 insertions(+), 22 deletions(-)
  7294. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  7295. index c71f90d..fde2085 100644
  7296. --- a/xbmc/guilib/GUIFontTTF.h
  7297. +++ b/xbmc/guilib/GUIFontTTF.h
  7298. @@ -61,14 +61,6 @@ struct SVertex
  7299. unsigned char r, g, b, a;
  7300. #endif
  7301. float u, v;
  7302. - struct SVertex Offset(float translate[3]) const
  7303. - {
  7304. - SVertex out = *this;
  7305. - out.x += translate[0];
  7306. - out.y += translate[1];
  7307. - out.z += translate[2];
  7308. - return out;
  7309. - }
  7310. };
  7311. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7312. index f6aa081..fbffaa0 100644
  7313. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7314. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7315. @@ -29,6 +29,7 @@
  7316. #include "utils/log.h"
  7317. #include "utils/GLUtils.h"
  7318. #include "windowing/WindowingFactory.h"
  7319. +#include "guilib/MatrixGLES.h"
  7320. // stuff for freetype
  7321. #include <ft2build.h>
  7322. @@ -145,6 +146,7 @@ void CGUIFontTTFGL::LastEnd()
  7323. GLint posLoc = g_Windowing.GUIShaderGetPos();
  7324. GLint colLoc = g_Windowing.GUIShaderGetCol();
  7325. GLint tex0Loc = g_Windowing.GUIShaderGetCoord0();
  7326. + GLint modelLoc = g_Windowing.GUIShaderGetModel();
  7327. // Enable the attributes used by this shader
  7328. glEnableVertexAttribArray(posLoc);
  7329. @@ -183,25 +185,35 @@ void CGUIFontTTFGL::LastEnd()
  7330. std::vector<SVertex> vecVertices;
  7331. for (size_t i = 0; i < m_vertexTrans.size(); i++)
  7332. {
  7333. - float translate[3] = { m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ };
  7334. + // Apply the translation to the currently active (top-of-stack) model view matrix
  7335. + g_matrices.MatrixMode(MM_MODELVIEW);
  7336. + g_matrices.PushMatrix();
  7337. + g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ);
  7338. + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7339. +
  7340. + vecVertices.clear();
  7341. for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
  7342. {
  7343. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j].Offset(translate));
  7344. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
  7345. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
  7346. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1].Offset(translate));
  7347. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3].Offset(translate));
  7348. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2].Offset(translate));
  7349. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]);
  7350. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
  7351. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
  7352. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
  7353. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]);
  7354. + vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
  7355. }
  7356. - }
  7357. - SVertex *vertices = &vecVertices[0];
  7358. + SVertex *vertices = &vecVertices[0];
  7359. - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7360. - // Normalize color values. Does not affect Performance at all.
  7361. - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7362. - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7363. + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7364. + // Normalize color values. Does not affect Performance at all.
  7365. + glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7366. + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7367. - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7368. + glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7369. +
  7370. + g_matrices.PopMatrix();
  7371. + }
  7372. + // Restore the original model view matrix
  7373. + glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7374. }
  7375. // Disable the attributes used by this shader
  7376. diff --git a/xbmc/guilib/GUIShader.h b/xbmc/guilib/GUIShader.h
  7377. index 86ce4cc..ba01956 100644
  7378. --- a/xbmc/guilib/GUIShader.h
  7379. +++ b/xbmc/guilib/GUIShader.h
  7380. @@ -41,6 +41,7 @@ class CGUIShader : public CGLSLShaderProgram
  7381. GLint GetCord1Loc() { return m_hCord1; }
  7382. GLint GetUniColLoc() { return m_hUniCol; }
  7383. GLint GetCoord0MatrixLoc() { return m_hCoord0Matrix; }
  7384. + GLint GetModelLoc() { return m_hModel; }
  7385. bool HardwareClipIsPossible() { return m_clipPossible; }
  7386. GLfloat GetClipXFactor() { return m_clipXFactor; }
  7387. GLfloat GetClipXOffset() { return m_clipXOffset; }
  7388. diff --git a/xbmc/rendering/gles/RenderSystemGLES.cpp b/xbmc/rendering/gles/RenderSystemGLES.cpp
  7389. index deb3afc..0904d1f 100644
  7390. --- a/xbmc/rendering/gles/RenderSystemGLES.cpp
  7391. +++ b/xbmc/rendering/gles/RenderSystemGLES.cpp
  7392. @@ -691,4 +691,12 @@ bool CRenderSystemGLES::SupportsStereo(RENDER_STEREO_MODE mode)
  7393. }
  7394. }
  7395. +GLint CRenderSystemGLES::GUIShaderGetModel()
  7396. +{
  7397. + if (m_pGUIshader[m_method])
  7398. + return m_pGUIshader[m_method]->GetModelLoc();
  7399. +
  7400. + return -1;
  7401. +}
  7402. +
  7403. #endif
  7404. diff --git a/xbmc/rendering/gles/RenderSystemGLES.h b/xbmc/rendering/gles/RenderSystemGLES.h
  7405. index 81ee49e..d2f9cd1 100644
  7406. --- a/xbmc/rendering/gles/RenderSystemGLES.h
  7407. +++ b/xbmc/rendering/gles/RenderSystemGLES.h
  7408. @@ -91,6 +91,7 @@ class CRenderSystemGLES : public CRenderSystemBase
  7409. GLint GUIShaderGetCoord1();
  7410. GLint GUIShaderGetUniCol();
  7411. GLint GUIShaderGetCoord0Matrix();
  7412. + GLint GUIShaderGetModel();
  7413. protected:
  7414. virtual void SetVSyncImpl(bool enable) = 0;
  7415. --
  7416. 1.9.3
  7417. From 473ccc4cbe616f672a72108d2ec98107780ac7da Mon Sep 17 00:00:00 2001
  7418. From: Ben Avison <bavison@riscosopen.org>
  7419. Date: Wed, 29 Jan 2014 13:21:19 +0000
  7420. Subject: [PATCH 28/94] Enable hardware clipping.
  7421. ---
  7422. xbmc/guilib/GUIFontTTF.cpp | 4 ++--
  7423. xbmc/guilib/GUIFontTTF.h | 5 ++++-
  7424. xbmc/guilib/GUIFontTTFGL.cpp | 6 ++++++
  7425. 3 files changed, 12 insertions(+), 3 deletions(-)
  7426. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  7427. index ad0a53b..4dc4c8e 100644
  7428. --- a/xbmc/guilib/GUIFontTTF.cpp
  7429. +++ b/xbmc/guilib/GUIFontTTF.cpp
  7430. @@ -459,10 +459,10 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  7431. cursorX += ch->advance;
  7432. }
  7433. if (hardwareClipping)
  7434. - m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices));
  7435. + m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion()));
  7436. }
  7437. else if (hardwareClipping)
  7438. - m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices));
  7439. + m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion()));
  7440. if (!hardwareClipping)
  7441. /* Append the new vertices (from the cache or otherwise) to the set collected
  7442. * since the first Begin() call */
  7443. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  7444. index fde2085..5e7c31f 100644
  7445. --- a/xbmc/guilib/GUIFontTTF.h
  7446. +++ b/xbmc/guilib/GUIFontTTF.h
  7447. @@ -27,6 +27,8 @@
  7448. *
  7449. */
  7450. +#include "Geometry.h"
  7451. +
  7452. // forward definition
  7453. class CBaseTexture;
  7454. @@ -166,7 +168,8 @@ class CGUIFontTTFBase
  7455. float translateY;
  7456. float translateZ;
  7457. const std::vector<SVertex> *vertexBuffer;
  7458. - CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector<SVertex> *vertexBuffer) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer) {}
  7459. + CRect clip;
  7460. + CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector<SVertex> *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
  7461. };
  7462. std::vector<CTranslatedVertices> m_vertexTrans;
  7463. std::vector<SVertex> m_vertex;
  7464. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7465. index fbffaa0..b7618e1 100644
  7466. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7467. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7468. @@ -185,6 +185,10 @@ void CGUIFontTTFGL::LastEnd()
  7469. std::vector<SVertex> vecVertices;
  7470. for (size_t i = 0; i < m_vertexTrans.size(); i++)
  7471. {
  7472. + // Apply the clip rectangle
  7473. + CRect clip = g_Windowing.ClipRectToScissorRect(m_vertexTrans[i].clip);
  7474. + g_graphicsContext.SetScissors(clip);
  7475. +
  7476. // Apply the translation to the currently active (top-of-stack) model view matrix
  7477. g_matrices.MatrixMode(MM_MODELVIEW);
  7478. g_matrices.PushMatrix();
  7479. @@ -212,6 +216,8 @@ void CGUIFontTTFGL::LastEnd()
  7480. g_matrices.PopMatrix();
  7481. }
  7482. + // Restore the original scissor rectangle
  7483. + g_graphicsContext.ResetScissors();
  7484. // Restore the original model view matrix
  7485. glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7486. }
  7487. --
  7488. 1.9.3
  7489. From f39c4523a1c05425fb94d3536a510709784f9558 Mon Sep 17 00:00:00 2001
  7490. From: Ben Avison <bavison@riscosopen.org>
  7491. Date: Wed, 15 Jan 2014 15:32:51 +0000
  7492. Subject: [PATCH 29/94] Move the vertex data across to a vertex buffer object
  7493. just prior to drawing.
  7494. ---
  7495. xbmc/guilib/GUIFontTTFGL.cpp | 24 +++++++++++++++++++-----
  7496. 1 file changed, 19 insertions(+), 5 deletions(-)
  7497. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7498. index b7618e1..0df3749 100644
  7499. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7500. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7501. @@ -207,12 +207,24 @@ void CGUIFontTTFGL::LastEnd()
  7502. }
  7503. SVertex *vertices = &vecVertices[0];
  7504. - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, x));
  7505. - // Normalize color values. Does not affect Performance at all.
  7506. - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, r));
  7507. - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (char*)vertices + offsetof(SVertex, u));
  7508. -
  7509. + // Generate a unique buffer object name and put it in vertexBuffer
  7510. + GLuint vertexBuffer;
  7511. + glGenBuffers(1, &vertexBuffer);
  7512. + // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
  7513. + glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
  7514. + // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
  7515. + // binding point (i.e. our buffer object) and initialise it from the
  7516. + // specified client-side pointer
  7517. + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW);
  7518. + // Set up the offsets of the various vertex attributes within the buffer
  7519. + // object bound to GL_ARRAY_BUFFER
  7520. + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
  7521. + glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
  7522. + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
  7523. + // Do the actual drawing operation, using the full set of vertices in the buffer
  7524. glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7525. + // Release the buffer name for reuse
  7526. + glDeleteBuffers(1, &vertexBuffer);
  7527. g_matrices.PopMatrix();
  7528. }
  7529. @@ -220,6 +232,8 @@ void CGUIFontTTFGL::LastEnd()
  7530. g_graphicsContext.ResetScissors();
  7531. // Restore the original model view matrix
  7532. glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7533. + // Unbind GL_ARRAY_BUFFER
  7534. + glBindBuffer(GL_ARRAY_BUFFER, 0);
  7535. }
  7536. // Disable the attributes used by this shader
  7537. --
  7538. 1.9.3
  7539. From 3c6c1c4f9c7aec0f41fd22d7d4e7f5918a70c69a Mon Sep 17 00:00:00 2001
  7540. From: Ben Avison <bavison@riscosopen.org>
  7541. Date: Wed, 15 Jan 2014 16:04:04 +0000
  7542. Subject: [PATCH 30/94] Move vertex data into an OpenGL VBO when the font cache
  7543. entry is populated. The font cache now stores the "name" (handle) of the VBO,
  7544. rather than a vector of vertices.
  7545. ---
  7546. xbmc/guilib/GUIFontCache.cpp | 6 ++++
  7547. xbmc/guilib/GUIFontCache.h | 30 +++++++++++++++++-
  7548. xbmc/guilib/GUIFontTTF.cpp | 15 +++++++--
  7549. xbmc/guilib/GUIFontTTF.h | 7 +++--
  7550. xbmc/guilib/GUIFontTTFGL.cpp | 74 ++++++++++++++++++++++++++++++--------------
  7551. xbmc/guilib/GUIFontTTFGL.h | 5 +++
  7552. 6 files changed, 107 insertions(+), 30 deletions(-)
  7553. diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
  7554. index b66c00b..895fa72 100644
  7555. --- a/xbmc/guilib/GUIFontCache.cpp
  7556. +++ b/xbmc/guilib/GUIFontCache.cpp
  7557. @@ -111,3 +111,9 @@ template void CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDyna
  7558. template CGUIFontCacheEntry<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::~CGUIFontCacheEntry();
  7559. template CGUIFontCacheDynamicValue &CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Lookup(CGUIFontCacheDynamicPosition &, const vecColors &, const vecText &, uint32_t, float, bool, unsigned int, bool &);
  7560. template void CGUIFontCache<CGUIFontCacheDynamicPosition, CGUIFontCacheDynamicValue>::Flush();
  7561. +
  7562. +void CVertexBuffer::clear()
  7563. +{
  7564. + if (m_font != NULL)
  7565. + m_font->DestroyVertexBuffer(*this);
  7566. +}
  7567. diff --git a/xbmc/guilib/GUIFontCache.h b/xbmc/guilib/GUIFontCache.h
  7568. index d913dee..ff766bf 100644
  7569. --- a/xbmc/guilib/GUIFontCache.h
  7570. +++ b/xbmc/guilib/GUIFontCache.h
  7571. @@ -234,7 +234,35 @@ struct CGUIFontCacheDynamicPosition
  7572. }
  7573. };
  7574. -typedef std::vector<SVertex> CGUIFontCacheDynamicValue;
  7575. +struct CVertexBuffer
  7576. +{
  7577. + void *bufferHandle;
  7578. + size_t size;
  7579. + CVertexBuffer() : bufferHandle(NULL), size(0), m_font(NULL) {}
  7580. + CVertexBuffer(void *bufferHandle, size_t size, const CGUIFontTTFBase *font) : bufferHandle(bufferHandle), size(size), m_font(font) {}
  7581. + CVertexBuffer(const CVertexBuffer &other) : bufferHandle(other.bufferHandle), size(other.size), m_font(other.m_font)
  7582. + {
  7583. + /* In practice, the copy constructor is only called before a vertex buffer
  7584. + * has been attached. If this should ever change, we'll need another support
  7585. + * function in GUIFontTTFGL/DX to duplicate a buffer, given its handle. */
  7586. + assert(other.bufferHandle == 0);
  7587. + }
  7588. + CVertexBuffer &operator=(CVertexBuffer &other)
  7589. + {
  7590. + /* This is used with move-assignment semantics for initialising the object in the font cache */
  7591. + assert(bufferHandle == 0);
  7592. + bufferHandle = other.bufferHandle;
  7593. + other.bufferHandle = 0;
  7594. + size = other.size;
  7595. + m_font = other.m_font;
  7596. + return *this;
  7597. + }
  7598. + void clear();
  7599. +private:
  7600. + const CGUIFontTTFBase *m_font;
  7601. +};
  7602. +
  7603. +typedef CVertexBuffer CGUIFontCacheDynamicValue;
  7604. inline bool Match(const CGUIFontCacheDynamicPosition &a, const TransformMatrix &a_m,
  7605. const CGUIFontCacheDynamicPosition &b, const TransformMatrix &b_m,
  7606. diff --git a/xbmc/guilib/GUIFontTTF.cpp b/xbmc/guilib/GUIFontTTF.cpp
  7607. index 4dc4c8e..8b25306 100644
  7608. --- a/xbmc/guilib/GUIFontTTF.cpp
  7609. +++ b/xbmc/guilib/GUIFontTTF.cpp
  7610. @@ -343,13 +343,18 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  7611. g_graphicsContext.ScaleFinalYCoord(x, y),
  7612. g_graphicsContext.ScaleFinalZCoord(x, y));
  7613. }
  7614. - std::vector<SVertex> &vertices = hardwareClipping ?
  7615. + CVertexBuffer unusedVertexBuffer;
  7616. + CVertexBuffer &vertexBuffer = hardwareClipping ?
  7617. m_dynamicCache.Lookup(dynamicPos,
  7618. colors, text,
  7619. alignment, maxPixelWidth,
  7620. scrolling,
  7621. XbmcThreads::SystemClockMillis(),
  7622. dirtyCache) :
  7623. + unusedVertexBuffer;
  7624. + std::vector<SVertex> tempVertices;
  7625. + std::vector<SVertex> &vertices = hardwareClipping ?
  7626. + tempVertices :
  7627. m_staticCache.Lookup(staticPos,
  7628. colors, text,
  7629. alignment, maxPixelWidth,
  7630. @@ -459,10 +464,14 @@ void CGUIFontTTFBase::DrawTextInternal(float x, float y, const vecColors &colors
  7631. cursorX += ch->advance;
  7632. }
  7633. if (hardwareClipping)
  7634. - m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertices, g_graphicsContext.GetClipRegion()));
  7635. + {
  7636. + CVertexBuffer newVertexBuffer = CreateVertexBuffer(tempVertices);
  7637. + vertexBuffer = newVertexBuffer;
  7638. + m_vertexTrans.push_back(CTranslatedVertices(0, 0, 0, &vertexBuffer, g_graphicsContext.GetClipRegion()));
  7639. + }
  7640. }
  7641. else if (hardwareClipping)
  7642. - m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertices, g_graphicsContext.GetClipRegion()));
  7643. + m_vertexTrans.push_back(CTranslatedVertices(dynamicPos.m_x, dynamicPos.m_y, dynamicPos.m_z, &vertexBuffer, g_graphicsContext.GetClipRegion()));
  7644. if (!hardwareClipping)
  7645. /* Append the new vertices (from the cache or otherwise) to the set collected
  7646. * since the first Begin() call */
  7647. diff --git a/xbmc/guilib/GUIFontTTF.h b/xbmc/guilib/GUIFontTTF.h
  7648. index 5e7c31f..b1cd525 100644
  7649. --- a/xbmc/guilib/GUIFontTTF.h
  7650. +++ b/xbmc/guilib/GUIFontTTF.h
  7651. @@ -84,6 +84,9 @@ class CGUIFontTTFBase
  7652. void Begin();
  7653. void End();
  7654. + /* The next two should only be called if we've declared we can do hardware clipping */
  7655. + virtual CVertexBuffer CreateVertexBuffer(const std::vector<SVertex> &vertices) const { assert(false); return CVertexBuffer(); }
  7656. + virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const {}
  7657. const CStdString& GetFileName() const { return m_strFileName; };
  7658. @@ -167,9 +170,9 @@ class CGUIFontTTFBase
  7659. float translateX;
  7660. float translateY;
  7661. float translateZ;
  7662. - const std::vector<SVertex> *vertexBuffer;
  7663. + const CVertexBuffer *vertexBuffer;
  7664. CRect clip;
  7665. - CTranslatedVertices(float translateX, float translateY, float translateZ, const std::vector<SVertex> *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
  7666. + CTranslatedVertices(float translateX, float translateY, float translateZ, const CVertexBuffer *vertexBuffer, const CRect &clip) : translateX(translateX), translateY(translateY), translateZ(translateZ), vertexBuffer(vertexBuffer), clip(clip) {}
  7667. };
  7668. std::vector<CTranslatedVertices> m_vertexTrans;
  7669. std::vector<SVertex> m_vertex;
  7670. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7671. index 0df3749..1cd684b7 100644
  7672. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7673. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7674. @@ -49,6 +49,10 @@ CGUIFontTTFGL::CGUIFontTTFGL(const CStdString& strFileName)
  7675. CGUIFontTTFGL::~CGUIFontTTFGL(void)
  7676. {
  7677. + // It's important that all the CGUIFontCacheEntry objects are
  7678. + // destructed before the CGUIFontTTFGL goes out of scope, because
  7679. + // our virtual methods won't be accessible after this point
  7680. + m_dynamicCache.Flush();
  7681. }
  7682. bool CGUIFontTTFGL::FirstBegin()
  7683. @@ -182,7 +186,6 @@ void CGUIFontTTFGL::LastEnd()
  7684. if (m_vertexTrans.size() > 0)
  7685. {
  7686. // Deal with the vertices that can be hardware clipped and therefore translated
  7687. - std::vector<SVertex> vecVertices;
  7688. for (size_t i = 0; i < m_vertexTrans.size(); i++)
  7689. {
  7690. // Apply the clip rectangle
  7691. @@ -195,36 +198,17 @@ void CGUIFontTTFGL::LastEnd()
  7692. g_matrices.Translatef(m_vertexTrans[i].translateX, m_vertexTrans[i].translateY, m_vertexTrans[i].translateZ);
  7693. glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7694. - vecVertices.clear();
  7695. - for (size_t j = 0; j < m_vertexTrans[i].vertexBuffer->size(); j += 4)
  7696. - {
  7697. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j]);
  7698. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
  7699. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
  7700. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+1]);
  7701. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+3]);
  7702. - vecVertices.push_back((*m_vertexTrans[i].vertexBuffer)[j+2]);
  7703. - }
  7704. - SVertex *vertices = &vecVertices[0];
  7705. -
  7706. - // Generate a unique buffer object name and put it in vertexBuffer
  7707. - GLuint vertexBuffer;
  7708. - glGenBuffers(1, &vertexBuffer);
  7709. // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
  7710. - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
  7711. - // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
  7712. - // binding point (i.e. our buffer object) and initialise it from the
  7713. - // specified client-side pointer
  7714. - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof *vertices, vertices, GL_STATIC_DRAW);
  7715. + glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle);
  7716. +
  7717. // Set up the offsets of the various vertex attributes within the buffer
  7718. // object bound to GL_ARRAY_BUFFER
  7719. glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
  7720. glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
  7721. glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
  7722. +
  7723. // Do the actual drawing operation, using the full set of vertices in the buffer
  7724. - glDrawArrays(GL_TRIANGLES, 0, vecVertices.size());
  7725. - // Release the buffer name for reuse
  7726. - glDeleteBuffers(1, &vertexBuffer);
  7727. + glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size);
  7728. g_matrices.PopMatrix();
  7729. }
  7730. @@ -245,6 +229,48 @@ void CGUIFontTTFGL::LastEnd()
  7731. #endif
  7732. }
  7733. +#if HAS_GLES
  7734. +CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector<SVertex> &vertices) const
  7735. +{
  7736. + // Rearrange the vertices to describe triangles
  7737. + std::vector<SVertex> triangleVertices;
  7738. + triangleVertices.reserve(vertices.size() * 6 / 4);
  7739. + for (size_t i = 0; i < vertices.size(); i += 4)
  7740. + {
  7741. + triangleVertices.push_back(vertices[i]);
  7742. + triangleVertices.push_back(vertices[i+1]);
  7743. + triangleVertices.push_back(vertices[i+2]);
  7744. + triangleVertices.push_back(vertices[i+1]);
  7745. + triangleVertices.push_back(vertices[i+3]);
  7746. + triangleVertices.push_back(vertices[i+2]);
  7747. + }
  7748. +
  7749. + // Generate a unique buffer object name and put it in bufferHandle
  7750. + GLuint bufferHandle;
  7751. + glGenBuffers(1, &bufferHandle);
  7752. + // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
  7753. + glBindBuffer(GL_ARRAY_BUFFER, bufferHandle);
  7754. + // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
  7755. + // binding point (i.e. our buffer object) and initialise it from the
  7756. + // specified client-side pointer
  7757. + glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW);
  7758. + // Unbind GL_ARRAY_BUFFER
  7759. + glBindBuffer(GL_ARRAY_BUFFER, 0);
  7760. +
  7761. + return CVertexBuffer((void *) bufferHandle, vertices.size() / 4, this);
  7762. +}
  7763. +
  7764. +void CGUIFontTTFGL::DestroyVertexBuffer(CVertexBuffer &buffer) const
  7765. +{
  7766. + if (buffer.bufferHandle != 0)
  7767. + {
  7768. + // Release the buffer name for reuse
  7769. + glDeleteBuffers(1, (GLuint *) &buffer.bufferHandle);
  7770. + buffer.bufferHandle = 0;
  7771. + }
  7772. +}
  7773. +#endif
  7774. +
  7775. CBaseTexture* CGUIFontTTFGL::ReallocTexture(unsigned int& newHeight)
  7776. {
  7777. newHeight = CBaseTexture::PadPow2(newHeight);
  7778. diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
  7779. index 6736cf7..168fb21 100644
  7780. --- a/xbmc/guilib/GUIFontTTFGL.h
  7781. +++ b/xbmc/guilib/GUIFontTTFGL.h
  7782. @@ -29,6 +29,7 @@
  7783. #include "GUIFontTTF.h"
  7784. +#include "system.h"
  7785. /*!
  7786. @@ -43,6 +44,10 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
  7787. virtual bool FirstBegin();
  7788. virtual void LastEnd();
  7789. +#if HAS_GLES
  7790. + virtual CVertexBuffer CreateVertexBuffer(const std::vector<SVertex> &vertices) const;
  7791. + virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const;
  7792. +#endif
  7793. protected:
  7794. virtual CBaseTexture* ReallocTexture(unsigned int& newHeight);
  7795. --
  7796. 1.9.3
  7797. From 073c09ba7de6f6b7676c83d71b6933790626874f Mon Sep 17 00:00:00 2001
  7798. From: Ben Avison <bavison@riscosopen.org>
  7799. Date: Thu, 16 Jan 2014 16:29:42 +0000
  7800. Subject: [PATCH 31/94] Switch from glDrawArrays() to glDrawElements(). This
  7801. involves setting up a static VBO containing the indexes necessary to convert
  7802. from quads to triangles on the fly in the GPU.
  7803. ---
  7804. xbmc/guilib/GUIFontTTFGL.cpp | 72 +++++++++++++++++++++++++------------
  7805. xbmc/guilib/GUIFontTTFGL.h | 9 +++++
  7806. xbmc/windowing/egl/WinSystemEGL.cpp | 17 +++++++++
  7807. 3 files changed, 76 insertions(+), 22 deletions(-)
  7808. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  7809. index 1cd684b7..d476409 100644
  7810. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  7811. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  7812. @@ -186,6 +186,10 @@ void CGUIFontTTFGL::LastEnd()
  7813. if (m_vertexTrans.size() > 0)
  7814. {
  7815. // Deal with the vertices that can be hardware clipped and therefore translated
  7816. +
  7817. + // Bind our pre-calculated array to GL_ELEMENT_ARRAY_BUFFER
  7818. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle);
  7819. +
  7820. for (size_t i = 0; i < m_vertexTrans.size(); i++)
  7821. {
  7822. // Apply the clip rectangle
  7823. @@ -201,14 +205,21 @@ void CGUIFontTTFGL::LastEnd()
  7824. // Bind the buffer to the OpenGL context's GL_ARRAY_BUFFER binding point
  7825. glBindBuffer(GL_ARRAY_BUFFER, (GLuint) m_vertexTrans[i].vertexBuffer->bufferHandle);
  7826. - // Set up the offsets of the various vertex attributes within the buffer
  7827. - // object bound to GL_ARRAY_BUFFER
  7828. - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, x));
  7829. - glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, r));
  7830. - glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) offsetof(SVertex, u));
  7831. + // Do the actual drawing operation, split into groups of characters no
  7832. + // larger than the pre-determined size of the element array
  7833. + for (size_t character = 0; m_vertexTrans[i].vertexBuffer->size > character; character += ELEMENT_ARRAY_MAX_CHAR_INDEX)
  7834. + {
  7835. + size_t count = m_vertexTrans[i].vertexBuffer->size - character;
  7836. + count = std::min<size_t>(count, ELEMENT_ARRAY_MAX_CHAR_INDEX);
  7837. +
  7838. + // Set up the offsets of the various vertex attributes within the buffer
  7839. + // object bound to GL_ARRAY_BUFFER
  7840. + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, x)));
  7841. + glVertexAttribPointer(colLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, r)));
  7842. + glVertexAttribPointer(tex0Loc, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (GLvoid *) (character*sizeof(SVertex)*4 + offsetof(SVertex, u)));
  7843. - // Do the actual drawing operation, using the full set of vertices in the buffer
  7844. - glDrawArrays(GL_TRIANGLES, 0, 6 * m_vertexTrans[i].vertexBuffer->size);
  7845. + glDrawElements(GL_TRIANGLES, 6 * count, GL_UNSIGNED_SHORT, 0);
  7846. + }
  7847. g_matrices.PopMatrix();
  7848. }
  7849. @@ -216,8 +227,9 @@ void CGUIFontTTFGL::LastEnd()
  7850. g_graphicsContext.ResetScissors();
  7851. // Restore the original model view matrix
  7852. glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  7853. - // Unbind GL_ARRAY_BUFFER
  7854. + // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER
  7855. glBindBuffer(GL_ARRAY_BUFFER, 0);
  7856. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  7857. }
  7858. // Disable the attributes used by this shader
  7859. @@ -232,19 +244,6 @@ void CGUIFontTTFGL::LastEnd()
  7860. #if HAS_GLES
  7861. CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector<SVertex> &vertices) const
  7862. {
  7863. - // Rearrange the vertices to describe triangles
  7864. - std::vector<SVertex> triangleVertices;
  7865. - triangleVertices.reserve(vertices.size() * 6 / 4);
  7866. - for (size_t i = 0; i < vertices.size(); i += 4)
  7867. - {
  7868. - triangleVertices.push_back(vertices[i]);
  7869. - triangleVertices.push_back(vertices[i+1]);
  7870. - triangleVertices.push_back(vertices[i+2]);
  7871. - triangleVertices.push_back(vertices[i+1]);
  7872. - triangleVertices.push_back(vertices[i+3]);
  7873. - triangleVertices.push_back(vertices[i+2]);
  7874. - }
  7875. -
  7876. // Generate a unique buffer object name and put it in bufferHandle
  7877. GLuint bufferHandle;
  7878. glGenBuffers(1, &bufferHandle);
  7879. @@ -253,7 +252,7 @@ CVertexBuffer CGUIFontTTFGL::CreateVertexBuffer(const std::vector<SVertex> &vert
  7880. // Create a data store for the buffer object bound to the GL_ARRAY_BUFFER
  7881. // binding point (i.e. our buffer object) and initialise it from the
  7882. // specified client-side pointer
  7883. - glBufferData(GL_ARRAY_BUFFER, triangleVertices.size() * sizeof (SVertex), &triangleVertices[0], GL_STATIC_DRAW);
  7884. + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof (SVertex), &vertices[0], GL_STATIC_DRAW);
  7885. // Unbind GL_ARRAY_BUFFER
  7886. glBindBuffer(GL_ARRAY_BUFFER, 0);
  7887. @@ -348,4 +347,33 @@ void CGUIFontTTFGL::DeleteHardwareTexture()
  7888. }
  7889. }
  7890. +#if HAS_GLES
  7891. +void CGUIFontTTFGL::CreateStaticVertexBuffers(void)
  7892. +{
  7893. + // Bind a new buffer to the OpenGL context's GL_ELEMENT_ARRAY_BUFFER binding point
  7894. + glGenBuffers(1, &m_elementArrayHandle);
  7895. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementArrayHandle);
  7896. + // Create an array holding the mesh indices to convert quads to triangles
  7897. + GLushort index[ELEMENT_ARRAY_MAX_CHAR_INDEX][6];
  7898. + for (size_t i = 0; i < ELEMENT_ARRAY_MAX_CHAR_INDEX; i++)
  7899. + {
  7900. + index[i][0] = 4*i;
  7901. + index[i][1] = 4*i+1;
  7902. + index[i][2] = 4*i+2;
  7903. + index[i][3] = 4*i+1;
  7904. + index[i][4] = 4*i+3;
  7905. + index[i][5] = 4*i+2;
  7906. + }
  7907. + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof index, index, GL_STATIC_DRAW);
  7908. + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  7909. +}
  7910. +
  7911. +void CGUIFontTTFGL::DestroyStaticVertexBuffers(void)
  7912. +{
  7913. + glDeleteBuffers(1, &m_elementArrayHandle);
  7914. +}
  7915. +
  7916. +GLuint CGUIFontTTFGL::m_elementArrayHandle;
  7917. +#endif
  7918. +
  7919. #endif
  7920. diff --git a/xbmc/guilib/GUIFontTTFGL.h b/xbmc/guilib/GUIFontTTFGL.h
  7921. index 168fb21..a14ab7a 100644
  7922. --- a/xbmc/guilib/GUIFontTTFGL.h
  7923. +++ b/xbmc/guilib/GUIFontTTFGL.h
  7924. @@ -30,6 +30,7 @@
  7925. #include "GUIFontTTF.h"
  7926. #include "system.h"
  7927. +#include "system_gl.h"
  7928. /*!
  7929. @@ -47,6 +48,8 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
  7930. #if HAS_GLES
  7931. virtual CVertexBuffer CreateVertexBuffer(const std::vector<SVertex> &vertices) const;
  7932. virtual void DestroyVertexBuffer(CVertexBuffer &bufferHandle) const;
  7933. + static void CreateStaticVertexBuffers(void);
  7934. + static void DestroyStaticVertexBuffers(void);
  7935. #endif
  7936. protected:
  7937. @@ -54,6 +57,12 @@ class CGUIFontTTFGL : public CGUIFontTTFBase
  7938. virtual bool CopyCharToTexture(FT_BitmapGlyph bitGlyph, unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
  7939. virtual void DeleteHardwareTexture();
  7940. +#if HAS_GLES
  7941. +#define ELEMENT_ARRAY_MAX_CHAR_INDEX (1000)
  7942. +
  7943. + static GLuint m_elementArrayHandle;
  7944. +#endif
  7945. +
  7946. };
  7947. #endif
  7948. diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp
  7949. index dfc4672..0c32947 100644
  7950. --- a/xbmc/windowing/egl/WinSystemEGL.cpp
  7951. +++ b/xbmc/windowing/egl/WinSystemEGL.cpp
  7952. @@ -29,6 +29,7 @@
  7953. #include "settings/AdvancedSettings.h"
  7954. #include "settings/Settings.h"
  7955. #include "settings/DisplaySettings.h"
  7956. +#include "guilib/GUIFontTTFGL.h"
  7957. #include "utils/log.h"
  7958. #include "EGLWrapper.h"
  7959. #include "EGLQuirks.h"
  7960. @@ -192,6 +193,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
  7961. return false;
  7962. }
  7963. +#if HAS_GLES
  7964. + bool newContext = false;
  7965. +#endif
  7966. if (m_context == EGL_NO_CONTEXT)
  7967. {
  7968. if (!m_egl->CreateContext(m_display, m_config, contextAttrs, &m_context))
  7969. @@ -199,6 +203,9 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
  7970. CLog::Log(LOGERROR, "%s: Could not create context",__FUNCTION__);
  7971. return false;
  7972. }
  7973. +#if HAS_GLES
  7974. + newContext = true;
  7975. +#endif
  7976. }
  7977. if (!m_egl->BindContext(m_display, m_surface, m_context))
  7978. @@ -207,6 +214,11 @@ bool CWinSystemEGL::CreateWindow(RESOLUTION_INFO &res)
  7979. return false;
  7980. }
  7981. +#if HAS_GLES
  7982. + if (newContext)
  7983. + CGUIFontTTFGL::CreateStaticVertexBuffers();
  7984. +#endif
  7985. +
  7986. // for the non-trivial dirty region modes, we need the EGL buffer to be preserved across updates
  7987. if (g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_COST_REDUCTION ||
  7988. g_advancedSettings.m_guiAlgorithmDirtyRegions == DIRTYREGION_SOLVER_UNION)
  7989. @@ -228,7 +240,12 @@ bool CWinSystemEGL::DestroyWindowSystem()
  7990. DestroyWindow();
  7991. if (m_context != EGL_NO_CONTEXT)
  7992. + {
  7993. +#if HAS_GLES
  7994. + CGUIFontTTFGL::DestroyStaticVertexBuffers();
  7995. +#endif
  7996. m_egl->DestroyContext(m_display, m_context);
  7997. + }
  7998. m_context = EGL_NO_CONTEXT;
  7999. if (m_display != EGL_NO_DISPLAY)
  8000. --
  8001. 1.9.3
  8002. From ec39dce3628b276e3ed2fe19c95a056a1aa171b8 Mon Sep 17 00:00:00 2001
  8003. From: Ben Avison <bavison@riscosopen.org>
  8004. Date: Tue, 4 Feb 2014 16:17:57 +0000
  8005. Subject: [PATCH 32/94] Update Windows project files
  8006. ---
  8007. project/VS2010Express/XBMC.vcxproj | 2 ++
  8008. project/VS2010Express/XBMC.vcxproj.filters | 6 ++++++
  8009. 2 files changed, 8 insertions(+)
  8010. diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj
  8011. index c6de5ca..a9731de 100644
  8012. --- a/project/VS2010Express/XBMC.vcxproj
  8013. +++ b/project/VS2010Express/XBMC.vcxproj
  8014. @@ -540,6 +540,7 @@
  8015. <ClCompile Include="..\..\xbmc\guilib\GUIFadeLabelControl.cpp" />
  8016. <ClCompile Include="..\..\xbmc\guilib\GUIFixedListContainer.cpp" />
  8017. <ClCompile Include="..\..\xbmc\guilib\GUIFont.cpp" />
  8018. + <ClCompile Include="..\..\xbmc\guilib\GUIFontCache.cpp" />
  8019. <ClCompile Include="..\..\xbmc\guilib\GUIFontManager.cpp" />
  8020. <ClCompile Include="..\..\xbmc\guilib\GUIFontTTF.cpp" />
  8021. <ClCompile Include="..\..\xbmc\guilib\GUIFontTTFDX.cpp" />
  8022. @@ -2057,6 +2058,7 @@
  8023. <ClInclude Include="..\..\xbmc\guilib\GUIFadeLabelControl.h" />
  8024. <ClInclude Include="..\..\xbmc\guilib\GUIFixedListContainer.h" />
  8025. <ClInclude Include="..\..\xbmc\guilib\GUIFont.h" />
  8026. + <ClInclude Include="..\..\xbmc\guilib\GUIFontCache.h" />
  8027. <ClInclude Include="..\..\xbmc\guilib\GUIFontManager.h" />
  8028. <ClInclude Include="..\..\xbmc\guilib\GUIFontTTF.h" />
  8029. <ClInclude Include="..\..\xbmc\guilib\GUIFontTTFDX.h" />
  8030. diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters
  8031. index b536eb3..cb34443 100644
  8032. --- a/project/VS2010Express/XBMC.vcxproj.filters
  8033. +++ b/project/VS2010Express/XBMC.vcxproj.filters
  8034. @@ -1024,6 +1024,9 @@
  8035. <ClCompile Include="..\..\xbmc\guilib\GUIFont.cpp">
  8036. <Filter>guilib</Filter>
  8037. </ClCompile>
  8038. + <ClCompile Include="..\..\xbmc\guilib\GUIFontCache.cpp">
  8039. + <Filter>guilib</Filter>
  8040. + </ClCompile>
  8041. <ClCompile Include="..\..\xbmc\guilib\GUIFontManager.cpp">
  8042. <Filter>guilib</Filter>
  8043. </ClCompile>
  8044. @@ -3978,6 +3981,9 @@
  8045. <ClInclude Include="..\..\xbmc\guilib\GUIFont.h">
  8046. <Filter>guilib</Filter>
  8047. </ClInclude>
  8048. + <ClInclude Include="..\..\xbmc\guilib\GUIFontCache.h">
  8049. + <Filter>guilib</Filter>
  8050. + </ClInclude>
  8051. <ClInclude Include="..\..\xbmc\guilib\GUIFontManager.h">
  8052. <Filter>guilib</Filter>
  8053. </ClInclude>
  8054. --
  8055. 1.9.3
  8056. From e25eb385d09a5378be8616f10806610df90416db Mon Sep 17 00:00:00 2001
  8057. From: Ben Avison <bavison@riscosopen.org>
  8058. Date: Tue, 4 Feb 2014 16:49:45 +0000
  8059. Subject: [PATCH 33/94] Update XCode project file
  8060. ---
  8061. XBMC.xcodeproj/project.pbxproj | 10 ++++++++++
  8062. 1 file changed, 10 insertions(+)
  8063. diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj
  8064. index fdd10a1..62e7e69 100644
  8065. --- a/XBMC.xcodeproj/project.pbxproj
  8066. +++ b/XBMC.xcodeproj/project.pbxproj
  8067. @@ -168,6 +168,9 @@
  8068. 1D638128161E211E003603ED /* PeripheralImon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D638126161E211E003603ED /* PeripheralImon.cpp */; };
  8069. 1DAFDB7C16DFDCA7007F8C68 /* PeripheralBusCEC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DAFDB7A16DFDCA7007F8C68 /* PeripheralBusCEC.cpp */; };
  8070. 1DE0443515828F4B005DDB4D /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1DE0443315828F4B005DDB4D /* Exception.cpp */; };
  8071. + 2FD7EC5F18A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; };
  8072. + 2FD7EC6018A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; };
  8073. + 2FD7EC6118A14FE50047F86C /* GUIFontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */; };
  8074. 32C631281423A90F00F18420 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; };
  8075. 36A9443D15821E2800727135 /* DatabaseUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443B15821E2800727135 /* DatabaseUtils.cpp */; };
  8076. 36A9444115821E7C00727135 /* SortUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 36A9443F15821E7C00727135 /* SortUtils.cpp */; };
  8077. @@ -3546,6 +3549,8 @@
  8078. 1DAFDB7B16DFDCA7007F8C68 /* PeripheralBusCEC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusCEC.h; sourceTree = "<group>"; };
  8079. 1DE0443315828F4B005DDB4D /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exception.cpp; path = commons/Exception.cpp; sourceTree = "<group>"; };
  8080. 1DE0443415828F4B005DDB4D /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Exception.h; path = commons/Exception.h; sourceTree = "<group>"; };
  8081. + 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIFontCache.cpp; sourceTree = "<group>"; };
  8082. + 2FD7EC5E18A14FE50047F86C /* GUIFontCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIFontCache.h; sourceTree = "<group>"; };
  8083. 32C631261423A90F00F18420 /* JpegIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JpegIO.cpp; sourceTree = "<group>"; };
  8084. 32C631271423A90F00F18420 /* JpegIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JpegIO.h; sourceTree = "<group>"; };
  8085. 36A9443B15821E2800727135 /* DatabaseUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseUtils.cpp; sourceTree = "<group>"; };
  8086. @@ -5923,6 +5928,8 @@
  8087. 18B7C76A1294222E009E7A26 /* GUIFixedListContainer.cpp */,
  8088. 18B7C7101294222D009E7A26 /* GUIFixedListContainer.h */,
  8089. 18B7C76B1294222E009E7A26 /* GUIFont.cpp */,
  8090. + 2FD7EC5D18A14FE50047F86C /* GUIFontCache.cpp */,
  8091. + 2FD7EC5E18A14FE50047F86C /* GUIFontCache.h */,
  8092. 18B7C7111294222D009E7A26 /* GUIFont.h */,
  8093. 18B7C76C1294222E009E7A26 /* GUIFontManager.cpp */,
  8094. 18B7C7121294222D009E7A26 /* GUIFontManager.h */,
  8095. @@ -10930,6 +10937,7 @@
  8096. 7C8AE850189DE3CD00C33786 /* CoreAudioHardware.cpp in Sources */,
  8097. 7C8AE851189DE3CD00C33786 /* CoreAudioStream.cpp in Sources */,
  8098. 7C8AE854189DE47F00C33786 /* CoreAudioHelpers.cpp in Sources */,
  8099. + 2FD7EC5F18A14FE50047F86C /* GUIFontCache.cpp in Sources */,
  8100. );
  8101. runOnlyForDeploymentPostprocessing = 0;
  8102. };
  8103. @@ -11978,6 +11986,7 @@
  8104. F5CC234818150277006B5E91 /* AESinkNULL.cpp in Sources */,
  8105. F5CC238918150768006B5E91 /* AESinkProfiler.cpp in Sources */,
  8106. DF374B2518AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */,
  8107. + 2FD7EC6118A14FE50047F86C /* GUIFontCache.cpp in Sources */,
  8108. );
  8109. runOnlyForDeploymentPostprocessing = 0;
  8110. };
  8111. @@ -13028,6 +13037,7 @@
  8112. F5CC234718150277006B5E91 /* AESinkNULL.cpp in Sources */,
  8113. F5CC238818150768006B5E91 /* AESinkProfiler.cpp in Sources */,
  8114. DF374B2418AC2BA20076B514 /* CoreAudioHelpers.cpp in Sources */,
  8115. + 2FD7EC6018A14FE50047F86C /* GUIFontCache.cpp in Sources */,
  8116. );
  8117. runOnlyForDeploymentPostprocessing = 0;
  8118. };
  8119. --
  8120. 1.9.3
  8121. From 5f4ebd2e9fd6d503220627b916e522b671d7d9ba Mon Sep 17 00:00:00 2001
  8122. From: Ben Avison <bavison@riscosopen.org>
  8123. Date: Tue, 4 Feb 2014 17:44:34 +0000
  8124. Subject: [PATCH 34/94] Clang seems to be more picky than gcc about some C++
  8125. template syntax
  8126. ---
  8127. xbmc/guilib/GUIFontCache.cpp | 20 ++++++++++----------
  8128. 1 file changed, 10 insertions(+), 10 deletions(-)
  8129. diff --git a/xbmc/guilib/GUIFontCache.cpp b/xbmc/guilib/GUIFontCache.cpp
  8130. index 895fa72..bd84b9a 100644
  8131. --- a/xbmc/guilib/GUIFontCache.cpp
  8132. +++ b/xbmc/guilib/GUIFontCache.cpp
  8133. @@ -61,26 +61,26 @@ Value &CGUIFontCache<Position, Value>::Lookup(Position &pos,
  8134. alignment, maxPixelWidth,
  8135. scrolling, g_graphicsContext.GetGUIMatrix(),
  8136. g_graphicsContext.GetGUIScaleX(), g_graphicsContext.GetGUIScaleY());
  8137. - EntryHashIterator i = m_list.get<Hash>().find(key);
  8138. - if (i == m_list.get<Hash>().end())
  8139. + EntryHashIterator i = m_list.template get<Hash>().find(key);
  8140. + if (i == m_list.template get<Hash>().end())
  8141. {
  8142. /* Cache miss */
  8143. - EntryAgeIterator oldest = m_list.get<Age>().begin();
  8144. - if (!m_list.get<Age>().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT)
  8145. + EntryAgeIterator oldest = m_list.template get<Age>().begin();
  8146. + if (!m_list.template get<Age>().empty() && nowMillis - oldest->m_lastUsedMillis > FONT_CACHE_TIME_LIMIT)
  8147. {
  8148. /* The oldest existing entry is old enough to expire and reuse */
  8149. - m_list.get<Hash>().modify(m_list.project<Hash>(oldest), typename CGUIFontCacheEntry<Position, Value>::Reassign(key, nowMillis));
  8150. - m_list.get<Age>().relocate(m_list.get<Age>().end(), oldest);
  8151. + m_list.template get<Hash>().modify(m_list.template project<Hash>(oldest), typename CGUIFontCacheEntry<Position, Value>::Reassign(key, nowMillis));
  8152. + m_list.template get<Age>().relocate(m_list.template get<Age>().end(), oldest);
  8153. }
  8154. else
  8155. {
  8156. /* We need a new entry instead */
  8157. /* Yes, this causes the creation an destruction of a temporary entry, but
  8158. * this code ought to only be used infrequently, when the cache needs to grow */
  8159. - m_list.get<Age>().push_back(CGUIFontCacheEntry<Position, Value>(*this, key, nowMillis));
  8160. + m_list.template get<Age>().push_back(CGUIFontCacheEntry<Position, Value>(*this, key, nowMillis));
  8161. }
  8162. dirtyCache = true;
  8163. - return (--m_list.get<Age>().end())->m_value;
  8164. + return (--m_list.template get<Age>().end())->m_value;
  8165. }
  8166. else
  8167. {
  8168. @@ -90,7 +90,7 @@ Value &CGUIFontCache<Position, Value>::Lookup(Position &pos,
  8169. pos.UpdateWithOffsets(i->m_key.m_pos, scrolling);
  8170. /* Update time in entry and move to the back of the list */
  8171. i->m_lastUsedMillis = nowMillis;
  8172. - m_list.get<Age>().relocate(m_list.get<Age>().end(), m_list.project<Age>(i));
  8173. + m_list.template get<Age>().relocate(m_list.template get<Age>().end(), m_list.template project<Age>(i));
  8174. dirtyCache = false;
  8175. return i->m_value;
  8176. }
  8177. @@ -99,7 +99,7 @@ Value &CGUIFontCache<Position, Value>::Lookup(Position &pos,
  8178. template<class Position, class Value>
  8179. void CGUIFontCache<Position, Value>::Flush()
  8180. {
  8181. - m_list.get<Age>().clear();
  8182. + m_list.template get<Age>().clear();
  8183. }
  8184. template void CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue>::Reassign::operator()(CGUIFontCacheEntry<CGUIFontCacheStaticPosition, CGUIFontCacheStaticValue> &entry);
  8185. --
  8186. 1.9.3
  8187. From 33693dc9ff9ba7695bc0e702a41566d54a5135b9 Mon Sep 17 00:00:00 2001
  8188. From: Ben Avison <bavison@riscosopen.org>
  8189. Date: Tue, 4 Feb 2014 18:52:14 +0000
  8190. Subject: [PATCH 35/94] Fix header to hopefully permit iOS builds to work
  8191. again. GUIShader.cpp added #include windowing/egl/WinSystemEGL.h inside a but
  8192. also need the header windowing/osx/WinSystemIOS.h instead. The only thing
  8193. GUIShader.cpp needed was g_windowing.GetViewPort, which is provided by the
  8194. common base class CRenderSystemGLES of g_windowing in both cases, so I think
  8195. it should be sufficient to use windowing/WindowingFactory.h instead, which is
  8196. abstracted away from the other header files.
  8197. ---
  8198. xbmc/guilib/GUIShader.cpp | 2 +-
  8199. 1 file changed, 1 insertion(+), 1 deletion(-)
  8200. diff --git a/xbmc/guilib/GUIShader.cpp b/xbmc/guilib/GUIShader.cpp
  8201. index 53bce09..86330cc 100644
  8202. --- a/xbmc/guilib/GUIShader.cpp
  8203. +++ b/xbmc/guilib/GUIShader.cpp
  8204. @@ -26,7 +26,7 @@
  8205. #include "GUIShader.h"
  8206. #include "MatrixGLES.h"
  8207. #include "utils/log.h"
  8208. -#include "windowing/egl/WinSystemEGL.h"
  8209. +#include "windowing/WindowingFactory.h"
  8210. #include "guilib/GraphicContext.h"
  8211. CGUIShader::CGUIShader( const char *shader ) : CGLSLShaderProgram("guishader_vert.glsl", shader)
  8212. --
  8213. 1.9.3
  8214. From 9b95b3b13bd714d8320dc61c5039eee6cb3c5737 Mon Sep 17 00:00:00 2001
  8215. From: Ben Avison <bavison@riscosopen.org>
  8216. Date: Tue, 8 Apr 2014 18:14:55 +0100
  8217. Subject: [PATCH 36/94] Fix font display in stereoscopic modes
  8218. CGUIFontTTFGL::LastEnd was previously using the relatively high-level
  8219. CGraphicContext::SetScissors function to enforce hardware clipping. However,
  8220. the coordinates it passed in already contained the stereoscopic offset, so
  8221. the CGraphicContext::SetScissors effectively ended up double-applying the
  8222. offset, with the effect that clip rectangles were always off-screen. Changed
  8223. to call the low-level SetScissors call instead (using g_Windowing to select
  8224. the correct implementation, e.g. CRenderSystemGLES::SetScissors). This also
  8225. skips the intersection of the scissors with the screen limits, but that does
  8226. not appear to matter in practice.
  8227. ---
  8228. xbmc/guilib/GUIFontTTFGL.cpp | 4 ++--
  8229. 1 file changed, 2 insertions(+), 2 deletions(-)
  8230. diff --git a/xbmc/guilib/GUIFontTTFGL.cpp b/xbmc/guilib/GUIFontTTFGL.cpp
  8231. index d476409..8466a81 100644
  8232. --- a/xbmc/guilib/GUIFontTTFGL.cpp
  8233. +++ b/xbmc/guilib/GUIFontTTFGL.cpp
  8234. @@ -194,7 +194,7 @@ void CGUIFontTTFGL::LastEnd()
  8235. {
  8236. // Apply the clip rectangle
  8237. CRect clip = g_Windowing.ClipRectToScissorRect(m_vertexTrans[i].clip);
  8238. - g_graphicsContext.SetScissors(clip);
  8239. + g_Windowing.SetScissors(clip);
  8240. // Apply the translation to the currently active (top-of-stack) model view matrix
  8241. g_matrices.MatrixMode(MM_MODELVIEW);
  8242. @@ -224,7 +224,7 @@ void CGUIFontTTFGL::LastEnd()
  8243. g_matrices.PopMatrix();
  8244. }
  8245. // Restore the original scissor rectangle
  8246. - g_graphicsContext.ResetScissors();
  8247. + g_Windowing.ResetScissors();
  8248. // Restore the original model view matrix
  8249. glUniformMatrix4fv(modelLoc, 1, GL_FALSE, g_matrices.GetMatrix(MM_MODELVIEW));
  8250. // Unbind GL_ARRAY_BUFFER and GL_ELEMENT_ARRAY_BUFFER
  8251. --
  8252. 1.9.3
  8253. From d51ef43b61b50de46edb2832f457af8229995cab Mon Sep 17 00:00:00 2001
  8254. From: popcornmix <popcornmix@gmail.com>
  8255. Date: Fri, 10 Jan 2014 12:10:43 +0000
  8256. Subject: [PATCH 37/94] [rbp] Don't override dvdplayer with omxplayer.
  8257. Using dvdplayer can be useful on the Pi. We can actually play sd (up to 640x480 MPEG-4 video) video in real time.
  8258. This is useful for codec variants like DivX3 which we don't currently play.
  8259. This may expose bugs where dvdplayer is incorrectly used as the default player which will need to be fixed
  8260. ---
  8261. xbmc/cores/playercorefactory/PlayerCoreConfig.h | 7 -------
  8262. 1 file changed, 7 deletions(-)
  8263. diff --git a/xbmc/cores/playercorefactory/PlayerCoreConfig.h b/xbmc/cores/playercorefactory/PlayerCoreConfig.h
  8264. index 27f0bec..fc12bb7 100644
  8265. --- a/xbmc/cores/playercorefactory/PlayerCoreConfig.h
  8266. +++ b/xbmc/cores/playercorefactory/PlayerCoreConfig.h
  8267. @@ -88,14 +88,7 @@ friend class CPlayerCoreFactory;
  8268. {
  8269. case EPC_MPLAYER:
  8270. // TODO: this hack needs removal until we have a better player selection
  8271. -#if defined(HAS_OMXPLAYER)
  8272. - case EPC_DVDPLAYER:
  8273. - pPlayer = new COMXPlayer(callback);
  8274. - CLog::Log(LOGINFO, "Created player %s for core %d / OMXPlayer forced as DVDPlayer", "OMXPlayer", m_eCore);
  8275. - break;
  8276. -#else
  8277. case EPC_DVDPLAYER: pPlayer = new CDVDPlayer(callback); break;
  8278. -#endif
  8279. case EPC_PAPLAYER: pPlayer = new PAPlayer(callback); break;
  8280. case EPC_EXTPLAYER: pPlayer = new CExternalPlayer(callback); break;
  8281. #if defined(HAS_OMXPLAYER)
  8282. --
  8283. 1.9.3
  8284. From 3cd01da5418f1693e50ed40273cb17ca9f6d622a Mon Sep 17 00:00:00 2001
  8285. From: popcornmix <popcornmix@gmail.com>
  8286. Date: Fri, 10 Jan 2014 15:37:41 +0000
  8287. Subject: [PATCH 38/94] [players] Use default players rather than hard coded
  8288. DVDPlayer/PAPlayer
  8289. ---
  8290. system/playercorefactory.xml | 23 ++++++++++++-----------
  8291. 1 file changed, 12 insertions(+), 11 deletions(-)
  8292. diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml
  8293. index 57dfcdd..7be9799 100644
  8294. --- a/system/playercorefactory.xml
  8295. +++ b/system/playercorefactory.xml
  8296. @@ -11,31 +11,32 @@
  8297. </players>
  8298. <rules name="system rules">
  8299. - <rule name="rtv" protocols="rtv" player="DVDPlayer" />
  8300. - <rule name="hdhomerun/myth/mms/udp" protocols="hdhomerun|myth|cmyth|mms|mmsh|udp" player="DVDPlayer" />
  8301. - <rule name="lastfm/shout" protocols="lastfm|shout" player="PAPlayer" />
  8302. + <rule name="rtv" protocols="rtv" player="videodefaultplayer" />
  8303. + <rule name="hdhomerun/myth/mms/udp" protocols="hdhomerun|myth|cmyth|mms|mmsh|udp" player="videodefaultplayer" />
  8304. + <rule name="lastfm/shout" protocols="lastfm|shout" player="audiodefaultplayer" />
  8305. <rule name="rtmp" protocols="rtmp" player="videodefaultplayer" />
  8306. <!-- dvdplayer can play standard rtsp streams -->
  8307. - <rule name="rtsp" protocols="rtsp" filetypes="!(rm|ra)" player="PAPlayer" />
  8308. + <rule name="rtsp" protocols="rtsp" filetypes="!(rm|ra)" player="audiodefaultplayer" />
  8309. <!-- Internet streams -->
  8310. <rule name="streams" internetstream="true">
  8311. - <rule name="aacp/sdp" mimetypes="audio/aacp|application/sdp" player="DVDPlayer" />
  8312. - <rule name="mp2" mimetypes="application/octet-stream" filetypes="mp2" player="PAPlayer" />
  8313. + <rule name="aacp/sdp" mimetypes="audio/aacp|application/sdp" player="videodefaultplayer" />
  8314. + <rule name="mp2" mimetypes="application/octet-stream" filetypes="mp2" player="audiodefaultplayer" />
  8315. </rule>
  8316. <!-- DVDs -->
  8317. - <rule name="dvd" dvd="true" player="DVDPlayer" />
  8318. - <rule name="dvdimage" dvdimage="true" player="DVDPlayer" />
  8319. + <rule name="dvd" dvd="true" player="videodefaultdvdplayer" />
  8320. + <rule name="dvdfile" dvdfile="true" player="videodefaultdvdplayer" />
  8321. + <rule name="dvdimage" dvdimage="true" player="videodefaultdvdplayer" />
  8322. <!-- Only dvdplayer can handle these normally -->
  8323. - <rule name="sdp/asf" filetypes="sdp|asf" player="DVDPlayer" />
  8324. + <rule name="sdp/asf" filetypes="sdp|asf" player="videodefaultplayer" />
  8325. <!-- Pass these to dvdplayer as we do not know if they are audio or video -->
  8326. - <rule name="nsv" filetypes="nsv" player="DVDPlayer" />
  8327. + <rule name="nsv" filetypes="nsv" player="videodefaultplayer" />
  8328. <!-- pvr radio channels should be played by dvdplayer because they need buffering -->
  8329. - <rule name="radio" filetypes="pvr" filename=".*/radio/.*" player="DVDPlayer" />
  8330. + <rule name="radio" filetypes="pvr" filename=".*/radio/.*" player="videodefaultplayer" />
  8331. </rules>
  8332. </playercorefactory>
  8333. --
  8334. 1.9.3
  8335. From 5c4de293325bba93c4b820aed6863ee8d732ce2c Mon Sep 17 00:00:00 2001
  8336. From: popcornmix <popcornmix@gmail.com>
  8337. Date: Sat, 11 Jan 2014 18:23:42 +0000
  8338. Subject: [PATCH 39/94] [rbp] Don't force dvdplayer for airplay
  8339. ---
  8340. xbmc/network/AirPlayServer.cpp | 2 ++
  8341. 1 file changed, 2 insertions(+)
  8342. diff --git a/xbmc/network/AirPlayServer.cpp b/xbmc/network/AirPlayServer.cpp
  8343. index 8040d9b..182daaa 100644
  8344. --- a/xbmc/network/AirPlayServer.cpp
  8345. +++ b/xbmc/network/AirPlayServer.cpp
  8346. @@ -906,9 +906,11 @@ int CAirPlayServer::CTCPClient::ProcessRequest( CStdString& responseHeader,
  8347. CFileItem fileToPlay(location, false);
  8348. fileToPlay.SetProperty("StartPercent", position*100.0f);
  8349. ServerInstance->AnnounceToClients(EVENT_LOADING);
  8350. +#ifndef TARGET_RASPBERRY_PI
  8351. // froce to internal dvdplayer cause it is the only
  8352. // one who will work well with airplay
  8353. g_application.m_eForcedNextPlayer = EPC_DVDPLAYER;
  8354. +#endif
  8355. CApplicationMessenger::Get().MediaPlay(fileToPlay);
  8356. }
  8357. }
  8358. --
  8359. 1.9.3
  8360. From 454b77543018aac5d7e70769ef13231ae16eefb9 Mon Sep 17 00:00:00 2001
  8361. From: popcornmix <popcornmix@gmail.com>
  8362. Date: Mon, 13 Jan 2014 13:11:06 +0000
  8363. Subject: [PATCH 40/94] [rbp] Give plugins omxplayer when they request
  8364. dvdplayer on pi
  8365. ---
  8366. xbmc/interfaces/legacy/ModuleXbmc.cpp | 4 ++++
  8367. 1 file changed, 4 insertions(+)
  8368. diff --git a/xbmc/interfaces/legacy/ModuleXbmc.cpp b/xbmc/interfaces/legacy/ModuleXbmc.cpp
  8369. index 16f0174..b172d47 100644
  8370. --- a/xbmc/interfaces/legacy/ModuleXbmc.cpp
  8371. +++ b/xbmc/interfaces/legacy/ModuleXbmc.cpp
  8372. @@ -536,7 +536,11 @@ namespace XBMCAddon
  8373. int getPLAYLIST_MUSIC() { return PLAYLIST_MUSIC; }
  8374. int getPLAYLIST_VIDEO() { return PLAYLIST_VIDEO; }
  8375. int getPLAYER_CORE_AUTO() { return EPC_NONE; }
  8376. +#ifdef TARGET_RASPBERRY_PI
  8377. + int getPLAYER_CORE_DVDPLAYER() { return EPC_OMXPLAYER; }
  8378. +#else
  8379. int getPLAYER_CORE_DVDPLAYER() { return EPC_DVDPLAYER; }
  8380. +#endif
  8381. int getPLAYER_CORE_MPLAYER() { return EPC_MPLAYER; }
  8382. int getPLAYER_CORE_PAPLAYER() { return EPC_PAPLAYER; }
  8383. int getTRAY_OPEN() { return TRAY_OPEN; }
  8384. --
  8385. 1.9.3
  8386. From 7201ee3e0ca664518eaaf3142682b294c34c69c0 Mon Sep 17 00:00:00 2001
  8387. From: popcornmix <popcornmix@gmail.com>
  8388. Date: Tue, 14 Jan 2014 18:04:07 +0000
  8389. Subject: [PATCH 41/94] [rbp] Allow ALSA to be chosen in addition to Pi sink
  8390. Needs --enable-alsa in ./configure step and alsa support on platform
  8391. ---
  8392. configure.in | 1 -
  8393. tools/depends/target/Makefile | 6 +++---
  8394. xbmc/cores/AudioEngine/AESinkFactory.cpp | 17 +++++++++++++++--
  8395. 3 files changed, 18 insertions(+), 6 deletions(-)
  8396. diff --git a/configure.in b/configure.in
  8397. index a195d00..34dd038 100644
  8398. --- a/configure.in
  8399. +++ b/configure.in
  8400. @@ -742,7 +742,6 @@ case $use_platform in
  8401. use_arch="arm"
  8402. use_cpu=arm1176jzf-s
  8403. use_hardcoded_tables="yes"
  8404. - use_alsa="no"
  8405. ARCH="arm"
  8406. AC_DEFINE(HAS_EGLGLES, [1], [Define if supporting EGL based GLES Framebuffer])
  8407. USE_OMXLIB=1; AC_DEFINE([HAVE_OMXLIB],[1],["Define to 1 if OMX libs is enabled"])
  8408. diff --git a/tools/depends/target/Makefile b/tools/depends/target/Makefile
  8409. index 4588917..0fbd3e7 100644
  8410. --- a/tools/depends/target/Makefile
  8411. +++ b/tools/depends/target/Makefile
  8412. @@ -55,10 +55,10 @@ endif
  8413. ALSA_LIB=
  8414. LINUX_SYSTEM_LIBS=
  8415. ifeq ($(OS),linux)
  8416. - #not for raspberry pi
  8417. + DEPENDS += alsa-lib
  8418. + ALSA_LIB = alsa-lib
  8419. ifneq ($(CPU),arm)
  8420. - DEPENDS += alsa-lib libsdl linux-system-libs
  8421. - ALSA_LIB = alsa-lib
  8422. + DEPENDS += libsdl linux-system-libs
  8423. LINUX_SYSTEM_LIBS = linux-system-libs
  8424. endif
  8425. endif
  8426. diff --git a/xbmc/cores/AudioEngine/AESinkFactory.cpp b/xbmc/cores/AudioEngine/AESinkFactory.cpp
  8427. index e493123..7df6807 100644
  8428. --- a/xbmc/cores/AudioEngine/AESinkFactory.cpp
  8429. +++ b/xbmc/cores/AudioEngine/AESinkFactory.cpp
  8430. @@ -27,6 +27,7 @@
  8431. #include "Sinks/AESinkAUDIOTRACK.h"
  8432. #elif defined(TARGET_RASPBERRY_PI)
  8433. #include "Sinks/AESinkPi.h"
  8434. + #include "Sinks/AESinkALSA.h"
  8435. #elif defined(TARGET_DARWIN_IOS)
  8436. #include "Sinks/AESinkDARWINIOS.h"
  8437. #elif defined(TARGET_DARWIN_OSX)
  8438. @@ -66,6 +67,7 @@ void CAESinkFactory::ParseDevice(std::string &device, std::string &driver)
  8439. driver == "AUDIOTRACK" ||
  8440. #elif defined(TARGET_RASPBERRY_PI)
  8441. driver == "PI" ||
  8442. + driver == "ALSA" ||
  8443. #elif defined(TARGET_DARWIN_IOS)
  8444. driver == "DARWINIOS" ||
  8445. #elif defined(TARGET_DARWIN_OSX)
  8446. @@ -104,7 +106,12 @@ IAESink *CAESinkFactory::TrySink(std::string &driver, std::string &device, AEAud
  8447. #elif defined(TARGET_ANDROID)
  8448. sink = new CAESinkAUDIOTRACK();
  8449. #elif defined(TARGET_RASPBERRY_PI)
  8450. - sink = new CAESinkPi();
  8451. + else if (driver == "PI")
  8452. + sink = new CAESinkPi();
  8453. + #if defined(HAS_ALSA)
  8454. + else if (driver == "ALSA")
  8455. + sink = new CAESinkALSA();
  8456. + #endif
  8457. #elif defined(TARGET_DARWIN_IOS)
  8458. sink = new CAESinkDARWINIOS();
  8459. #elif defined(TARGET_DARWIN_OSX)
  8460. @@ -194,7 +201,13 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
  8461. CAESinkPi::EnumerateDevicesEx(info.m_deviceInfoList, force);
  8462. if(!info.m_deviceInfoList.empty())
  8463. list.push_back(info);
  8464. -
  8465. + #if defined(HAS_ALSA)
  8466. + info.m_deviceInfoList.clear();
  8467. + info.m_sinkName = "ALSA";
  8468. + CAESinkALSA::EnumerateDevicesEx(info.m_deviceInfoList, force);
  8469. + if(!info.m_deviceInfoList.empty())
  8470. + list.push_back(info);
  8471. + #endif
  8472. #elif defined(TARGET_DARWIN_IOS)
  8473. info.m_deviceInfoList.clear();
  8474. --
  8475. 1.9.3
  8476. From 8ffa85ccdc4760751849d75d37924fbf6cb1b1c8 Mon Sep 17 00:00:00 2001
  8477. From: popcornmix <popcornmix@gmail.com>
  8478. Date: Thu, 16 Jan 2014 01:39:29 +0000
  8479. Subject: [PATCH 42/94] [omxcodec] Add hardware decode to dvdplayer for Pi
  8480. Hijack the abandoned OpenMaxVideo codec
  8481. ---
  8482. configure.in | 21 +-
  8483. xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 12 +-
  8484. xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 6 +-
  8485. xbmc/cores/VideoRenderers/RenderManager.cpp | 2 +-
  8486. xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 7 +-
  8487. .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 7 +-
  8488. .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 295 +---
  8489. .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 34 +-
  8490. xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in | 1 -
  8491. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp | 269 ----
  8492. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h | 116 --
  8493. .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 1418 ++++++++++----------
  8494. .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 120 +-
  8495. xbmc/cores/dvdplayer/DVDPlayer.cpp | 2 +
  8496. xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 21 +-
  8497. xbmc/linux/OMXCore.cpp | 45 +-
  8498. xbmc/linux/OMXCore.h | 2 +-
  8499. 17 files changed, 894 insertions(+), 1484 deletions(-)
  8500. delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp
  8501. delete mode 100644 xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h
  8502. diff --git a/configure.in b/configure.in
  8503. index 34dd038..e7550c0 100644
  8504. --- a/configure.in
  8505. +++ b/configure.in
  8506. @@ -1956,9 +1956,24 @@ if test "$host_vendor" = "apple" ; then
  8507. USE_OPENMAX=0
  8508. AC_MSG_NOTICE($openmax_disabled)
  8509. elif test "$target_platform" = "target_raspberry_pi"; then
  8510. - use_openmax="no"
  8511. - USE_OPENMAX=0
  8512. - AC_MSG_NOTICE($openmax_disabled)
  8513. + if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then
  8514. + use_openmax="yes"
  8515. + USE_OPENMAX=1
  8516. + HAVE_LIBOPENMAX=1
  8517. + AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.])
  8518. + AC_DEFINE([OMX_SKIP64BIT], [1], [Define to 1 if you have the 'LIBOPENMAX' library.])
  8519. + AC_MSG_NOTICE($openmax_enabled)
  8520. + elif test "$use_gles" = "yes" && test "$use_openmax" = "yes"; then
  8521. + use_openmax="yes"
  8522. + USE_OPENMAX=1
  8523. + HAVE_LIBOPENMAX=1
  8524. + AC_DEFINE([HAVE_LIBOPENMAX], [1], [Define to 1 if you have the 'LIBOPENMAX' library.])
  8525. + AC_MSG_NOTICE($openmax_enabled)
  8526. + else
  8527. + AC_MSG_NOTICE($openmax_disabled)
  8528. + use_openmax=no
  8529. + USE_OPENMAX=0
  8530. + fi
  8531. else
  8532. if test "$use_gles" = "yes" && test "$use_openmax" = "auto"; then
  8533. PKG_CHECK_MODULES([OPENMAX], [libomxil-bellagio],
  8534. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  8535. index 30c0601..6d879e3 100644
  8536. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  8537. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  8538. @@ -44,7 +44,7 @@
  8539. #include "windowing/WindowingFactory.h"
  8540. #include "guilib/Texture.h"
  8541. #include "lib/DllSwScale.h"
  8542. -#include "../dvdplayer/DVDCodecs/Video/OpenMaxVideo.h"
  8543. +#include "DVDCodecs/Video/OpenMaxVideo.h"
  8544. #include "threads/SingleLock.h"
  8545. #include "RenderCapture.h"
  8546. #include "RenderFormats.h"
  8547. @@ -1330,6 +1330,10 @@ void CLinuxRendererGLES::RenderOpenMax(int index, int field)
  8548. glActiveTexture(GL_TEXTURE0);
  8549. glBindTexture(m_textureTarget, textureId);
  8550. + GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
  8551. + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
  8552. + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
  8553. +
  8554. g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
  8555. GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
  8556. @@ -2676,10 +2680,12 @@ unsigned int CLinuxRendererGLES::GetProcessorSize()
  8557. }
  8558. #ifdef HAVE_LIBOPENMAX
  8559. -void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
  8560. +void CLinuxRendererGLES::AddProcessor(COpenMaxVideoBuffer *openMaxBuffer, int index)
  8561. {
  8562. YUVBUFFER &buf = m_buffers[index];
  8563. - buf.openMaxBuffer = picture->openMaxBuffer;
  8564. + COpenMaxVideoBuffer *pic = openMaxBuffer->Acquire();
  8565. + SAFE_RELEASE(buf.openMaxBuffer);
  8566. + buf.openMaxBuffer = pic;
  8567. }
  8568. #endif
  8569. #ifdef HAVE_VIDEOTOOLBOXDECODER
  8570. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  8571. index 45e9c20..0ca56a2 100644
  8572. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  8573. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  8574. @@ -39,7 +39,7 @@ class CRenderCapture;
  8575. class CBaseTexture;
  8576. namespace Shaders { class BaseYUV2RGBShader; }
  8577. namespace Shaders { class BaseVideoFilterShader; }
  8578. -class COpenMaxVideo;
  8579. +class COpenMaxVideoBuffer;
  8580. class CDVDVideoCodecStageFright;
  8581. class CDVDMediaCodecInfo;
  8582. typedef std::vector<int> Features;
  8583. @@ -161,7 +161,7 @@ class CLinuxRendererGLES : public CBaseRenderer
  8584. virtual std::vector<ERenderFormat> SupportedFormats() { return m_formats; }
  8585. #ifdef HAVE_LIBOPENMAX
  8586. - virtual void AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index);
  8587. + virtual void AddProcessor(COpenMaxVideoBuffer *openMaxVideoBuffer, int index);
  8588. #endif
  8589. #ifdef HAVE_VIDEOTOOLBOXDECODER
  8590. virtual void AddProcessor(struct __CVBuffer *cvBufferRef, int index);
  8591. @@ -275,7 +275,7 @@ class CLinuxRendererGLES : public CBaseRenderer
  8592. unsigned flipindex; /* used to decide if this has been uploaded */
  8593. #ifdef HAVE_LIBOPENMAX
  8594. - OpenMaxVideoBuffer *openMaxBuffer;
  8595. + COpenMaxVideoBuffer *openMaxBuffer;
  8596. #endif
  8597. #ifdef HAVE_VIDEOTOOLBOXDECODER
  8598. struct __CVBuffer *cvBufferRef;
  8599. diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
  8600. index 6832721..3503988 100644
  8601. --- a/xbmc/cores/VideoRenderers/RenderManager.cpp
  8602. +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
  8603. @@ -912,7 +912,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
  8604. #endif
  8605. #ifdef HAVE_LIBOPENMAX
  8606. else if(pic.format == RENDER_FMT_OMXEGL)
  8607. - m_pRenderer->AddProcessor(pic.openMax, &pic, index);
  8608. + m_pRenderer->AddProcessor(pic.openMaxBuffer, index);
  8609. #endif
  8610. #ifdef TARGET_DARWIN
  8611. else if(pic.format == RENDER_FMT_CVBREF)
  8612. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  8613. index 14ad038..18b8e3a 100644
  8614. --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  8615. +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  8616. @@ -270,9 +270,12 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne
  8617. #endif
  8618. #if defined(HAVE_LIBOPENMAX)
  8619. - if (CSettings::Get().GetBool("videoplayer.useomx") && !hint.software )
  8620. + if (!hint.software && CSettings::Get().GetBool("videoplayer.useomx"))
  8621. {
  8622. - if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_VC1)
  8623. + if (hint.codec == AV_CODEC_ID_H264 || hint.codec == AV_CODEC_ID_H263 || hint.codec == AV_CODEC_ID_MPEG4 ||
  8624. + hint.codec == AV_CODEC_ID_MPEG1VIDEO || hint.codec == AV_CODEC_ID_MPEG2VIDEO ||
  8625. + hint.codec == AV_CODEC_ID_VP6 || hint.codec == AV_CODEC_ID_VP6F || hint.codec == AV_CODEC_ID_VP6A || hint.codec == AV_CODEC_ID_VP8 ||
  8626. + hint.codec == AV_CODEC_ID_THEORA || hint.codec == AV_CODEC_ID_MJPEG || hint.codec == AV_CODEC_ID_MJPEGB || hint.codec == AV_CODEC_ID_VC1 || hint.codec == AV_CODEC_ID_WMV3)
  8627. {
  8628. if ( (pCodec = OpenCodec(new CDVDVideoCodecOpenMax(), hint, options)) ) return pCodec;
  8629. }
  8630. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  8631. index f6751f4..dc047d7 100644
  8632. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  8633. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  8634. @@ -44,9 +44,7 @@ struct DVDCodecAvailableType
  8635. namespace DXVA { class CSurfaceContext; }
  8636. namespace VAAPI { struct CHolder; }
  8637. namespace VDPAU { class CVdpauRenderPicture; }
  8638. -class COpenMax;
  8639. -class COpenMaxVideo;
  8640. -struct OpenMaxVideoBuffer;
  8641. +class COpenMaxVideoBuffer;
  8642. class CDVDVideoCodecStageFright;
  8643. class CDVDMediaCodecInfo;
  8644. typedef void* EGLImageKHR;
  8645. @@ -75,8 +73,7 @@ struct DVDVideoPicture
  8646. };
  8647. struct {
  8648. - COpenMax *openMax;
  8649. - OpenMaxVideoBuffer *openMaxBuffer;
  8650. + COpenMaxVideoBuffer *openMaxBuffer;
  8651. };
  8652. struct {
  8653. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  8654. index b2e7816..7d33192 100644
  8655. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  8656. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  8657. @@ -29,113 +29,43 @@
  8658. #include "DVDStreamInfo.h"
  8659. #include "DVDVideoCodecOpenMax.h"
  8660. #include "OpenMaxVideo.h"
  8661. +#include "settings/Settings.h"
  8662. #include "utils/log.h"
  8663. -#define CLASSNAME "COpenMax"
  8664. +#define CLASSNAME "CDVDVideoCodecOpenMax"
  8665. ////////////////////////////////////////////////////////////////////////////////////////////
  8666. ////////////////////////////////////////////////////////////////////////////////////////////
  8667. -CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax() : CDVDVideoCodec()
  8668. +CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax()
  8669. {
  8670. m_omx_decoder = NULL;
  8671. - m_pFormatName = "omx-xxxx";
  8672. -
  8673. - m_convert_bitstream = false;
  8674. - memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
  8675. + CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this);
  8676. }
  8677. CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax()
  8678. {
  8679. + CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this);
  8680. Dispose();
  8681. }
  8682. bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  8683. {
  8684. - // we always qualify even if DVDFactoryCodec does this too.
  8685. - if (CSettings::Get().GetBool("videoplayer.useomx") && !hints.software)
  8686. - {
  8687. - m_convert_bitstream = false;
  8688. -
  8689. - switch (hints.codec)
  8690. - {
  8691. - case AV_CODEC_ID_H264:
  8692. - {
  8693. - m_pFormatName = "omx-h264";
  8694. - if (hints.extrasize < 7 || hints.extradata == NULL)
  8695. - {
  8696. - CLog::Log(LOGNOTICE,
  8697. - "%s::%s - avcC data too small or missing", CLASSNAME, __func__);
  8698. - return false;
  8699. - }
  8700. - // valid avcC data (bitstream) always starts with the value 1 (version)
  8701. - if ( *(char*)hints.extradata == 1 )
  8702. - m_convert_bitstream = bitstream_convert_init(hints.extradata, hints.extrasize);
  8703. - }
  8704. - break;
  8705. - case AV_CODEC_ID_MPEG4:
  8706. - m_pFormatName = "omx-mpeg4";
  8707. - break;
  8708. - case AV_CODEC_ID_MPEG2VIDEO:
  8709. - m_pFormatName = "omx-mpeg2";
  8710. - break;
  8711. - case AV_CODEC_ID_VC1:
  8712. - m_pFormatName = "omx-vc1";
  8713. - break;
  8714. - default:
  8715. - return false;
  8716. - break;
  8717. - }
  8718. -
  8719. - m_omx_decoder = new COpenMaxVideo;
  8720. - if (!m_omx_decoder->Open(hints))
  8721. - {
  8722. - CLog::Log(LOGERROR,
  8723. - "%s::%s - failed to open, codec(%d), profile(%d), level(%d)",
  8724. - CLASSNAME, __func__, hints.codec, hints.profile, hints.level);
  8725. - return false;
  8726. - }
  8727. -
  8728. - // allocate a YV12 DVDVideoPicture buffer.
  8729. - // first make sure all properties are reset.
  8730. - memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
  8731. -
  8732. - m_videobuffer.dts = DVD_NOPTS_VALUE;
  8733. - m_videobuffer.pts = DVD_NOPTS_VALUE;
  8734. - //m_videobuffer.format = RENDER_FMT_YUV420P;
  8735. - m_videobuffer.format = RENDER_FMT_OMXEGL;
  8736. - m_videobuffer.color_range = 0;
  8737. - m_videobuffer.color_matrix = 4;
  8738. - m_videobuffer.iFlags = DVP_FLAG_ALLOCATED;
  8739. - m_videobuffer.iWidth = hints.width;
  8740. - m_videobuffer.iHeight = hints.height;
  8741. - m_videobuffer.iDisplayWidth = hints.width;
  8742. - m_videobuffer.iDisplayHeight = hints.height;
  8743. -
  8744. - return true;
  8745. - }
  8746. + m_omx_decoder = new COpenMaxVideo;
  8747. + return m_omx_decoder->Open(hints, options);
  8748. +}
  8749. - return false;
  8750. +const char* CDVDVideoCodecOpenMax::GetName(void)
  8751. +{
  8752. + return m_omx_decoder ? m_omx_decoder->GetName() : "omx-xxx";
  8753. }
  8754. void CDVDVideoCodecOpenMax::Dispose()
  8755. {
  8756. if (m_omx_decoder)
  8757. {
  8758. - m_omx_decoder->Close();
  8759. + m_omx_decoder->Dispose();
  8760. delete m_omx_decoder;
  8761. m_omx_decoder = NULL;
  8762. }
  8763. - if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED)
  8764. - {
  8765. - m_videobuffer.iFlags = 0;
  8766. - }
  8767. - if (m_convert_bitstream)
  8768. - {
  8769. - if (m_sps_pps_context.sps_pps_data)
  8770. - {
  8771. - free(m_sps_pps_context.sps_pps_data);
  8772. - m_sps_pps_context.sps_pps_data = NULL;
  8773. - }
  8774. - }
  8775. }
  8776. void CDVDVideoCodecOpenMax::SetDropState(bool bDrop)
  8777. @@ -145,37 +75,12 @@ void CDVDVideoCodecOpenMax::SetDropState(bool bDrop)
  8778. int CDVDVideoCodecOpenMax::Decode(uint8_t* pData, int iSize, double dts, double pts)
  8779. {
  8780. - if (pData)
  8781. - {
  8782. - int rtn;
  8783. - int demuxer_bytes = iSize;
  8784. - uint8_t *demuxer_content = pData;
  8785. - bool bitstream_convered = false;
  8786. -
  8787. - if (m_convert_bitstream)
  8788. - {
  8789. - // convert demuxer packet from bitstream to bytestream (AnnexB)
  8790. - int bytestream_size = 0;
  8791. - uint8_t *bytestream_buff = NULL;
  8792. -
  8793. - bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size);
  8794. - if (bytestream_buff && (bytestream_size > 0))
  8795. - {
  8796. - bitstream_convered = true;
  8797. - demuxer_bytes = bytestream_size;
  8798. - demuxer_content = bytestream_buff;
  8799. - }
  8800. - }
  8801. -
  8802. - rtn = m_omx_decoder->Decode(demuxer_content, demuxer_bytes, dts, pts);
  8803. -
  8804. - if (bitstream_convered)
  8805. - free(demuxer_content);
  8806. + return m_omx_decoder->Decode(pData, iSize, dts, pts);
  8807. +}
  8808. - return rtn;
  8809. - }
  8810. -
  8811. - return VC_BUFFER;
  8812. +unsigned CDVDVideoCodecOpenMax::GetAllowedReferences()
  8813. +{
  8814. + return m_omx_decoder->GetAllowedReferences();
  8815. }
  8816. void CDVDVideoCodecOpenMax::Reset(void)
  8817. @@ -185,172 +90,12 @@ void CDVDVideoCodecOpenMax::Reset(void)
  8818. bool CDVDVideoCodecOpenMax::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  8819. {
  8820. - m_omx_decoder->GetPicture(&m_videobuffer);
  8821. - *pDvdVideoPicture = m_videobuffer;
  8822. -
  8823. - return VC_PICTURE | VC_BUFFER;
  8824. -}
  8825. -
  8826. -////////////////////////////////////////////////////////////////////////////////////////////
  8827. -bool CDVDVideoCodecOpenMax::bitstream_convert_init(void *in_extradata, int in_extrasize)
  8828. -{
  8829. - // based on h264_mp4toannexb_bsf.c (ffmpeg)
  8830. - // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
  8831. - // and Licensed GPL 2.1 or greater
  8832. -
  8833. - m_sps_pps_size = 0;
  8834. - m_sps_pps_context.sps_pps_data = NULL;
  8835. -
  8836. - // nothing to filter
  8837. - if (!in_extradata || in_extrasize < 6)
  8838. - return false;
  8839. -
  8840. - uint16_t unit_size;
  8841. - uint32_t total_size = 0;
  8842. - uint8_t *out = NULL, unit_nb, sps_done = 0;
  8843. - const uint8_t *extradata = (uint8_t*)in_extradata + 4;
  8844. - static const uint8_t nalu_header[4] = {0, 0, 0, 1};
  8845. -
  8846. - // retrieve length coded size
  8847. - m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1;
  8848. - if (m_sps_pps_context.length_size == 3)
  8849. - return false;
  8850. -
  8851. - // retrieve sps and pps unit(s)
  8852. - unit_nb = *extradata++ & 0x1f; // number of sps unit(s)
  8853. - if (!unit_nb)
  8854. - {
  8855. - unit_nb = *extradata++; // number of pps unit(s)
  8856. - sps_done++;
  8857. - }
  8858. - while (unit_nb--)
  8859. - {
  8860. - unit_size = extradata[0] << 8 | extradata[1];
  8861. - total_size += unit_size + 4;
  8862. - if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) )
  8863. - {
  8864. - free(out);
  8865. - return false;
  8866. - }
  8867. - uint8_t* new_out = (uint8_t*)realloc(out, total_size);
  8868. - if (new_out)
  8869. - {
  8870. - out = new_out;
  8871. - }
  8872. - else
  8873. - {
  8874. - CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__);
  8875. - free(out);
  8876. - return false;
  8877. - }
  8878. -
  8879. - memcpy(out + total_size - unit_size - 4, nalu_header, 4);
  8880. - memcpy(out + total_size - unit_size, extradata + 2, unit_size);
  8881. - extradata += 2 + unit_size;
  8882. -
  8883. - if (!unit_nb && !sps_done++)
  8884. - unit_nb = *extradata++; // number of pps unit(s)
  8885. - }
  8886. -
  8887. - m_sps_pps_context.sps_pps_data = out;
  8888. - m_sps_pps_context.size = total_size;
  8889. - m_sps_pps_context.first_idr = 1;
  8890. -
  8891. - return true;
  8892. -}
  8893. -
  8894. -bool CDVDVideoCodecOpenMax::bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size)
  8895. -{
  8896. - // based on h264_mp4toannexb_bsf.c (ffmpeg)
  8897. - // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
  8898. - // and Licensed GPL 2.1 or greater
  8899. -
  8900. - uint8_t *buf = pData;
  8901. - uint32_t buf_size = iSize;
  8902. - uint8_t unit_type;
  8903. - int32_t nal_size;
  8904. - uint32_t cumul_size = 0;
  8905. - const uint8_t *buf_end = buf + buf_size;
  8906. -
  8907. - do
  8908. - {
  8909. - if (buf + m_sps_pps_context.length_size > buf_end)
  8910. - goto fail;
  8911. -
  8912. - if (m_sps_pps_context.length_size == 1)
  8913. - nal_size = buf[0];
  8914. - else if (m_sps_pps_context.length_size == 2)
  8915. - nal_size = buf[0] << 8 | buf[1];
  8916. - else
  8917. - nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
  8918. -
  8919. - buf += m_sps_pps_context.length_size;
  8920. - unit_type = *buf & 0x1f;
  8921. -
  8922. - if (buf + nal_size > buf_end || nal_size < 0)
  8923. - goto fail;
  8924. -
  8925. - // prepend only to the first type 5 NAL unit of an IDR picture
  8926. - if (m_sps_pps_context.first_idr && unit_type == 5)
  8927. - {
  8928. - bitstream_alloc_and_copy(poutbuf, poutbuf_size,
  8929. - m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size);
  8930. - m_sps_pps_context.first_idr = 0;
  8931. - }
  8932. - else
  8933. - {
  8934. - bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size);
  8935. - if (!m_sps_pps_context.first_idr && unit_type == 1)
  8936. - m_sps_pps_context.first_idr = 1;
  8937. - }
  8938. -
  8939. - buf += nal_size;
  8940. - cumul_size += nal_size + m_sps_pps_context.length_size;
  8941. - } while (cumul_size < buf_size);
  8942. -
  8943. - return true;
  8944. -
  8945. -fail:
  8946. - free(*poutbuf);
  8947. - *poutbuf = NULL;
  8948. - *poutbuf_size = 0;
  8949. - return false;
  8950. + return m_omx_decoder->GetPicture(pDvdVideoPicture);
  8951. }
  8952. -void CDVDVideoCodecOpenMax::bitstream_alloc_and_copy(
  8953. - uint8_t **poutbuf, int *poutbuf_size,
  8954. - const uint8_t *sps_pps, uint32_t sps_pps_size,
  8955. - const uint8_t *in, uint32_t in_size)
  8956. +bool CDVDVideoCodecOpenMax::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
  8957. {
  8958. - // based on h264_mp4toannexb_bsf.c (ffmpeg)
  8959. - // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
  8960. - // and Licensed GPL 2.1 or greater
  8961. -
  8962. - #define CHD_WB32(p, d) { \
  8963. - ((uint8_t*)(p))[3] = (d); \
  8964. - ((uint8_t*)(p))[2] = (d) >> 8; \
  8965. - ((uint8_t*)(p))[1] = (d) >> 16; \
  8966. - ((uint8_t*)(p))[0] = (d) >> 24; }
  8967. -
  8968. - uint32_t offset = *poutbuf_size;
  8969. - uint8_t nal_header_size = offset ? 3 : 4;
  8970. -
  8971. - *poutbuf_size += sps_pps_size + in_size + nal_header_size;
  8972. - *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size);
  8973. - if (sps_pps)
  8974. - memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
  8975. -
  8976. - memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
  8977. - if (!offset)
  8978. - {
  8979. - CHD_WB32(*poutbuf + sps_pps_size, 1);
  8980. - }
  8981. - else
  8982. - {
  8983. - (*poutbuf + offset + sps_pps_size)[0] = 0;
  8984. - (*poutbuf + offset + sps_pps_size)[1] = 0;
  8985. - (*poutbuf + offset + sps_pps_size)[2] = 1;
  8986. - }
  8987. + return m_omx_decoder->ClearPicture(pDvdVideoPicture);
  8988. }
  8989. #endif
  8990. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  8991. index fb80d02..67cc235 100644
  8992. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  8993. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  8994. @@ -23,7 +23,7 @@
  8995. #include "DVDVideoCodec.h"
  8996. -class COpenVideoMax;
  8997. +class COpenMaxVideo;
  8998. class CDVDVideoCodecOpenMax : public CDVDVideoCodec
  8999. {
  9000. public:
  9001. @@ -36,39 +36,13 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec
  9002. virtual int Decode(uint8_t *pData, int iSize, double dts, double pts);
  9003. virtual void Reset(void);
  9004. virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
  9005. + virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
  9006. + virtual unsigned GetAllowedReferences();
  9007. virtual void SetDropState(bool bDrop);
  9008. - virtual const char* GetName(void) { return (const char*)m_pFormatName; }
  9009. + virtual const char* GetName(void);
  9010. protected:
  9011. - const char *m_pFormatName;
  9012. COpenMaxVideo *m_omx_decoder;
  9013. - DVDVideoPicture m_videobuffer;
  9014. -
  9015. - // bitstream to bytestream (Annex B) conversion support.
  9016. - bool bitstream_convert_init(void *in_extradata, int in_extrasize);
  9017. - bool bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size);
  9018. - static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size,
  9019. - const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size);
  9020. -
  9021. - typedef struct omx_bitstream_ctx {
  9022. - uint8_t length_size;
  9023. - uint8_t first_idr;
  9024. - uint8_t *sps_pps_data;
  9025. - uint32_t size;
  9026. -
  9027. - omx_bitstream_ctx()
  9028. - {
  9029. - length_size = 0;
  9030. - first_idr = 0;
  9031. - sps_pps_data = NULL;
  9032. - size = 0;
  9033. - }
  9034. -
  9035. - } omx_bitstream_ctx;
  9036. -
  9037. - uint32_t m_sps_pps_size;
  9038. - omx_bitstream_ctx m_sps_pps_context;
  9039. - bool m_convert_bitstream;
  9040. };
  9041. #endif
  9042. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
  9043. index 8a97889..ebf7123 100644
  9044. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
  9045. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in
  9046. @@ -20,7 +20,6 @@ SRCS += DVDVideoCodecVDA.cpp
  9047. SRCS += VDA.cpp
  9048. endif
  9049. ifeq (@USE_OPENMAX@,1)
  9050. -SRCS += OpenMax.cpp
  9051. SRCS += OpenMaxVideo.cpp
  9052. SRCS += DVDVideoCodecOpenMax.cpp
  9053. endif
  9054. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp
  9055. deleted file mode 100644
  9056. index 7b0a0c2ef..0000000
  9057. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.cpp
  9058. +++ /dev/null
  9059. @@ -1,269 +0,0 @@
  9060. -/*
  9061. - * Copyright (C) 2010-2013 Team XBMC
  9062. - * http://xbmc.org
  9063. - *
  9064. - * This Program is free software; you can redistribute it and/or modify
  9065. - * it under the terms of the GNU General Public License as published by
  9066. - * the Free Software Foundation; either version 2, or (at your option)
  9067. - * any later version.
  9068. - *
  9069. - * This Program is distributed in the hope that it will be useful,
  9070. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9071. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9072. - * GNU General Public License for more details.
  9073. - *
  9074. - * You should have received a copy of the GNU General Public License
  9075. - * along with XBMC; see the file COPYING. If not, see
  9076. - * <http://www.gnu.org/licenses/>.
  9077. - *
  9078. - */
  9079. -
  9080. -#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
  9081. - #include "config.h"
  9082. -#elif defined(TARGET_WINDOWS)
  9083. -#include "system.h"
  9084. -#endif
  9085. -
  9086. -#if defined(HAVE_LIBOPENMAX)
  9087. -#include "OpenMax.h"
  9088. -#include "DynamicDll.h"
  9089. -#include "DVDClock.h"
  9090. -#include "DVDStreamInfo.h"
  9091. -#include "windowing/WindowingFactory.h"
  9092. -#include "DVDVideoCodec.h"
  9093. -#include "utils/log.h"
  9094. -#include "utils/TimeUtils.h"
  9095. -#include "ApplicationMessenger.h"
  9096. -#include "Application.h"
  9097. -
  9098. -#include <OMX_Core.h>
  9099. -#include <OMX_Component.h>
  9100. -#include <OMX_Index.h>
  9101. -#include <OMX_Image.h>
  9102. -
  9103. -#define CLASSNAME "COpenMax"
  9104. -
  9105. -
  9106. -////////////////////////////////////////////////////////////////////////////////////////////
  9107. -class DllLibOpenMaxInterface
  9108. -{
  9109. -public:
  9110. - virtual ~DllLibOpenMaxInterface() {}
  9111. -
  9112. - virtual OMX_ERRORTYPE OMX_Init(void) = 0;
  9113. - virtual OMX_ERRORTYPE OMX_Deinit(void) = 0;
  9114. - virtual OMX_ERRORTYPE OMX_GetHandle(
  9115. - OMX_HANDLETYPE *pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE *pCallBacks) = 0;
  9116. - virtual OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent) = 0;
  9117. - virtual OMX_ERRORTYPE OMX_GetComponentsOfRole(OMX_STRING role, OMX_U32 *pNumComps, OMX_U8 **compNames) = 0;
  9118. - virtual OMX_ERRORTYPE OMX_GetRolesOfComponent(OMX_STRING compName, OMX_U32 *pNumRoles, OMX_U8 **roles) = 0;
  9119. - virtual OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex) = 0;
  9120. -};
  9121. -
  9122. -class DllLibOpenMax : public DllDynamic, DllLibOpenMaxInterface
  9123. -{
  9124. - DECLARE_DLL_WRAPPER(DllLibOpenMax, "/usr/lib/libnvomx.so")
  9125. -
  9126. - DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Init)
  9127. - DEFINE_METHOD0(OMX_ERRORTYPE, OMX_Deinit)
  9128. - DEFINE_METHOD4(OMX_ERRORTYPE, OMX_GetHandle, (OMX_HANDLETYPE *p1, OMX_STRING p2, OMX_PTR p3, OMX_CALLBACKTYPE *p4))
  9129. - DEFINE_METHOD1(OMX_ERRORTYPE, OMX_FreeHandle, (OMX_HANDLETYPE p1))
  9130. - DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetComponentsOfRole, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3))
  9131. - DEFINE_METHOD3(OMX_ERRORTYPE, OMX_GetRolesOfComponent, (OMX_STRING p1, OMX_U32 *p2, OMX_U8 **p3))
  9132. - DEFINE_METHOD3(OMX_ERRORTYPE, OMX_ComponentNameEnum, (OMX_STRING p1, OMX_U32 p2, OMX_U32 p3))
  9133. - BEGIN_METHOD_RESOLVE()
  9134. - RESOLVE_METHOD(OMX_Init)
  9135. - RESOLVE_METHOD(OMX_Deinit)
  9136. - RESOLVE_METHOD(OMX_GetHandle)
  9137. - RESOLVE_METHOD(OMX_FreeHandle)
  9138. - RESOLVE_METHOD(OMX_GetComponentsOfRole)
  9139. - RESOLVE_METHOD(OMX_GetRolesOfComponent)
  9140. - RESOLVE_METHOD(OMX_ComponentNameEnum)
  9141. - END_METHOD_RESOLVE()
  9142. -};
  9143. -
  9144. -////////////////////////////////////////////////////////////////////////////////////////////
  9145. -#define OMX_INIT_STRUCTURE(a) \
  9146. - memset(&(a), 0, sizeof(a)); \
  9147. - (a).nSize = sizeof(a); \
  9148. - (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
  9149. - (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
  9150. - (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
  9151. - (a).nVersion.s.nStep = OMX_VERSION_STEP
  9152. -
  9153. -////////////////////////////////////////////////////////////////////////////////////////////
  9154. -////////////////////////////////////////////////////////////////////////////////////////////
  9155. -COpenMax::COpenMax()
  9156. -{
  9157. - #if defined(OMX_DEBUG_VERBOSE)
  9158. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  9159. - #endif
  9160. - m_dll = new DllLibOpenMax;
  9161. - m_dll->Load();
  9162. - m_is_open = false;
  9163. -
  9164. - m_omx_decoder = NULL;
  9165. - m_omx_client_state = DEAD;
  9166. - m_omx_decoder_state = 0;
  9167. - sem_init(m_omx_decoder_state_change, 0, 0);
  9168. - /*
  9169. - m_omx_flush_input = (sem_t*)malloc(sizeof(sem_t));
  9170. - sem_init(m_omx_flush_input, 0, 0);
  9171. - m_omx_flush_output = (sem_t*)malloc(sizeof(sem_t));
  9172. - sem_init(m_omx_flush_output, 0, 0);
  9173. - */
  9174. -}
  9175. -
  9176. -COpenMax::~COpenMax()
  9177. -{
  9178. - #if defined(OMX_DEBUG_VERBOSE)
  9179. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  9180. - #endif
  9181. - /*
  9182. - sem_destroy(m_omx_flush_input);
  9183. - free(m_omx_flush_input);
  9184. - sem_destroy(m_omx_flush_output);
  9185. - free(m_omx_flush_output);
  9186. - */
  9187. - delete m_dll;
  9188. -}
  9189. -
  9190. -
  9191. -
  9192. -
  9193. -////////////////////////////////////////////////////////////////////////////////////////////
  9194. -// DecoderEventHandler -- OMX event callback
  9195. -OMX_ERRORTYPE COpenMax::DecoderEventHandlerCallback(
  9196. - OMX_HANDLETYPE hComponent,
  9197. - OMX_PTR pAppData,
  9198. - OMX_EVENTTYPE eEvent,
  9199. - OMX_U32 nData1,
  9200. - OMX_U32 nData2,
  9201. - OMX_PTR pEventData)
  9202. -{
  9203. - COpenMax *ctx = (COpenMax*)pAppData;
  9204. - return ctx->DecoderEventHandler(hComponent, pAppData, eEvent, nData1, nData2, pEventData);
  9205. -}
  9206. -
  9207. -// DecoderEmptyBufferDone -- OpenMax input buffer has been emptied
  9208. -OMX_ERRORTYPE COpenMax::DecoderEmptyBufferDoneCallback(
  9209. - OMX_HANDLETYPE hComponent,
  9210. - OMX_PTR pAppData,
  9211. - OMX_BUFFERHEADERTYPE* pBuffer)
  9212. -{
  9213. - COpenMax *ctx = (COpenMax*)pAppData;
  9214. - return ctx->DecoderEmptyBufferDone( hComponent, pAppData, pBuffer);
  9215. -}
  9216. -
  9217. -// DecoderFillBufferDone -- OpenMax output buffer has been filled
  9218. -OMX_ERRORTYPE COpenMax::DecoderFillBufferDoneCallback(
  9219. - OMX_HANDLETYPE hComponent,
  9220. - OMX_PTR pAppData,
  9221. - OMX_BUFFERHEADERTYPE* pBuffer)
  9222. -{
  9223. - COpenMax *ctx = (COpenMax*)pAppData;
  9224. - return ctx->DecoderFillBufferDone(hComponent, pAppData, pBuffer);
  9225. -}
  9226. -
  9227. -
  9228. -
  9229. -// Wait for a component to transition to the specified state
  9230. -OMX_ERRORTYPE COpenMax::WaitForState(OMX_STATETYPE state)
  9231. -{
  9232. - OMX_STATETYPE test_state;
  9233. - int tries = 0;
  9234. - struct timespec timeout;
  9235. - OMX_ERRORTYPE omx_error = OMX_GetState(m_omx_decoder, &test_state);
  9236. -
  9237. - #if defined(OMX_DEBUG_VERBOSE)
  9238. - CLog::Log(LOGDEBUG, "%s::%s - waiting for state(%d)\n", CLASSNAME, __func__, state);
  9239. - #endif
  9240. - while ((omx_error == OMX_ErrorNone) && (test_state != state))
  9241. - {
  9242. - clock_gettime(CLOCK_REALTIME, &timeout);
  9243. - timeout.tv_sec += 1;
  9244. - sem_timedwait(m_omx_decoder_state_change, &timeout);
  9245. - if (errno == ETIMEDOUT)
  9246. - tries++;
  9247. - if (tries > 5)
  9248. - return OMX_ErrorUndefined;
  9249. -
  9250. - omx_error = OMX_GetState(m_omx_decoder, &test_state);
  9251. - }
  9252. -
  9253. - return omx_error;
  9254. -}
  9255. -
  9256. -// SetStateForAllComponents
  9257. -// Blocks until all state changes have completed
  9258. -OMX_ERRORTYPE COpenMax::SetStateForComponent(OMX_STATETYPE state)
  9259. -{
  9260. - OMX_ERRORTYPE omx_err;
  9261. -
  9262. - #if defined(OMX_DEBUG_VERBOSE)
  9263. - CLog::Log(LOGDEBUG, "%s::%s - state(%d)\n", CLASSNAME, __func__, state);
  9264. - #endif
  9265. - omx_err = OMX_SendCommand(m_omx_decoder, OMX_CommandStateSet, state, 0);
  9266. - if (omx_err)
  9267. - CLog::Log(LOGERROR, "%s::%s - OMX_CommandStateSet failed with omx_err(0x%x)\n",
  9268. - CLASSNAME, __func__, omx_err);
  9269. - else
  9270. - omx_err = WaitForState(state);
  9271. -
  9272. - return omx_err;
  9273. -}
  9274. -
  9275. -bool COpenMax::Initialize( const CStdString &decoder_name)
  9276. -{
  9277. - OMX_ERRORTYPE omx_err = m_dll->OMX_Init();
  9278. - if (omx_err)
  9279. - {
  9280. - CLog::Log(LOGERROR,
  9281. - "%s::%s - OpenMax failed to init, status(%d), ", // codec(%d), profile(%d), level(%d)
  9282. - CLASSNAME, __func__, omx_err );//, hints.codec, hints.profile, hints.level);
  9283. - return false;
  9284. - }
  9285. -
  9286. - // Get video decoder handle setting up callbacks, component is in loaded state on return.
  9287. - static OMX_CALLBACKTYPE decoder_callbacks = {
  9288. - &DecoderEventHandlerCallback, &DecoderEmptyBufferDoneCallback, &DecoderFillBufferDoneCallback };
  9289. - omx_err = m_dll->OMX_GetHandle(&m_omx_decoder, (char*)decoder_name.c_str(), this, &decoder_callbacks);
  9290. - if (omx_err)
  9291. - {
  9292. - CLog::Log(LOGERROR,
  9293. - "%s::%s - could not get decoder handle\n", CLASSNAME, __func__);
  9294. - m_dll->OMX_Deinit();
  9295. - return false;
  9296. - }
  9297. -
  9298. - return true;
  9299. -}
  9300. -
  9301. -void COpenMax::Deinitialize()
  9302. -{
  9303. - CLog::Log(LOGERROR,
  9304. - "%s::%s - failed to get component port parameter\n", CLASSNAME, __func__);
  9305. - m_dll->OMX_FreeHandle(m_omx_decoder);
  9306. - m_omx_decoder = NULL;
  9307. - m_dll->OMX_Deinit();
  9308. -}
  9309. -
  9310. -// OpenMax decoder callback routines.
  9311. -OMX_ERRORTYPE COpenMax::DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
  9312. - OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
  9313. -{
  9314. - return OMX_ErrorNone;
  9315. -}
  9316. -
  9317. -OMX_ERRORTYPE COpenMax::DecoderEmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer)
  9318. -{
  9319. - return OMX_ErrorNone;
  9320. -}
  9321. -
  9322. -OMX_ERRORTYPE COpenMax::DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader)
  9323. -{
  9324. - return OMX_ErrorNone;
  9325. -}
  9326. -
  9327. -#endif
  9328. -
  9329. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h
  9330. deleted file mode 100644
  9331. index 0d9ff18..0000000
  9332. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMax.h
  9333. +++ /dev/null
  9334. @@ -1,116 +0,0 @@
  9335. -#pragma once
  9336. -/*
  9337. - * Copyright (C) 2010-2013 Team XBMC
  9338. - * http://xbmc.org
  9339. - *
  9340. - * This Program is free software; you can redistribute it and/or modify
  9341. - * it under the terms of the GNU General Public License as published by
  9342. - * the Free Software Foundation; either version 2, or (at your option)
  9343. - * any later version.
  9344. - *
  9345. - * This Program is distributed in the hope that it will be useful,
  9346. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9347. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9348. - * GNU General Public License for more details.
  9349. - *
  9350. - * You should have received a copy of the GNU General Public License
  9351. - * along with XBMC; see the file COPYING. If not, see
  9352. - * <http://www.gnu.org/licenses/>.
  9353. - *
  9354. - */
  9355. -
  9356. -#if defined(HAVE_LIBOPENMAX)
  9357. -
  9358. -#include "cores/dvdplayer/DVDStreamInfo.h"
  9359. -#include "DVDVideoCodec.h"
  9360. -#include "threads/Event.h"
  9361. -
  9362. -#include <queue>
  9363. -#include <semaphore.h>
  9364. -#include <OMX_Core.h>
  9365. -
  9366. -////////////////////////////////////////////////////////////////////////////////////////////
  9367. -// debug spew defines
  9368. -#if 0
  9369. -#define OMX_DEBUG_VERBOSE
  9370. -#define OMX_DEBUG_EVENTHANDLER
  9371. -#define OMX_DEBUG_FILLBUFFERDONE
  9372. -#define OMX_DEBUG_EMPTYBUFFERDONE
  9373. -#endif
  9374. -
  9375. -typedef struct omx_codec_capability {
  9376. - // level is OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE,
  9377. - // or OMX_VIDEO_MPEG4PROFILETYPE depending on context.
  9378. - OMX_U32 level;
  9379. - // level is OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE,
  9380. - // or OMX_VIDEO_MPEG4PROFILETYPE depending on context.
  9381. - OMX_U32 profile;
  9382. -} omx_codec_capability;
  9383. -
  9384. -typedef struct omx_demux_packet {
  9385. - OMX_U8 *buff;
  9386. - int size;
  9387. - double dts;
  9388. - double pts;
  9389. -} omx_demux_packet;
  9390. -
  9391. -class DllLibOpenMax;
  9392. -class COpenMax
  9393. -{
  9394. -public:
  9395. - COpenMax();
  9396. - virtual ~COpenMax();
  9397. -
  9398. -protected:
  9399. - enum OMX_CLIENT_STATE {
  9400. - DEAD,
  9401. - LOADED,
  9402. - LOADED_TO_IDLE,
  9403. - IDLE_TO_EXECUTING,
  9404. - EXECUTING,
  9405. - EXECUTING_TO_IDLE,
  9406. - IDLE_TO_LOADED,
  9407. - RECONFIGURING,
  9408. - ERROR
  9409. - };
  9410. -
  9411. - // initialize OpenMax and get decoder component
  9412. - bool Initialize( const CStdString &decoder_name);
  9413. - void Deinitialize();
  9414. -
  9415. - // OpenMax Decoder delegate callback routines.
  9416. - static OMX_ERRORTYPE DecoderEventHandlerCallback(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
  9417. - OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData);
  9418. - static OMX_ERRORTYPE DecoderEmptyBufferDoneCallback(
  9419. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
  9420. - static OMX_ERRORTYPE DecoderFillBufferDoneCallback(
  9421. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader);
  9422. -
  9423. - // OpenMax decoder callback routines.
  9424. - virtual OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
  9425. - OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData);
  9426. - virtual OMX_ERRORTYPE DecoderEmptyBufferDone(
  9427. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
  9428. - virtual OMX_ERRORTYPE DecoderFillBufferDone(
  9429. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader);
  9430. -
  9431. - // OpenMax helper routines
  9432. - OMX_ERRORTYPE WaitForState(OMX_STATETYPE state);
  9433. - OMX_ERRORTYPE SetStateForComponent(OMX_STATETYPE state);
  9434. -
  9435. - DllLibOpenMax *m_dll;
  9436. - bool m_is_open;
  9437. - OMX_HANDLETYPE m_omx_decoder; // openmax decoder component reference
  9438. -
  9439. - // OpenMax state tracking
  9440. - OMX_CLIENT_STATE m_omx_client_state;
  9441. - volatile int m_omx_decoder_state;
  9442. - sem_t *m_omx_decoder_state_change;
  9443. - std::vector<omx_codec_capability> m_omx_decoder_capabilities;
  9444. -
  9445. -private:
  9446. - COpenMax(const COpenMax& other);
  9447. - COpenMax& operator=(const COpenMax&);
  9448. -};
  9449. -
  9450. -#endif
  9451. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  9452. index dcbdb1e..aca2e0d 100644
  9453. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  9454. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  9455. @@ -32,673 +32,891 @@
  9456. #include "DVDVideoCodec.h"
  9457. #include "utils/log.h"
  9458. #include "utils/TimeUtils.h"
  9459. +#include "settings/Settings.h"
  9460. #include "ApplicationMessenger.h"
  9461. #include "Application.h"
  9462. +#include "threads/Atomics.h"
  9463. -#include <OMX_Core.h>
  9464. -#include <OMX_Component.h>
  9465. -#include <OMX_Index.h>
  9466. -#include <OMX_Image.h>
  9467. +#include <IL/OMX_Core.h>
  9468. +#include <IL/OMX_Component.h>
  9469. +#include <IL/OMX_Index.h>
  9470. +#include <IL/OMX_Image.h>
  9471. +#include "cores/omxplayer/OMXImage.h"
  9472. +
  9473. +#define DTS_QUEUE
  9474. +
  9475. +#define DEFAULT_TIMEOUT 1000
  9476. +#ifdef _DEBUG
  9477. +#define OMX_DEBUG_VERBOSE
  9478. +#endif
  9479. #define CLASSNAME "COpenMaxVideo"
  9480. -// TODO: These are Nvidia Tegra2 dependent, need to dynamiclly find the
  9481. -// right codec matched to video format.
  9482. -#define OMX_H264BASE_DECODER "OMX.Nvidia.h264.decode"
  9483. -// OMX.Nvidia.h264ext.decode segfaults, not sure why.
  9484. -//#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264ext.decode"
  9485. -#define OMX_H264MAIN_DECODER "OMX.Nvidia.h264.decode"
  9486. -#define OMX_H264HIGH_DECODER "OMX.Nvidia.h264ext.decode"
  9487. -#define OMX_MPEG4_DECODER "OMX.Nvidia.mp4.decode"
  9488. -#define OMX_MPEG4EXT_DECODER "OMX.Nvidia.mp4ext.decode"
  9489. -#define OMX_MPEG2V_DECODER "OMX.Nvidia.mpeg2v.decode"
  9490. -#define OMX_VC1_DECODER "OMX.Nvidia.vc1.decode"
  9491. -
  9492. -// EGL extension functions
  9493. -static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
  9494. -static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
  9495. -#define GETEXTENSION(type, ext) \
  9496. -do \
  9497. -{ \
  9498. - ext = (type) eglGetProcAddress(#ext); \
  9499. - if (!ext) \
  9500. - { \
  9501. - CLog::Log(LOGERROR, "%s::%s - ERROR getting proc addr of " #ext "\n", CLASSNAME, __func__); \
  9502. - } \
  9503. -} while (0);
  9504. -
  9505. -#define OMX_INIT_STRUCTURE(a) \
  9506. - memset(&(a), 0, sizeof(a)); \
  9507. - (a).nSize = sizeof(a); \
  9508. - (a).nVersion.s.nVersionMajor = OMX_VERSION_MAJOR; \
  9509. - (a).nVersion.s.nVersionMinor = OMX_VERSION_MINOR; \
  9510. - (a).nVersion.s.nRevision = OMX_VERSION_REVISION; \
  9511. - (a).nVersion.s.nStep = OMX_VERSION_STEP
  9512. +COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv)
  9513. + : m_omv(omv), m_refs(0)
  9514. +{
  9515. + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  9516. + omx_buffer = NULL;
  9517. + width = 0;
  9518. + height = 0;
  9519. + index = 0;
  9520. + egl_image = 0;
  9521. + texture_id = 0;
  9522. +}
  9523. +
  9524. +COpenMaxVideoBuffer::~COpenMaxVideoBuffer()
  9525. +{
  9526. + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  9527. +}
  9528. -COpenMaxVideo::COpenMaxVideo()
  9529. +// DecoderFillBufferDone -- OpenMax output buffer has been filled
  9530. +static OMX_ERRORTYPE DecoderFillBufferDoneCallback(
  9531. + OMX_HANDLETYPE hComponent,
  9532. + OMX_PTR pAppData,
  9533. + OMX_BUFFERHEADERTYPE* pBuffer)
  9534. +{
  9535. + COpenMaxVideoBuffer *pic = static_cast<COpenMaxVideoBuffer*>(pBuffer->pAppPrivate);
  9536. + COpenMaxVideo *ctx = pic->m_omv;
  9537. + return ctx->DecoderFillBufferDone(hComponent, pBuffer);
  9538. +}
  9539. +
  9540. +
  9541. +COpenMaxVideoBuffer* COpenMaxVideoBuffer::Acquire()
  9542. +{
  9543. + long count = AtomicIncrement(&m_refs);
  9544. + #if defined(OMX_DEBUG_VERBOSE)
  9545. + CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, count);
  9546. + #endif
  9547. + (void)count;
  9548. + return this;
  9549. +}
  9550. +
  9551. +long COpenMaxVideoBuffer::Release()
  9552. {
  9553. - m_portChanging = false;
  9554. + long count = AtomicDecrement(&m_refs);
  9555. + if (count == 0)
  9556. + {
  9557. + m_omv->ReleaseOpenMaxBuffer(this);
  9558. + }
  9559. +
  9560. + #if defined(OMX_DEBUG_VERBOSE)
  9561. + CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, count);
  9562. + #endif
  9563. + return count;
  9564. +}
  9565. - pthread_mutex_init(&m_omx_input_mutex, NULL);
  9566. +void COpenMaxVideoBuffer::Sync()
  9567. +{
  9568. + #if defined(OMX_DEBUG_VERBOSE)
  9569. + CLog::Log(LOGDEBUG, "%s::%s %p ref:%ld", CLASSNAME, __func__, this, m_refs);
  9570. + #endif
  9571. + Release();
  9572. +}
  9573. +
  9574. +COpenMaxVideo::COpenMaxVideo()
  9575. +{
  9576. + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  9577. pthread_mutex_init(&m_omx_output_mutex, NULL);
  9578. - m_omx_decoder_state_change = (sem_t*)malloc(sizeof(sem_t));
  9579. - sem_init(m_omx_decoder_state_change, 0, 0);
  9580. - memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
  9581. m_drop_state = false;
  9582. m_decoded_width = 0;
  9583. m_decoded_height = 0;
  9584. - m_omx_input_eos = false;
  9585. - m_omx_input_port = 0;
  9586. - m_omx_output_eos = false;
  9587. - m_omx_output_port = 0;
  9588. - m_videoplayback_done = false;
  9589. + m_egl_buffer_count = 0;
  9590. +
  9591. + m_port_settings_changed = false;
  9592. + m_pFormatName = "omx-xxxx";
  9593. }
  9594. COpenMaxVideo::~COpenMaxVideo()
  9595. {
  9596. #if defined(OMX_DEBUG_VERBOSE)
  9597. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  9598. + CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  9599. #endif
  9600. - if (m_is_open)
  9601. - Close();
  9602. - pthread_mutex_destroy(&m_omx_input_mutex);
  9603. + if (m_omx_decoder.IsInitialized())
  9604. + {
  9605. + if (m_omx_tunnel.IsInitialized())
  9606. + m_omx_tunnel.Deestablish();
  9607. +
  9608. + StopDecoder();
  9609. +
  9610. + if (m_omx_egl_render.IsInitialized())
  9611. + m_omx_egl_render.Deinitialize();
  9612. + if (m_omx_decoder.IsInitialized())
  9613. + m_omx_decoder.Deinitialize();
  9614. + }
  9615. pthread_mutex_destroy(&m_omx_output_mutex);
  9616. - sem_destroy(m_omx_decoder_state_change);
  9617. - free(m_omx_decoder_state_change);
  9618. }
  9619. -bool COpenMaxVideo::Open(CDVDStreamInfo &hints)
  9620. +bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  9621. {
  9622. #if defined(OMX_DEBUG_VERBOSE)
  9623. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  9624. + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  9625. #endif
  9626. + // we always qualify even if DVDFactoryCodec does this too.
  9627. + if (!CSettings::Get().GetBool("videoplayer.useomx") || hints.software)
  9628. + return false;
  9629. +
  9630. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  9631. - std::string decoder_name;
  9632. m_decoded_width = hints.width;
  9633. m_decoded_height = hints.height;
  9634. + m_egl_display = g_Windowing.GetEGLDisplay();
  9635. + m_egl_context = g_Windowing.GetEGLContext();
  9636. + m_egl_buffer_count = 4;
  9637. +
  9638. + m_codingType = OMX_VIDEO_CodingUnused;
  9639. +
  9640. switch (hints.codec)
  9641. {
  9642. case AV_CODEC_ID_H264:
  9643. - {
  9644. - switch(hints.profile)
  9645. - {
  9646. - case FF_PROFILE_H264_BASELINE:
  9647. - // (role name) video_decoder.avc
  9648. - // H.264 Baseline profile
  9649. - decoder_name = OMX_H264BASE_DECODER;
  9650. - break;
  9651. - case FF_PROFILE_H264_MAIN:
  9652. - // (role name) video_decoder.avc
  9653. - // H.264 Main profile
  9654. - decoder_name = OMX_H264MAIN_DECODER;
  9655. - break;
  9656. - case FF_PROFILE_H264_HIGH:
  9657. - // (role name) video_decoder.avc
  9658. - // H.264 Main profile
  9659. - decoder_name = OMX_H264HIGH_DECODER;
  9660. - break;
  9661. - default:
  9662. - return false;
  9663. - break;
  9664. - }
  9665. - }
  9666. + // H.264
  9667. + m_codingType = OMX_VIDEO_CodingAVC;
  9668. + m_pFormatName = "omx-h264";
  9669. break;
  9670. + case AV_CODEC_ID_H263:
  9671. case AV_CODEC_ID_MPEG4:
  9672. - // (role name) video_decoder.mpeg4
  9673. - // MPEG-4, DivX 4/5 and Xvid compatible
  9674. - decoder_name = OMX_MPEG4_DECODER;
  9675. - break;
  9676. - /*
  9677. - TODO: what mpeg4 formats are "ext" ????
  9678. - case NvxStreamType_MPEG4Ext:
  9679. - // (role name) video_decoder.mpeg4
  9680. // MPEG-4, DivX 4/5 and Xvid compatible
  9681. - decoder_name = OMX_MPEG4EXT_DECODER;
  9682. + m_codingType = OMX_VIDEO_CodingMPEG4;
  9683. m_pFormatName = "omx-mpeg4";
  9684. break;
  9685. - */
  9686. + case AV_CODEC_ID_MPEG1VIDEO:
  9687. case AV_CODEC_ID_MPEG2VIDEO:
  9688. - // (role name) video_decoder.mpeg2
  9689. // MPEG-2
  9690. - decoder_name = OMX_MPEG2V_DECODER;
  9691. + m_codingType = OMX_VIDEO_CodingMPEG2;
  9692. + m_pFormatName = "omx-mpeg2";
  9693. + break;
  9694. + case AV_CODEC_ID_VP6:
  9695. + // this form is encoded upside down
  9696. + // fall through
  9697. + case AV_CODEC_ID_VP6F:
  9698. + case AV_CODEC_ID_VP6A:
  9699. + // VP6
  9700. + m_codingType = OMX_VIDEO_CodingVP6;
  9701. + m_pFormatName = "omx-vp6";
  9702. + break;
  9703. + case AV_CODEC_ID_VP8:
  9704. + // VP8
  9705. + m_codingType = OMX_VIDEO_CodingVP8;
  9706. + m_pFormatName = "omx-vp8";
  9707. + break;
  9708. + case AV_CODEC_ID_THEORA:
  9709. + // theora
  9710. + m_codingType = OMX_VIDEO_CodingTheora;
  9711. + m_pFormatName = "omx-theora";
  9712. + break;
  9713. + case AV_CODEC_ID_MJPEG:
  9714. + case AV_CODEC_ID_MJPEGB:
  9715. + // mjpg
  9716. + m_codingType = OMX_VIDEO_CodingMJPEG;
  9717. + m_pFormatName = "omx-mjpg";
  9718. break;
  9719. case AV_CODEC_ID_VC1:
  9720. - // (role name) video_decoder.vc1
  9721. + case AV_CODEC_ID_WMV3:
  9722. // VC-1, WMV9
  9723. - decoder_name = OMX_VC1_DECODER;
  9724. - break;
  9725. + m_codingType = OMX_VIDEO_CodingWMV;
  9726. + m_pFormatName = "omx-vc1";
  9727. + break;
  9728. default:
  9729. + CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec);
  9730. return false;
  9731. break;
  9732. }
  9733. // initialize OpenMAX.
  9734. - if (!Initialize(decoder_name))
  9735. + if (!m_omx_decoder.Initialize("OMX.broadcom.video_decode", OMX_IndexParamVideoInit))
  9736. {
  9737. + CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.Initialize", CLASSNAME, __func__);
  9738. return false;
  9739. }
  9740. - // TODO: Find component from role name.
  9741. - // Get the port information. This will obtain information about the
  9742. - // number of ports and index of the first port.
  9743. - OMX_PORT_PARAM_TYPE port_param;
  9744. - OMX_INIT_STRUCTURE(port_param);
  9745. - omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamVideoInit, &port_param);
  9746. - if (omx_err)
  9747. + omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle);
  9748. + if (omx_err != OMX_ErrorNone)
  9749. {
  9750. - Deinitialize();
  9751. + CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9752. return false;
  9753. }
  9754. - m_omx_input_port = port_param.nStartPortNumber;
  9755. - m_omx_output_port = m_omx_input_port + 1;
  9756. - #if defined(OMX_DEBUG_VERBOSE)
  9757. - CLog::Log(LOGDEBUG,
  9758. - "%s::%s - decoder_component(0x%p), input_port(0x%x), output_port(0x%x)\n",
  9759. - CLASSNAME, __func__, m_omx_decoder, m_omx_input_port, m_omx_output_port);
  9760. - #endif
  9761. - // TODO: Set role for the component because components could have multiple roles.
  9762. - //QueryCodec();
  9763. + OMX_VIDEO_PARAM_PORTFORMATTYPE formatType;
  9764. + OMX_INIT_STRUCTURE(formatType);
  9765. + formatType.nPortIndex = m_omx_decoder.GetInputPort();
  9766. + formatType.eCompressionFormat = m_codingType;
  9767. +
  9768. + omx_err = m_omx_decoder.SetParameter(OMX_IndexParamVideoPortFormat, &formatType);
  9769. + if (omx_err != OMX_ErrorNone)
  9770. + {
  9771. + CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9772. + return false;
  9773. + }
  9774. + OMX_PARAM_PORTDEFINITIONTYPE portParam;
  9775. + OMX_INIT_STRUCTURE(portParam);
  9776. + portParam.nPortIndex = m_omx_decoder.GetInputPort();
  9777. +
  9778. + omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &portParam);
  9779. + if (omx_err != OMX_ErrorNone)
  9780. + {
  9781. + CLog::Log(LOGERROR, "%s::%s error OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9782. + return false;
  9783. + }
  9784. +
  9785. + portParam.nPortIndex = m_omx_decoder.GetInputPort();
  9786. + portParam.nBufferCountActual = 20;
  9787. + portParam.format.video.nFrameWidth = m_decoded_width;
  9788. + portParam.format.video.nFrameHeight = m_decoded_height;
  9789. +
  9790. + omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &portParam);
  9791. + if (omx_err != OMX_ErrorNone)
  9792. + {
  9793. + CLog::Log(LOGERROR, "%s::%s error OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9794. + return false;
  9795. + }
  9796. +
  9797. + // request portsettingschanged on aspect ratio change
  9798. + OMX_CONFIG_REQUESTCALLBACKTYPE notifications;
  9799. + OMX_INIT_STRUCTURE(notifications);
  9800. + notifications.nPortIndex = m_omx_decoder.GetOutputPort();
  9801. + notifications.nIndex = OMX_IndexParamBrcmPixelAspectRatio;
  9802. + notifications.bEnable = OMX_TRUE;
  9803. +
  9804. + omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, &notifications);
  9805. + if (omx_err != OMX_ErrorNone)
  9806. + {
  9807. + CLog::Log(LOGERROR, "%s::%s OMX_IndexConfigRequestCallback error (0%08x)", CLASSNAME, __func__, omx_err);
  9808. + return false;
  9809. + }
  9810. +
  9811. + if (NaluFormatStartCodes(hints.codec, (uint8_t *)hints.extradata, hints.extrasize))
  9812. + {
  9813. + OMX_NALSTREAMFORMATTYPE nalStreamFormat;
  9814. + OMX_INIT_STRUCTURE(nalStreamFormat);
  9815. + nalStreamFormat.nPortIndex = m_omx_decoder.GetInputPort();
  9816. + nalStreamFormat.eNaluFormat = OMX_NaluFormatStartCodes;
  9817. +
  9818. + omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexParamNalStreamFormatSelect, &nalStreamFormat);
  9819. + if (omx_err != OMX_ErrorNone)
  9820. + {
  9821. + CLog::Log(LOGERROR, "%s::%s OMX_IndexParamNalStreamFormatSelect error (0%08x)", CLASSNAME, __func__, omx_err);
  9822. + return false;
  9823. + }
  9824. + }
  9825. - // Component will be in OMX_StateLoaded now so we can alloc omx input/output buffers.
  9826. - // we can only alloc them in OMX_StateLoaded state or if the component port is disabled
  9827. // Alloc buffers for the omx input port.
  9828. - omx_err = AllocOMXInputBuffers();
  9829. - if (omx_err)
  9830. + omx_err = m_omx_decoder.AllocInputBuffers();
  9831. + if (omx_err != OMX_ErrorNone)
  9832. {
  9833. - Deinitialize();
  9834. + CLog::Log(LOGERROR, "%s::%s AllocInputBuffers error (0%08x)", CLASSNAME, __func__, omx_err);
  9835. return false;
  9836. }
  9837. - // Alloc buffers for the omx output port.
  9838. - m_egl_display = g_Windowing.GetEGLDisplay();
  9839. - m_egl_context = g_Windowing.GetEGLContext();
  9840. - omx_err = AllocOMXOutputBuffers();
  9841. - if (omx_err)
  9842. +
  9843. + omx_err = m_omx_decoder.SetStateForComponent(OMX_StateExecuting);
  9844. + if (omx_err != OMX_ErrorNone)
  9845. {
  9846. - FreeOMXInputBuffers(false);
  9847. - Deinitialize();
  9848. + CLog::Log(LOGERROR, "%s::%s error m_omx_decoder.SetStateForComponent error (0%08x)", CLASSNAME, __func__, omx_err);
  9849. return false;
  9850. }
  9851. - m_is_open = true;
  9852. - m_drop_state = false;
  9853. - m_videoplayback_done = false;
  9854. + if (!SendDecoderConfig((uint8_t *)hints.extradata, hints.extrasize))
  9855. + return false;
  9856. - // crank it up.
  9857. - StartDecoder();
  9858. + m_drop_state = false;
  9859. return true;
  9860. }
  9861. -void COpenMaxVideo::Close()
  9862. +void COpenMaxVideo::Dispose()
  9863. {
  9864. #if defined(OMX_DEBUG_VERBOSE)
  9865. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  9866. + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  9867. #endif
  9868. - if (m_omx_decoder)
  9869. - {
  9870. - if (m_omx_decoder_state != OMX_StateLoaded)
  9871. - StopDecoder();
  9872. - Deinitialize();
  9873. - }
  9874. - m_is_open = false;
  9875. }
  9876. void COpenMaxVideo::SetDropState(bool bDrop)
  9877. {
  9878. +#if defined(OMX_DEBUG_VERBOSE)
  9879. + if (m_drop_state != bDrop)
  9880. + CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)",
  9881. + CLASSNAME, __func__, bDrop);
  9882. +#endif
  9883. m_drop_state = bDrop;
  9884. +}
  9885. - if (m_drop_state)
  9886. +bool COpenMaxVideo::SendDecoderConfig(uint8_t *extradata, int extrasize)
  9887. +{
  9888. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  9889. +
  9890. + /* send decoder config */
  9891. + if (extrasize > 0 && extradata != NULL)
  9892. {
  9893. - OMX_ERRORTYPE omx_err;
  9894. + OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer();
  9895. - // blow all but the last ready video frame
  9896. - pthread_mutex_lock(&m_omx_output_mutex);
  9897. - while (m_omx_output_ready.size() > 1)
  9898. + if (omx_buffer == NULL)
  9899. {
  9900. - m_dts_queue.pop();
  9901. - OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_output_ready.front()->omx_buffer;
  9902. - m_omx_output_ready.pop();
  9903. - // return the omx buffer back to OpenMax to fill.
  9904. - omx_err = OMX_FillThisBuffer(m_omx_decoder, omx_buffer);
  9905. - if (omx_err)
  9906. - CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n",
  9907. - CLASSNAME, __func__, omx_err);
  9908. + CLog::Log(LOGERROR, "%s::%s - buffer error 0x%08x", CLASSNAME, __func__, omx_err);
  9909. + return false;
  9910. }
  9911. - pthread_mutex_unlock(&m_omx_output_mutex);
  9912. - #if defined(OMX_DEBUG_VERBOSE)
  9913. - CLog::Log(LOGDEBUG, "%s::%s - m_drop_state(%d)\n",
  9914. - CLASSNAME, __func__, m_drop_state);
  9915. - #endif
  9916. + omx_buffer->nOffset = 0;
  9917. + omx_buffer->nFilledLen = extrasize;
  9918. + if (omx_buffer->nFilledLen > omx_buffer->nAllocLen)
  9919. + {
  9920. + CLog::Log(LOGERROR, "%s::%s - omx_buffer->nFilledLen > omx_buffer->nAllocLen", CLASSNAME, __func__);
  9921. + return false;
  9922. + }
  9923. +
  9924. + memcpy((unsigned char *)omx_buffer->pBuffer, extradata, omx_buffer->nFilledLen);
  9925. + omx_buffer->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME;
  9926. +
  9927. +//CLog::Log(LOGINFO, "%s::%s - Empty(%d,%x)", CLASSNAME, __func__, omx_buffer->nFilledLen, omx_buffer->nFlags); CLog::MemDump((char *)omx_buffer->pBuffer, std::min(64U, omx_buffer->nFilledLen));
  9928. + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  9929. + if (omx_err != OMX_ErrorNone)
  9930. + {
  9931. + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err);
  9932. + return false;
  9933. + }
  9934. }
  9935. + return true;
  9936. }
  9937. -int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  9938. +bool COpenMaxVideo::NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize)
  9939. +{
  9940. + switch(codec)
  9941. + {
  9942. + case AV_CODEC_ID_H264:
  9943. + if (extrasize < 7 || extradata == NULL)
  9944. + return true;
  9945. + // valid avcC atom data always starts with the value 1 (version), otherwise annexb
  9946. + else if ( *extradata != 1 )
  9947. + return true;
  9948. + default: break;
  9949. + }
  9950. + return false;
  9951. +}
  9952. +
  9953. +bool COpenMaxVideo::PortSettingsChanged()
  9954. {
  9955. - if (pData)
  9956. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  9957. +
  9958. + if (m_port_settings_changed)
  9959. + {
  9960. + m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
  9961. + }
  9962. +
  9963. + OMX_PARAM_PORTDEFINITIONTYPE port_def;
  9964. + OMX_INIT_STRUCTURE(port_def);
  9965. + port_def.nPortIndex = m_omx_decoder.GetOutputPort();
  9966. + omx_err = m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  9967. + if (omx_err != OMX_ErrorNone)
  9968. + {
  9969. + CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9970. + return false;
  9971. + }
  9972. +
  9973. + OMX_CONFIG_POINTTYPE pixel_aspect;
  9974. + OMX_INIT_STRUCTURE(pixel_aspect);
  9975. + pixel_aspect.nPortIndex = m_omx_decoder.GetOutputPort();
  9976. + omx_err = m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio, &pixel_aspect);
  9977. + if (omx_err != OMX_ErrorNone)
  9978. + {
  9979. + CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  9980. + return false;
  9981. + }
  9982. +
  9983. + if (m_port_settings_changed)
  9984. {
  9985. - int demuxer_bytes = iSize;
  9986. - uint8_t *demuxer_content = pData;
  9987. + m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
  9988. + return true;
  9989. + }
  9990. +
  9991. + // convert in stripes
  9992. + port_def.format.video.nSliceHeight = 16;
  9993. + port_def.format.video.nStride = 0;
  9994. +
  9995. + omx_err = m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  9996. + if (omx_err != OMX_ErrorNone)
  9997. + {
  9998. + CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter result(0x%x)", CLASSNAME, __func__, omx_err);
  9999. + return false;
  10000. + }
  10001. +
  10002. + OMX_CALLBACKTYPE callbacks = { NULL, NULL, DecoderFillBufferDoneCallback };
  10003. + if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit, &callbacks))
  10004. + {
  10005. + CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.Initialize", CLASSNAME, __func__);
  10006. + return false;
  10007. + }
  10008. +
  10009. + OMX_CONFIG_PORTBOOLEANTYPE discardMode;
  10010. + OMX_INIT_STRUCTURE(discardMode);
  10011. + discardMode.nPortIndex = m_omx_egl_render.GetInputPort();
  10012. + discardMode.bEnabled = OMX_FALSE;
  10013. + omx_err = m_omx_egl_render.SetParameter(OMX_IndexParamBrcmVideoEGLRenderDiscardMode, &discardMode);
  10014. + if (omx_err != OMX_ErrorNone)
  10015. + {
  10016. + CLog::Log(LOGERROR, "%s::%s - error m_omx_egl_render.SetParameter(OMX_IndexParamBrcmVideoEGLRenderDiscardMode) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10017. + return false;
  10018. + }
  10019. +
  10020. + m_omx_egl_render.ResetEos();
  10021. +
  10022. + CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  10023. + port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight,
  10024. + port_def.format.video.xFramerate / (float)(1<<16), 0,0);
  10025. +
  10026. + m_omx_tunnel.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  10027. +
  10028. + omx_err = m_omx_tunnel.Establish();
  10029. + if (omx_err != OMX_ErrorNone)
  10030. + {
  10031. + CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10032. + return false;
  10033. + }
  10034. +
  10035. + // Obtain the information about the output port.
  10036. + OMX_PARAM_PORTDEFINITIONTYPE port_format;
  10037. + OMX_INIT_STRUCTURE(port_format);
  10038. + port_format.nPortIndex = m_omx_egl_render.GetOutputPort();
  10039. + omx_err = m_omx_egl_render.GetParameter(OMX_IndexParamPortDefinition, &port_format);
  10040. + if (omx_err != OMX_ErrorNone)
  10041. + CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.GetParameter OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10042. +
  10043. + port_format.nBufferCountActual = m_egl_buffer_count;
  10044. + omx_err = m_omx_egl_render.SetParameter(OMX_IndexParamPortDefinition, &port_format);
  10045. + if (omx_err != OMX_ErrorNone)
  10046. + CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.SetParameter OMX_IndexParamPortDefinition omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10047. +
  10048. + #if defined(OMX_DEBUG_VERBOSE)
  10049. + CLog::Log(LOGDEBUG,
  10050. + "%s::%s (1) - oport(%d), nFrameWidth(%u), nFrameHeight(%u), nStride(%x), nBufferCountMin(%u), nBufferCountActual(%u), nBufferSize(%u)",
  10051. + CLASSNAME, __func__, m_omx_egl_render.GetOutputPort(),
  10052. + port_format.format.video.nFrameWidth, port_format.format.video.nFrameHeight,port_format.format.video.nStride,
  10053. + port_format.nBufferCountMin, port_format.nBufferCountActual, port_format.nBufferSize);
  10054. + #endif
  10055. +
  10056. - // we need to queue then de-queue the demux packet, seems silly but
  10057. - // omx might not have a omx input buffer avaliable when we are called
  10058. - // and we must store the demuxer packet and try again later.
  10059. + omx_err = m_omx_egl_render.EnablePort(m_omx_egl_render.GetOutputPort(), false);
  10060. + if (omx_err != OMX_ErrorNone)
  10061. + {
  10062. + CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.EnablePort omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10063. + return false;
  10064. + }
  10065. +
  10066. + if (!AllocOMXOutputBuffers())
  10067. + {
  10068. + CLog::Log(LOGERROR, "%s::%s - AllocOMXOutputBuffers failed", CLASSNAME, __func__);
  10069. + return false;
  10070. + }
  10071. +
  10072. + omx_err = m_omx_egl_render.WaitForCommand(OMX_CommandPortEnable, m_omx_egl_render.GetOutputPort());
  10073. + if (omx_err != OMX_ErrorNone)
  10074. + {
  10075. + CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.WaitForCommand(OMX_CommandPortEnable) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10076. + return false;
  10077. + }
  10078. +
  10079. + assert(m_omx_output_busy.empty());
  10080. + assert(m_omx_output_ready.empty());
  10081. +
  10082. + omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateExecuting);
  10083. + if (omx_err != OMX_ErrorNone)
  10084. + {
  10085. + CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.SetStateForComponent omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10086. + return false;
  10087. + }
  10088. +
  10089. + omx_err = PrimeFillBuffers();
  10090. + if (omx_err != OMX_ErrorNone)
  10091. + {
  10092. + CLog::Log(LOGERROR, "%s::%s - m_omx_egl_render.PrimeFillBuffers omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10093. + return false;
  10094. + }
  10095. +
  10096. + m_port_settings_changed = true;
  10097. + return true;
  10098. +}
  10099. +
  10100. +
  10101. +int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  10102. +{
  10103. + #if defined(OMX_DEBUG_VERBOSE)
  10104. + CLog::Log(LOGDEBUG, "%s::%s - %-8p %-6d dts:%.3f pts:%.3f demux_queue(%d) dts_queue(%d) ready_queue(%d) busy_queue(%d)",
  10105. + CLASSNAME, __func__, pData, iSize, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, m_demux_queue.size(), m_dts_queue.size(), m_omx_output_ready.size(), m_omx_output_busy.size());
  10106. + #endif
  10107. +
  10108. + OMX_ERRORTYPE omx_err;
  10109. + unsigned int demuxer_bytes = 0;
  10110. + uint8_t *demuxer_content = NULL;
  10111. +
  10112. + // we need to queue then de-queue the demux packet, seems silly but
  10113. + // omx might not have a omx input buffer available when we are called
  10114. + // and we must store the demuxer packet and try again later.
  10115. + if (pData && m_demux_queue.empty() && m_omx_decoder.GetInputBufferSpace() >= (unsigned int)iSize)
  10116. + {
  10117. + demuxer_bytes = iSize;
  10118. + demuxer_content = pData;
  10119. + }
  10120. + else if (pData && iSize)
  10121. + {
  10122. omx_demux_packet demux_packet;
  10123. demux_packet.dts = dts;
  10124. demux_packet.pts = pts;
  10125. -
  10126. - demux_packet.size = demuxer_bytes;
  10127. - demux_packet.buff = new OMX_U8[demuxer_bytes];
  10128. - memcpy(demux_packet.buff, demuxer_content, demuxer_bytes);
  10129. + demux_packet.size = iSize;
  10130. + demux_packet.buff = new OMX_U8[iSize];
  10131. + memcpy(demux_packet.buff, pData, iSize);
  10132. m_demux_queue.push(demux_packet);
  10133. + }
  10134. - // we can look at m_omx_input_avaliable.empty without needing to lock/unlock
  10135. + OMX_U8 *buffer_to_free = NULL;
  10136. + while (1)
  10137. + {
  10138. // try to send any/all demux packets to omx decoder.
  10139. - while (!m_omx_input_avaliable.empty() && !m_demux_queue.empty() )
  10140. + if (!demuxer_bytes && !m_demux_queue.empty())
  10141. {
  10142. - OMX_ERRORTYPE omx_err;
  10143. - OMX_BUFFERHEADERTYPE* omx_buffer;
  10144. -
  10145. - demux_packet = m_demux_queue.front();
  10146. - m_demux_queue.pop();
  10147. - // need to lock here to retreve an input buffer and pop the queue
  10148. - pthread_mutex_lock(&m_omx_input_mutex);
  10149. - omx_buffer = m_omx_input_avaliable.front();
  10150. - m_omx_input_avaliable.pop();
  10151. - pthread_mutex_unlock(&m_omx_input_mutex);
  10152. -
  10153. - // delete the previous demuxer buffer
  10154. - delete [] omx_buffer->pBuffer;
  10155. - // setup a new omx_buffer.
  10156. - omx_buffer->nFlags = m_omx_input_eos ? OMX_BUFFERFLAG_EOS : 0;
  10157. + omx_demux_packet &demux_packet = m_demux_queue.front();
  10158. + if (m_omx_decoder.GetInputBufferSpace() >= (unsigned int)demux_packet.size)
  10159. + {
  10160. + // need to lock here to retrieve an input buffer and pop the queue
  10161. + m_demux_queue.pop();
  10162. + demuxer_bytes = (unsigned int)demux_packet.size;
  10163. + demuxer_content = demux_packet.buff;
  10164. + buffer_to_free = demux_packet.buff;
  10165. + dts = demux_packet.dts;
  10166. + pts = demux_packet.pts;
  10167. + }
  10168. + }
  10169. +
  10170. + if (demuxer_content)
  10171. + {
  10172. + // 500ms timeout
  10173. + OMX_BUFFERHEADERTYPE *omx_buffer = m_omx_decoder.GetInputBuffer(500);
  10174. + if (omx_buffer == NULL)
  10175. + {
  10176. + CLog::Log(LOGERROR, "%s::%s - m_omx_decoder.GetInputBuffer timeout", CLASSNAME, __func__);
  10177. + return VC_ERROR;
  10178. + }
  10179. + #if defined(OMX_DEBUG_VERBOSE)
  10180. + //CLog::Log(LOGDEBUG, "%s::%s - omx_buffer=%p", CLASSNAME, __func__, omx_buffer);
  10181. + #endif
  10182. + omx_buffer->nFlags = 0;
  10183. omx_buffer->nOffset = 0;
  10184. - omx_buffer->pBuffer = demux_packet.buff;
  10185. - omx_buffer->nAllocLen = demux_packet.size;
  10186. - omx_buffer->nFilledLen = demux_packet.size;
  10187. - omx_buffer->nTimeStamp = (demux_packet.pts == DVD_NOPTS_VALUE) ? 0 : demux_packet.pts * 1000.0; // in microseconds;
  10188. +
  10189. + omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
  10190. + omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts);
  10191. omx_buffer->pAppPrivate = omx_buffer;
  10192. - omx_buffer->nInputPortIndex = m_omx_input_port;
  10193. + memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);
  10194. - #if defined(OMX_DEBUG_EMPTYBUFFERDONE)
  10195. - CLog::Log(LOGDEBUG,
  10196. - "%s::%s - feeding decoder, omx_buffer->pBuffer(0x%p), demuxer_bytes(%d)\n",
  10197. - CLASSNAME, __func__, omx_buffer->pBuffer, demuxer_bytes);
  10198. - #endif
  10199. - // Give this omx_buffer to OpenMax to be decoded.
  10200. - omx_err = OMX_EmptyThisBuffer(m_omx_decoder, omx_buffer);
  10201. - if (omx_err)
  10202. + demuxer_bytes -= omx_buffer->nFilledLen;
  10203. + demuxer_content += omx_buffer->nFilledLen;
  10204. +
  10205. + if (demuxer_bytes == 0)
  10206. + omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
  10207. + if (pts == DVD_NOPTS_VALUE)
  10208. + omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
  10209. + if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored)
  10210. + omx_buffer->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
  10211. +
  10212. +#if defined(OMX_DEBUG_VERBOSE)
  10213. + CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x",
  10214. + CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags);
  10215. +#endif
  10216. +
  10217. + omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  10218. + if (omx_err != OMX_ErrorNone)
  10219. {
  10220. - CLog::Log(LOGDEBUG,
  10221. - "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)\n",
  10222. - CLASSNAME, __func__, omx_err);
  10223. + CLog::Log(LOGERROR, "%s::%s - OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err);
  10224. return VC_ERROR;
  10225. }
  10226. - // only push if we are successful with feeding OMX_EmptyThisBuffer
  10227. - m_dts_queue.push(demux_packet.dts);
  10228. -
  10229. - // if m_omx_input_avaliable and/or demux_queue are now empty,
  10230. - // wait up to 20ms for OpenMax to consume a demux packet
  10231. - if (m_omx_input_avaliable.empty() || m_demux_queue.empty())
  10232. - m_input_consumed_event.WaitMSec(1);
  10233. + if (demuxer_bytes == 0)
  10234. + {
  10235. +#ifdef DTS_QUEUE
  10236. + // only push if we are successful with feeding OMX_EmptyThisBuffer
  10237. + m_dts_queue.push(dts);
  10238. + assert(m_dts_queue.size() < 32);
  10239. +#endif
  10240. + if (buffer_to_free)
  10241. + {
  10242. + delete [] buffer_to_free;
  10243. + buffer_to_free = NULL;
  10244. + demuxer_content = NULL;
  10245. + continue;
  10246. + }
  10247. + }
  10248. + }
  10249. + omx_err = m_omx_decoder.WaitForEvent(OMX_EventPortSettingsChanged, 0);
  10250. + if (omx_err == OMX_ErrorNone)
  10251. + {
  10252. + if (!PortSettingsChanged())
  10253. + {
  10254. + CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10255. + return VC_ERROR;
  10256. + }
  10257. + }
  10258. + else if (omx_err != OMX_ErrorTimeout)
  10259. + {
  10260. + CLog::Log(LOGERROR, "%s::%s - video not supported omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10261. + return VC_ERROR;
  10262. }
  10263. - if (m_omx_input_avaliable.empty() && !m_demux_queue.empty())
  10264. - m_input_consumed_event.WaitMSec(1);
  10265. -
  10266. - #if defined(OMX_DEBUG_VERBOSE)
  10267. - if (m_omx_input_avaliable.empty())
  10268. - CLog::Log(LOGDEBUG,
  10269. - "%s::%s - buffering demux, m_demux_queue_size(%d), demuxer_bytes(%d)\n",
  10270. - CLASSNAME, __func__, m_demux_queue.size(), demuxer_bytes);
  10271. - #endif
  10272. + omx_err = m_omx_decoder.WaitForEvent(OMX_EventParamOrConfigChanged, 0);
  10273. + if (omx_err == OMX_ErrorNone)
  10274. + {
  10275. + if (!PortSettingsChanged())
  10276. + {
  10277. + CLog::Log(LOGERROR, "%s::%s - error PortSettingsChanged (EventParamOrConfigChanged) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10278. + return VC_ERROR;
  10279. + }
  10280. + }
  10281. + else if (omx_err == OMX_ErrorStreamCorrupt)
  10282. + {
  10283. + CLog::Log(LOGERROR, "%s::%s - video not supported 2 omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  10284. + return VC_ERROR;
  10285. + }
  10286. + if (!demuxer_bytes)
  10287. + break;
  10288. }
  10289. +#if defined(OMX_DEBUG_VERBOSE)
  10290. + if (!m_omx_decoder.GetInputBufferSpace())
  10291. + CLog::Log(LOGDEBUG,
  10292. + "%s::%s - buffering demux, m_demux_queue_size(%d), demuxer_bytes(%d) m_dts_queue.size(%d)",
  10293. + CLASSNAME, __func__, m_demux_queue.size(), demuxer_bytes, m_dts_queue.size());
  10294. + #endif
  10295. +
  10296. if (m_omx_output_ready.empty())
  10297. + {
  10298. + //CLog::Log(LOGDEBUG, "%s::%s - empty: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size());
  10299. return VC_BUFFER;
  10300. + }
  10301. - return VC_PICTURE | VC_BUFFER;
  10302. + //CLog::Log(LOGDEBUG, "%s::%s - full: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size());
  10303. + return VC_PICTURE;
  10304. }
  10305. void COpenMaxVideo::Reset(void)
  10306. {
  10307. #if defined(OMX_DEBUG_VERBOSE)
  10308. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  10309. + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  10310. #endif
  10311. -/*
  10312. - // only reset OpenMax decoder if it's running
  10313. - if (m_omx_decoder_state == OMX_StateExecuting)
  10314. + m_omx_egl_render.FlushAll();
  10315. + m_omx_decoder.FlushAll();
  10316. + // blow all ready video frames
  10317. + while (!m_omx_output_ready.empty())
  10318. {
  10319. - OMX_ERRORTYPE omx_err;
  10320. -
  10321. - omx_err = StopDecoder();
  10322. - // Alloc OpenMax input buffers.
  10323. - omx_err = AllocOMXInputBuffers();
  10324. - // Alloc OpenMax output buffers.
  10325. - omx_err = AllocOMXOutputBuffers();
  10326. -
  10327. - omx_err = StartDecoder();
  10328. + pthread_mutex_lock(&m_omx_output_mutex);
  10329. + COpenMaxVideoBuffer *pic = m_omx_output_ready.front();
  10330. + m_omx_output_ready.pop();
  10331. + pthread_mutex_unlock(&m_omx_output_mutex);
  10332. + // return the omx buffer back to OpenMax to fill.
  10333. + ReturnOpenMaxBuffer(pic);
  10334. }
  10335. -*/
  10336. - ::Sleep(100);
  10337. +#ifdef DTS_QUEUE
  10338. + while (!m_dts_queue.empty())
  10339. + m_dts_queue.pop();
  10340. +#endif
  10341. +
  10342. + while (!m_demux_queue.empty())
  10343. + m_demux_queue.pop();
  10344. }
  10345. -bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  10346. +
  10347. +OMX_ERRORTYPE COpenMaxVideo::ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer)
  10348. {
  10349. - while (m_omx_output_busy.size() > 1)
  10350. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10351. +#if defined(OMX_DEBUG_VERBOSE)
  10352. + CLog::Log(LOGDEBUG, "%s::%s %p (%d)", CLASSNAME, __func__, buffer, m_omx_output_busy.size());
  10353. +#endif
  10354. + bool done = buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_EOS;
  10355. + if (!done)
  10356. {
  10357. - // fetch a output buffer and pop it off the busy list
  10358. - pthread_mutex_lock(&m_omx_output_mutex);
  10359. - OpenMaxVideoBuffer *buffer = m_omx_output_busy.front();
  10360. - m_omx_output_busy.pop();
  10361. - pthread_mutex_unlock(&m_omx_output_mutex);
  10362. + // return the omx buffer back to OpenMax to fill.
  10363. + buffer->omx_buffer->nFlags = 0;
  10364. + buffer->omx_buffer->nFilledLen = 0;
  10365. - bool done = buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_EOS;
  10366. - if (!done)
  10367. - {
  10368. - // return the omx buffer back to OpenMax to fill.
  10369. - OMX_ERRORTYPE omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer);
  10370. - if (omx_err)
  10371. - CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)\n",
  10372. - CLASSNAME, __func__, omx_err);
  10373. - }
  10374. + assert(buffer->omx_buffer->nOutputPortIndex == m_omx_egl_render.GetOutputPort());
  10375. +#if defined(OMX_DEBUG_VERBOSE)
  10376. + CLog::Log(LOGDEBUG, "%s::%s FillThisBuffer(%p) %p->%ld", CLASSNAME, __func__, buffer, buffer->omx_buffer, buffer->m_refs);
  10377. +#endif
  10378. + OMX_ERRORTYPE omx_err = m_omx_egl_render.FillThisBuffer(buffer->omx_buffer);
  10379. +
  10380. + if (omx_err)
  10381. + CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer, omx_err(0x%x)", CLASSNAME, __func__, omx_err);
  10382. }
  10383. + return omx_err;
  10384. +}
  10385. +
  10386. +void COpenMaxVideo::ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer)
  10387. +{
  10388. + // remove from busy list
  10389. + pthread_mutex_lock(&m_omx_output_mutex);
  10390. + m_omx_output_busy.erase(std::remove(m_omx_output_busy.begin(), m_omx_output_busy.end(), buffer), m_omx_output_busy.end());
  10391. + pthread_mutex_unlock(&m_omx_output_mutex);
  10392. + ReturnOpenMaxBuffer(buffer);
  10393. +}
  10394. +
  10395. +bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  10396. +{
  10397. + //CLog::Log(LOGDEBUG, "%s::%s - m_omx_output_busy.size()=%d m_omx_output_ready.size()=%d", CLASSNAME, __func__, m_omx_output_busy.size(), m_omx_output_ready.size());
  10398. + //CLog::Log(LOGDEBUG, "%s::%s - full: buffers:%d", CLASSNAME, __func__, m_omx_output_ready.size());
  10399. if (!m_omx_output_ready.empty())
  10400. {
  10401. - OpenMaxVideoBuffer *buffer;
  10402. + COpenMaxVideoBuffer *buffer;
  10403. // fetch a output buffer and pop it off the ready list
  10404. pthread_mutex_lock(&m_omx_output_mutex);
  10405. buffer = m_omx_output_ready.front();
  10406. m_omx_output_ready.pop();
  10407. - m_omx_output_busy.push(buffer);
  10408. + m_omx_output_busy.push_back(buffer);
  10409. pthread_mutex_unlock(&m_omx_output_mutex);
  10410. + memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture);
  10411. pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
  10412. pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
  10413. pDvdVideoPicture->format = RENDER_FMT_OMXEGL;
  10414. - pDvdVideoPicture->openMax = this;
  10415. pDvdVideoPicture->openMaxBuffer = buffer;
  10416. -
  10417. + pDvdVideoPicture->color_range = 0;
  10418. + pDvdVideoPicture->color_matrix = 4;
  10419. + pDvdVideoPicture->iWidth = m_decoded_width;
  10420. + pDvdVideoPicture->iHeight = m_decoded_height;
  10421. + pDvdVideoPicture->iDisplayWidth = m_decoded_width;
  10422. + pDvdVideoPicture->iDisplayHeight = m_decoded_height;
  10423. +
  10424. +#ifdef DTS_QUEUE
  10425. if (!m_dts_queue.empty())
  10426. {
  10427. pDvdVideoPicture->dts = m_dts_queue.front();
  10428. m_dts_queue.pop();
  10429. }
  10430. +#endif
  10431. // nTimeStamp is in microseconds
  10432. - pDvdVideoPicture->pts = (buffer->omx_buffer->nTimeStamp == 0) ? DVD_NOPTS_VALUE : (double)buffer->omx_buffer->nTimeStamp / 1000.0;
  10433. + double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp);
  10434. + pDvdVideoPicture->pts = (ts == 0) ? DVD_NOPTS_VALUE : ts;
  10435. + pDvdVideoPicture->openMaxBuffer->Acquire();
  10436. + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
  10437. + if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT)
  10438. + pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
  10439. +#if defined(OMX_DEBUG_VERBOSE)
  10440. + CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__,
  10441. + pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6,
  10442. + pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id);
  10443. +#endif
  10444. }
  10445. - #if defined(OMX_DEBUG_VERBOSE)
  10446. else
  10447. {
  10448. - CLog::Log(LOGDEBUG, "%s::%s - called but m_omx_output_ready is empty\n",
  10449. - CLASSNAME, __func__);
  10450. + CLog::Log(LOGERROR, "%s::%s - called but m_omx_output_ready is empty", CLASSNAME, __func__);
  10451. + return false;
  10452. }
  10453. - #endif
  10454. -
  10455. - pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
  10456. - pDvdVideoPicture->iFlags |= m_drop_state ? DVP_FLAG_DROPPED : 0;
  10457. -
  10458. return true;
  10459. }
  10460. -
  10461. -// DecoderEmptyBufferDone -- OpenMax input buffer has been emptied
  10462. -OMX_ERRORTYPE COpenMaxVideo::DecoderEmptyBufferDone(
  10463. - OMX_HANDLETYPE hComponent,
  10464. - OMX_PTR pAppData,
  10465. - OMX_BUFFERHEADERTYPE* pBuffer)
  10466. +bool COpenMaxVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
  10467. {
  10468. - COpenMaxVideo *ctx = static_cast<COpenMaxVideo*>(pAppData);
  10469. -/*
  10470. - #if defined(OMX_DEBUG_EMPTYBUFFERDONE)
  10471. - CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n",
  10472. - CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0);
  10473. - #endif
  10474. -*/
  10475. - // queue free input buffer to avaliable list.
  10476. - pthread_mutex_lock(&ctx->m_omx_input_mutex);
  10477. - ctx->m_omx_input_avaliable.push(pBuffer);
  10478. - ctx->m_input_consumed_event.Set();
  10479. - pthread_mutex_unlock(&ctx->m_omx_input_mutex);
  10480. -
  10481. - return OMX_ErrorNone;
  10482. +#if defined(OMX_DEBUG_VERBOSE)
  10483. + CLog::Log(LOGDEBUG, "%s::%s - %p", CLASSNAME, __func__, pDvdVideoPicture->openMaxBuffer);
  10484. +#endif
  10485. + if (pDvdVideoPicture->format == RENDER_FMT_OMXEGL)
  10486. + pDvdVideoPicture->openMaxBuffer->Release();
  10487. + memset(pDvdVideoPicture, 0, sizeof *pDvdVideoPicture);
  10488. + return true;
  10489. }
  10490. -// DecoderFillBufferDone -- OpenMax output buffer has been filled
  10491. + // DecoderFillBufferDone -- OpenMax output buffer has been filled
  10492. OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone(
  10493. OMX_HANDLETYPE hComponent,
  10494. - OMX_PTR pAppData,
  10495. OMX_BUFFERHEADERTYPE* pBuffer)
  10496. {
  10497. - COpenMaxVideo *ctx = static_cast<COpenMaxVideo*>(pAppData);
  10498. - OpenMaxVideoBuffer *buffer = (OpenMaxVideoBuffer*)pBuffer->pAppPrivate;
  10499. + COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate;
  10500. - #if defined(OMX_DEBUG_FILLBUFFERDONE)
  10501. - CLog::Log(LOGDEBUG, "%s::%s - buffer_size(%lu), timestamp(%f)\n",
  10502. - CLASSNAME, __func__, pBuffer->nFilledLen, (double)pBuffer->nTimeStamp / 1000.0);
  10503. + #if defined(OMX_DEBUG_VERBOSE)
  10504. + CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f",
  10505. + CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6);
  10506. #endif
  10507. - if (!ctx->m_portChanging)
  10508. - {
  10509. - // queue output omx buffer to ready list.
  10510. - pthread_mutex_lock(&ctx->m_omx_output_mutex);
  10511. - ctx->m_omx_output_ready.push(buffer);
  10512. - pthread_mutex_unlock(&ctx->m_omx_output_mutex);
  10513. - }
  10514. + // queue output omx buffer to ready list.
  10515. + pthread_mutex_lock(&m_omx_output_mutex);
  10516. + m_omx_output_ready.push(buffer);
  10517. + pthread_mutex_unlock(&m_omx_output_mutex);
  10518. return OMX_ErrorNone;
  10519. }
  10520. -void COpenMaxVideo::QueryCodec(void)
  10521. -{
  10522. - OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10523. - OMX_VIDEO_PARAM_PROFILELEVELTYPE port_param;
  10524. - OMX_INIT_STRUCTURE(port_param);
  10525. -
  10526. - port_param.nPortIndex = m_omx_input_port;
  10527. -
  10528. - for (port_param.nProfileIndex = 0;; port_param.nProfileIndex++)
  10529. - {
  10530. - omx_err = OMX_GetParameter(m_omx_decoder,
  10531. - OMX_IndexParamVideoProfileLevelQuerySupported, &port_param);
  10532. - if (omx_err)
  10533. - break;
  10534. -
  10535. - omx_codec_capability omx_capability;
  10536. - omx_capability.level = port_param.eLevel;
  10537. - omx_capability.profile = port_param.eProfile;
  10538. - m_omx_decoder_capabilities.push_back(omx_capability);
  10539. - }
  10540. -}
  10541. -
  10542. OMX_ERRORTYPE COpenMaxVideo::PrimeFillBuffers(void)
  10543. {
  10544. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10545. - OpenMaxVideoBuffer *buffer;
  10546. + COpenMaxVideoBuffer *buffer;
  10547. #if defined(OMX_DEBUG_VERBOSE)
  10548. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  10549. + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  10550. #endif
  10551. // tell OpenMax to start filling output buffers
  10552. for (size_t i = 0; i < m_omx_output_buffers.size(); i++)
  10553. {
  10554. buffer = m_omx_output_buffers[i];
  10555. // always set the port index.
  10556. - buffer->omx_buffer->nOutputPortIndex = m_omx_output_port;
  10557. - // Need to clear the EOS flag.
  10558. - buffer->omx_buffer->nFlags &= ~OMX_BUFFERFLAG_EOS;
  10559. + buffer->omx_buffer->nOutputPortIndex = m_omx_egl_render.GetOutputPort();
  10560. buffer->omx_buffer->pAppPrivate = buffer;
  10561. -
  10562. - omx_err = OMX_FillThisBuffer(m_omx_decoder, buffer->omx_buffer);
  10563. - if (omx_err)
  10564. - CLog::Log(LOGERROR, "%s::%s - OMX_FillThisBuffer failed with omx_err(0x%x)\n",
  10565. - CLASSNAME, __func__, omx_err);
  10566. + omx_err = ReturnOpenMaxBuffer(buffer);
  10567. }
  10568. -
  10569. return omx_err;
  10570. }
  10571. -OMX_ERRORTYPE COpenMaxVideo::AllocOMXInputBuffers(void)
  10572. -{
  10573. - OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10574. -
  10575. - // Obtain the information about the decoder input port.
  10576. - OMX_PARAM_PORTDEFINITIONTYPE port_format;
  10577. - OMX_INIT_STRUCTURE(port_format);
  10578. - port_format.nPortIndex = m_omx_input_port;
  10579. - OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format);
  10580. -
  10581. - #if defined(OMX_DEBUG_VERBOSE)
  10582. - CLog::Log(LOGDEBUG,
  10583. - "%s::%s - iport(%d), nBufferCountMin(%lu), nBufferSize(%lu)\n",
  10584. - CLASSNAME, __func__, m_omx_input_port, port_format.nBufferCountMin, port_format.nBufferSize);
  10585. - #endif
  10586. - for (size_t i = 0; i < port_format.nBufferCountMin; i++)
  10587. - {
  10588. - OMX_BUFFERHEADERTYPE *buffer = NULL;
  10589. - // use an external buffer that's sized according to actual demux
  10590. - // packet size, start at internal's buffer size, will get deleted when
  10591. - // we start pulling demuxer packets and using demux packet sized buffers.
  10592. - OMX_U8* data = new OMX_U8[port_format.nBufferSize];
  10593. - omx_err = OMX_UseBuffer(m_omx_decoder, &buffer, m_omx_input_port, NULL, port_format.nBufferSize, data);
  10594. - if (omx_err)
  10595. - {
  10596. - CLog::Log(LOGERROR, "%s::%s - OMX_UseBuffer failed with omx_err(0x%x)\n",
  10597. - CLASSNAME, __func__, omx_err);
  10598. - return(omx_err);
  10599. - }
  10600. - m_omx_input_buffers.push_back(buffer);
  10601. - // don't have to lock/unlock here, we are not decoding
  10602. - m_omx_input_avaliable.push(buffer);
  10603. - }
  10604. - m_omx_input_eos = false;
  10605. -
  10606. - return(omx_err);
  10607. -}
  10608. -OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(bool wait)
  10609. +OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(void)
  10610. {
  10611. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10612. - /*
  10613. - omx_err = OMX_SendCommand(m_omx_decoder, OMX_CommandFlush, m_omx_input_port, 0);
  10614. - if (omx_err)
  10615. - CLog::Log(LOGERROR, "%s::%s - OMX_CommandFlush failed with omx_err(0x%x)\n",
  10616. - CLASSNAME, __func__, omx_err);
  10617. - else if (wait)
  10618. - sem_wait(m_omx_flush_input);
  10619. - */
  10620. -
  10621. - // free omx input port buffers.
  10622. - for (size_t i = 0; i < m_omx_input_buffers.size(); i++)
  10623. - {
  10624. - // using external buffers (OMX_UseBuffer), free our external buffers
  10625. - // before calling OMX_FreeBuffer which frees the omx buffer.
  10626. - delete [] m_omx_input_buffers[i]->pBuffer;
  10627. - m_omx_input_buffers[i]->pBuffer = NULL;
  10628. - omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_input_port, m_omx_input_buffers[i]);
  10629. - }
  10630. - m_omx_input_buffers.clear();
  10631. -
  10632. // empty input buffer queue. not decoding so don't need lock/unlock.
  10633. - while (!m_omx_input_avaliable.empty())
  10634. - m_omx_input_avaliable.pop();
  10635. while (!m_demux_queue.empty())
  10636. m_demux_queue.pop();
  10637. +#ifdef DTS_QUEUE
  10638. while (!m_dts_queue.empty())
  10639. m_dts_queue.pop();
  10640. -
  10641. +#endif
  10642. return(omx_err);
  10643. }
  10644. -void COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata)
  10645. +bool COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata)
  10646. {
  10647. COpenMaxVideo *omx = static_cast<COpenMaxVideo*>(userdata);
  10648. - omx->AllocOMXOutputEGLTextures();
  10649. + return omx->AllocOMXOutputEGLTextures() == OMX_ErrorNone;
  10650. }
  10651. -void COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata)
  10652. +bool COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata)
  10653. {
  10654. COpenMaxVideo *omx = static_cast<COpenMaxVideo*>(userdata);
  10655. - omx->FreeOMXOutputEGLTextures(true);
  10656. + return omx->FreeOMXOutputEGLTextures() == OMX_ErrorNone;
  10657. }
  10658. -OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputBuffers(void)
  10659. +bool COpenMaxVideo::AllocOMXOutputBuffers(void)
  10660. {
  10661. - OMX_ERRORTYPE omx_err;
  10662. -
  10663. - if ( g_application.IsCurrentThread() )
  10664. - {
  10665. - omx_err = AllocOMXOutputEGLTextures();
  10666. - }
  10667. - else
  10668. - {
  10669. - ThreadMessageCallback callbackData;
  10670. - callbackData.callback = &CallbackAllocOMXEGLTextures;
  10671. - callbackData.userptr = (void *)this;
  10672. -
  10673. - ThreadMessage tMsg;
  10674. - tMsg.dwMessage = TMSG_CALLBACK;
  10675. - tMsg.lpVoid = (void*)&callbackData;
  10676. -
  10677. - g_application.getApplicationMessenger().SendMessage(tMsg, true);
  10678. -
  10679. - omx_err = OMX_ErrorNone;
  10680. - }
  10681. -
  10682. - return omx_err;
  10683. + return g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this);
  10684. }
  10685. -OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputBuffers(bool wait)
  10686. +bool COpenMaxVideo::FreeOMXOutputBuffers(void)
  10687. {
  10688. - OMX_ERRORTYPE omx_err = FreeOMXOutputEGLTextures(wait);
  10689. -
  10690. - return omx_err;
  10691. + return g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this);
  10692. }
  10693. OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  10694. {
  10695. - OMX_ERRORTYPE omx_err;
  10696. -
  10697. - if (!eglCreateImageKHR)
  10698. - {
  10699. - GETEXTENSION(PFNEGLCREATEIMAGEKHRPROC, eglCreateImageKHR);
  10700. - }
  10701. -
  10702. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10703. EGLint attrib = EGL_NONE;
  10704. - OpenMaxVideoBuffer *egl_buffer;
  10705. -
  10706. - // Obtain the information about the output port.
  10707. - OMX_PARAM_PORTDEFINITIONTYPE port_format;
  10708. - OMX_INIT_STRUCTURE(port_format);
  10709. - port_format.nPortIndex = m_omx_output_port;
  10710. - omx_err = OMX_GetParameter(m_omx_decoder, OMX_IndexParamPortDefinition, &port_format);
  10711. -
  10712. - #if defined(OMX_DEBUG_VERBOSE)
  10713. - CLog::Log(LOGDEBUG,
  10714. - "%s::%s (1) - oport(%d), nFrameWidth(%lu), nFrameHeight(%lu), nStride(%lx), nBufferCountMin(%lu), nBufferSize(%lu)\n",
  10715. - CLASSNAME, __func__, m_omx_output_port,
  10716. - port_format.format.video.nFrameWidth, port_format.format.video.nFrameHeight,port_format.format.video.nStride,
  10717. - port_format.nBufferCountMin, port_format.nBufferSize);
  10718. - #endif
  10719. + COpenMaxVideoBuffer *egl_buffer;
  10720. glActiveTexture(GL_TEXTURE0);
  10721. - for (size_t i = 0; i < port_format.nBufferCountMin; i++)
  10722. + for (size_t i = 0; i < m_egl_buffer_count; i++)
  10723. {
  10724. - egl_buffer = new OpenMaxVideoBuffer;
  10725. - memset(egl_buffer, 0, sizeof(*egl_buffer));
  10726. + egl_buffer = new COpenMaxVideoBuffer(this);
  10727. egl_buffer->width = m_decoded_width;
  10728. egl_buffer->height = m_decoded_height;
  10729. glGenTextures(1, &egl_buffer->texture_id);
  10730. glBindTexture(GL_TEXTURE_2D, egl_buffer->texture_id);
  10731. + // no mipmaps
  10732. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  10733. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  10734. +
  10735. // create space for buffer with a texture
  10736. glTexImage2D(
  10737. GL_TEXTURE_2D, // target
  10738. @@ -710,8 +928,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  10739. GL_RGBA, // format
  10740. GL_UNSIGNED_BYTE, // type
  10741. NULL); // pixels -- will be provided later
  10742. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  10743. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  10744. // create EGLImage from texture
  10745. egl_buffer->egl_image = eglCreateImageKHR(
  10746. @@ -722,49 +938,40 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  10747. &attrib);
  10748. if (!egl_buffer->egl_image)
  10749. {
  10750. - CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage\n", CLASSNAME, __func__);
  10751. + CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage", CLASSNAME, __func__);
  10752. return(OMX_ErrorUndefined);
  10753. }
  10754. egl_buffer->index = i;
  10755. // tell decoder output port that it will be using EGLImage
  10756. - omx_err = OMX_UseEGLImage(
  10757. - m_omx_decoder, &egl_buffer->omx_buffer, m_omx_output_port, egl_buffer, egl_buffer->egl_image);
  10758. + omx_err = m_omx_egl_render.UseEGLImage(
  10759. + &egl_buffer->omx_buffer, m_omx_egl_render.GetOutputPort(), egl_buffer, egl_buffer->egl_image);
  10760. if (omx_err)
  10761. {
  10762. - CLog::Log(LOGERROR, "%s::%s - OMX_UseEGLImage failed with omx_err(0x%x)\n",
  10763. + CLog::Log(LOGERROR, "%s::%s - OMX_UseEGLImage failed with omx_err(0x%x)",
  10764. CLASSNAME, __func__, omx_err);
  10765. return(omx_err);
  10766. }
  10767. m_omx_output_buffers.push_back(egl_buffer);
  10768. - CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d\n",
  10769. + CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d",
  10770. CLASSNAME, __func__, egl_buffer->egl_image, egl_buffer->width, egl_buffer->height);
  10771. }
  10772. - m_omx_output_eos = false;
  10773. - while (!m_omx_output_busy.empty())
  10774. - m_omx_output_busy.pop();
  10775. - while (!m_omx_output_ready.empty())
  10776. - m_omx_output_ready.pop();
  10777. -
  10778. return omx_err;
  10779. }
  10780. -OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(bool wait)
  10781. +OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(void)
  10782. {
  10783. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  10784. - OpenMaxVideoBuffer *egl_buffer;
  10785. -
  10786. - if (!eglDestroyImageKHR)
  10787. - {
  10788. - GETEXTENSION(PFNEGLDESTROYIMAGEKHRPROC, eglDestroyImageKHR);
  10789. - }
  10790. + COpenMaxVideoBuffer *egl_buffer;
  10791. for (size_t i = 0; i < m_omx_output_buffers.size(); i++)
  10792. {
  10793. egl_buffer = m_omx_output_buffers[i];
  10794. // tell decoder output port to stop using the EGLImage
  10795. - omx_err = OMX_FreeBuffer(m_omx_decoder, m_omx_output_port, egl_buffer->omx_buffer);
  10796. + omx_err = m_omx_egl_render.FreeOutputBuffer(egl_buffer->omx_buffer);
  10797. + if (omx_err != OMX_ErrorNone)
  10798. + CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.FreeOutputBuffer(%p) omx_err(0x%08x)", CLASSNAME, __func__, egl_buffer->omx_buffer, omx_err);
  10799. // destroy egl_image
  10800. eglDestroyImageKHR(m_egl_display, egl_buffer->egl_image);
  10801. // free texture
  10802. @@ -777,274 +984,45 @@ OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(bool wait)
  10803. }
  10804. -////////////////////////////////////////////////////////////////////////////////////////////
  10805. -// DecoderEventHandler -- OMX event callback
  10806. -OMX_ERRORTYPE COpenMaxVideo::DecoderEventHandler(
  10807. - OMX_HANDLETYPE hComponent,
  10808. - OMX_PTR pAppData,
  10809. - OMX_EVENTTYPE eEvent,
  10810. - OMX_U32 nData1,
  10811. - OMX_U32 nData2,
  10812. - OMX_PTR pEventData)
  10813. -{
  10814. - OMX_ERRORTYPE omx_err;
  10815. - COpenMaxVideo *ctx = static_cast<COpenMaxVideo*>(pAppData);
  10816. -
  10817. -/*
  10818. - #if defined(OMX_DEBUG_VERBOSE)
  10819. - CLog::Log(LOGDEBUG,
  10820. - "COpenMax::%s - hComponent(0x%p), eEvent(0x%x), nData1(0x%lx), nData2(0x%lx), pEventData(0x%p)\n",
  10821. - __func__, hComponent, eEvent, nData1, nData2, pEventData);
  10822. - #endif
  10823. -*/
  10824. -
  10825. - switch (eEvent)
  10826. - {
  10827. - case OMX_EventCmdComplete:
  10828. - switch(nData1)
  10829. - {
  10830. - case OMX_CommandStateSet:
  10831. - ctx->m_omx_decoder_state = (int)nData2;
  10832. - switch (ctx->m_omx_decoder_state)
  10833. - {
  10834. - case OMX_StateInvalid:
  10835. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StateInvalid\n", CLASSNAME, __func__);
  10836. - break;
  10837. - case OMX_StateLoaded:
  10838. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StateLoaded\n", CLASSNAME, __func__);
  10839. - break;
  10840. - case OMX_StateIdle:
  10841. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StateIdle\n", CLASSNAME, __func__);
  10842. - break;
  10843. - case OMX_StateExecuting:
  10844. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StateExecuting\n", CLASSNAME, __func__);
  10845. - break;
  10846. - case OMX_StatePause:
  10847. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StatePause\n", CLASSNAME, __func__);
  10848. - break;
  10849. - case OMX_StateWaitForResources:
  10850. - CLog::Log(LOGDEBUG, "%s::%s - OMX_StateWaitForResources\n", CLASSNAME, __func__);
  10851. - break;
  10852. - default:
  10853. - CLog::Log(LOGDEBUG,
  10854. - "%s::%s - Unknown OMX_Statexxxxx, state(%d)\n",
  10855. - CLASSNAME, __func__, ctx->m_omx_decoder_state);
  10856. - break;
  10857. - }
  10858. - sem_post(ctx->m_omx_decoder_state_change);
  10859. - break;
  10860. - case OMX_CommandFlush:
  10861. - /*
  10862. - if (OMX_ALL == (int)nData2)
  10863. - {
  10864. - sem_post(ctx->m_omx_flush_input);
  10865. - sem_post(ctx->m_omx_flush_output);
  10866. - CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input/output\n",__func__);
  10867. - }
  10868. - else if (ctx->m_omx_input_port == (int)nData2)
  10869. - {
  10870. - sem_post(ctx->m_omx_flush_input);
  10871. - CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush input\n",__func__);
  10872. - }
  10873. - else if (ctx->m_omx_output_port == (int)nData2)
  10874. - {
  10875. - sem_post(ctx->m_omx_flush_output);
  10876. - CLog::Log(LOGDEBUG, "COpenMax::%s - OMX_CommandFlush ouput\n",__func__);
  10877. - }
  10878. - else
  10879. - */
  10880. - {
  10881. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10882. - CLog::Log(LOGDEBUG,
  10883. - "%s::%s - OMX_CommandFlush, nData2(0x%lx)\n",
  10884. - CLASSNAME, __func__, nData2);
  10885. - #endif
  10886. - }
  10887. - break;
  10888. - case OMX_CommandPortDisable:
  10889. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10890. - CLog::Log(LOGDEBUG,
  10891. - "%s::%s - OMX_CommandPortDisable, nData1(0x%lx), nData2(0x%lx)\n",
  10892. - CLASSNAME, __func__, nData1, nData2);
  10893. - #endif
  10894. - if (ctx->m_omx_output_port == (int)nData2)
  10895. - {
  10896. - // Got OMX_CommandPortDisable event, alloc new buffers for the output port.
  10897. - ctx->AllocOMXOutputBuffers();
  10898. - omx_err = OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortEnable, ctx->m_omx_output_port, NULL);
  10899. - }
  10900. - break;
  10901. - case OMX_CommandPortEnable:
  10902. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10903. - CLog::Log(LOGDEBUG,
  10904. - "%s::%s - OMX_CommandPortEnable, nData1(0x%lx), nData2(0x%lx)\n",
  10905. - CLASSNAME, __func__, nData1, nData2);
  10906. - #endif
  10907. - if (ctx->m_omx_output_port == (int)nData2)
  10908. - {
  10909. - // Got OMX_CommandPortEnable event.
  10910. - // OMX_CommandPortDisable will have re-alloced new ones so re-prime
  10911. - ctx->PrimeFillBuffers();
  10912. - }
  10913. - ctx->m_portChanging = false;
  10914. - break;
  10915. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10916. - case OMX_CommandMarkBuffer:
  10917. - CLog::Log(LOGDEBUG,
  10918. - "%s::%s - OMX_CommandMarkBuffer, nData1(0x%lx), nData2(0x%lx)\n",
  10919. - CLASSNAME, __func__, nData1, nData2);
  10920. - break;
  10921. - #endif
  10922. - }
  10923. - break;
  10924. - case OMX_EventBufferFlag:
  10925. - if (ctx->m_omx_decoder == hComponent && (nData2 & OMX_BUFFERFLAG_EOS)) {
  10926. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10927. - if(ctx->m_omx_input_port == (int)nData1)
  10928. - CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(input)\n",
  10929. - CLASSNAME, __func__);
  10930. - #endif
  10931. - if(ctx->m_omx_output_port == (int)nData1)
  10932. - {
  10933. - ctx->m_videoplayback_done = true;
  10934. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10935. - CLog::Log(LOGDEBUG, "%s::%s - OMX_EventBufferFlag(output)\n",
  10936. - CLASSNAME, __func__);
  10937. - #endif
  10938. - }
  10939. - }
  10940. - break;
  10941. - case OMX_EventPortSettingsChanged:
  10942. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10943. - CLog::Log(LOGDEBUG,
  10944. - "%s::%s - OMX_EventPortSettingsChanged(output)\n", CLASSNAME, __func__);
  10945. - #endif
  10946. - // not sure nData2 is the input/output ports in this call, docs don't say
  10947. - if (ctx->m_omx_output_port == (int)nData2)
  10948. - {
  10949. - // free the current OpenMax output buffers, you must do this before sending
  10950. - // OMX_CommandPortDisable to component as it expects output buffers
  10951. - // to be freed before it will issue a OMX_CommandPortDisable event.
  10952. - ctx->m_portChanging = true;
  10953. - OMX_SendCommand(ctx->m_omx_decoder, OMX_CommandPortDisable, ctx->m_omx_output_port, NULL);
  10954. - omx_err = ctx->FreeOMXOutputBuffers(false);
  10955. - }
  10956. - break;
  10957. - #if defined(OMX_DEBUG_EVENTHANDLER)
  10958. - case OMX_EventMark:
  10959. - CLog::Log(LOGDEBUG, "%s::%s - OMX_EventMark\n", CLASSNAME, __func__);
  10960. - break;
  10961. - case OMX_EventResourcesAcquired:
  10962. - CLog::Log(LOGDEBUG, "%s::%s - OMX_EventResourcesAcquired\n", CLASSNAME, __func__);
  10963. - break;
  10964. - #endif
  10965. - case OMX_EventError:
  10966. - switch((OMX_S32)nData1)
  10967. - {
  10968. - case OMX_ErrorInsufficientResources:
  10969. - CLog::Log(LOGERROR, "%s::%s - OMX_EventError, insufficient resources\n",
  10970. - CLASSNAME, __func__);
  10971. - // we are so frack'ed
  10972. - //exit(0);
  10973. - break;
  10974. - case OMX_ErrorFormatNotDetected:
  10975. - CLog::Log(LOGERROR, "%s::%s - OMX_EventError, cannot parse input stream\n",
  10976. - CLASSNAME, __func__);
  10977. - break;
  10978. - case OMX_ErrorPortUnpopulated:
  10979. - // silently ignore these. We can get them when setting OMX_CommandPortDisable
  10980. - // on the output port and the component flushes the output buffers.
  10981. - break;
  10982. - case OMX_ErrorStreamCorrupt:
  10983. - CLog::Log(LOGERROR, "%s::%s - OMX_EventError, Bitstream corrupt\n",
  10984. - CLASSNAME, __func__);
  10985. - ctx->m_videoplayback_done = true;
  10986. - break;
  10987. - default:
  10988. - CLog::Log(LOGERROR, "%s::%s - OMX_EventError detected, nData1(0x%lx), nData2(0x%lx)\n",
  10989. - CLASSNAME, __func__, nData1, nData2);
  10990. - break;
  10991. - }
  10992. - // do this so we don't hang on errors
  10993. - /*
  10994. - sem_post(ctx->m_omx_flush_input);
  10995. - sem_post(ctx->m_omx_flush_output);
  10996. - */
  10997. - sem_post(ctx->m_omx_decoder_state_change);
  10998. - break;
  10999. - default:
  11000. - CLog::Log(LOGWARNING,
  11001. - "%s::%s - Unknown eEvent(0x%x), nData1(0x%lx), nData2(0x%lx)\n",
  11002. - CLASSNAME, __func__, eEvent, nData1, nData2);
  11003. - break;
  11004. - }
  11005. -
  11006. - return OMX_ErrorNone;
  11007. -}
  11008. -
  11009. -// StartPlayback -- Kick off video playback.
  11010. -OMX_ERRORTYPE COpenMaxVideo::StartDecoder(void)
  11011. -{
  11012. - OMX_ERRORTYPE omx_err;
  11013. -
  11014. - #if defined(OMX_DEBUG_VERBOSE)
  11015. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  11016. - #endif
  11017. -
  11018. - // transition decoder component to IDLE state
  11019. - omx_err = SetStateForComponent(OMX_StateIdle);
  11020. - if (omx_err)
  11021. - {
  11022. - CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n",
  11023. - CLASSNAME, __func__, omx_err);
  11024. - return omx_err;
  11025. - }
  11026. -
  11027. - // transition decoder component to executing state
  11028. - omx_err = SetStateForComponent(OMX_StateExecuting);
  11029. - if (omx_err)
  11030. - {
  11031. - CLog::Log(LOGERROR, "%s::%s - setting OMX_StateExecuting failed with omx_err(0x%x)\n",
  11032. - CLASSNAME, __func__, omx_err);
  11033. - return omx_err;
  11034. - }
  11035. -
  11036. - //prime the omx output buffers.
  11037. - PrimeFillBuffers();
  11038. -
  11039. - return omx_err;
  11040. -}
  11041. -
  11042. // StopPlayback -- Stop video playback
  11043. OMX_ERRORTYPE COpenMaxVideo::StopDecoder(void)
  11044. {
  11045. - OMX_ERRORTYPE omx_err;
  11046. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  11047. #if defined(OMX_DEBUG_VERBOSE)
  11048. - CLog::Log(LOGDEBUG, "%s::%s\n", CLASSNAME, __func__);
  11049. + CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  11050. #endif
  11051. +
  11052. // transition decoder component from executing to idle
  11053. - omx_err = SetStateForComponent(OMX_StateIdle);
  11054. - if (omx_err)
  11055. + if (m_omx_decoder.IsInitialized())
  11056. {
  11057. - CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)\n",
  11058. - CLASSNAME, __func__, omx_err);
  11059. - return omx_err;
  11060. + omx_err = m_omx_decoder.SetStateForComponent(OMX_StateIdle);
  11061. + if (omx_err)
  11062. + CLog::Log(LOGERROR, "%s::%s - setting OMX_StateIdle failed with omx_err(0x%x)",
  11063. + CLASSNAME, __func__, omx_err);
  11064. }
  11065. // we can free our allocated port buffers in OMX_StateIdle state.
  11066. // free OpenMax input buffers.
  11067. - FreeOMXInputBuffers(true);
  11068. - // free OpenMax output buffers.
  11069. - FreeOMXOutputBuffers(true);
  11070. + FreeOMXInputBuffers();
  11071. +
  11072. + if (m_omx_egl_render.IsInitialized())
  11073. + {
  11074. + omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateIdle);
  11075. + if (omx_err)
  11076. + CLog::Log(LOGERROR, "%s::%s - setting egl OMX_StateIdle failed with omx_err(0x%x)",
  11077. + CLASSNAME, __func__, omx_err);
  11078. + // free OpenMax output buffers.
  11079. + omx_err = m_omx_egl_render.DisablePort(m_omx_egl_render.GetOutputPort(), false);
  11080. + if (omx_err != OMX_ErrorNone)
  11081. + CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.DisablePort(%d) omx_err(0x%08x)", CLASSNAME, __func__, m_omx_egl_render.GetOutputPort(), omx_err);
  11082. - // transition decoder component from idle to loaded
  11083. - omx_err = SetStateForComponent(OMX_StateLoaded);
  11084. - if (omx_err)
  11085. - CLog::Log(LOGERROR,
  11086. - "%s::%s - setting OMX_StateLoaded failed with omx_err(0x%x)\n",
  11087. - CLASSNAME, __func__, omx_err);
  11088. + FreeOMXOutputBuffers();
  11089. + omx_err = m_omx_egl_render.WaitForCommand(OMX_CommandPortDisable, m_omx_egl_render.GetOutputPort());
  11090. + if (omx_err != OMX_ErrorNone)
  11091. + CLog::Log(LOGERROR, "%s::%s WaitForCommand:OMX_CommandPortDisable omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11092. + }
  11093. return omx_err;
  11094. }
  11095. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11096. index e06c41d..9079c13 100644
  11097. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11098. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11099. @@ -21,12 +21,35 @@
  11100. #if defined(HAVE_LIBOPENMAX)
  11101. -#include "OpenMax.h"
  11102. +#include "system_gl.h"
  11103. #include <EGL/egl.h>
  11104. #include <EGL/eglext.h>
  11105. +#include "linux/OMXCore.h"
  11106. +#include "linux/OMXClock.h"
  11107. +
  11108. +#include "cores/dvdplayer/DVDStreamInfo.h"
  11109. +#include "DVDVideoCodec.h"
  11110. +#include "threads/Event.h"
  11111. +
  11112. +#include <queue>
  11113. +#include <semaphore.h>
  11114. +
  11115. +typedef struct omx_demux_packet {
  11116. + OMX_U8 *buff;
  11117. + int size;
  11118. + double dts;
  11119. + double pts;
  11120. +} omx_demux_packet;
  11121. +
  11122. +class COpenMaxVideo;
  11123. // an omx egl video frame
  11124. -typedef struct OpenMaxVideoBuffer {
  11125. +class COpenMaxVideoBuffer
  11126. +{
  11127. +public:
  11128. + COpenMaxVideoBuffer(COpenMaxVideo *omv);
  11129. + virtual ~COpenMaxVideoBuffer();
  11130. +
  11131. OMX_BUFFERHEADERTYPE *omx_buffer;
  11132. int width;
  11133. int height;
  11134. @@ -35,79 +58,86 @@ typedef struct OpenMaxVideoBuffer {
  11135. // used for egl based rendering if active
  11136. EGLImageKHR egl_image;
  11137. GLuint texture_id;
  11138. -} OpenMaxVideoBuffer;
  11139. + // reference counting
  11140. + COpenMaxVideoBuffer* Acquire();
  11141. + long Release();
  11142. + void Sync();
  11143. +
  11144. + COpenMaxVideo *m_omv;
  11145. + long m_refs;
  11146. +private:
  11147. +};
  11148. -class COpenMaxVideo : public COpenMax
  11149. +class COpenMaxVideo
  11150. {
  11151. public:
  11152. COpenMaxVideo();
  11153. virtual ~COpenMaxVideo();
  11154. // Required overrides
  11155. - bool Open(CDVDStreamInfo &hints);
  11156. - void Close(void);
  11157. - int Decode(uint8_t *pData, int iSize, double dts, double pts);
  11158. - void Reset(void);
  11159. - bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
  11160. - void SetDropState(bool bDrop);
  11161. + virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options);
  11162. + virtual void Dispose(void);
  11163. + virtual int Decode(uint8_t *pData, int iSize, double dts, double pts);
  11164. + virtual void Reset(void);
  11165. + virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
  11166. + virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
  11167. + virtual unsigned GetAllowedReferences() { return 2; }
  11168. + virtual void SetDropState(bool bDrop);
  11169. + virtual const char* GetName(void) { return (const char*)m_pFormatName; }
  11170. +
  11171. + // OpenMax decoder callback routines.
  11172. + OMX_ERRORTYPE DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer);
  11173. + void ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer);
  11174. +
  11175. protected:
  11176. void QueryCodec(void);
  11177. OMX_ERRORTYPE PrimeFillBuffers(void);
  11178. OMX_ERRORTYPE AllocOMXInputBuffers(void);
  11179. - OMX_ERRORTYPE FreeOMXInputBuffers(bool wait);
  11180. - OMX_ERRORTYPE AllocOMXOutputBuffers(void);
  11181. - OMX_ERRORTYPE FreeOMXOutputBuffers(bool wait);
  11182. - static void CallbackAllocOMXEGLTextures(void*);
  11183. + OMX_ERRORTYPE FreeOMXInputBuffers(void);
  11184. + bool AllocOMXOutputBuffers(void);
  11185. + bool FreeOMXOutputBuffers(void);
  11186. + static bool CallbackAllocOMXEGLTextures(void*);
  11187. OMX_ERRORTYPE AllocOMXOutputEGLTextures(void);
  11188. - static void CallbackFreeOMXEGLTextures(void*);
  11189. - OMX_ERRORTYPE FreeOMXOutputEGLTextures(bool wait);
  11190. -
  11191. - // TODO Those should move into the base class. After start actions can be executed by callbacks.
  11192. - OMX_ERRORTYPE StartDecoder(void);
  11193. + static bool CallbackFreeOMXEGLTextures(void*);
  11194. + OMX_ERRORTYPE FreeOMXOutputEGLTextures(void);
  11195. OMX_ERRORTYPE StopDecoder(void);
  11196. -
  11197. - // OpenMax decoder callback routines.
  11198. - virtual OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
  11199. - OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData);
  11200. - virtual OMX_ERRORTYPE DecoderEmptyBufferDone(
  11201. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer);
  11202. - virtual OMX_ERRORTYPE DecoderFillBufferDone(
  11203. - OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader);
  11204. + OMX_ERRORTYPE ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer);
  11205. // EGL Resources
  11206. EGLDisplay m_egl_display;
  11207. EGLContext m_egl_context;
  11208. // Video format
  11209. - DVDVideoPicture m_videobuffer;
  11210. bool m_drop_state;
  11211. int m_decoded_width;
  11212. int m_decoded_height;
  11213. + unsigned int m_egl_buffer_count;
  11214. +
  11215. + bool m_port_settings_changed;
  11216. + const char *m_pFormatName;
  11217. std::queue<double> m_dts_queue;
  11218. std::queue<omx_demux_packet> m_demux_queue;
  11219. - // OpenMax input buffers (demuxer packets)
  11220. - pthread_mutex_t m_omx_input_mutex;
  11221. - std::queue<OMX_BUFFERHEADERTYPE*> m_omx_input_avaliable;
  11222. - std::vector<OMX_BUFFERHEADERTYPE*> m_omx_input_buffers;
  11223. - bool m_omx_input_eos;
  11224. - int m_omx_input_port;
  11225. - //sem_t *m_omx_flush_input;
  11226. - CEvent m_input_consumed_event;
  11227. -
  11228. // OpenMax output buffers (video frames)
  11229. pthread_mutex_t m_omx_output_mutex;
  11230. - std::queue<OpenMaxVideoBuffer*> m_omx_output_busy;
  11231. - std::queue<OpenMaxVideoBuffer*> m_omx_output_ready;
  11232. - std::vector<OpenMaxVideoBuffer*> m_omx_output_buffers;
  11233. - bool m_omx_output_eos;
  11234. - int m_omx_output_port;
  11235. - //sem_t *m_omx_flush_output;
  11236. + std::vector<COpenMaxVideoBuffer*> m_omx_output_busy;
  11237. + std::queue<COpenMaxVideoBuffer*> m_omx_output_ready;
  11238. + std::vector<COpenMaxVideoBuffer*> m_omx_output_buffers;
  11239. +
  11240. + // initialize OpenMax and get decoder component
  11241. + bool Initialize( const CStdString &decoder_name);
  11242. +
  11243. + // Components
  11244. + COMXCoreComponent m_omx_decoder;
  11245. + COMXCoreComponent m_omx_egl_render;
  11246. - bool m_portChanging;
  11247. + COMXCoreTunel m_omx_tunnel;
  11248. + OMX_VIDEO_CODINGTYPE m_codingType;
  11249. - volatile bool m_videoplayback_done;
  11250. + bool PortSettingsChanged();
  11251. + bool SendDecoderConfig(uint8_t *extradata, int extrasize);
  11252. + bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize);
  11253. };
  11254. // defined(HAVE_LIBOPENMAX)
  11255. diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
  11256. index a485275..d607f55 100644
  11257. --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
  11258. +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
  11259. @@ -2988,7 +2988,9 @@ bool CDVDPlayer::OpenVideoStream(int iStream, int source, bool reset)
  11260. hint.aspect = aspect;
  11261. hint.forced_aspect = true;
  11262. }
  11263. +#ifndef TARGET_RASPBERRY_PI
  11264. hint.software = true;
  11265. +#endif
  11266. }
  11267. boost::shared_ptr<CPVRClient> client;
  11268. diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  11269. index 99b3155..fddb7f7 100644
  11270. --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  11271. +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  11272. @@ -325,6 +325,9 @@ void CDVDPlayerVideo::Process()
  11273. while (!m_bStop)
  11274. {
  11275. + DemuxPacket staticPacket = {};
  11276. + DemuxPacket* pPacket = NULL;
  11277. + bool bPacketDrop = false;
  11278. int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000;
  11279. int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0;
  11280. @@ -361,8 +364,10 @@ void CDVDPlayerVideo::Process()
  11281. OutputPicture(&picture, pts);
  11282. pts+= frametime;
  11283. }
  11284. -
  11285. - continue;
  11286. + pPacket = &staticPacket;
  11287. + bPacketDrop = false;
  11288. + goto submit_empty_packet;
  11289. + //continue;
  11290. }
  11291. if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE))
  11292. @@ -489,9 +494,12 @@ void CDVDPlayerVideo::Process()
  11293. if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
  11294. {
  11295. - DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket();
  11296. - bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop();
  11297. -
  11298. + pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket();
  11299. + bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop();
  11300. + }
  11301. +submit_empty_packet:
  11302. + if (ret == MSGQ_TIMEOUT || pMsg->IsType(CDVDMsg::DEMUXER_PACKET))
  11303. + {
  11304. if (m_stalled)
  11305. {
  11306. CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe left, switching to normal playback");
  11307. @@ -749,7 +757,8 @@ void CDVDPlayerVideo::Process()
  11308. }
  11309. // all data is used by the decoder, we can safely free it now
  11310. - pMsg->Release();
  11311. + if (ret != MSGQ_TIMEOUT)
  11312. + pMsg->Release();
  11313. }
  11314. // we need to let decoder release any picture retained resources.
  11315. diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp
  11316. index 6e7d9a9..99e407a 100644
  11317. --- a/xbmc/linux/OMXCore.cpp
  11318. +++ b/xbmc/linux/OMXCore.cpp
  11319. @@ -460,7 +460,12 @@ void COMXCoreComponent::FlushInput()
  11320. CLog::Log(LOGERROR, "COMXCoreComponent::FlushInput - Error on component %s omx_err(0x%08x)",
  11321. m_componentName.c_str(), (int)omx_err);
  11322. }
  11323. - WaitForCommand(OMX_CommandFlush, m_input_port);
  11324. + omx_err = WaitForCommand(OMX_CommandFlush, m_input_port);
  11325. + if(omx_err != OMX_ErrorNone)
  11326. + {
  11327. + CLog::Log(LOGERROR, "COMXCoreComponent::FlushInput - %s WaitForCommand omx_err(0x%08x)",
  11328. + m_componentName.c_str(), (int)omx_err);
  11329. + }
  11330. }
  11331. void COMXCoreComponent::FlushOutput()
  11332. @@ -477,7 +482,12 @@ void COMXCoreComponent::FlushOutput()
  11333. CLog::Log(LOGERROR, "COMXCoreComponent::FlushOutput - Error on component %s omx_err(0x%08x)",
  11334. m_componentName.c_str(), (int)omx_err);
  11335. }
  11336. - WaitForCommand(OMX_CommandFlush, m_output_port);
  11337. + omx_err = WaitForCommand(OMX_CommandFlush, m_output_port);
  11338. + if(omx_err != OMX_ErrorNone)
  11339. + {
  11340. + CLog::Log(LOGERROR, "COMXCoreComponent::FlushOutput - %s WaitForCommand omx_err(0x%08x)",
  11341. + m_componentName.c_str(), (int)omx_err);
  11342. + }
  11343. }
  11344. // timeout in milliseconds
  11345. @@ -1149,7 +1159,12 @@ OMX_STATETYPE COMXCoreComponent::GetState()
  11346. OMX_STATETYPE state;
  11347. - OMX_GetState(m_handle, &state);
  11348. + OMX_ERRORTYPE omx_err = OMX_GetState(m_handle, &state);
  11349. + if (omx_err != OMX_ErrorNone)
  11350. + {
  11351. + CLog::Log(LOGERROR, "COMXCoreComponent::GetState - %s failed with omx_err(0x%x)\n",
  11352. + m_componentName.c_str(), omx_err);
  11353. + }
  11354. return state;
  11355. }
  11356. @@ -1307,6 +1322,8 @@ OMX_ERRORTYPE COMXCoreComponent::DisablePort(unsigned int port, bool wait)
  11357. OMX_ERRORTYPE COMXCoreComponent::UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage)
  11358. {
  11359. +if (m_callbacks.FillBufferDone == &COMXCoreComponent::DecoderFillBufferDoneCallback)
  11360. +{
  11361. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  11362. if(!m_handle)
  11363. @@ -1383,8 +1400,21 @@ OMX_ERRORTYPE COMXCoreComponent::UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr,
  11364. return omx_err;
  11365. }
  11366. +else
  11367. +{
  11368. + OMX_ERRORTYPE omx_err;
  11369. + omx_err = OMX_UseEGLImage(m_handle, ppBufferHdr, nPortIndex, pAppPrivate, eglImage);
  11370. + if(omx_err != OMX_ErrorNone)
  11371. + {
  11372. + CLog::Log(LOGERROR, "%s::%s - %s failed with omx_err(0x%x)\n",
  11373. + CLASSNAME, __func__, m_componentName.c_str(), omx_err);
  11374. + return omx_err;
  11375. + }
  11376. + return omx_err;
  11377. +}
  11378. +}
  11379. -bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEXTYPE index)
  11380. +bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEXTYPE index, OMX_CALLBACKTYPE *callbacks)
  11381. {
  11382. OMX_ERRORTYPE omx_err;
  11383. @@ -1419,6 +1449,13 @@ bool COMXCoreComponent::Initialize( const std::string &component_name, OMX_INDEX
  11384. m_callbacks.EmptyBufferDone = &COMXCoreComponent::DecoderEmptyBufferDoneCallback;
  11385. m_callbacks.FillBufferDone = &COMXCoreComponent::DecoderFillBufferDoneCallback;
  11386. + if (callbacks && callbacks->EventHandler)
  11387. + m_callbacks.EventHandler = callbacks->EventHandler;
  11388. + if (callbacks && callbacks->EmptyBufferDone)
  11389. + m_callbacks.EmptyBufferDone = callbacks->EmptyBufferDone;
  11390. + if (callbacks && callbacks->FillBufferDone)
  11391. + m_callbacks.FillBufferDone = callbacks->FillBufferDone;
  11392. +
  11393. // Get video component handle setting up callbacks, component is in loaded state on return.
  11394. if(!m_handle)
  11395. {
  11396. diff --git a/xbmc/linux/OMXCore.h b/xbmc/linux/OMXCore.h
  11397. index 54d35aa..5b9c2f9 100644
  11398. --- a/xbmc/linux/OMXCore.h
  11399. +++ b/xbmc/linux/OMXCore.h
  11400. @@ -109,7 +109,7 @@ class COMXCoreComponent
  11401. OMX_ERRORTYPE DisablePort(unsigned int port, bool wait = true);
  11402. OMX_ERRORTYPE UseEGLImage(OMX_BUFFERHEADERTYPE** ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, void* eglImage);
  11403. - bool Initialize( const std::string &component_name, OMX_INDEXTYPE index);
  11404. + bool Initialize( const std::string &component_name, OMX_INDEXTYPE index, OMX_CALLBACKTYPE *callbacks = NULL);
  11405. bool IsInitialized();
  11406. bool Deinitialize();
  11407. --
  11408. 1.9.3
  11409. From e9b71fb1ee80896444d3301f919bf315a96530a3 Mon Sep 17 00:00:00 2001
  11410. From: popcornmix <popcornmix@gmail.com>
  11411. Date: Sat, 3 May 2014 11:57:25 +0100
  11412. Subject: [PATCH 43/94] [omxcodec] Enable for dvd menus
  11413. ---
  11414. xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp | 4 ++++
  11415. 1 file changed, 4 insertions(+)
  11416. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  11417. index 18b8e3a..c85c8d2 100644
  11418. --- a/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  11419. +++ b/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  11420. @@ -194,6 +194,10 @@ CDVDVideoCodec* CDVDFactoryCodec::CreateVideoCodec(CDVDStreamInfo &hint, unsigne
  11421. CLog::Log(LOGDEBUG, "CDVDFactoryCodec: compiled in hardware support: %s", hwSupport.c_str());
  11422. +#if defined(HAVE_LIBOPENMAX)
  11423. + // libopenmax can handle dvd playback including stills
  11424. + if (!CSettings::Get().GetBool("videoplayer.useomx"))
  11425. +#endif
  11426. if (hint.stills && (hint.codec == AV_CODEC_ID_MPEG2VIDEO || hint.codec == AV_CODEC_ID_MPEG1VIDEO))
  11427. {
  11428. // If dvd is an mpeg2 and hint.stills
  11429. --
  11430. 1.9.3
  11431. From a7a4ccc26d85d1362a77b718564ddb1f08ca1246 Mon Sep 17 00:00:00 2001
  11432. From: popcornmix <popcornmix@gmail.com>
  11433. Date: Mon, 3 Feb 2014 22:27:44 +0000
  11434. Subject: [PATCH 44/94] [omxcodec] Add omx specific texture
  11435. create/upload/delete functions
  11436. ---
  11437. xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 33 +++++++++++++++++++++++++
  11438. xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 +++
  11439. 2 files changed, 37 insertions(+)
  11440. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11441. index 6d879e3..279aa90 100644
  11442. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11443. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11444. @@ -805,6 +805,12 @@ void CLinuxRendererGLES::LoadShaders(int field)
  11445. m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture;
  11446. m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture;
  11447. }
  11448. + else if (m_format == RENDER_FMT_OMXEGL)
  11449. + {
  11450. + m_textureUpload = &CLinuxRendererGLES::UploadOMXEGLTexture;
  11451. + m_textureCreate = &CLinuxRendererGLES::CreateOMXEGLTexture;
  11452. + m_textureDelete = &CLinuxRendererGLES::DeleteOMXEGLTexture;
  11453. + }
  11454. else
  11455. {
  11456. // default to YV12 texture handlers
  11457. @@ -2487,6 +2493,33 @@ bool CLinuxRendererGLES::CreateSurfaceTexture(int index)
  11458. return true;
  11459. }
  11460. +//********************************************************************************************************
  11461. +// SurfaceTexture creation, deletion, copying + clearing
  11462. +//********************************************************************************************************
  11463. +void CLinuxRendererGLES::UploadOMXEGLTexture(int index)
  11464. +{
  11465. +#ifdef HAVE_LIBOPENMAX
  11466. + YUVBUFFER &buf = m_buffers[index];
  11467. + if (buf.openMaxBuffer)
  11468. + {
  11469. + //buf.openMaxBuffer->Sync();
  11470. + }
  11471. +#endif
  11472. +}
  11473. +void CLinuxRendererGLES::DeleteOMXEGLTexture(int index)
  11474. +{
  11475. +#ifdef HAVE_LIBOPENMAX
  11476. + YUVBUFFER &buf = m_buffers[index];
  11477. + if (buf.openMaxBuffer)
  11478. + SAFE_RELEASE(buf.openMaxBuffer);
  11479. +#endif
  11480. +}
  11481. +bool CLinuxRendererGLES::CreateOMXEGLTexture(int index)
  11482. +{
  11483. + DeleteOMXEGLTexture(index);
  11484. + return true;
  11485. +}
  11486. +
  11487. void CLinuxRendererGLES::SetTextureFilter(GLenum method)
  11488. {
  11489. for (int i = 0 ; i<m_NumYV12Buffers ; i++)
  11490. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  11491. index 0ca56a2..f3dd3d3 100644
  11492. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  11493. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
  11494. @@ -212,6 +212,10 @@ class CLinuxRendererGLES : public CBaseRenderer
  11495. void DeleteSurfaceTexture(int index);
  11496. bool CreateSurfaceTexture(int index);
  11497. + void UploadOMXEGLTexture(int index);
  11498. + void DeleteOMXEGLTexture(int index);
  11499. + bool CreateOMXEGLTexture(int index);
  11500. +
  11501. void CalculateTextureSourceRects(int source, int num_planes);
  11502. // renderers
  11503. --
  11504. 1.9.3
  11505. From 6a8bd5509ada85a05ad4672a33b76418573382ea Mon Sep 17 00:00:00 2001
  11506. From: popcornmix <popcornmix@gmail.com>
  11507. Date: Mon, 3 Feb 2014 22:50:43 +0000
  11508. Subject: [PATCH 45/94] [omxcodec] Add shared pointer to delay shutdown of
  11509. codec until buffers are returned
  11510. ---
  11511. .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 13 +++----------
  11512. .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 3 ++-
  11513. .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 21 ++++++++++++++++++++-
  11514. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 5 ++++-
  11515. 4 files changed, 29 insertions(+), 13 deletions(-)
  11516. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  11517. index 7d33192..ef10555 100644
  11518. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  11519. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  11520. @@ -28,7 +28,6 @@
  11521. #include "DVDClock.h"
  11522. #include "DVDStreamInfo.h"
  11523. #include "DVDVideoCodecOpenMax.h"
  11524. -#include "OpenMaxVideo.h"
  11525. #include "settings/Settings.h"
  11526. #include "utils/log.h"
  11527. @@ -36,8 +35,8 @@
  11528. ////////////////////////////////////////////////////////////////////////////////////////////
  11529. ////////////////////////////////////////////////////////////////////////////////////////////
  11530. CDVDVideoCodecOpenMax::CDVDVideoCodecOpenMax()
  11531. + : m_omx_decoder( new COpenMaxVideo )
  11532. {
  11533. - m_omx_decoder = NULL;
  11534. CLog::Log(LOGDEBUG, "%s::%s %p\n", CLASSNAME, __func__, this);
  11535. }
  11536. @@ -49,8 +48,7 @@ CDVDVideoCodecOpenMax::~CDVDVideoCodecOpenMax()
  11537. bool CDVDVideoCodecOpenMax::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  11538. {
  11539. - m_omx_decoder = new COpenMaxVideo;
  11540. - return m_omx_decoder->Open(hints, options);
  11541. + return m_omx_decoder->Open(hints, options, m_omx_decoder);
  11542. }
  11543. const char* CDVDVideoCodecOpenMax::GetName(void)
  11544. @@ -60,12 +58,7 @@ const char* CDVDVideoCodecOpenMax::GetName(void)
  11545. void CDVDVideoCodecOpenMax::Dispose()
  11546. {
  11547. - if (m_omx_decoder)
  11548. - {
  11549. - m_omx_decoder->Dispose();
  11550. - delete m_omx_decoder;
  11551. - m_omx_decoder = NULL;
  11552. - }
  11553. + m_omx_decoder->Dispose();
  11554. }
  11555. void CDVDVideoCodecOpenMax::SetDropState(bool bDrop)
  11556. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  11557. index 67cc235..b7c0c1b 100644
  11558. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  11559. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  11560. @@ -22,6 +22,7 @@
  11561. #if defined(HAVE_LIBOPENMAX)
  11562. #include "DVDVideoCodec.h"
  11563. +#include "OpenMaxVideo.h"
  11564. class COpenMaxVideo;
  11565. class CDVDVideoCodecOpenMax : public CDVDVideoCodec
  11566. @@ -42,7 +43,7 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec
  11567. virtual const char* GetName(void);
  11568. protected:
  11569. - COpenMaxVideo *m_omx_decoder;
  11570. + OpenMaxVideoPtr m_omx_decoder;
  11571. };
  11572. #endif
  11573. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11574. index aca2e0d..29b5bb9 100644
  11575. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11576. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11577. @@ -126,6 +126,7 @@ COpenMaxVideo::COpenMaxVideo()
  11578. m_egl_buffer_count = 0;
  11579. m_port_settings_changed = false;
  11580. + m_finished = false;
  11581. m_pFormatName = "omx-xxxx";
  11582. }
  11583. @@ -134,6 +135,7 @@ COpenMaxVideo::~COpenMaxVideo()
  11584. #if defined(OMX_DEBUG_VERBOSE)
  11585. CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  11586. #endif
  11587. + assert(m_finished);
  11588. if (m_omx_decoder.IsInitialized())
  11589. {
  11590. if (m_omx_tunnel.IsInitialized())
  11591. @@ -149,7 +151,7 @@ COpenMaxVideo::~COpenMaxVideo()
  11592. pthread_mutex_destroy(&m_omx_output_mutex);
  11593. }
  11594. -bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  11595. +bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself)
  11596. {
  11597. #if defined(OMX_DEBUG_VERBOSE)
  11598. CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  11599. @@ -161,6 +163,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  11600. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  11601. + m_myself = myself;
  11602. m_decoded_width = hints.width;
  11603. m_decoded_height = hints.height;
  11604. @@ -331,6 +334,15 @@ void COpenMaxVideo::Dispose()
  11605. #if defined(OMX_DEBUG_VERBOSE)
  11606. CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  11607. #endif
  11608. + // we are happy to exit, but let last shared pointer being deleted trigger the destructor
  11609. + bool done = false;
  11610. + pthread_mutex_lock(&m_omx_output_mutex);
  11611. + if (m_omx_output_busy.empty())
  11612. + done = true;
  11613. + m_finished = true;
  11614. + pthread_mutex_unlock(&m_omx_output_mutex);
  11615. + if (done)
  11616. + m_myself.reset();
  11617. }
  11618. void COpenMaxVideo::SetDropState(bool bDrop)
  11619. @@ -752,6 +764,13 @@ void COpenMaxVideo::ReleaseOpenMaxBuffer(COpenMaxVideoBuffer *buffer)
  11620. m_omx_output_busy.erase(std::remove(m_omx_output_busy.begin(), m_omx_output_busy.end(), buffer), m_omx_output_busy.end());
  11621. pthread_mutex_unlock(&m_omx_output_mutex);
  11622. ReturnOpenMaxBuffer(buffer);
  11623. + bool done = false;
  11624. + pthread_mutex_lock(&m_omx_output_mutex);
  11625. + if (m_finished && m_omx_output_busy.empty())
  11626. + done = true;
  11627. + pthread_mutex_unlock(&m_omx_output_mutex);
  11628. + if (done)
  11629. + m_myself.reset();
  11630. }
  11631. bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  11632. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11633. index 9079c13..0975e8a 100644
  11634. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11635. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11636. @@ -43,6 +43,7 @@ typedef struct omx_demux_packet {
  11637. } omx_demux_packet;
  11638. class COpenMaxVideo;
  11639. +typedef boost::shared_ptr<COpenMaxVideo> OpenMaxVideoPtr;
  11640. // an omx egl video frame
  11641. class COpenMaxVideoBuffer
  11642. {
  11643. @@ -75,7 +76,7 @@ class COpenMaxVideo
  11644. virtual ~COpenMaxVideo();
  11645. // Required overrides
  11646. - virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options);
  11647. + virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself);
  11648. virtual void Dispose(void);
  11649. virtual int Decode(uint8_t *pData, int iSize, double dts, double pts);
  11650. virtual void Reset(void);
  11651. @@ -112,9 +113,11 @@ class COpenMaxVideo
  11652. int m_decoded_width;
  11653. int m_decoded_height;
  11654. unsigned int m_egl_buffer_count;
  11655. + bool m_finished;
  11656. bool m_port_settings_changed;
  11657. const char *m_pFormatName;
  11658. + OpenMaxVideoPtr m_myself;
  11659. std::queue<double> m_dts_queue;
  11660. std::queue<omx_demux_packet> m_demux_queue;
  11661. --
  11662. 1.9.3
  11663. From e8f40e625203fe4113e2687d3730c38770cc0857 Mon Sep 17 00:00:00 2001
  11664. From: popcornmix <popcornmix@gmail.com>
  11665. Date: Mon, 3 Feb 2014 23:11:31 +0000
  11666. Subject: [PATCH 46/94] [omxcodec] Fix for aspect ratio in non-square pixel
  11667. modes
  11668. ---
  11669. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 17 +++++++++++++++++
  11670. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 3 +++
  11671. 2 files changed, 20 insertions(+)
  11672. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11673. index 29b5bb9..7e23c87 100644
  11674. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11675. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11676. @@ -63,6 +63,7 @@ COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv)
  11677. index = 0;
  11678. egl_image = 0;
  11679. texture_id = 0;
  11680. + m_aspect_ratio = 0.0f;
  11681. }
  11682. COpenMaxVideoBuffer::~COpenMaxVideoBuffer()
  11683. @@ -166,6 +167,8 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  11684. m_myself = myself;
  11685. m_decoded_width = hints.width;
  11686. m_decoded_height = hints.height;
  11687. + m_forced_aspect_ratio = hints.forced_aspect;
  11688. + m_aspect_ratio = hints.aspect;
  11689. m_egl_display = g_Windowing.GetEGLDisplay();
  11690. m_egl_context = g_Windowing.GetEGLContext();
  11691. @@ -435,6 +438,9 @@ bool COpenMaxVideo::PortSettingsChanged()
  11692. CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11693. return false;
  11694. }
  11695. + if (!m_forced_aspect_ratio && pixel_aspect.nX && pixel_aspect.nY)
  11696. + m_aspect_ratio = (float)pixel_aspect.nX * port_def.format.video.nFrameWidth /
  11697. + ((float)pixel_aspect.nY * port_def.format.video.nFrameHeight);
  11698. if (m_port_settings_changed)
  11699. {
  11700. @@ -800,6 +806,16 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  11701. pDvdVideoPicture->iDisplayWidth = m_decoded_width;
  11702. pDvdVideoPicture->iDisplayHeight = m_decoded_height;
  11703. + if (buffer->m_aspect_ratio > 0.0 && !m_forced_aspect_ratio)
  11704. + {
  11705. + pDvdVideoPicture->iDisplayWidth = ((int)lrint(pDvdVideoPicture->iHeight * buffer->m_aspect_ratio)) & -3;
  11706. + if (pDvdVideoPicture->iDisplayWidth > pDvdVideoPicture->iWidth)
  11707. + {
  11708. + pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth;
  11709. + pDvdVideoPicture->iDisplayHeight = ((int)lrint(pDvdVideoPicture->iWidth / buffer->m_aspect_ratio)) & -3;
  11710. + }
  11711. + }
  11712. +
  11713. #ifdef DTS_QUEUE
  11714. if (!m_dts_queue.empty())
  11715. {
  11716. @@ -853,6 +869,7 @@ OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone(
  11717. // queue output omx buffer to ready list.
  11718. pthread_mutex_lock(&m_omx_output_mutex);
  11719. + buffer->m_aspect_ratio = m_aspect_ratio;
  11720. m_omx_output_ready.push(buffer);
  11721. pthread_mutex_unlock(&m_omx_output_mutex);
  11722. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11723. index 0975e8a..9138a20 100644
  11724. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11725. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11726. @@ -54,6 +54,7 @@ class COpenMaxVideoBuffer
  11727. OMX_BUFFERHEADERTYPE *omx_buffer;
  11728. int width;
  11729. int height;
  11730. + float m_aspect_ratio;
  11731. int index;
  11732. // used for egl based rendering if active
  11733. @@ -114,6 +115,8 @@ class COpenMaxVideo
  11734. int m_decoded_height;
  11735. unsigned int m_egl_buffer_count;
  11736. bool m_finished;
  11737. + float m_aspect_ratio;
  11738. + bool m_forced_aspect_ratio;
  11739. bool m_port_settings_changed;
  11740. const char *m_pFormatName;
  11741. --
  11742. 1.9.3
  11743. From e42ca92b464ad88dbe0f8b0d86080d64d52e08a8 Mon Sep 17 00:00:00 2001
  11744. From: popcornmix <popcornmix@gmail.com>
  11745. Date: Mon, 3 Feb 2014 23:19:22 +0000
  11746. Subject: [PATCH 47/94] [omxcodec] Report error when codec not enabled
  11747. ---
  11748. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 10 +++++++++-
  11749. 1 file changed, 9 insertions(+), 1 deletion(-)
  11750. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11751. index 7e23c87..2ae722b 100644
  11752. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11753. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11754. @@ -43,6 +43,7 @@
  11755. #include <IL/OMX_Image.h>
  11756. #include "cores/omxplayer/OMXImage.h"
  11757. +#include "linux/RBP.h"
  11758. #define DTS_QUEUE
  11759. @@ -155,7 +156,7 @@ COpenMaxVideo::~COpenMaxVideo()
  11760. bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenMaxVideoPtr myself)
  11761. {
  11762. #if defined(OMX_DEBUG_VERBOSE)
  11763. - CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  11764. + CLog::Log(LOGDEBUG, "%s::%s useomx:%d software:%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.useomx"), hints.software);
  11765. #endif
  11766. // we always qualify even if DVDFactoryCodec does this too.
  11767. @@ -232,6 +233,13 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  11768. break;
  11769. }
  11770. + if ( (m_codingType == OMX_VIDEO_CodingMPEG2 && !g_RBP.GetCodecMpg2() ) ||
  11771. + (m_codingType == OMX_VIDEO_CodingWMV && !g_RBP.GetCodecWvc1() ) )
  11772. + {
  11773. + CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported\n", CLASSNAME, __func__, m_pFormatName);
  11774. + return false;
  11775. + }
  11776. +
  11777. // initialize OpenMAX.
  11778. if (!m_omx_decoder.Initialize("OMX.broadcom.video_decode", OMX_IndexParamVideoInit))
  11779. {
  11780. --
  11781. 1.9.3
  11782. From 55b0b157ba32d03ca0ec854b7935aee5601810d8 Mon Sep 17 00:00:00 2001
  11783. From: popcornmix <popcornmix@gmail.com>
  11784. Date: Tue, 4 Feb 2014 17:29:37 +0000
  11785. Subject: [PATCH 48/94] [omxcodec] Add deinterlace support
  11786. ---
  11787. xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 +-
  11788. .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 106 ++++++++++++++++++---
  11789. .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 9 +-
  11790. 3 files changed, 103 insertions(+), 14 deletions(-)
  11791. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11792. index 279aa90..a57abe4 100644
  11793. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11794. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  11795. @@ -2607,7 +2607,7 @@ bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
  11796. return true;
  11797. if(m_renderMethod & RENDER_OMXEGL)
  11798. - return false;
  11799. + return true;
  11800. if(m_renderMethod & RENDER_EGLIMG)
  11801. return false;
  11802. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11803. index 2ae722b..fbf1458 100644
  11804. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11805. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  11806. @@ -33,6 +33,7 @@
  11807. #include "utils/log.h"
  11808. #include "utils/TimeUtils.h"
  11809. #include "settings/Settings.h"
  11810. +#include "settings/MediaSettings.h"
  11811. #include "ApplicationMessenger.h"
  11812. #include "Application.h"
  11813. #include "threads/Atomics.h"
  11814. @@ -130,6 +131,10 @@ COpenMaxVideo::COpenMaxVideo()
  11815. m_port_settings_changed = false;
  11816. m_finished = false;
  11817. m_pFormatName = "omx-xxxx";
  11818. +
  11819. + m_deinterlace = false;
  11820. + m_deinterlace_request = VS_DEINTERLACEMODE_OFF;
  11821. + m_deinterlace_second_field = false;
  11822. }
  11823. COpenMaxVideo::~COpenMaxVideo()
  11824. @@ -140,13 +145,17 @@ COpenMaxVideo::~COpenMaxVideo()
  11825. assert(m_finished);
  11826. if (m_omx_decoder.IsInitialized())
  11827. {
  11828. - if (m_omx_tunnel.IsInitialized())
  11829. - m_omx_tunnel.Deestablish();
  11830. + if (m_omx_tunnel_decoder.IsInitialized())
  11831. + m_omx_tunnel_decoder.Deestablish();
  11832. + if (m_omx_tunnel_image_fx.IsInitialized())
  11833. + m_omx_tunnel_image_fx.Deestablish();
  11834. StopDecoder();
  11835. if (m_omx_egl_render.IsInitialized())
  11836. m_omx_egl_render.Deinitialize();
  11837. + if (m_omx_image_fx.IsInitialized())
  11838. + m_omx_image_fx.Deinitialize();
  11839. if (m_omx_decoder.IsInitialized())
  11840. m_omx_decoder.Deinitialize();
  11841. }
  11842. @@ -165,6 +174,8 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  11843. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  11844. + m_deinterlace_request = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
  11845. +
  11846. m_myself = myself;
  11847. m_decoded_width = hints.width;
  11848. m_decoded_height = hints.height;
  11849. @@ -467,6 +478,49 @@ bool COpenMaxVideo::PortSettingsChanged()
  11850. return false;
  11851. }
  11852. + OMX_CONFIG_INTERLACETYPE interlace;
  11853. + OMX_INIT_STRUCTURE(interlace);
  11854. + interlace.nPortIndex = m_omx_decoder.GetOutputPort();
  11855. + omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
  11856. +
  11857. + if (m_deinterlace_request == VS_DEINTERLACEMODE_FORCE)
  11858. + m_deinterlace = true;
  11859. + else if (m_deinterlace_request == VS_DEINTERLACEMODE_OFF)
  11860. + m_deinterlace = false;
  11861. + else
  11862. + m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
  11863. +
  11864. + CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d",
  11865. + CLASSNAME, __func__, port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight, port_def.format.video.xFramerate / (float) (1 << 16),
  11866. + interlace.eMode, m_deinterlace);
  11867. +
  11868. + if (m_deinterlace)
  11869. + {
  11870. + if (!m_omx_image_fx.Initialize("OMX.broadcom.image_fx", OMX_IndexParamImageInit))
  11871. + {
  11872. + CLog::Log(LOGERROR, "%s::%s error m_omx_image_fx.Initialize", CLASSNAME, __func__);
  11873. + return false;
  11874. + }
  11875. + }
  11876. +
  11877. + if (m_deinterlace)
  11878. + {
  11879. + OMX_CONFIG_IMAGEFILTERPARAMSTYPE image_filter;
  11880. + OMX_INIT_STRUCTURE(image_filter);
  11881. +
  11882. + image_filter.nPortIndex = m_omx_image_fx.GetOutputPort();
  11883. + image_filter.nNumParams = 1;
  11884. + image_filter.nParams[0] = 3;
  11885. + image_filter.eImageFilter = OMX_ImageFilterDeInterlaceAdvanced;
  11886. +
  11887. + omx_err = m_omx_image_fx.SetConfig(OMX_IndexConfigCommonImageFilterParameters, &image_filter);
  11888. + if (omx_err != OMX_ErrorNone)
  11889. + {
  11890. + CLog::Log(LOGERROR, "%s::%s - OMX_IndexConfigCommonImageFilterParameters omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11891. + return false;
  11892. + }
  11893. + }
  11894. +
  11895. OMX_CALLBACKTYPE callbacks = { NULL, NULL, DecoderFillBufferDoneCallback };
  11896. if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit, &callbacks))
  11897. {
  11898. @@ -487,19 +541,40 @@ bool COpenMaxVideo::PortSettingsChanged()
  11899. m_omx_egl_render.ResetEos();
  11900. - CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  11901. - port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight,
  11902. - port_def.format.video.xFramerate / (float)(1<<16), 0,0);
  11903. -
  11904. - m_omx_tunnel.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  11905. + if (m_deinterlace)
  11906. + {
  11907. + m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_image_fx, m_omx_image_fx.GetInputPort());
  11908. + m_omx_tunnel_image_fx.Initialize(&m_omx_image_fx, m_omx_image_fx.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  11909. + }
  11910. + else
  11911. + {
  11912. + m_omx_tunnel_decoder.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  11913. + }
  11914. - omx_err = m_omx_tunnel.Establish();
  11915. + omx_err = m_omx_tunnel_decoder.Establish();
  11916. if (omx_err != OMX_ErrorNone)
  11917. {
  11918. - CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11919. + CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_decoder.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11920. return false;
  11921. }
  11922. + if (m_deinterlace)
  11923. + {
  11924. + omx_err = m_omx_tunnel_image_fx.Establish();
  11925. + if (omx_err != OMX_ErrorNone)
  11926. + {
  11927. + CLog::Log(LOGERROR, "%s::%s - m_omx_tunnel_image_fx.Establish omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  11928. + return false;
  11929. + }
  11930. + omx_err = m_omx_image_fx.SetStateForComponent(OMX_StateExecuting);
  11931. + if (omx_err != OMX_ErrorNone)
  11932. + {
  11933. + CLog::Log(LOGERROR, "%s::%s - m_omx_image_fx.SetStateForComponent omx_err(0x%08x)",
  11934. + CLASSNAME, __func__, omx_err);
  11935. + return false;
  11936. + }
  11937. + }
  11938. +
  11939. // Obtain the information about the output port.
  11940. OMX_PARAM_PORTDEFINITIONTYPE port_format;
  11941. OMX_INIT_STRUCTURE(port_format);
  11942. @@ -724,8 +799,12 @@ void COpenMaxVideo::Reset(void)
  11943. #if defined(OMX_DEBUG_VERBOSE)
  11944. CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__);
  11945. #endif
  11946. - m_omx_egl_render.FlushAll();
  11947. - m_omx_decoder.FlushAll();
  11948. + if (m_omx_egl_render.IsInitialized())
  11949. + m_omx_egl_render.FlushAll();
  11950. + if (m_omx_image_fx.IsInitialized())
  11951. + m_omx_image_fx.FlushAll();
  11952. + if (m_omx_decoder.IsInitialized())
  11953. + m_omx_decoder.FlushAll();
  11954. // blow all ready video frames
  11955. while (!m_omx_output_ready.empty())
  11956. {
  11957. @@ -825,11 +904,14 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  11958. }
  11959. #ifdef DTS_QUEUE
  11960. - if (!m_dts_queue.empty())
  11961. + if (!m_deinterlace_second_field)
  11962. {
  11963. + assert(!m_dts_queue.empty());
  11964. pDvdVideoPicture->dts = m_dts_queue.front();
  11965. m_dts_queue.pop();
  11966. }
  11967. + if (m_deinterlace)
  11968. + m_deinterlace_second_field = !m_deinterlace_second_field;
  11969. #endif
  11970. // nTimeStamp is in microseconds
  11971. double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp);
  11972. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11973. index 9138a20..c8ad4d8 100644
  11974. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11975. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  11976. @@ -31,6 +31,7 @@
  11977. #include "cores/dvdplayer/DVDStreamInfo.h"
  11978. #include "DVDVideoCodec.h"
  11979. #include "threads/Event.h"
  11980. +#include "xbmc/settings/VideoSettings.h"
  11981. #include <queue>
  11982. #include <semaphore.h>
  11983. @@ -136,11 +137,17 @@ class COpenMaxVideo
  11984. // Components
  11985. COMXCoreComponent m_omx_decoder;
  11986. + COMXCoreComponent m_omx_image_fx;
  11987. COMXCoreComponent m_omx_egl_render;
  11988. - COMXCoreTunel m_omx_tunnel;
  11989. + COMXCoreTunel m_omx_tunnel_decoder;
  11990. + COMXCoreTunel m_omx_tunnel_image_fx;
  11991. OMX_VIDEO_CODINGTYPE m_codingType;
  11992. + bool m_deinterlace;
  11993. + EDEINTERLACEMODE m_deinterlace_request;
  11994. + bool m_deinterlace_second_field;
  11995. +
  11996. bool PortSettingsChanged();
  11997. bool SendDecoderConfig(uint8_t *extradata, int extrasize);
  11998. bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize);
  11999. --
  12000. 1.9.3
  12001. From 0701b41709e6a18567b9f6bfd0d491285546eedc Mon Sep 17 00:00:00 2001
  12002. From: Ben Avison <bavison@riscosopen.org>
  12003. Date: Wed, 12 Feb 2014 18:43:14 +0000
  12004. Subject: [PATCH 49/94] Improved file buffering in CArchive.
  12005. CArchive already did some file buffering, but only on writes. Added the
  12006. equivalent code for reads. Also improved the write buffer case so that it
  12007. only ever issues sector-aligned writes (the read code does this from the
  12008. start). Shuffled various bits of code into the header file to squeeze a bit
  12009. more performance out of it.
  12010. Profiled the effect on CFileItemList::Archive(), which is one of the slow
  12011. parts of the process of reopening a media library, on a non-overclocked
  12012. Raspberry Pi. Times are in seconds:
  12013. TV shows (253 items)
  12014. Before After
  12015. Mean StdDev Mean StdDev Confidence Change
  12016. 0.394 0.005 0.151 0.005 100.0% +159.8%
  12017. Songs (4115 items)
  12018. Before After
  12019. Mean StdDev Mean StdDev Confidence Change
  12020. 2.931 0.045 0.690 0.019 100.0% +324.4%
  12021. ---
  12022. xbmc/utils/Archive.cpp | 158 ++++++++++++++++++-------------------------------
  12023. xbmc/utils/Archive.h | 130 ++++++++++++++++++++++++++++++++++------
  12024. 2 files changed, 172 insertions(+), 116 deletions(-)
  12025. diff --git a/xbmc/utils/Archive.cpp b/xbmc/utils/Archive.cpp
  12026. index 4519e19..b2ad273 100644
  12027. --- a/xbmc/utils/Archive.cpp
  12028. +++ b/xbmc/utils/Archive.cpp
  12029. @@ -30,24 +30,29 @@
  12030. using namespace XFILE;
  12031. -#define BUFFER_MAX 4096
  12032. -
  12033. CArchive::CArchive(CFile* pFile, int mode)
  12034. {
  12035. m_pFile = pFile;
  12036. m_iMode = mode;
  12037. - m_pBuffer = new uint8_t[BUFFER_MAX];
  12038. - memset(m_pBuffer, 0, BUFFER_MAX);
  12039. -
  12040. - m_BufferPos = 0;
  12041. + m_pBuffer = new uint8_t[CARCHIVE_BUFFER_MAX];
  12042. + memset(m_pBuffer, 0, CARCHIVE_BUFFER_MAX);
  12043. + if (mode == load)
  12044. + {
  12045. + m_BufferPos = m_pBuffer + CARCHIVE_BUFFER_MAX;
  12046. + m_BufferRemain = 0;
  12047. + }
  12048. + else
  12049. + {
  12050. + m_BufferPos = m_pBuffer;
  12051. + m_BufferRemain = CARCHIVE_BUFFER_MAX;
  12052. + }
  12053. }
  12054. CArchive::~CArchive()
  12055. {
  12056. FlushBuffer();
  12057. delete[] m_pBuffer;
  12058. - m_BufferPos = 0;
  12059. }
  12060. void CArchive::Close()
  12061. @@ -214,89 +219,6 @@ CArchive& CArchive::operator<<(const std::vector<int>& iArray)
  12062. return *this;
  12063. }
  12064. -inline CArchive& CArchive::streamout(const void* dataPtr, size_t size)
  12065. -{
  12066. - const uint8_t* ptr = (const uint8_t*)dataPtr;
  12067. -
  12068. - if (size + m_BufferPos >= BUFFER_MAX)
  12069. - {
  12070. - FlushBuffer();
  12071. - while (size >= BUFFER_MAX)
  12072. - {
  12073. - memcpy(m_pBuffer, ptr, BUFFER_MAX);
  12074. - m_BufferPos = BUFFER_MAX;
  12075. - ptr += BUFFER_MAX;
  12076. - size -= BUFFER_MAX;
  12077. - FlushBuffer();
  12078. - }
  12079. - }
  12080. -
  12081. - memcpy(m_pBuffer + m_BufferPos, ptr, size);
  12082. - m_BufferPos += size;
  12083. -
  12084. - return *this;
  12085. -}
  12086. -
  12087. -CArchive& CArchive::operator>>(float& f)
  12088. -{
  12089. - return streamin(&f, sizeof(f));
  12090. -}
  12091. -
  12092. -CArchive& CArchive::operator>>(double& d)
  12093. -{
  12094. - return streamin(&d, sizeof(d));
  12095. -}
  12096. -
  12097. -CArchive& CArchive::operator>>(short int& s)
  12098. -{
  12099. - return streamin(&s, sizeof(s));
  12100. -}
  12101. -
  12102. -CArchive& CArchive::operator>>(unsigned short int& us)
  12103. -{
  12104. - return streamin(&us, sizeof(us));
  12105. -}
  12106. -
  12107. -CArchive& CArchive::operator>>(int& i)
  12108. -{
  12109. - return streamin(&i, sizeof(i));
  12110. -}
  12111. -
  12112. -CArchive& CArchive::operator>>(unsigned int& ui)
  12113. -{
  12114. - return streamin(&ui, sizeof(ui));
  12115. -}
  12116. -
  12117. -CArchive& CArchive::operator>>(long int& l)
  12118. -{
  12119. - return streamin(&l, sizeof(l));
  12120. -}
  12121. -
  12122. -CArchive& CArchive::operator>>(unsigned long int& ul)
  12123. -{
  12124. - return streamin(&ul, sizeof(ul));
  12125. -}
  12126. -
  12127. -CArchive& CArchive::operator>>(long long int& ll)
  12128. -{
  12129. - return streamin(&ll, sizeof(ll));
  12130. -}
  12131. -
  12132. -CArchive& CArchive::operator>>(unsigned long long int& ull)
  12133. -{
  12134. - return streamin(&ull, sizeof(ull));
  12135. -}
  12136. -
  12137. -CArchive& CArchive::operator>>(bool& b)
  12138. -{
  12139. - return streamin(&b, sizeof(b));
  12140. -}
  12141. -
  12142. -CArchive& CArchive::operator>>(char& c)
  12143. -{
  12144. - return streamin(&c, sizeof(c));
  12145. -}
  12146. -
  12147. CArchive& CArchive::operator>>(std::string& str)
  12148. {
  12149. size_t iLength = 0;
  12150. @@ -450,23 +372,61 @@ CArchive& CArchive::operator>>(std::vector<int>& iArray)
  12151. return *this;
  12152. }
  12153. -inline CArchive& CArchive::streamin(void* dataPtr, const size_t size)
  12154. +void CArchive::FlushBuffer()
  12155. {
  12156. - size_t read = m_pFile->Read(dataPtr, size);
  12157. - if (read < size)
  12158. + if (m_iMode == store && m_BufferPos != m_pBuffer)
  12159. {
  12160. - CLog::Log(LOGERROR, "%s: can't stream out: requested %lu bytes, was read %lu bytes", __FUNCTION__, (unsigned long)size, (unsigned long)read);
  12161. - memset(dataPtr, 0, size);
  12162. + m_pFile->Write(m_pBuffer, m_BufferPos - m_pBuffer);
  12163. + m_BufferPos = m_pBuffer;
  12164. + m_BufferRemain = CARCHIVE_BUFFER_MAX;
  12165. }
  12166. +}
  12167. +CArchive &CArchive::streamout_bufferwrap(const uint8_t *ptr, size_t size)
  12168. +{
  12169. + do
  12170. + {
  12171. + size_t chunkSize = std::min(size, m_BufferRemain);
  12172. + m_BufferPos = std::copy(ptr, ptr + chunkSize, m_BufferPos);
  12173. + ptr += chunkSize;
  12174. + size -= chunkSize;
  12175. + m_BufferRemain -= chunkSize;
  12176. + if (m_BufferRemain == 0)
  12177. + FlushBuffer();
  12178. + } while (size > 0);
  12179. return *this;
  12180. }
  12181. -void CArchive::FlushBuffer()
  12182. +void CArchive::FillBuffer()
  12183. {
  12184. - if (m_BufferPos > 0)
  12185. + if (m_iMode == load && m_BufferRemain == 0)
  12186. {
  12187. - m_pFile->Write(m_pBuffer, m_BufferPos);
  12188. - m_BufferPos = 0;
  12189. + m_BufferRemain = m_pFile->Read(m_pBuffer, CARCHIVE_BUFFER_MAX);
  12190. + m_BufferPos = m_pBuffer;
  12191. }
  12192. }
  12193. +
  12194. +CArchive &CArchive::streamin_bufferwrap(uint8_t *ptr, size_t size)
  12195. +{
  12196. + uint8_t *orig_ptr = ptr;
  12197. + size_t orig_size = size;
  12198. + do
  12199. + {
  12200. + if (m_BufferRemain == 0)
  12201. + {
  12202. + FillBuffer();
  12203. + if (m_BufferRemain < CARCHIVE_BUFFER_MAX && m_BufferRemain < size)
  12204. + {
  12205. + CLog::Log(LOGERROR, "%s: can't stream in: requested %lu bytes, was read %lu bytes", __FUNCTION__, (unsigned long) orig_size, (unsigned long) (ptr - orig_ptr + m_BufferRemain));
  12206. + memset(orig_ptr, 0, orig_size);
  12207. + return *this;
  12208. + }
  12209. + }
  12210. + size_t chunkSize = std::min(size, m_BufferRemain);
  12211. + ptr = std::copy(m_BufferPos, m_BufferPos + chunkSize, ptr);
  12212. + m_BufferPos += chunkSize;
  12213. + m_BufferRemain -= chunkSize;
  12214. + size -= chunkSize;
  12215. + } while (size > 0);
  12216. + return *this;
  12217. +}
  12218. diff --git a/xbmc/utils/Archive.h b/xbmc/utils/Archive.h
  12219. index 0148fcb..5b25be5 100644
  12220. --- a/xbmc/utils/Archive.h
  12221. +++ b/xbmc/utils/Archive.h
  12222. @@ -24,6 +24,8 @@
  12223. #include <vector>
  12224. #include "PlatformDefs.h" // for SYSTEMTIME
  12225. +#define CARCHIVE_BUFFER_MAX 4096
  12226. +
  12227. namespace XFILE
  12228. {
  12229. class CFile;
  12230. @@ -77,18 +79,66 @@ class CArchive
  12231. CArchive& operator<<(const std::vector<int>& iArray);
  12232. // loading
  12233. - CArchive& operator>>(float& f);
  12234. - CArchive& operator>>(double& d);
  12235. - CArchive& operator>>(short int& s);
  12236. - CArchive& operator>>(unsigned short int& us);
  12237. - CArchive& operator>>(int& i);
  12238. - CArchive& operator>>(unsigned int& ui);
  12239. - CArchive& operator>>(long int& l);
  12240. - CArchive& operator>>(unsigned long int& ul);
  12241. - CArchive& operator>>(long long int& ll);
  12242. - CArchive& operator>>(unsigned long long int& ull);
  12243. - CArchive& operator>>(bool& b);
  12244. - CArchive& operator>>(char& c);
  12245. + inline CArchive& operator>>(float& f)
  12246. + {
  12247. + return streamin(&f, sizeof(f));
  12248. + }
  12249. +
  12250. + inline CArchive& operator>>(double& d)
  12251. + {
  12252. + return streamin(&d, sizeof(d));
  12253. + }
  12254. +
  12255. + inline CArchive& operator>>(short int& s)
  12256. + {
  12257. + return streamin(&s, sizeof(s));
  12258. + }
  12259. +
  12260. + inline CArchive& operator>>(unsigned short int& us)
  12261. + {
  12262. + return streamin(&us, sizeof(us));
  12263. + }
  12264. +
  12265. + inline CArchive& operator>>(int& i)
  12266. + {
  12267. + return streamin(&i, sizeof(i));
  12268. + }
  12269. +
  12270. + inline CArchive& operator>>(unsigned int& ui)
  12271. + {
  12272. + return streamin(&ui, sizeof(ui));
  12273. + }
  12274. +
  12275. + inline CArchive& operator>>(long int& l)
  12276. + {
  12277. + return streamin(&l, sizeof(l));
  12278. + }
  12279. +
  12280. + inline CArchive& operator>>(unsigned long int& ul)
  12281. + {
  12282. + return streamin(&ul, sizeof(ul));
  12283. + }
  12284. +
  12285. + inline CArchive& operator>>(long long int& ll)
  12286. + {
  12287. + return streamin(&ll, sizeof(ll));
  12288. + }
  12289. +
  12290. + inline CArchive& operator>>(unsigned long long int& ull)
  12291. + {
  12292. + return streamin(&ull, sizeof(ull));
  12293. + }
  12294. +
  12295. + inline CArchive& operator>>(bool& b)
  12296. + {
  12297. + return streamin(&b, sizeof(b));
  12298. + }
  12299. +
  12300. + inline CArchive& operator>>(char& c)
  12301. + {
  12302. + return streamin(&c, sizeof(c));
  12303. + }
  12304. +
  12305. CArchive& operator>>(std::string &str);
  12306. CArchive& operator>>(std::wstring& wstr);
  12307. CArchive& operator>>(SYSTEMTIME& time);
  12308. @@ -105,12 +155,58 @@ class CArchive
  12309. enum Mode {load = 0, store};
  12310. protected:
  12311. - CArchive& streamout(const void* dataPtr, size_t size);
  12312. - CArchive& streamin(void* dataPtr, const size_t size);
  12313. - void FlushBuffer();
  12314. + inline CArchive &streamout(const void *dataPtr, size_t size)
  12315. + {
  12316. + const uint8_t *ptr = (const uint8_t *) dataPtr;
  12317. + /* Note, the buffer is flushed as soon as it is full (m_BufferRemain == size) rather
  12318. + * than waiting until we attempt to put more data into an already full buffer */
  12319. + if (m_BufferRemain > size)
  12320. + {
  12321. + switch (size)
  12322. + {
  12323. + case 1: *m_BufferPos++ = *ptr; m_BufferRemain--; break;
  12324. + case 2: *(uint16_t *) m_BufferPos = *(const uint16_t *) ptr; m_BufferPos += 2; m_BufferRemain -= 2; break;
  12325. + case 4: *(uint32_t *) m_BufferPos = *(const uint32_t *) ptr; m_BufferPos += 4; m_BufferRemain -= 4; break;
  12326. + default: m_BufferPos = std::copy(ptr, ptr + size, m_BufferPos); m_BufferRemain -= size; break;
  12327. + }
  12328. + return *this;
  12329. + }
  12330. + else
  12331. + {
  12332. + return streamout_bufferwrap(ptr, size);
  12333. + }
  12334. + }
  12335. +
  12336. + inline CArchive &streamin(void *dataPtr, size_t size)
  12337. + {
  12338. + uint8_t *ptr = (uint8_t *) dataPtr;
  12339. + /* Note, refilling the buffer is deferred until we know we need to read more from it */
  12340. + if (m_BufferRemain >= size)
  12341. + {
  12342. + switch (size)
  12343. + {
  12344. + case 1: *ptr = *m_BufferPos++; m_BufferRemain--; break;
  12345. + case 2: *(uint16_t *) ptr = *(const uint16_t *) m_BufferPos; m_BufferPos += 2; m_BufferRemain -= 2; break;
  12346. + case 4: *(uint32_t *) ptr = *(const uint32_t *) m_BufferPos; m_BufferPos += 4; m_BufferRemain -= 4; break;
  12347. + default: std::copy(m_BufferPos, m_BufferPos + size, ptr); m_BufferPos += size; m_BufferRemain -= size; break;
  12348. + }
  12349. + return *this;
  12350. + }
  12351. + else
  12352. + {
  12353. + return streamin_bufferwrap(ptr, size);
  12354. + }
  12355. + }
  12356. +
  12357. XFILE::CFile* m_pFile;
  12358. int m_iMode;
  12359. uint8_t *m_pBuffer;
  12360. - int m_BufferPos;
  12361. -};
  12362. + uint8_t *m_BufferPos;
  12363. + size_t m_BufferRemain;
  12364. +private:
  12365. + void FlushBuffer();
  12366. + CArchive &streamout_bufferwrap(const uint8_t *ptr, size_t size);
  12367. + void FillBuffer();
  12368. + CArchive &streamin_bufferwrap(uint8_t *ptr, size_t size);
  12369. +};
  12370. --
  12371. 1.9.3
  12372. From 2ae9667952e98ab91b0056094231e923570fa64b Mon Sep 17 00:00:00 2001
  12373. From: popcornmix <popcornmix@gmail.com>
  12374. Date: Wed, 5 Feb 2014 11:46:33 +0000
  12375. Subject: [PATCH 50/94] [rbp/settings] Allow av sync type to be enabled
  12376. It works for dvdplayer
  12377. ---
  12378. system/settings/rbp.xml | 7 -------
  12379. 1 file changed, 7 deletions(-)
  12380. diff --git a/system/settings/rbp.xml b/system/settings/rbp.xml
  12381. index 2b7d0a6..1429256 100644
  12382. --- a/system/settings/rbp.xml
  12383. +++ b/system/settings/rbp.xml
  12384. @@ -1,13 +1,6 @@
  12385. <?xml version="1.0" encoding="utf-8" ?>
  12386. <settings>
  12387. <section id="videos">
  12388. - <category id="videoplayer">
  12389. - <group id="2">
  12390. - <setting id="videoplayer.synctype">
  12391. - <visible>false</visible>
  12392. - </setting>
  12393. - </group>
  12394. - </category>
  12395. <category id="videoacceleration">
  12396. <group id="1">
  12397. <visible>false</visible>
  12398. --
  12399. 1.9.3
  12400. From 4fb1419b986a36f2e53a5bca71caf90bd13443ba Mon Sep 17 00:00:00 2001
  12401. From: popcornmix <popcornmix@gmail.com>
  12402. Date: Sun, 16 Feb 2014 17:38:05 +0000
  12403. Subject: [PATCH 51/94] [omxcodec] Only do essential calls in texture thread
  12404. [omxcodec] Fix for files with no valid pts values. [omxcodec] Fix stall on
  12405. seek/trickplay - need to reset start flag [omxcodec] Make sure we have a
  12406. valid context when video decode starts before first fanart is decoded
  12407. [omxcodec] More care with dropping frames quickly
  12408. ---
  12409. .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 127 ++++++++++++++-------
  12410. .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 14 +--
  12411. 2 files changed, 89 insertions(+), 52 deletions(-)
  12412. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  12413. index fbf1458..71d19af 100644
  12414. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  12415. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  12416. @@ -55,6 +55,9 @@
  12417. #define CLASSNAME "COpenMaxVideo"
  12418. +#define OMX_BUFFERFLAG_PTS_INVALID (1<<28)
  12419. +#define OMX_BUFFERFLAG_DROPPED (1<<29)
  12420. +
  12421. COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv)
  12422. : m_omv(omv), m_refs(0)
  12423. {
  12424. @@ -120,7 +123,9 @@ void COpenMaxVideoBuffer::Sync()
  12425. COpenMaxVideo::COpenMaxVideo()
  12426. {
  12427. + #if defined(OMX_DEBUG_VERBOSE)
  12428. CLog::Log(LOGDEBUG, "%s::%s %p", CLASSNAME, __func__, this);
  12429. + #endif
  12430. pthread_mutex_init(&m_omx_output_mutex, NULL);
  12431. m_drop_state = false;
  12432. @@ -135,6 +140,7 @@ COpenMaxVideo::COpenMaxVideo()
  12433. m_deinterlace = false;
  12434. m_deinterlace_request = VS_DEINTERLACEMODE_OFF;
  12435. m_deinterlace_second_field = false;
  12436. + m_startframe = false;
  12437. }
  12438. COpenMaxVideo::~COpenMaxVideo()
  12439. @@ -182,8 +188,6 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  12440. m_forced_aspect_ratio = hints.forced_aspect;
  12441. m_aspect_ratio = hints.aspect;
  12442. - m_egl_display = g_Windowing.GetEGLDisplay();
  12443. - m_egl_context = g_Windowing.GetEGLContext();
  12444. m_egl_buffer_count = 4;
  12445. m_codingType = OMX_VIDEO_CodingUnused;
  12446. @@ -347,6 +351,7 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  12447. return false;
  12448. m_drop_state = false;
  12449. + m_startframe = false;
  12450. return true;
  12451. }
  12452. @@ -375,6 +380,25 @@ void COpenMaxVideo::SetDropState(bool bDrop)
  12453. CLASSNAME, __func__, bDrop);
  12454. #endif
  12455. m_drop_state = bDrop;
  12456. + if (m_drop_state)
  12457. + {
  12458. + while (1)
  12459. + {
  12460. + COpenMaxVideoBuffer *buffer = NULL;
  12461. + pthread_mutex_lock(&m_omx_output_mutex);
  12462. + // fetch a output buffer and pop it off the ready list
  12463. + if (!m_omx_output_ready.empty())
  12464. + {
  12465. + buffer = m_omx_output_ready.front();
  12466. + m_omx_output_ready.pop();
  12467. + }
  12468. + pthread_mutex_unlock(&m_omx_output_mutex);
  12469. + if (buffer)
  12470. + ReturnOpenMaxBuffer(buffer);
  12471. + else
  12472. + break;
  12473. + }
  12474. + }
  12475. }
  12476. bool COpenMaxVideo::SendDecoderConfig(uint8_t *extradata, int extrasize)
  12477. @@ -713,10 +737,13 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  12478. if (demuxer_bytes == 0)
  12479. omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
  12480. - if (pts == DVD_NOPTS_VALUE)
  12481. + // openmax doesn't like an unknown timestamp as first frame
  12482. + if (pts == DVD_NOPTS_VALUE && m_startframe)
  12483. omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
  12484. + if (pts == DVD_NOPTS_VALUE) // hijack an omx flag to indicate there wasn't a real timestamp - it will be returned with the picture (but otherwise ignored)
  12485. + omx_buffer->nFlags |= OMX_BUFFERFLAG_PTS_INVALID;
  12486. if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored)
  12487. - omx_buffer->nFlags |= OMX_BUFFERFLAG_DATACORRUPT;
  12488. + omx_buffer->nFlags |= OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED;
  12489. #if defined(OMX_DEBUG_VERBOSE)
  12490. CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x",
  12491. @@ -731,10 +758,14 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  12492. }
  12493. if (demuxer_bytes == 0)
  12494. {
  12495. + m_startframe = true;
  12496. #ifdef DTS_QUEUE
  12497. - // only push if we are successful with feeding OMX_EmptyThisBuffer
  12498. - m_dts_queue.push(dts);
  12499. - assert(m_dts_queue.size() < 32);
  12500. + if (!m_drop_state)
  12501. + {
  12502. + // only push if we are successful with feeding OMX_EmptyThisBuffer
  12503. + m_dts_queue.push(dts);
  12504. + assert(m_dts_queue.size() < 32);
  12505. + }
  12506. #endif
  12507. if (buffer_to_free)
  12508. {
  12509. @@ -806,15 +837,8 @@ void COpenMaxVideo::Reset(void)
  12510. if (m_omx_decoder.IsInitialized())
  12511. m_omx_decoder.FlushAll();
  12512. // blow all ready video frames
  12513. - while (!m_omx_output_ready.empty())
  12514. - {
  12515. - pthread_mutex_lock(&m_omx_output_mutex);
  12516. - COpenMaxVideoBuffer *pic = m_omx_output_ready.front();
  12517. - m_omx_output_ready.pop();
  12518. - pthread_mutex_unlock(&m_omx_output_mutex);
  12519. - // return the omx buffer back to OpenMax to fill.
  12520. - ReturnOpenMaxBuffer(pic);
  12521. - }
  12522. + SetDropState(true);
  12523. + SetDropState(false);
  12524. #ifdef DTS_QUEUE
  12525. while (!m_dts_queue.empty())
  12526. m_dts_queue.pop();
  12527. @@ -822,6 +846,7 @@ void COpenMaxVideo::Reset(void)
  12528. while (!m_demux_queue.empty())
  12529. m_demux_queue.pop();
  12530. + m_startframe = false;
  12531. }
  12532. @@ -914,17 +939,17 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  12533. m_deinterlace_second_field = !m_deinterlace_second_field;
  12534. #endif
  12535. // nTimeStamp is in microseconds
  12536. - double ts = FromOMXTime(buffer->omx_buffer->nTimeStamp);
  12537. - pDvdVideoPicture->pts = (ts == 0) ? DVD_NOPTS_VALUE : ts;
  12538. + pDvdVideoPicture->pts = FromOMXTime(buffer->omx_buffer->nTimeStamp);
  12539. pDvdVideoPicture->openMaxBuffer->Acquire();
  12540. pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
  12541. - if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_DATACORRUPT)
  12542. - pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
  12543. + if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_PTS_INVALID)
  12544. + pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
  12545. #if defined(OMX_DEBUG_VERBOSE)
  12546. CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__,
  12547. pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6,
  12548. pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id);
  12549. #endif
  12550. + assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED)));
  12551. }
  12552. else
  12553. {
  12554. @@ -953,10 +978,11 @@ OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone(
  12555. COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate;
  12556. #if defined(OMX_DEBUG_VERBOSE)
  12557. - CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f",
  12558. - CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6);
  12559. + CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x",
  12560. + CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags);
  12561. #endif
  12562. + assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED)));
  12563. // queue output omx buffer to ready list.
  12564. pthread_mutex_lock(&m_omx_output_mutex);
  12565. buffer->m_aspect_ratio = m_aspect_ratio;
  12566. @@ -1000,41 +1026,60 @@ OMX_ERRORTYPE COpenMaxVideo::FreeOMXInputBuffers(void)
  12567. return(omx_err);
  12568. }
  12569. -bool COpenMaxVideo::CallbackAllocOMXEGLTextures(void *userdata)
  12570. +bool COpenMaxVideo::CallbackAllocOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void *userdata)
  12571. {
  12572. COpenMaxVideo *omx = static_cast<COpenMaxVideo*>(userdata);
  12573. - return omx->AllocOMXOutputEGLTextures() == OMX_ErrorNone;
  12574. + return omx->AllocOMXOutputEGLTextures(egl_display, egl_context) == OMX_ErrorNone;
  12575. }
  12576. -bool COpenMaxVideo::CallbackFreeOMXEGLTextures(void *userdata)
  12577. +bool COpenMaxVideo::CallbackFreeOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void *userdata)
  12578. {
  12579. COpenMaxVideo *omx = static_cast<COpenMaxVideo*>(userdata);
  12580. - return omx->FreeOMXOutputEGLTextures() == OMX_ErrorNone;
  12581. + return omx->FreeOMXOutputEGLTextures(egl_display, egl_context) == OMX_ErrorNone;
  12582. }
  12583. bool COpenMaxVideo::AllocOMXOutputBuffers(void)
  12584. {
  12585. - return g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this);
  12586. + pthread_mutex_lock(&m_omx_output_mutex);
  12587. + for (size_t i = 0; i < m_egl_buffer_count; i++)
  12588. + {
  12589. + COpenMaxVideoBuffer *egl_buffer = new COpenMaxVideoBuffer(this);
  12590. + egl_buffer->width = m_decoded_width;
  12591. + egl_buffer->height = m_decoded_height;
  12592. + egl_buffer->index = i;
  12593. + m_omx_output_buffers.push_back(egl_buffer);
  12594. + }
  12595. + bool ret = g_OMXImage.SendMessage(CallbackAllocOMXEGLTextures, (void *)this);
  12596. + pthread_mutex_unlock(&m_omx_output_mutex);
  12597. + return ret;
  12598. }
  12599. bool COpenMaxVideo::FreeOMXOutputBuffers(void)
  12600. {
  12601. - return g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this);
  12602. + pthread_mutex_lock(&m_omx_output_mutex);
  12603. + bool ret = g_OMXImage.SendMessage(CallbackFreeOMXEGLTextures, (void *)this);
  12604. +
  12605. + for (size_t i = 0; i < m_omx_output_buffers.size(); i++)
  12606. + {
  12607. + COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i];
  12608. + delete egl_buffer;
  12609. + }
  12610. +
  12611. + m_omx_output_buffers.clear();
  12612. + pthread_mutex_unlock(&m_omx_output_mutex);
  12613. + return ret;
  12614. }
  12615. -OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  12616. +OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context)
  12617. {
  12618. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  12619. EGLint attrib = EGL_NONE;
  12620. - COpenMaxVideoBuffer *egl_buffer;
  12621. glActiveTexture(GL_TEXTURE0);
  12622. for (size_t i = 0; i < m_egl_buffer_count; i++)
  12623. {
  12624. - egl_buffer = new COpenMaxVideoBuffer(this);
  12625. - egl_buffer->width = m_decoded_width;
  12626. - egl_buffer->height = m_decoded_height;
  12627. + COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i];
  12628. glGenTextures(1, &egl_buffer->texture_id);
  12629. glBindTexture(GL_TEXTURE_2D, egl_buffer->texture_id);
  12630. @@ -1057,8 +1102,8 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  12631. // create EGLImage from texture
  12632. egl_buffer->egl_image = eglCreateImageKHR(
  12633. - m_egl_display,
  12634. - m_egl_context,
  12635. + egl_display,
  12636. + egl_context,
  12637. EGL_GL_TEXTURE_2D_KHR,
  12638. (EGLClientBuffer)(egl_buffer->texture_id),
  12639. &attrib);
  12640. @@ -1067,7 +1112,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  12641. CLog::Log(LOGERROR, "%s::%s - ERROR creating EglImage", CLASSNAME, __func__);
  12642. return(OMX_ErrorUndefined);
  12643. }
  12644. - egl_buffer->index = i;
  12645. // tell decoder output port that it will be using EGLImage
  12646. omx_err = m_omx_egl_render.UseEGLImage(
  12647. @@ -1078,7 +1122,6 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  12648. CLASSNAME, __func__, omx_err);
  12649. return(omx_err);
  12650. }
  12651. - m_omx_output_buffers.push_back(egl_buffer);
  12652. CLog::Log(LOGDEBUG, "%s::%s - Texture %p Width %d Height %d",
  12653. CLASSNAME, __func__, egl_buffer->egl_image, egl_buffer->width, egl_buffer->height);
  12654. @@ -1086,26 +1129,22 @@ OMX_ERRORTYPE COpenMaxVideo::AllocOMXOutputEGLTextures(void)
  12655. return omx_err;
  12656. }
  12657. -OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(void)
  12658. +OMX_ERRORTYPE COpenMaxVideo::FreeOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context)
  12659. {
  12660. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  12661. - COpenMaxVideoBuffer *egl_buffer;
  12662. for (size_t i = 0; i < m_omx_output_buffers.size(); i++)
  12663. {
  12664. - egl_buffer = m_omx_output_buffers[i];
  12665. + COpenMaxVideoBuffer *egl_buffer = m_omx_output_buffers[i];
  12666. // tell decoder output port to stop using the EGLImage
  12667. omx_err = m_omx_egl_render.FreeOutputBuffer(egl_buffer->omx_buffer);
  12668. if (omx_err != OMX_ErrorNone)
  12669. CLog::Log(LOGERROR, "%s::%s m_omx_egl_render.FreeOutputBuffer(%p) omx_err(0x%08x)", CLASSNAME, __func__, egl_buffer->omx_buffer, omx_err);
  12670. // destroy egl_image
  12671. - eglDestroyImageKHR(m_egl_display, egl_buffer->egl_image);
  12672. + eglDestroyImageKHR(egl_display, egl_buffer->egl_image);
  12673. // free texture
  12674. glDeleteTextures(1, &egl_buffer->texture_id);
  12675. - delete egl_buffer;
  12676. }
  12677. - m_omx_output_buffers.clear();
  12678. -
  12679. return omx_err;
  12680. }
  12681. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  12682. index c8ad4d8..f234f6d 100644
  12683. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  12684. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  12685. @@ -99,17 +99,13 @@ class COpenMaxVideo
  12686. OMX_ERRORTYPE FreeOMXInputBuffers(void);
  12687. bool AllocOMXOutputBuffers(void);
  12688. bool FreeOMXOutputBuffers(void);
  12689. - static bool CallbackAllocOMXEGLTextures(void*);
  12690. - OMX_ERRORTYPE AllocOMXOutputEGLTextures(void);
  12691. - static bool CallbackFreeOMXEGLTextures(void*);
  12692. - OMX_ERRORTYPE FreeOMXOutputEGLTextures(void);
  12693. + static bool CallbackAllocOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void*);
  12694. + OMX_ERRORTYPE AllocOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context);
  12695. + static bool CallbackFreeOMXEGLTextures(EGLDisplay egl_display, EGLContext egl_context, void*);
  12696. + OMX_ERRORTYPE FreeOMXOutputEGLTextures(EGLDisplay egl_display, EGLContext egl_context);
  12697. OMX_ERRORTYPE StopDecoder(void);
  12698. OMX_ERRORTYPE ReturnOpenMaxBuffer(COpenMaxVideoBuffer *buffer);
  12699. - // EGL Resources
  12700. - EGLDisplay m_egl_display;
  12701. - EGLContext m_egl_context;
  12702. -
  12703. // Video format
  12704. bool m_drop_state;
  12705. int m_decoded_width;
  12706. @@ -148,6 +144,8 @@ class COpenMaxVideo
  12707. EDEINTERLACEMODE m_deinterlace_request;
  12708. bool m_deinterlace_second_field;
  12709. + bool m_startframe;
  12710. +
  12711. bool PortSettingsChanged();
  12712. bool SendDecoderConfig(uint8_t *extradata, int extrasize);
  12713. bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize);
  12714. --
  12715. 1.9.3
  12716. From 182b137323347482bfca46dbb857813e4f984298 Mon Sep 17 00:00:00 2001
  12717. From: popcornmix <popcornmix@gmail.com>
  12718. Date: Sat, 1 Mar 2014 14:24:08 +0000
  12719. Subject: [PATCH 52/94] [omxplayer] Allow small audio packets to be
  12720. concatenated to make better use of audio fifo
  12721. Some audio codecs produce small packets which causes a high overhead when submitting to GPU, and doesn't make full use of GPU side buffering.
  12722. TrueHD in particular can produce packets with 40 samples (so 1200 packets per second) which causes very high overhead.
  12723. What this aims to do is to concatenate audio packets until they approach the ideal audio packet size,
  12724. and then deal with the awkardness of concatenated planar formats.
  12725. ---
  12726. xbmc/cores/omxplayer/OMXAudio.cpp | 67 +++++++++++++++++++---------
  12727. xbmc/cores/omxplayer/OMXAudio.h | 3 +-
  12728. xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 72 +++++++++++++++++++++----------
  12729. xbmc/cores/omxplayer/OMXAudioCodecOMX.h | 9 +++-
  12730. xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 9 ++--
  12731. 5 files changed, 110 insertions(+), 50 deletions(-)
  12732. diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
  12733. index dd80412..e67dc94 100644
  12734. --- a/xbmc/cores/omxplayer/OMXAudio.cpp
  12735. +++ b/xbmc/cores/omxplayer/OMXAudio.cpp
  12736. @@ -43,6 +43,10 @@
  12737. using namespace std;
  12738. +// the size of the audio_render output port buffers
  12739. +#define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
  12740. +static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3};
  12741. +
  12742. static const uint16_t AC3Bitrates[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
  12743. static const uint16_t AC3FSCod [] = {48000, 44100, 32000, 0};
  12744. @@ -61,6 +65,7 @@ COMXAudio::COMXAudio() :
  12745. m_Passthrough (false ),
  12746. m_HWDecode (false ),
  12747. m_BytesPerSec (0 ),
  12748. + m_InputBytesPerSec(0 ),
  12749. m_BufferLen (0 ),
  12750. m_ChunkLen (0 ),
  12751. m_InputChannels (0 ),
  12752. @@ -490,11 +495,15 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
  12753. m_SampleRate = m_format.m_sampleRate;
  12754. m_BitsPerSample = CAEUtil::DataFormatToBits(m_format.m_dataFormat);
  12755. - m_BufferLen = m_BytesPerSec = m_format.m_sampleRate * (16 >> 3) * m_InputChannels;
  12756. - m_BufferLen *= AUDIO_BUFFER_SECONDS;
  12757. + m_BytesPerSec = m_SampleRate * 2 << rounded_up_channels_shift[m_InputChannels];
  12758. + m_BufferLen = m_BytesPerSec * AUDIO_BUFFER_SECONDS;
  12759. + m_InputBytesPerSec = m_SampleRate * m_BitsPerSample * m_InputChannels >> 3;
  12760. +
  12761. + // should be big enough that common formats (e.g. 6 channel DTS) fit in a single packet.
  12762. + // we don't mind less common formats being split (e.g. ape/wma output large frames)
  12763. // the audio_decode output buffer size is 32K, and typically we convert from
  12764. - // 6 channel 32bpp float to 8 channel 16bpp in, so a full 48K input buffer will fit the outbut buffer
  12765. - m_ChunkLen = 48*1024;
  12766. + // 6 channel 32bpp float to 8 channel 16bpp in, so a full 48K input buffer will fit the output buffer
  12767. + m_ChunkLen = AUDIO_DECODE_OUTPUT_BUFFER * (m_InputChannels * m_BitsPerSample) >> (rounded_up_channels_shift[m_InputChannels] + 4);
  12768. m_wave_header.Samples.wSamplesPerBlock = 0;
  12769. m_wave_header.Format.nChannels = m_InputChannels;
  12770. @@ -682,7 +691,7 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
  12771. m_maxLevel = 0.0f;
  12772. CLog::Log(LOGDEBUG, "COMXAudio::Initialize Input bps %d samplerate %d channels %d buffer size %d bytes per second %d",
  12773. - (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_BytesPerSec);
  12774. + (int)m_pcm_input.nBitPerSample, (int)m_pcm_input.nSamplingRate, (int)m_pcm_input.nChannels, m_BufferLen, m_InputBytesPerSec);
  12775. PrintPCM(&m_pcm_input, std::string("input"));
  12776. CLog::Log(LOGDEBUG, "COMXAudio::Initialize device passthrough %d hwdecode %d",
  12777. m_Passthrough, m_HWDecode);
  12778. @@ -865,11 +874,11 @@ bool COMXAudio::ApplyVolume(void)
  12779. //***********************************************************************************************
  12780. unsigned int COMXAudio::AddPackets(const void* data, unsigned int len)
  12781. {
  12782. - return AddPackets(data, len, 0, 0);
  12783. + return AddPackets(data, len, 0, 0, 0);
  12784. }
  12785. //***********************************************************************************************
  12786. -unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts)
  12787. +unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dts, double pts, unsigned int frame_size)
  12788. {
  12789. CSingleLock lock (m_critSection);
  12790. @@ -916,24 +925,40 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt
  12791. omx_buffer->nOffset = 0;
  12792. omx_buffer->nFlags = 0;
  12793. + // we want audio_decode output buffer size to be no more than AUDIO_DECODE_OUTPUT_BUFFER.
  12794. + // it will be 16-bit and rounded up to next power of 2 in channels
  12795. + unsigned int max_buffer = AUDIO_DECODE_OUTPUT_BUFFER * (m_InputChannels * m_BitsPerSample) >> (rounded_up_channels_shift[m_InputChannels] + 4);
  12796. +
  12797. unsigned int remaining = demuxer_samples-demuxer_samples_sent;
  12798. - unsigned int samples_space = omx_buffer->nAllocLen/pitch;
  12799. + unsigned int samples_space = std::min(max_buffer, omx_buffer->nAllocLen)/pitch;
  12800. unsigned int samples = std::min(remaining, samples_space);
  12801. omx_buffer->nFilledLen = samples * pitch;
  12802. - if (samples < demuxer_samples && m_BitsPerSample==32 && !(m_Passthrough || m_HWDecode))
  12803. + unsigned int frames = frame_size ? len/frame_size:0;
  12804. + if ((samples < demuxer_samples || frames > 1) && m_BitsPerSample==32 && !(m_Passthrough || m_HWDecode))
  12805. {
  12806. - uint8_t *dst = omx_buffer->pBuffer;
  12807. - uint8_t *src = demuxer_content + demuxer_samples_sent * (m_BitsPerSample >> 3);
  12808. - // we need to extract samples from planar audio, so the copying needs to be done per plane
  12809. - for (int i=0; i<(int)m_InputChannels; i++)
  12810. - {
  12811. - memcpy(dst, src, omx_buffer->nFilledLen / m_InputChannels);
  12812. - dst += omx_buffer->nFilledLen / m_InputChannels;
  12813. - src += demuxer_samples * (m_BitsPerSample >> 3);
  12814. - }
  12815. - assert(dst <= omx_buffer->pBuffer + m_ChunkLen);
  12816. + const unsigned int sample_pitch = m_BitsPerSample >> 3;
  12817. + const unsigned int frame_samples = frame_size / pitch;
  12818. + const unsigned int plane_size = frame_samples * sample_pitch;
  12819. + const unsigned int out_plane_size = samples * sample_pitch;
  12820. + //CLog::Log(LOGDEBUG, "%s::%s samples:%d/%d ps:%d ops:%d fs:%d pitch:%d filled:%d frames=%d", CLASSNAME, __func__, samples, demuxer_samples, plane_size, out_plane_size, frame_size, pitch, omx_buffer->nFilledLen, frames);
  12821. + for (unsigned int sample = 0; sample < samples; )
  12822. + {
  12823. + unsigned int frame = (demuxer_samples_sent + sample) / frame_samples;
  12824. + unsigned int sample_in_frame = (demuxer_samples_sent + sample) - frame * frame_samples;
  12825. + int out_remaining = std::min(std::min(frame_samples - sample_in_frame, samples), samples-sample);
  12826. + uint8_t *src = demuxer_content + frame*frame_size + sample_in_frame * sample_pitch;
  12827. + uint8_t *dst = (uint8_t *)omx_buffer->pBuffer + sample * sample_pitch;
  12828. + for (unsigned int channel = 0; channel < m_InputChannels; channel++)
  12829. + {
  12830. + //CLog::Log(LOGDEBUG, "%s::%s copy(%d,%d,%d) (s:%d f:%d sin:%d c:%d)", CLASSNAME, __func__, dst-(uint8_t *)omx_buffer->pBuffer, src-demuxer_content, out_remaining, sample, frame, sample_in_frame, channel);
  12831. + memcpy(dst, src, out_remaining * sample_pitch);
  12832. + src += plane_size;
  12833. + dst += out_plane_size;
  12834. + }
  12835. + sample += out_remaining;
  12836. + }
  12837. }
  12838. else
  12839. {
  12840. @@ -1114,7 +1139,9 @@ float COMXAudio::GetCacheTime()
  12841. float COMXAudio::GetCacheTotal()
  12842. {
  12843. - return m_BytesPerSec ? (float)m_BufferLen / (float)m_BytesPerSec : 0.0f;
  12844. + float audioplus_buffer = m_SampleRate ? 0.0f : 32.0f * 512.0f / m_SampleRate;
  12845. + float input_buffer = (float)m_omx_decoder.GetInputBufferSize() / (float)m_InputBytesPerSec;
  12846. + return AUDIO_BUFFER_SECONDS + input_buffer + audioplus_buffer;
  12847. }
  12848. //***********************************************************************************************
  12849. diff --git a/xbmc/cores/omxplayer/OMXAudio.h b/xbmc/cores/omxplayer/OMXAudio.h
  12850. index 804bd2a..b0264d8 100644
  12851. --- a/xbmc/cores/omxplayer/OMXAudio.h
  12852. +++ b/xbmc/cores/omxplayer/OMXAudio.h
  12853. @@ -66,7 +66,7 @@ class COMXAudio
  12854. ~COMXAudio();
  12855. unsigned int AddPackets(const void* data, unsigned int len);
  12856. - unsigned int AddPackets(const void* data, unsigned int len, double dts, double pts);
  12857. + unsigned int AddPackets(const void* data, unsigned int len, double dts, double pts, unsigned int frame_size);
  12858. unsigned int GetSpace();
  12859. bool Deinitialize();
  12860. @@ -114,6 +114,7 @@ class COMXAudio
  12861. bool m_Passthrough;
  12862. bool m_HWDecode;
  12863. unsigned int m_BytesPerSec;
  12864. + unsigned int m_InputBytesPerSec;
  12865. unsigned int m_BufferLen;
  12866. unsigned int m_ChunkLen;
  12867. unsigned int m_InputChannels;
  12868. diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  12869. index 5503a0e..557e847 100644
  12870. --- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  12871. +++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  12872. @@ -26,10 +26,15 @@
  12873. #include "cores/AudioEngine/Utils/AEUtil.h"
  12874. +// the size of the audio_render output port buffers
  12875. +#define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
  12876. +static const char rounded_up_channels_shift[] = {0,0,1,2,2,3,3,3,3};
  12877. +
  12878. COMXAudioCodecOMX::COMXAudioCodecOMX()
  12879. {
  12880. m_pBufferOutput = NULL;
  12881. m_iBufferOutputAlloced = 0;
  12882. + m_iBufferOutputUsed = 0;
  12883. m_pCodecContext = NULL;
  12884. m_pConvert = NULL;
  12885. @@ -37,7 +42,10 @@ COMXAudioCodecOMX::COMXAudioCodecOMX()
  12886. m_channels = 0;
  12887. m_pFrame1 = NULL;
  12888. + m_frameSize = 0;
  12889. m_bGotFrame = false;
  12890. + m_bNoConcatenate = false;
  12891. +
  12892. m_iSampleFormat = AV_SAMPLE_FMT_NONE;
  12893. m_desiredSampleFormat = AV_SAMPLE_FMT_NONE;
  12894. }
  12895. @@ -47,6 +55,7 @@ COMXAudioCodecOMX::~COMXAudioCodecOMX()
  12896. m_dllAvUtil.av_free(m_pBufferOutput);
  12897. m_pBufferOutput = NULL;
  12898. m_iBufferOutputAlloced = 0;
  12899. + m_iBufferOutputUsed = 0;
  12900. Dispose();
  12901. }
  12902. @@ -83,6 +92,10 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints)
  12903. m_pCodecContext->bit_rate = hints.bitrate;
  12904. m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
  12905. + // vorbis has variable sized planar output, so skip concatenation
  12906. + if (hints.codec == AV_CODEC_ID_VORBIS)
  12907. + m_bNoConcatenate = true;
  12908. +
  12909. if(m_pCodecContext->bits_per_coded_sample == 0)
  12910. m_pCodecContext->bits_per_coded_sample = 16;
  12911. @@ -132,7 +145,7 @@ void COMXAudioCodecOMX::Dispose()
  12912. m_bGotFrame = false;
  12913. }
  12914. -int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize)
  12915. +int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize, double dts, double pts)
  12916. {
  12917. int iBytesUsed, got_frame;
  12918. if (!m_pCodecContext) return -1;
  12919. @@ -167,10 +180,15 @@ int COMXAudioCodecOMX::Decode(BYTE* pData, int iSize)
  12920. }
  12921. m_bGotFrame = true;
  12922. + if (!m_iBufferOutputUsed)
  12923. + {
  12924. + m_dts = dts;
  12925. + m_pts = pts;
  12926. + }
  12927. return iBytesUsed;
  12928. }
  12929. -int COMXAudioCodecOMX::GetData(BYTE** dst)
  12930. +int COMXAudioCodecOMX::GetData(BYTE** dst, double &dts, double &pts)
  12931. {
  12932. if (!m_bGotFrame)
  12933. return 0;
  12934. @@ -179,13 +197,11 @@ int COMXAudioCodecOMX::GetData(BYTE** dst)
  12935. int inputSize = m_dllAvUtil.av_samples_get_buffer_size(&inLineSize, m_pCodecContext->channels, m_pFrame1->nb_samples, m_pCodecContext->sample_fmt, 0);
  12936. /* output audio will be packed */
  12937. int outputSize = m_dllAvUtil.av_samples_get_buffer_size(&outLineSize, m_pCodecContext->channels, m_pFrame1->nb_samples, m_desiredSampleFormat, 1);
  12938. - bool cont = !m_pFrame1->data[1] || (m_pFrame1->data[1] == m_pFrame1->data[0] + inLineSize && inLineSize == outLineSize && inLineSize * m_pCodecContext->channels == inputSize);
  12939. - if (m_iBufferOutputAlloced < outputSize)
  12940. + if (m_iBufferOutputAlloced < m_iBufferOutputUsed + outputSize)
  12941. {
  12942. - m_dllAvUtil.av_free(m_pBufferOutput);
  12943. - m_pBufferOutput = (BYTE*)m_dllAvUtil.av_malloc(outputSize + FF_INPUT_BUFFER_PADDING_SIZE);
  12944. - m_iBufferOutputAlloced = outputSize;
  12945. + m_pBufferOutput = (BYTE*)m_dllAvUtil.av_realloc(m_pBufferOutput, m_iBufferOutputUsed + outputSize + FF_INPUT_BUFFER_PADDING_SIZE);
  12946. + m_iBufferOutputAlloced = m_iBufferOutputUsed + outputSize;
  12947. }
  12948. *dst = m_pBufferOutput;
  12949. @@ -217,7 +233,7 @@ int COMXAudioCodecOMX::GetData(BYTE** dst)
  12950. /* use unaligned flag to keep output packed */
  12951. uint8_t *out_planes[m_pCodecContext->channels];
  12952. - if(m_dllAvUtil.av_samples_fill_arrays(out_planes, NULL, m_pBufferOutput, m_pCodecContext->channels, m_pFrame1->nb_samples, m_desiredSampleFormat, 1) < 0 ||
  12953. + if(m_dllAvUtil.av_samples_fill_arrays(out_planes, NULL, m_pBufferOutput + m_iBufferOutputUsed, m_pCodecContext->channels, m_pFrame1->nb_samples, m_desiredSampleFormat, 1) < 0 ||
  12954. m_dllSwResample.swr_convert(m_pConvert, out_planes, m_pFrame1->nb_samples, (const uint8_t **)m_pFrame1->data, m_pFrame1->nb_samples) < 0)
  12955. {
  12956. CLog::Log(LOGERROR, "COMXAudioCodecOMX::Decode - Unable to convert format %d to %d", (int)m_pCodecContext->sample_fmt, m_desiredSampleFormat);
  12957. @@ -226,35 +242,45 @@ int COMXAudioCodecOMX::GetData(BYTE** dst)
  12958. }
  12959. else
  12960. {
  12961. - /* if it is already contiguous, just return decoded frame */
  12962. - if (cont)
  12963. - {
  12964. - *dst = m_pFrame1->data[0];
  12965. - }
  12966. - else
  12967. + /* copy to a contiguous buffer */
  12968. + uint8_t *out_planes[m_pCodecContext->channels];
  12969. + if (m_dllAvUtil.av_samples_fill_arrays(out_planes, NULL, m_pBufferOutput + m_iBufferOutputUsed, m_pCodecContext->channels, m_pFrame1->nb_samples, m_desiredSampleFormat, 1) < 0 ||
  12970. + m_dllAvUtil.av_samples_copy(out_planes, m_pFrame1->data, 0, 0, m_pFrame1->nb_samples, m_pCodecContext->channels, m_desiredSampleFormat) < 0 )
  12971. {
  12972. - /* copy to a contiguous buffer */
  12973. - uint8_t *out_planes[m_pCodecContext->channels];
  12974. - if (m_dllAvUtil.av_samples_fill_arrays(out_planes, NULL, m_pBufferOutput, m_pCodecContext->channels, m_pFrame1->nb_samples, m_desiredSampleFormat, 1) < 0 ||
  12975. - m_dllAvUtil.av_samples_copy(out_planes, m_pFrame1->data, 0, 0, m_pFrame1->nb_samples, m_pCodecContext->channels, m_desiredSampleFormat) < 0 )
  12976. - {
  12977. - outputSize = 0;
  12978. - }
  12979. + outputSize = 0;
  12980. }
  12981. }
  12982. + int desired_size = AUDIO_DECODE_OUTPUT_BUFFER * (m_pCodecContext->channels * GetBitsPerSample()) >> (rounded_up_channels_shift[m_pCodecContext->channels] + 4);
  12983. if (m_bFirstFrame)
  12984. {
  12985. - CLog::Log(LOGDEBUG, "COMXAudioCodecOMX::GetData size=%d/%d line=%d/%d cont=%d buf=%p", inputSize, outputSize, inLineSize, outLineSize, cont, *dst);
  12986. + CLog::Log(LOGDEBUG, "COMXAudioCodecOMX::GetData size=%d/%d line=%d/%d buf=%p, desired=%d", inputSize, outputSize, inLineSize, outLineSize, *dst, desired_size);
  12987. m_bFirstFrame = false;
  12988. }
  12989. - return outputSize;
  12990. + m_iBufferOutputUsed += outputSize;
  12991. +
  12992. + if (!m_bNoConcatenate && m_pCodecContext->sample_fmt == AV_SAMPLE_FMT_FLTP && m_frameSize && (int)m_frameSize != outputSize)
  12993. + CLog::Log(LOGERROR, "COMXAudioCodecOMX::GetData Unexpected change of size (%d->%d)", m_frameSize, outputSize);
  12994. + m_frameSize = outputSize;
  12995. +
  12996. + // if next buffer submitted won't fit then flush it out
  12997. + if (m_iBufferOutputUsed + outputSize > desired_size || m_bNoConcatenate)
  12998. + {
  12999. + int ret = m_iBufferOutputUsed;
  13000. + m_bGotFrame = false;
  13001. + m_iBufferOutputUsed = 0;
  13002. + dts = m_dts;
  13003. + pts = m_pts;
  13004. + return ret;
  13005. + }
  13006. + return 0;
  13007. }
  13008. void COMXAudioCodecOMX::Reset()
  13009. {
  13010. if (m_pCodecContext) m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
  13011. m_bGotFrame = false;
  13012. + m_iBufferOutputUsed = 0;
  13013. }
  13014. int COMXAudioCodecOMX::GetChannels()
  13015. diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  13016. index 343465c..66e5b4a 100644
  13017. --- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  13018. +++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  13019. @@ -36,8 +36,8 @@ class COMXAudioCodecOMX
  13020. virtual ~COMXAudioCodecOMX();
  13021. bool Open(CDVDStreamInfo &hints);
  13022. void Dispose();
  13023. - int Decode(BYTE* pData, int iSize);
  13024. - int GetData(BYTE** dst);
  13025. + int Decode(BYTE* pData, int iSize, double dts, double pts);
  13026. + int GetData(BYTE** dst, double &dts, double &pts);
  13027. void Reset();
  13028. int GetChannels();
  13029. uint64_t GetChannelMap();
  13030. @@ -45,6 +45,7 @@ class COMXAudioCodecOMX
  13031. int GetBitsPerSample();
  13032. static const char* GetName() { return "FFmpeg"; }
  13033. int GetBitRate();
  13034. + unsigned int GetFrameSize() { return m_frameSize; }
  13035. protected:
  13036. AVCodecContext* m_pCodecContext;
  13037. @@ -55,6 +56,7 @@ class COMXAudioCodecOMX
  13038. AVFrame* m_pFrame1;
  13039. BYTE *m_pBufferOutput;
  13040. + int m_iBufferOutputUsed;
  13041. int m_iBufferOutputAlloced;
  13042. bool m_bOpenedCodec;
  13043. @@ -63,6 +65,9 @@ class COMXAudioCodecOMX
  13044. bool m_bFirstFrame;
  13045. bool m_bGotFrame;
  13046. + bool m_bNoConcatenate;
  13047. + unsigned int m_frameSize;
  13048. + double m_dts, m_pts;
  13049. DllAvCodec m_dllAvCodec;
  13050. DllAvUtil m_dllAvUtil;
  13051. DllSwResample m_dllSwResample;
  13052. diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  13053. index 8219015..a4c11777 100644
  13054. --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  13055. +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  13056. @@ -227,9 +227,10 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
  13057. if(!OMX_IS_RAW(m_format.m_dataFormat) && !bDropPacket)
  13058. {
  13059. + double dts = pkt->dts, pts=pkt->pts;
  13060. while(!m_bStop && data_len > 0)
  13061. {
  13062. - int len = m_pAudioCodec->Decode((BYTE *)data_dec, data_len);
  13063. + int len = m_pAudioCodec->Decode((BYTE *)data_dec, data_len, dts, pts);
  13064. if( (len < 0) || (len > data_len) )
  13065. {
  13066. m_pAudioCodec->Reset();
  13067. @@ -240,7 +241,7 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
  13068. data_len -= len;
  13069. uint8_t *decoded;
  13070. - int decoded_size = m_pAudioCodec->GetData(&decoded);
  13071. + int decoded_size = m_pAudioCodec->GetData(&decoded, dts, pts);
  13072. if(decoded_size <=0)
  13073. continue;
  13074. @@ -274,7 +275,7 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
  13075. if(m_silence)
  13076. memset(decoded, 0x0, decoded_size);
  13077. - ret = m_omxAudio.AddPackets(decoded, decoded_size, m_audioClock, m_audioClock);
  13078. + ret = m_omxAudio.AddPackets(decoded, decoded_size, dts, pts, m_pAudioCodec->GetFrameSize());
  13079. if(ret != decoded_size)
  13080. {
  13081. @@ -312,7 +313,7 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
  13082. if(m_silence)
  13083. memset(pkt->pData, 0x0, pkt->iSize);
  13084. - m_omxAudio.AddPackets(pkt->pData, pkt->iSize, m_audioClock, m_audioClock);
  13085. + m_omxAudio.AddPackets(pkt->pData, pkt->iSize, m_audioClock, m_audioClock, 0);
  13086. }
  13087. m_audioStats.AddSampleBytes(pkt->iSize);
  13088. --
  13089. 1.9.3
  13090. From 10a9d6134a624bf59096831851ee12191f658da1 Mon Sep 17 00:00:00 2001
  13091. From: popcornmix <popcornmix@gmail.com>
  13092. Date: Wed, 5 Mar 2014 22:10:01 +0000
  13093. Subject: [PATCH 53/94] [omxplayer] Use media for determing audio delay and
  13094. cache time
  13095. I've also added caching to the call to OMXMediaTime as the GPU round trip is expensive when called too frequently
  13096. ---
  13097. xbmc/cores/omxplayer/OMXAudio.cpp | 33 ++++++++++++++-------
  13098. xbmc/linux/OMXClock.cpp | 62 +++++++++++++++++++++++++++------------
  13099. xbmc/linux/OMXClock.h | 2 ++
  13100. 3 files changed, 68 insertions(+), 29 deletions(-)
  13101. diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
  13102. index e67dc94..3e64de0 100644
  13103. --- a/xbmc/cores/omxplayer/OMXAudio.cpp
  13104. +++ b/xbmc/cores/omxplayer/OMXAudio.cpp
  13105. @@ -1118,29 +1118,40 @@ void COMXAudio::UpdateAttenuation()
  13106. //***********************************************************************************************
  13107. unsigned int COMXAudio::GetSpace()
  13108. {
  13109. - int free = m_omx_decoder.GetInputBufferSpace();
  13110. - return free;
  13111. + return m_omx_decoder.GetInputBufferSpace();
  13112. }
  13113. float COMXAudio::GetDelay()
  13114. {
  13115. - unsigned int free = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
  13116. - return m_BytesPerSec ? (float)free / (float)m_BytesPerSec : 0.0f;
  13117. + CSingleLock lock (m_critSection);
  13118. + double stamp = DVD_NOPTS_VALUE;
  13119. + double ret = 0.0;
  13120. + if (m_last_pts != DVD_NOPTS_VALUE && m_av_clock)
  13121. + stamp = m_av_clock->OMXMediaTime();
  13122. + // if possible the delay is current media time - time of last submitted packet
  13123. + if (stamp != DVD_NOPTS_VALUE)
  13124. + {
  13125. + ret = (m_last_pts - stamp) * (1.0 / DVD_TIME_BASE);
  13126. + //CLog::Log(LOGINFO, "%s::%s - %.2f %.0f %.0f", CLASSNAME, __func__, ret, stamp, m_last_pts);
  13127. + }
  13128. + else // just measure the input fifo
  13129. + {
  13130. + unsigned int used = m_omx_decoder.GetInputBufferSize() - m_omx_decoder.GetInputBufferSpace();
  13131. + float ret = m_InputBytesPerSec ? (float)used / (float)m_InputBytesPerSec : 0.0f;
  13132. + //CLog::Log(LOGINFO, "%s::%s - %.2f %d, %d, %d", CLASSNAME, __func__, ret, used, m_omx_decoder.GetInputBufferSize(), m_omx_decoder.GetInputBufferSpace());
  13133. + }
  13134. + return ret;
  13135. }
  13136. float COMXAudio::GetCacheTime()
  13137. {
  13138. - float fBufferLenFull = (float)m_BufferLen - (float)GetSpace();
  13139. - if(fBufferLenFull < 0)
  13140. - fBufferLenFull = 0;
  13141. - float ret = m_BytesPerSec ? fBufferLenFull / (float)m_BytesPerSec : 0.0f;
  13142. - return ret;
  13143. + return GetDelay();
  13144. }
  13145. float COMXAudio::GetCacheTotal()
  13146. {
  13147. - float audioplus_buffer = m_SampleRate ? 0.0f : 32.0f * 512.0f / m_SampleRate;
  13148. - float input_buffer = (float)m_omx_decoder.GetInputBufferSize() / (float)m_InputBytesPerSec;
  13149. + float audioplus_buffer = m_SampleRate ? 32.0f * 512.0f / m_SampleRate : 0.0f;
  13150. + float input_buffer = m_InputBytesPerSec ? (float)m_omx_decoder.GetInputBufferSize() / (float)m_InputBytesPerSec : 0;
  13151. return AUDIO_BUFFER_SECONDS + input_buffer + audioplus_buffer;
  13152. }
  13153. diff --git a/xbmc/linux/OMXClock.cpp b/xbmc/linux/OMXClock.cpp
  13154. index 241657b..bee7bac 100644
  13155. --- a/xbmc/linux/OMXClock.cpp
  13156. +++ b/xbmc/linux/OMXClock.cpp
  13157. @@ -45,6 +45,8 @@ OMXClock::OMXClock()
  13158. m_eState = OMX_TIME_ClockStateStopped;
  13159. m_eClock = OMX_TIME_RefClockNone;
  13160. m_clock = NULL;
  13161. + m_last_media_time = 0.0f;
  13162. + m_last_media_time_read = 0.0f;
  13163. pthread_mutex_init(&m_lock, NULL);
  13164. }
  13165. @@ -113,6 +115,7 @@ bool OMXClock::OMXSetReferenceClock(bool has_audio, bool lock /* = true */)
  13166. }
  13167. m_eClock = refClock.eClock;
  13168. }
  13169. + m_last_media_time = 0.0f;
  13170. if(lock)
  13171. UnLock();
  13172. @@ -142,6 +145,7 @@ void OMXClock::OMXDeinitialize()
  13173. m_omx_clock.Deinitialize();
  13174. m_omx_speed = DVD_PLAYSPEED_NORMAL;
  13175. + m_last_media_time = 0.0f;
  13176. }
  13177. bool OMXClock::OMXStateExecute(bool lock /* = true */)
  13178. @@ -169,6 +173,7 @@ bool OMXClock::OMXStateExecute(bool lock /* = true */)
  13179. }
  13180. }
  13181. + m_last_media_time = 0.0f;
  13182. if(lock)
  13183. UnLock();
  13184. @@ -186,6 +191,7 @@ void OMXClock::OMXStateIdle(bool lock /* = true */)
  13185. if(m_omx_clock.GetState() != OMX_StateIdle)
  13186. m_omx_clock.SetStateForComponent(OMX_StateIdle);
  13187. + m_last_media_time = 0.0f;
  13188. if(lock)
  13189. UnLock();
  13190. }
  13191. @@ -222,6 +228,7 @@ bool OMXClock::OMXStop(bool lock /* = true */)
  13192. }
  13193. m_eState = clock.eState;
  13194. + m_last_media_time = 0.0f;
  13195. if(lock)
  13196. UnLock();
  13197. @@ -252,6 +259,7 @@ bool OMXClock::OMXStep(int steps /* = 1 */, bool lock /* = true */)
  13198. return false;
  13199. }
  13200. + m_last_media_time = 0.0f;
  13201. if(lock)
  13202. UnLock();
  13203. @@ -302,6 +310,7 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
  13204. }
  13205. }
  13206. + m_last_media_time = 0.0f;
  13207. if(lock)
  13208. UnLock();
  13209. @@ -310,33 +319,45 @@ bool OMXClock::OMXReset(bool has_video, bool has_audio, bool lock /* = true */)
  13210. double OMXClock::OMXMediaTime(bool lock /* = true */)
  13211. {
  13212. + double pts = 0.0;
  13213. if(m_omx_clock.GetComponent() == NULL)
  13214. return 0;
  13215. - if(lock)
  13216. - Lock();
  13217. + double now = GetAbsoluteClock();
  13218. + if (now - m_last_media_time_read > DVD_MSEC_TO_TIME(100) || m_last_media_time == 0.0)
  13219. + {
  13220. + if(lock)
  13221. + Lock();
  13222. - OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  13223. - double pts = 0;
  13224. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  13225. - OMX_TIME_CONFIG_TIMESTAMPTYPE timeStamp;
  13226. - OMX_INIT_STRUCTURE(timeStamp);
  13227. - timeStamp.nPortIndex = m_omx_clock.GetInputPort();
  13228. + OMX_TIME_CONFIG_TIMESTAMPTYPE timeStamp;
  13229. + OMX_INIT_STRUCTURE(timeStamp);
  13230. + timeStamp.nPortIndex = m_omx_clock.GetInputPort();
  13231. +
  13232. + omx_err = m_omx_clock.GetConfig(OMX_IndexConfigTimeCurrentMediaTime, &timeStamp);
  13233. + if(omx_err != OMX_ErrorNone)
  13234. + {
  13235. + CLog::Log(LOGERROR, "OMXClock::MediaTime error getting OMX_IndexConfigTimeCurrentMediaTime\n");
  13236. + if(lock)
  13237. + UnLock();
  13238. + return 0;
  13239. + }
  13240. +
  13241. + pts = FromOMXTime(timeStamp.nTimestamp);
  13242. + //CLog::Log(LOGINFO, "OMXClock::MediaTime %.2f (%.2f, %.2f)", pts, m_last_media_time, now - m_last_media_time_read);
  13243. + m_last_media_time = pts;
  13244. + m_last_media_time_read = now;
  13245. - omx_err = m_omx_clock.GetConfig(OMX_IndexConfigTimeCurrentMediaTime, &timeStamp);
  13246. - if(omx_err != OMX_ErrorNone)
  13247. - {
  13248. - CLog::Log(LOGERROR, "OMXClock::MediaTime error getting OMX_IndexConfigTimeCurrentMediaTime\n");
  13249. if(lock)
  13250. UnLock();
  13251. - return 0;
  13252. }
  13253. -
  13254. - pts = FromOMXTime(timeStamp.nTimestamp);
  13255. -
  13256. - if(lock)
  13257. - UnLock();
  13258. -
  13259. + else
  13260. + {
  13261. + double speed = m_pause ? 0.0 : (double)m_omx_speed / DVD_PLAYSPEED_NORMAL;
  13262. + pts = m_last_media_time + (now - m_last_media_time_read) * speed;
  13263. + //CLog::Log(LOGINFO, "OMXClock::MediaTime cached %.2f (%.2f, %.2f)", pts, m_last_media_time, now - m_last_media_time_read);
  13264. + }
  13265. return pts;
  13266. }
  13267. @@ -409,6 +430,7 @@ bool OMXClock::OMXMediaTime(double pts, bool lock /* = true*/)
  13268. CLog::Log(LOGDEBUG, "OMXClock::OMXMediaTime set config %s = %.2f", index == OMX_IndexConfigTimeCurrentAudioReference ?
  13269. "OMX_IndexConfigTimeCurrentAudioReference":"OMX_IndexConfigTimeCurrentVideoReference", pts);
  13270. + m_last_media_time = 0.0f;
  13271. if(lock)
  13272. UnLock();
  13273. @@ -428,6 +450,7 @@ bool OMXClock::OMXPause(bool lock /* = true */)
  13274. if (OMXSetSpeed(0, false, true))
  13275. m_pause = true;
  13276. + m_last_media_time = 0.0f;
  13277. if(lock)
  13278. UnLock();
  13279. }
  13280. @@ -447,6 +470,7 @@ bool OMXClock::OMXResume(bool lock /* = true */)
  13281. if (OMXSetSpeed(m_omx_speed, false, true))
  13282. m_pause = false;
  13283. + m_last_media_time = 0.0f;
  13284. if(lock)
  13285. UnLock();
  13286. }
  13287. @@ -485,6 +509,7 @@ bool OMXClock::OMXSetSpeed(int speed, bool lock /* = true */, bool pause_resume
  13288. if (!pause_resume)
  13289. m_omx_speed = speed;
  13290. + m_last_media_time = 0.0f;
  13291. if(lock)
  13292. UnLock();
  13293. @@ -521,6 +546,7 @@ bool OMXClock::HDMIClockSync(bool lock /* = true */)
  13294. return false;
  13295. }
  13296. + m_last_media_time = 0.0f;
  13297. if(lock)
  13298. UnLock();
  13299. diff --git a/xbmc/linux/OMXClock.h b/xbmc/linux/OMXClock.h
  13300. index d7d06fe..f83074a 100644
  13301. --- a/xbmc/linux/OMXClock.h
  13302. +++ b/xbmc/linux/OMXClock.h
  13303. @@ -58,6 +58,8 @@ class OMXClock
  13304. CDVDClock *m_clock;
  13305. private:
  13306. COMXCoreComponent m_omx_clock;
  13307. + double m_last_media_time;
  13308. + double m_last_media_time_read;
  13309. public:
  13310. OMXClock();
  13311. ~OMXClock();
  13312. --
  13313. 1.9.3
  13314. From 29c5c42b2f5be546c242bc8ef02dc06a8dd0fd17 Mon Sep 17 00:00:00 2001
  13315. From: popcornmix <popcornmix@gmail.com>
  13316. Date: Mon, 3 Mar 2014 22:24:19 +0000
  13317. Subject: [PATCH 54/94] [omx] Skip the resize when not needed when decoding
  13318. jpegs
  13319. The decode to texture path almost always uses cached jpegs that are the correct size, so the resize is rarely needed.
  13320. The re-enc path usually needs resizing, but may not where the source is small.
  13321. Skipping the resize stage saves a little time and memory on GPU and also saves some setup time.
  13322. ---
  13323. xbmc/cores/omxplayer/OMXImage.cpp | 262 ++++++++++++++++++++++----------------
  13324. 1 file changed, 152 insertions(+), 110 deletions(-)
  13325. diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp
  13326. index 4456fdb..262a004 100644
  13327. --- a/xbmc/cores/omxplayer/OMXImage.cpp
  13328. +++ b/xbmc/cores/omxplayer/OMXImage.cpp
  13329. @@ -1477,9 +1477,22 @@ bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned
  13330. return false;
  13331. }
  13332. + if (resize_width != port_def.format.image.nFrameWidth || resize_height != port_def.format.image.nFrameHeight || (orientation & 4))
  13333. + {
  13334. + if(!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit))
  13335. + {
  13336. + CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__);
  13337. + return false;
  13338. + }
  13339. + }
  13340. +
  13341. // TODO: jpeg decoder can decimate by factors of 2
  13342. port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
  13343. - port_def.format.image.nSliceHeight = 16;//(port_def.format.image.nFrameHeight+15) & ~15;
  13344. + if (m_omx_resize.IsInitialized())
  13345. + port_def.format.image.nSliceHeight = 16;
  13346. + else
  13347. + port_def.format.image.nSliceHeight = (resize_height+15) & ~15;
  13348. +
  13349. port_def.format.image.nStride = 0;
  13350. m_omx_decoder.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13351. @@ -1489,38 +1502,35 @@ bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned
  13352. return false;
  13353. }
  13354. - if(!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit))
  13355. + if (m_omx_resize.IsInitialized())
  13356. {
  13357. - CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize\n", CLASSNAME, __func__);
  13358. - return false;
  13359. - }
  13360. -
  13361. - port_def.nPortIndex = m_omx_resize.GetInputPort();
  13362. + port_def.nPortIndex = m_omx_resize.GetInputPort();
  13363. - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13364. - if(omx_err != OMX_ErrorNone)
  13365. - {
  13366. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13367. - return false;
  13368. - }
  13369. + m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13370. + if(omx_err != OMX_ErrorNone)
  13371. + {
  13372. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13373. + return false;
  13374. + }
  13375. - port_def.nPortIndex = m_omx_resize.GetOutputPort();
  13376. - m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13377. - if(omx_err != OMX_ErrorNone)
  13378. - {
  13379. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13380. - return false;
  13381. - }
  13382. - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
  13383. - port_def.format.image.nFrameWidth = resize_width;
  13384. - port_def.format.image.nFrameHeight = resize_height;
  13385. - port_def.format.image.nSliceHeight = (resize_height+15) & ~15;
  13386. - port_def.format.image.nStride = 0;
  13387. - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13388. - if(omx_err != OMX_ErrorNone)
  13389. - {
  13390. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13391. - return false;
  13392. + port_def.nPortIndex = m_omx_resize.GetOutputPort();
  13393. + m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13394. + if(omx_err != OMX_ErrorNone)
  13395. + {
  13396. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13397. + return false;
  13398. + }
  13399. + port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
  13400. + port_def.format.image.nFrameWidth = resize_width;
  13401. + port_def.format.image.nFrameHeight = resize_height;
  13402. + port_def.format.image.nSliceHeight = (resize_height+15) & ~15;
  13403. + port_def.format.image.nStride = 0;
  13404. + m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13405. + if(omx_err != OMX_ErrorNone)
  13406. + {
  13407. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13408. + return false;
  13409. + }
  13410. }
  13411. if(!m_omx_encoder.Initialize("OMX.broadcom.image_encode", OMX_IndexParamImageInit))
  13412. @@ -1621,31 +1631,44 @@ bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned
  13413. return false;
  13414. }
  13415. - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort());
  13416. -
  13417. - omx_err = m_omx_tunnel_decode.Establish();
  13418. - if(omx_err != OMX_ErrorNone)
  13419. + if (m_omx_resize.IsInitialized())
  13420. {
  13421. - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish\n", CLASSNAME, __func__);
  13422. - return false;
  13423. - }
  13424. + m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort());
  13425. - m_omx_tunnel_resize.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_encoder, m_omx_encoder.GetInputPort());
  13426. + omx_err = m_omx_tunnel_decode.Establish();
  13427. + if(omx_err != OMX_ErrorNone)
  13428. + {
  13429. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish\n", CLASSNAME, __func__);
  13430. + return false;
  13431. + }
  13432. - omx_err = m_omx_tunnel_resize.Establish();
  13433. - if(omx_err != OMX_ErrorNone)
  13434. - {
  13435. - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_resize.Establish\n", CLASSNAME, __func__);
  13436. - return false;
  13437. - }
  13438. + m_omx_tunnel_resize.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_encoder, m_omx_encoder.GetInputPort());
  13439. - omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting);
  13440. - if(omx_err != OMX_ErrorNone)
  13441. - {
  13442. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13443. - return false;
  13444. + omx_err = m_omx_tunnel_resize.Establish();
  13445. + if(omx_err != OMX_ErrorNone)
  13446. + {
  13447. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_resize.Establish\n", CLASSNAME, __func__);
  13448. + return false;
  13449. + }
  13450. +
  13451. + omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting);
  13452. + if(omx_err != OMX_ErrorNone)
  13453. + {
  13454. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetStateForComponent result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13455. + return false;
  13456. + }
  13457. }
  13458. + else
  13459. + {
  13460. + m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_encoder, m_omx_encoder.GetInputPort());
  13461. + omx_err = m_omx_tunnel_decode.Establish();
  13462. + if(omx_err != OMX_ErrorNone)
  13463. + {
  13464. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish\n", CLASSNAME, __func__);
  13465. + return false;
  13466. + }
  13467. + }
  13468. omx_err = m_omx_encoder.SetStateForComponent(OMX_StateExecuting);
  13469. if (omx_err != OMX_ErrorNone)
  13470. {
  13471. @@ -1662,24 +1685,27 @@ bool COMXImageReEnc::HandlePortSettingChange(unsigned int resize_width, unsigned
  13472. // a little surprising, make a note
  13473. CLog::Log(LOGDEBUG, "%s::%s m_omx_resize second port changed event\n", CLASSNAME, __func__);
  13474. m_omx_decoder.DisablePort(m_omx_decoder.GetOutputPort(), true);
  13475. - m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), true);
  13476. + if (m_omx_resize.IsInitialized())
  13477. + {
  13478. + m_omx_resize.DisablePort(m_omx_resize.GetInputPort(), true);
  13479. - OMX_PARAM_PORTDEFINITIONTYPE port_def;
  13480. - OMX_INIT_STRUCTURE(port_def);
  13481. + OMX_PARAM_PORTDEFINITIONTYPE port_def;
  13482. + OMX_INIT_STRUCTURE(port_def);
  13483. - port_def.nPortIndex = m_omx_decoder.GetOutputPort();
  13484. - m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13485. - port_def.nPortIndex = m_omx_resize.GetInputPort();
  13486. - m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13487. + port_def.nPortIndex = m_omx_decoder.GetOutputPort();
  13488. + m_omx_decoder.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13489. + port_def.nPortIndex = m_omx_resize.GetInputPort();
  13490. + m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13491. - omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged);
  13492. - if(omx_err != OMX_ErrorNone)
  13493. - {
  13494. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x\n", CLASSNAME, __func__, omx_err);
  13495. - return false;
  13496. + omx_err = m_omx_resize.WaitForEvent(OMX_EventPortSettingsChanged);
  13497. + if(omx_err != OMX_ErrorNone)
  13498. + {
  13499. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.WaitForEvent=%x\n", CLASSNAME, __func__, omx_err);
  13500. + return false;
  13501. + }
  13502. + m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), true);
  13503. }
  13504. m_omx_decoder.EnablePort(m_omx_decoder.GetOutputPort(), true);
  13505. - m_omx_resize.EnablePort(m_omx_resize.GetInputPort(), true);
  13506. }
  13507. return true;
  13508. }
  13509. @@ -1918,42 +1944,45 @@ bool COMXTexture::HandlePortSettingChange(unsigned int resize_width, unsigned in
  13510. CLog::Log(LOGERROR, "%s::%s m_omx_decoder.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13511. return false;
  13512. }
  13513. -
  13514. - if (!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit))
  13515. + if (resize_width != port_def.format.image.nFrameWidth || resize_height != port_def.format.image.nFrameHeight)
  13516. {
  13517. - CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize", CLASSNAME, __func__);
  13518. - return false;
  13519. + if (!m_omx_resize.Initialize("OMX.broadcom.resize", OMX_IndexParamImageInit))
  13520. + {
  13521. + CLog::Log(LOGERROR, "%s::%s error m_omx_resize.Initialize", CLASSNAME, __func__);
  13522. + return false;
  13523. + }
  13524. }
  13525. -
  13526. - port_def.nPortIndex = m_omx_resize.GetInputPort();
  13527. -
  13528. - omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13529. - if (omx_err != OMX_ErrorNone)
  13530. + if (m_omx_resize.IsInitialized())
  13531. {
  13532. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13533. - return false;
  13534. - }
  13535. + port_def.nPortIndex = m_omx_resize.GetInputPort();
  13536. - port_def.nPortIndex = m_omx_resize.GetOutputPort();
  13537. - omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13538. - if (omx_err != OMX_ErrorNone)
  13539. - {
  13540. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13541. - return false;
  13542. - }
  13543. + omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13544. + if (omx_err != OMX_ErrorNone)
  13545. + {
  13546. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13547. + return false;
  13548. + }
  13549. - port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
  13550. - port_def.format.image.nFrameWidth = resize_width;
  13551. - port_def.format.image.nFrameHeight = resize_height;
  13552. - port_def.format.image.nSliceHeight = 16;
  13553. - port_def.format.image.nStride = 0;
  13554. - omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13555. - if (omx_err != OMX_ErrorNone)
  13556. - {
  13557. - CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13558. - return false;
  13559. - }
  13560. + port_def.nPortIndex = m_omx_resize.GetOutputPort();
  13561. + omx_err = m_omx_resize.GetParameter(OMX_IndexParamPortDefinition, &port_def);
  13562. + if (omx_err != OMX_ErrorNone)
  13563. + {
  13564. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.GetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13565. + return false;
  13566. + }
  13567. + port_def.format.image.eColorFormat = OMX_COLOR_FormatYUV420PackedPlanar;
  13568. + port_def.format.image.nFrameWidth = resize_width;
  13569. + port_def.format.image.nFrameHeight = resize_height;
  13570. + port_def.format.image.nSliceHeight = 16;
  13571. + port_def.format.image.nStride = 0;
  13572. + omx_err = m_omx_resize.SetParameter(OMX_IndexParamPortDefinition, &port_def);
  13573. + if (omx_err != OMX_ErrorNone)
  13574. + {
  13575. + CLog::Log(LOGERROR, "%s::%s m_omx_resize.SetParameter result(0x%x)\n", CLASSNAME, __func__, omx_err);
  13576. + return false;
  13577. + }
  13578. + }
  13579. if (!m_omx_egl_render.Initialize("OMX.broadcom.egl_render", OMX_IndexParamVideoInit))
  13580. {
  13581. CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.Initialize", CLASSNAME, __func__);
  13582. @@ -1983,30 +2012,43 @@ bool COMXTexture::HandlePortSettingChange(unsigned int resize_width, unsigned in
  13583. CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.UseEGLImage (%x)", CLASSNAME, __func__, omx_err);
  13584. return false;
  13585. }
  13586. + if (m_omx_resize.IsInitialized())
  13587. + {
  13588. + m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort());
  13589. - m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_resize, m_omx_resize.GetInputPort());
  13590. + omx_err = m_omx_tunnel_decode.Establish();
  13591. + if (omx_err != OMX_ErrorNone)
  13592. + {
  13593. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish (%x)", CLASSNAME, __func__, omx_err);
  13594. + return false;
  13595. + }
  13596. - omx_err = m_omx_tunnel_decode.Establish();
  13597. - if (omx_err != OMX_ErrorNone)
  13598. - {
  13599. - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish (%x)", CLASSNAME, __func__, omx_err);
  13600. - return false;
  13601. - }
  13602. + m_omx_tunnel_egl.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  13603. - m_omx_tunnel_egl.Initialize(&m_omx_resize, m_omx_resize.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  13604. + omx_err = m_omx_tunnel_egl.Establish();
  13605. + if (omx_err != OMX_ErrorNone)
  13606. + {
  13607. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_egl.Establish (%x)", CLASSNAME, __func__, omx_err);
  13608. + return false;
  13609. + }
  13610. - omx_err = m_omx_tunnel_egl.Establish();
  13611. - if (omx_err != OMX_ErrorNone)
  13612. - {
  13613. - CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_egl.Establish (%x)", CLASSNAME, __func__, omx_err);
  13614. - return false;
  13615. + omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting);
  13616. + if (omx_err != OMX_ErrorNone)
  13617. + {
  13618. + CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.GetParameter (%x)", CLASSNAME, __func__, omx_err);
  13619. + return false;
  13620. + }
  13621. }
  13622. -
  13623. - omx_err = m_omx_resize.SetStateForComponent(OMX_StateExecuting);
  13624. - if (omx_err != OMX_ErrorNone)
  13625. + else
  13626. {
  13627. - CLog::Log(LOGERROR, "%s::%s error m_omx_egl_render.GetParameter (%x)", CLASSNAME, __func__, omx_err);
  13628. - return false;
  13629. + m_omx_tunnel_decode.Initialize(&m_omx_decoder, m_omx_decoder.GetOutputPort(), &m_omx_egl_render, m_omx_egl_render.GetInputPort());
  13630. +
  13631. + omx_err = m_omx_tunnel_decode.Establish();
  13632. + if (omx_err != OMX_ErrorNone)
  13633. + {
  13634. + CLog::Log(LOGERROR, "%s::%s m_omx_tunnel_decode.Establish (%x)", CLASSNAME, __func__, omx_err);
  13635. + return false;
  13636. + }
  13637. }
  13638. omx_err = m_omx_egl_render.SetStateForComponent(OMX_StateExecuting);
  13639. --
  13640. 1.9.3
  13641. From 1156d9abfac43de458d4ba66e5494c1d027e0f17 Mon Sep 17 00:00:00 2001
  13642. From: popcornmix <popcornmix@gmail.com>
  13643. Date: Sat, 8 Mar 2014 15:36:06 +0000
  13644. Subject: [PATCH 55/94] [hifiberry] Hack: force it to be recognised as IEC958
  13645. capable to enable passthrough options
  13646. ---
  13647. xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp | 4 ++++
  13648. 1 file changed, 4 insertions(+)
  13649. diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
  13650. index b48a4fc..d9897e5 100644
  13651. --- a/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
  13652. +++ b/xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
  13653. @@ -932,6 +932,10 @@ void CAESinkALSA::EnumerateDevice(AEDeviceInfoList &list, const std::string &dev
  13654. if (snd_card_get_name(cardNr, &cardName) == 0)
  13655. info.m_displayName = cardName;
  13656. + // hack: hifiberry digi doesn't correctly report as iec958 device. Needs fixing in kernel driver
  13657. + if (info.m_displayName == "snd_rpi_hifiberry_digi")
  13658. + info.m_deviceType = AE_DEVTYPE_IEC958;
  13659. +
  13660. if (info.m_deviceType == AE_DEVTYPE_HDMI && info.m_displayName.size() > 5 &&
  13661. info.m_displayName.substr(info.m_displayName.size()-5) == " HDMI")
  13662. {
  13663. --
  13664. 1.9.3
  13665. From 03aa9ebf0993f06d24a34f8dd7d86a183ebd2dcd Mon Sep 17 00:00:00 2001
  13666. From: popcornmix <popcornmix@gmail.com>
  13667. Date: Tue, 11 Mar 2014 18:50:23 +0000
  13668. Subject: [PATCH 56/94] [dvdplayer] Use inexact seeking like omxplayer
  13669. ---
  13670. xbmc/cores/dvdplayer/DVDPlayer.cpp | 11 +++++++++++
  13671. 1 file changed, 11 insertions(+)
  13672. diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp
  13673. index d607f55..1d4ba52 100644
  13674. --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp
  13675. +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp
  13676. @@ -1935,7 +1935,11 @@ void CDVDPlayer::CheckAutoSceneSkip()
  13677. /*
  13678. * Seeking is NOT flushed so any content up to the demux point is retained when playing forwards.
  13679. */
  13680. +#ifdef TARGET_RASPBERRY_PI
  13681. + m_messenger.Put(new CDVDMsgPlayerSeek((int)seek, true, true, true, false, true));
  13682. +#else
  13683. m_messenger.Put(new CDVDMsgPlayerSeek((int)seek, true, false, true, false, true));
  13684. +#endif
  13685. /*
  13686. * Seek doesn't always work reliably. Last physical seek time is recorded to prevent looping
  13687. * if there was an error with seeking and it landed somewhere unexpected, perhaps back in the
  13688. @@ -1953,7 +1957,11 @@ void CDVDPlayer::CheckAutoSceneSkip()
  13689. /*
  13690. * Seeking is NOT flushed so any content up to the demux point is retained when playing forwards.
  13691. */
  13692. +#ifdef TARGET_RASPBERRY_PI
  13693. + m_messenger.Put(new CDVDMsgPlayerSeek(cut.end + 1, true, false, true, false, true));
  13694. +#else
  13695. m_messenger.Put(new CDVDMsgPlayerSeek(cut.end + 1, true, false, true, false, true));
  13696. +#endif
  13697. /*
  13698. * Each commercial break is only skipped once so poorly detected commercial breaks can be
  13699. * manually re-entered. Start and end are recorded to prevent looping and to allow seeking back
  13700. @@ -3293,9 +3301,12 @@ bool CDVDPlayer::CloseTeletextStream(bool bWaitForBuffers)
  13701. void CDVDPlayer::FlushBuffers(bool queued, double pts, bool accurate)
  13702. {
  13703. double startpts;
  13704. +#ifndef TARGET_RASPBERRY_PI
  13705. + /* for now, ignore accurate flag as it discards keyframes and causes corrupt frames */
  13706. if(accurate)
  13707. startpts = pts;
  13708. else
  13709. +#endif
  13710. startpts = DVD_NOPTS_VALUE;
  13711. /* call with demuxer pts */
  13712. --
  13713. 1.9.3
  13714. From d4487b87819003a44f59a607074a41108f644915 Mon Sep 17 00:00:00 2001
  13715. From: popcornmix <popcornmix@gmail.com>
  13716. Date: Thu, 13 Mar 2014 16:08:46 +0000
  13717. Subject: [PATCH 57/94] [omxplayer] Make use of TrueHD fastpath when downmixing
  13718. The TrueHD codec actually works in 3 stages. It decodes the downmixed stereo. It then decodes the differences required to produce 5.1.
  13719. It then decodes the differences required to produce 7.1.
  13720. Many users end up downmixing this 7.1 stream back to 2.0.
  13721. Much better to tell the codec we only need the 2.0 stream. It saves about 50% of the CPU required
  13722. ---
  13723. xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 12 ++++++++++++
  13724. 1 file changed, 12 insertions(+)
  13725. diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  13726. index 557e847..7f6ef6e 100644
  13727. --- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  13728. +++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  13729. @@ -25,6 +25,8 @@
  13730. #include "utils/log.h"
  13731. #include "cores/AudioEngine/Utils/AEUtil.h"
  13732. +#include "settings/Settings.h"
  13733. +#include "PCMRemap.h"
  13734. // the size of the audio_render output port buffers
  13735. #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
  13736. @@ -91,6 +93,16 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints)
  13737. m_pCodecContext->block_align = hints.blockalign;
  13738. m_pCodecContext->bit_rate = hints.bitrate;
  13739. m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
  13740. + enum PCMLayout layout = (enum PCMLayout)std::max(0, CSettings::Get().GetInt("audiooutput.channels")-1);
  13741. + if (hints.codec == AV_CODEC_ID_TRUEHD)
  13742. + {
  13743. + if (layout == PCM_LAYOUT_2_0)
  13744. + m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_STEREO;
  13745. + else if (layout <= PCM_LAYOUT_5_1)
  13746. + m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_5POINT1;
  13747. + }
  13748. + if (m_pCodecContext->request_channel_layout)
  13749. + CLog::Log(LOGNOTICE,"COMXAudioCodecOMX::Open() Requesting channel layout of %d", (unsigned)m_pCodecContext->request_channel_layout);
  13750. // vorbis has variable sized planar output, so skip concatenation
  13751. if (hints.codec == AV_CODEC_ID_VORBIS)
  13752. --
  13753. 1.9.3
  13754. From 8dedad4307cbca1416262af9e2ac2404c7490713 Mon Sep 17 00:00:00 2001
  13755. From: popcornmix <popcornmix@gmail.com>
  13756. Date: Sat, 15 Mar 2014 19:38:38 +0000
  13757. Subject: [PATCH 58/94] [omxplayer] When in dual audio mode, make one output
  13758. the slave
  13759. May help audio sync between the two outputs
  13760. ---
  13761. xbmc/cores/omxplayer/OMXAudio.cpp | 4 ++--
  13762. 1 file changed, 2 insertions(+), 2 deletions(-)
  13763. diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
  13764. index 3e64de0..72e42ec 100644
  13765. --- a/xbmc/cores/omxplayer/OMXAudio.cpp
  13766. +++ b/xbmc/cores/omxplayer/OMXAudio.cpp
  13767. @@ -245,7 +245,7 @@ bool COMXAudio::PortSettingsChanged()
  13768. {
  13769. // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
  13770. // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
  13771. - if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
  13772. + if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || (CSettings::Get().GetBool("audiooutput.dualaudio") && CSettings::Get().GetString("audiooutput.audiodevice") != "PI:Analogue"))
  13773. {
  13774. OMX_CONFIG_BOOLEANTYPE configBool;
  13775. OMX_INIT_STRUCTURE(configBool);
  13776. @@ -271,7 +271,7 @@ bool COMXAudio::PortSettingsChanged()
  13777. {
  13778. // By default audio_render is the clock master, and if output samples don't fit the timestamps, it will speed up/slow down the clock.
  13779. // This tends to be better for maintaining audio sync and avoiding audio glitches, but can affect video/display sync
  13780. - if(CSettings::Get().GetBool("videoplayer.usedisplayasclock"))
  13781. + if(CSettings::Get().GetBool("videoplayer.usedisplayasclock") || (CSettings::Get().GetBool("audiooutput.dualaudio") && CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue"))
  13782. {
  13783. OMX_CONFIG_BOOLEANTYPE configBool;
  13784. OMX_INIT_STRUCTURE(configBool);
  13785. --
  13786. 1.9.3
  13787. From 96842193cb39ac3625a1dcbdd67388141733a5ee Mon Sep 17 00:00:00 2001
  13788. From: popcornmix <popcornmix@gmail.com>
  13789. Date: Mon, 30 Dec 2013 12:02:14 +0000
  13790. Subject: [PATCH 59/94] [rbp] Hardware accelerated resampling
  13791. This replaces the format conversion, up/down mixing and resampling code from ActiveAE with a GPU accelerated version.
  13792. Should significantly reduce CPU when using paplayer or dvdplayer.
  13793. Requires updated firmware
  13794. ---
  13795. .../Engines/ActiveAE/ActiveAEResample.cpp | 5 +
  13796. .../Engines/ActiveAE/ActiveAEResample.h | 9 +
  13797. .../Engines/ActiveAE/ActiveAEResamplePi.cpp | 592 +++++++++++++++++++++
  13798. .../Engines/ActiveAE/ActiveAEResamplePi.h | 65 +++
  13799. xbmc/cores/AudioEngine/Makefile.in | 1 +
  13800. xbmc/linux/OMXCore.cpp | 4 +-
  13801. 6 files changed, 674 insertions(+), 2 deletions(-)
  13802. create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  13803. create mode 100644 xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h
  13804. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp
  13805. index e131f16..94b69a0 100644
  13806. --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp
  13807. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.cpp
  13808. @@ -18,6 +18,10 @@
  13809. *
  13810. */
  13811. +#include "system.h"
  13812. +
  13813. +#if !defined(TARGET_RASPBERRY_PI)
  13814. +
  13815. #include "ActiveAEResample.h"
  13816. using namespace ActiveAE;
  13817. @@ -344,3 +348,4 @@ int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layo
  13818. {
  13819. return m_dllAvUtil.av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel));
  13820. }
  13821. +#endif
  13822. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h
  13823. index 1e0e342..6a8949b 100644
  13824. --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h
  13825. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResample.h
  13826. @@ -21,11 +21,18 @@
  13827. #include "DllAvUtil.h"
  13828. #include "DllSwResample.h"
  13829. +
  13830. +#include "system.h"
  13831. +
  13832. #include "cores/AudioEngine/Utils/AEChannelInfo.h"
  13833. #include "cores/AudioEngine/Utils/AEAudioFormat.h"
  13834. #include "cores/AudioEngine/Engines/ActiveAE/ActiveAEBuffer.h"
  13835. #include "cores/AudioEngine/Interfaces/AE.h"
  13836. +#if defined(TARGET_RASPBERRY_PI)
  13837. +#include "ActiveAEResamplePi.h"
  13838. +#else
  13839. +
  13840. namespace ActiveAE
  13841. {
  13842. @@ -62,3 +69,5 @@ class CActiveAEResample
  13843. };
  13844. }
  13845. +
  13846. +#endif
  13847. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  13848. new file mode 100644
  13849. index 0000000..1d7b425
  13850. --- /dev/null
  13851. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  13852. @@ -0,0 +1,592 @@
  13853. +/*
  13854. + * Copyright (C) 2010-2013 Team XBMC
  13855. + * http://xbmc.org
  13856. + *
  13857. + * This Program is free software; you can redistribute it and/or modify
  13858. + * it under the terms of the GNU General Public License as published by
  13859. + * the Free Software Foundation; either version 2, or (at your option)
  13860. + * any later version.
  13861. + *
  13862. + * This Program is distributed in the hope that it will be useful,
  13863. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13864. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13865. + * GNU General Public License for more details.
  13866. + *
  13867. + * You should have received a copy of the GNU General Public License
  13868. + * along with XBMC; see the file COPYING. If not, see
  13869. + * <http://www.gnu.org/licenses/>.
  13870. + *
  13871. + */
  13872. +
  13873. +#include "system.h"
  13874. +
  13875. +#if defined(TARGET_RASPBERRY_PI)
  13876. +
  13877. +#include "ActiveAEResample.h"
  13878. +#include "linux/RBP.h"
  13879. +#include "cores/omxplayer/PCMRemap.h"
  13880. +#include "settings/Settings.h"
  13881. +#include "utils/log.h"
  13882. +
  13883. +//#define DEBUG_VERBOSE
  13884. +
  13885. +#define CLASSNAME "CActiveAEResamplePi"
  13886. +
  13887. +#define BUFFERSIZE (32*1024*2*8)
  13888. +
  13889. +//#define BENCHMARKING
  13890. +#ifdef BENCHMARKING
  13891. +#define LOGTIMEINIT(f) \
  13892. + struct timespec now; \
  13893. + uint64_t Start, End; \
  13894. + clock_gettime(CLOCK_MONOTONIC, &now); \
  13895. + Start = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \
  13896. + const char *_filename = f;
  13897. +
  13898. +#define LOGTIME(n) \
  13899. + clock_gettime(CLOCK_MONOTONIC, &now); \
  13900. + End = ((int64_t)now.tv_sec * 1000000000L) + now.tv_nsec; \
  13901. + CLog::Log(LOGNOTICE, "ActiveAE::%s %d - resample %s took %.0fms", __FUNCTION__, n, _filename, (End-Start)*1e-6); \
  13902. + Start=End;
  13903. +#else
  13904. +#define LOGTIMEINIT(f)
  13905. +#define LOGTIME(n)
  13906. +#endif
  13907. +
  13908. +using namespace ActiveAE;
  13909. +
  13910. +CActiveAEResample::CActiveAEResample()
  13911. +{
  13912. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  13913. + m_loaded = false;
  13914. +
  13915. + if (m_dllAvUtil.Load() && m_dllSwResample.Load())
  13916. + m_loaded = true;
  13917. +
  13918. + m_Initialized = false;
  13919. + m_last_src_fmt = AV_SAMPLE_FMT_NONE;
  13920. + m_last_dst_fmt = AV_SAMPLE_FMT_NONE;
  13921. + m_last_src_channels = 0;
  13922. + m_last_dst_channels = 0;
  13923. +}
  13924. +
  13925. +CActiveAEResample::~CActiveAEResample()
  13926. +{
  13927. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  13928. + DeInit();
  13929. + m_dllAvUtil.Unload();
  13930. + m_dllSwResample.Unload();
  13931. +}
  13932. +
  13933. +void CActiveAEResample::DeInit()
  13934. +{
  13935. + CLog::Log(LOGDEBUG, "%s:%s", CLASSNAME, __func__);
  13936. + if (m_Initialized)
  13937. + {
  13938. + m_omx_mixer.FlushAll();
  13939. + m_omx_mixer.Deinitialize();
  13940. + m_Initialized = false;
  13941. + }
  13942. +}
  13943. +
  13944. +bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality)
  13945. +{
  13946. + LOGTIMEINIT("x");
  13947. +
  13948. + CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d rate:%d->%d format:%d->%d bits:%d->%d norm:%d upmix:%d", CLASSNAME, __func__, remapLayout, src_channels, dst_channels, src_rate, dst_rate, src_fmt, dst_fmt, src_bits, dst_bits, normalize, upmix);
  13949. + if (!m_loaded)
  13950. + return false;
  13951. +
  13952. + m_dst_chan_layout = dst_chan_layout;
  13953. + m_dst_channels = dst_channels;
  13954. + m_dst_rate = dst_rate;
  13955. + m_dst_fmt = dst_fmt;
  13956. + m_dst_bits = dst_bits ? dst_bits : 8;
  13957. + m_src_chan_layout = src_chan_layout;
  13958. + m_src_channels = src_channels;
  13959. + m_src_rate = src_rate;
  13960. + m_src_fmt = src_fmt;
  13961. + m_src_bits = src_bits ? src_bits : 8;
  13962. +
  13963. + if (m_dst_chan_layout == 0)
  13964. + m_dst_chan_layout = m_dllAvUtil.av_get_default_channel_layout(m_dst_channels);
  13965. + if (m_src_chan_layout == 0)
  13966. + m_src_chan_layout = m_dllAvUtil.av_get_default_channel_layout(m_src_channels);
  13967. +
  13968. + OMX_CONFIG_BRCMAUDIODOWNMIXCOEFFICIENTS8x8 mix;
  13969. + OMX_INIT_STRUCTURE(mix);
  13970. +
  13971. + assert(sizeof(mix.coeff)/sizeof(mix.coeff[0]) == 64);
  13972. +
  13973. + LOGTIME(1);
  13974. +// this code is just uses ffmpeg to produce the 8x8 mixing matrix
  13975. +{
  13976. + // dummy sample rate and format, as we only care about channel mapping
  13977. + SwrContext *m_pContext = m_dllSwResample.swr_alloc_set_opts(NULL, m_dst_chan_layout, AV_SAMPLE_FMT_FLT, 48000,
  13978. + m_src_chan_layout, AV_SAMPLE_FMT_FLT, 48000, 0, NULL);
  13979. + if (!m_pContext)
  13980. + {
  13981. + CLog::Log(LOGERROR, "CActiveAEResample::Init - create context failed");
  13982. + return false;
  13983. + }
  13984. + // tell resampler to clamp float values
  13985. + // not required for sink stage (remapLayout == true)
  13986. + if (!remapLayout && normalize)
  13987. + {
  13988. + m_dllAvUtil.av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0);
  13989. + }
  13990. +
  13991. + if (remapLayout)
  13992. + {
  13993. + // one-to-one mapping of channels
  13994. + // remapLayout is the layout of the sink, if the channel is in our src layout
  13995. + // the channel is mapped by setting coef 1.0
  13996. + double m_rematrix[AE_CH_MAX][AE_CH_MAX];
  13997. + memset(m_rematrix, 0, sizeof(m_rematrix));
  13998. + m_dst_chan_layout = 0;
  13999. + for (unsigned int out=0; out<remapLayout->Count(); out++)
  14000. + {
  14001. + m_dst_chan_layout += (uint64_t) (1 << out);
  14002. + int idx = GetAVChannelIndex((*remapLayout)[out], m_src_chan_layout);
  14003. + if (idx >= 0)
  14004. + {
  14005. + m_rematrix[out][idx] = 1.0;
  14006. + }
  14007. + }
  14008. +
  14009. + m_dllAvUtil.av_opt_set_int(m_pContext, "out_channel_count", m_dst_channels, 0);
  14010. + m_dllAvUtil.av_opt_set_int(m_pContext, "out_channel_layout", m_dst_chan_layout, 0);
  14011. +
  14012. + if (m_dllSwResample.swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0)
  14013. + {
  14014. + CLog::Log(LOGERROR, "CActiveAEResample::Init - setting channel matrix failed");
  14015. + return false;
  14016. + }
  14017. + }
  14018. + // stereo upmix
  14019. + else if (upmix && m_src_channels == 2 && m_dst_channels > 2)
  14020. + {
  14021. + double m_rematrix[AE_CH_MAX][AE_CH_MAX];
  14022. + memset(m_rematrix, 0, sizeof(m_rematrix));
  14023. + for (int out=0; out<m_dst_channels; out++)
  14024. + {
  14025. + uint64_t out_chan = m_dllAvUtil.av_channel_layout_extract_channel(m_dst_chan_layout, out);
  14026. + switch(out_chan)
  14027. + {
  14028. + case AV_CH_FRONT_LEFT:
  14029. + case AV_CH_BACK_LEFT:
  14030. + case AV_CH_SIDE_LEFT:
  14031. + m_rematrix[out][0] = 1.0;
  14032. + break;
  14033. + case AV_CH_FRONT_RIGHT:
  14034. + case AV_CH_BACK_RIGHT:
  14035. + case AV_CH_SIDE_RIGHT:
  14036. + m_rematrix[out][1] = 1.0;
  14037. + break;
  14038. + case AV_CH_FRONT_CENTER:
  14039. + m_rematrix[out][0] = 0.5;
  14040. + m_rematrix[out][1] = 0.5;
  14041. + break;
  14042. + case AV_CH_LOW_FREQUENCY:
  14043. + m_rematrix[out][0] = 0.5;
  14044. + m_rematrix[out][1] = 0.5;
  14045. + break;
  14046. + default:
  14047. + break;
  14048. + }
  14049. + }
  14050. +
  14051. + if (m_dllSwResample.swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0)
  14052. + {
  14053. + CLog::Log(LOGERROR, "CActiveAEResample::Init - setting channel matrix failed");
  14054. + return false;
  14055. + }
  14056. + }
  14057. +
  14058. + if (m_dllSwResample.swr_init(m_pContext) < 0)
  14059. + {
  14060. + CLog::Log(LOGERROR, "CActiveAEResample::Init - init resampler failed");
  14061. + return false;
  14062. + }
  14063. +
  14064. + const int samples = 8;
  14065. + uint8_t *output, *input;
  14066. + av_samples_alloc(&output, NULL, m_dst_channels, samples, AV_SAMPLE_FMT_FLT, 1);
  14067. + av_samples_alloc(&input , NULL, m_src_channels, samples, AV_SAMPLE_FMT_FLT, 1);
  14068. +
  14069. + // Produce "identity" samples
  14070. + float *f = (float *)input;
  14071. + for (int j=0; j < samples; j++)
  14072. + for (int i=0; i < m_src_channels; i++)
  14073. + *f++ = i == j ? 1.0f : 0.0f;
  14074. +
  14075. + int ret = m_dllSwResample.swr_convert(m_pContext, &output, samples, (const uint8_t **)&input, samples);
  14076. + if (ret < 0)
  14077. + CLog::Log(LOGERROR, "CActiveAEResample::Resample - resample failed");
  14078. +
  14079. + f = (float *)output;
  14080. + for (int j=0; j < samples; j++)
  14081. + for (int i=0; i < m_dst_channels; i++)
  14082. + mix.coeff[8*i+j] = *f++ * (1<<16);
  14083. +
  14084. + for (int j=0; j < 8; j++)
  14085. + {
  14086. + char s[128] = {}, *t=s;
  14087. + for (int i=0; i < 8; i++)
  14088. + t += sprintf(t, "% 6.2f ", mix.coeff[j*8+i] * (1.0/0x10000));
  14089. + CLog::Log(LOGINFO, "%s::%s %s", CLASSNAME, __func__, s);
  14090. + }
  14091. + av_freep(&input);
  14092. + av_freep(&output);
  14093. + m_dllSwResample.swr_free(&m_pContext);
  14094. +}
  14095. + LOGTIME(2);
  14096. +
  14097. + // This may be called before Application calls g_RBP.Initialise, so call it here too
  14098. + g_RBP.Initialize();
  14099. +
  14100. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  14101. +
  14102. + if (!m_omx_mixer.Initialize("OMX.broadcom.audio_mixer", OMX_IndexParamAudioInit))
  14103. + CLog::Log(LOGERROR, "%s::%s - m_omx_mixer.Initialize omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14104. +
  14105. + LOGTIME(3);
  14106. +
  14107. + OMX_INIT_STRUCTURE(m_pcm_input);
  14108. + m_pcm_input.nPortIndex = m_omx_mixer.GetInputPort();
  14109. + m_pcm_input.eNumData = OMX_NumericalDataSigned;
  14110. + m_pcm_input.eEndian = OMX_EndianLittle;
  14111. + m_pcm_input.bInterleaved = OMX_TRUE;
  14112. + m_pcm_input.nBitPerSample = m_src_bits;
  14113. + m_pcm_input.ePCMMode = m_src_fmt == AV_SAMPLE_FMT_FLT ? (OMX_AUDIO_PCMMODETYPE)0x8000 : OMX_AUDIO_PCMModeLinear;
  14114. + m_pcm_input.nChannels = src_channels;
  14115. + m_pcm_input.nSamplingRate = src_rate;
  14116. +
  14117. + omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_input);
  14118. + if (omx_err != OMX_ErrorNone)
  14119. + CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer in SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14120. +
  14121. + OMX_INIT_STRUCTURE(m_pcm_output);
  14122. + m_pcm_output.nPortIndex = m_omx_mixer.GetOutputPort();
  14123. + m_pcm_output.eNumData = OMX_NumericalDataSigned;
  14124. + m_pcm_output.eEndian = OMX_EndianLittle;
  14125. + m_pcm_output.bInterleaved = OMX_TRUE;
  14126. + m_pcm_output.nBitPerSample = m_dst_bits;
  14127. + m_pcm_output.ePCMMode = m_dst_fmt == AV_SAMPLE_FMT_FLT ? (OMX_AUDIO_PCMMODETYPE)0x8000 : OMX_AUDIO_PCMModeLinear;
  14128. + m_pcm_output.nChannels = dst_channels;
  14129. + m_pcm_output.nSamplingRate = dst_rate;
  14130. +
  14131. + omx_err = m_omx_mixer.SetParameter(OMX_IndexParamAudioPcm, &m_pcm_output);
  14132. + if (omx_err != OMX_ErrorNone)
  14133. + CLog::Log(LOGERROR, "%s::%s - error m_omx_mixer out SetParameter omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14134. +
  14135. + LOGTIME(4);
  14136. +
  14137. + mix.nPortIndex = m_omx_mixer.GetInputPort();
  14138. + omx_err = m_omx_mixer.SetConfig(OMX_IndexConfigBrcmAudioDownmixCoefficients8x8, &mix);
  14139. + if (omx_err != OMX_ErrorNone)
  14140. + {
  14141. + CLog::Log(LOGERROR, "%s::%s - error setting mixer OMX_IndexConfigBrcmAudioDownmixCoefficients, error 0x%08x\n",
  14142. + CLASSNAME, __func__, omx_err);
  14143. + return false;
  14144. + }
  14145. +
  14146. + // set up the number/size of buffers for decoder input
  14147. + OMX_PARAM_PORTDEFINITIONTYPE port_param;
  14148. + OMX_INIT_STRUCTURE(port_param);
  14149. + port_param.nPortIndex = m_omx_mixer.GetInputPort();
  14150. +
  14151. + omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param);
  14152. + if (omx_err != OMX_ErrorNone)
  14153. + CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14154. +
  14155. + port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1);
  14156. + port_param.nBufferSize = BUFFERSIZE;
  14157. +
  14158. + omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param);
  14159. + if (omx_err != OMX_ErrorNone)
  14160. + CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14161. +
  14162. + LOGTIME(5);
  14163. +
  14164. + omx_err = m_omx_mixer.AllocInputBuffers();
  14165. + if (omx_err != OMX_ErrorNone)
  14166. + CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err);
  14167. +
  14168. + LOGTIME(6);
  14169. +
  14170. + // set up the number/size of buffers for decoder output
  14171. + OMX_INIT_STRUCTURE(port_param);
  14172. + port_param.nPortIndex = m_omx_mixer.GetOutputPort();
  14173. +
  14174. + omx_err = m_omx_mixer.GetParameter(OMX_IndexParamPortDefinition, &port_param);
  14175. + if (omx_err != OMX_ErrorNone)
  14176. + CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14177. +
  14178. + port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)1);
  14179. + port_param.nBufferSize = BUFFERSIZE;
  14180. +
  14181. + omx_err = m_omx_mixer.SetParameter(OMX_IndexParamPortDefinition, &port_param);
  14182. + if (omx_err != OMX_ErrorNone)
  14183. + CLog::Log(LOGERROR, "%s:%s - error set OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14184. +
  14185. + LOGTIME(7);
  14186. +
  14187. + omx_err = m_omx_mixer.AllocOutputBuffers();
  14188. + if (omx_err != OMX_ErrorNone)
  14189. + CLog::Log(LOGERROR, "%s:%s - Error alloc buffers 0x%08x", CLASSNAME, __func__, omx_err);
  14190. +
  14191. + LOGTIME(8);
  14192. +
  14193. + omx_err = m_omx_mixer.SetStateForComponent(OMX_StateExecuting);
  14194. + if (omx_err != OMX_ErrorNone)
  14195. + CLog::Log(LOGERROR, "%s:%s - m_omx_mixer OMX_StateExecuting omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  14196. +
  14197. + LOGTIME(9);
  14198. +
  14199. + m_Initialized = true;
  14200. +
  14201. + return true;
  14202. +}
  14203. +
  14204. +int CActiveAEResample::Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio)
  14205. +{
  14206. + #ifdef DEBUG_VERBOSE
  14207. + CLog::Log(LOGINFO, "%s::%s samples:%d->%d (%.2f)", CLASSNAME, __func__, src_samples, dst_samples, ratio);
  14208. + #endif
  14209. + if (!m_Initialized)
  14210. + return 0;
  14211. + OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  14212. +
  14213. + const int s_pitch = m_pcm_input.nChannels * m_src_bits >> 3;
  14214. + const int d_pitch = m_pcm_output.nChannels * m_dst_bits >> 3;
  14215. + int sent = 0;
  14216. + int received = 0;
  14217. + while (sent < src_samples)
  14218. + {
  14219. + OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
  14220. + OMX_BUFFERHEADERTYPE *m_encoded_buffer = NULL;
  14221. +
  14222. + omx_buffer = m_omx_mixer.GetInputBuffer(1000);
  14223. + if (omx_buffer == NULL)
  14224. + return false;
  14225. +
  14226. + const int max_src_samples = BUFFERSIZE / s_pitch;
  14227. + const int max_dst_samples = (long long)(BUFFERSIZE/d_pitch) * m_src_rate / (m_dst_rate + m_src_rate-1);
  14228. + int send = std::min(std::min(max_dst_samples, max_src_samples), src_samples - sent);
  14229. +
  14230. + omx_buffer->nOffset = 0;
  14231. + omx_buffer->nFlags = OMX_BUFFERFLAG_EOS;
  14232. + omx_buffer->nFilledLen = send * s_pitch;
  14233. +
  14234. + assert(omx_buffer->nFilledLen > 0 && omx_buffer->nFilledLen <= omx_buffer->nAllocLen);
  14235. +
  14236. + if (omx_buffer->nFilledLen)
  14237. + {
  14238. + memcpy(omx_buffer->pBuffer, src_buffer[0] + sent * s_pitch, omx_buffer->nFilledLen);
  14239. + sent += send;
  14240. + }
  14241. +
  14242. + omx_err = m_omx_mixer.EmptyThisBuffer(omx_buffer);
  14243. + if (omx_err != OMX_ErrorNone)
  14244. + {
  14245. + CLog::Log(LOGERROR, "%s::%s OMX_EmptyThisBuffer() failed with result(0x%x)", CLASSNAME, __func__, omx_err);
  14246. + return false;
  14247. + }
  14248. +
  14249. + m_encoded_buffer = m_omx_mixer.GetOutputBuffer();
  14250. +
  14251. + if (!m_encoded_buffer)
  14252. + {
  14253. + CLog::Log(LOGERROR, "%s::%s no output buffer", CLASSNAME, __func__);
  14254. + return false;
  14255. + }
  14256. +
  14257. + omx_err = m_omx_mixer.FillThisBuffer(m_encoded_buffer);
  14258. + if (omx_err != OMX_ErrorNone)
  14259. + return false;
  14260. +
  14261. + omx_err = m_omx_mixer.WaitForOutputDone(1000);
  14262. + if (omx_err != OMX_ErrorNone)
  14263. + {
  14264. + CLog::Log(LOGERROR, "%s::%s m_omx_mixer.WaitForOutputDone result(0x%x)", CLASSNAME, __func__, omx_err);
  14265. + return false;
  14266. + }
  14267. + assert(m_encoded_buffer->nFilledLen > 0 && m_encoded_buffer->nFilledLen <= m_encoded_buffer->nAllocLen);
  14268. +
  14269. + if (m_omx_mixer.BadState())
  14270. + {
  14271. + CLog::Log(LOGERROR, "%s::%s m_omx_mixer.BadState", CLASSNAME, __func__);
  14272. + return false;
  14273. + }
  14274. +
  14275. + if (m_encoded_buffer->nFilledLen)
  14276. + {
  14277. + memcpy(dst_buffer[0] + received * d_pitch, m_encoded_buffer->pBuffer, m_encoded_buffer->nFilledLen);
  14278. + received += m_encoded_buffer->nFilledLen / d_pitch;
  14279. + }
  14280. + }
  14281. + #ifdef DEBUG_VERBOSE
  14282. + CLog::Log(LOGINFO, "%s::%s format:%d->%d rate:%d->%d chan:%d->%d samples %d->%d (%f) %d =%d", CLASSNAME, __func__,
  14283. + (int)m_src_fmt, (int)m_dst_fmt, m_src_rate, m_dst_rate, m_src_channels, m_dst_channels, src_samples, dst_samples, ratio, m_Initialized, received);
  14284. + #endif
  14285. + return received;
  14286. +}
  14287. +
  14288. +int64_t CActiveAEResample::GetDelay(int64_t base)
  14289. +{
  14290. + int ret = 0;
  14291. + #ifdef DEBUG_VERBOSE
  14292. + CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
  14293. + #endif
  14294. + return ret;
  14295. +}
  14296. +
  14297. +int CActiveAEResample::GetBufferedSamples()
  14298. +{
  14299. + int ret = 0;
  14300. + #ifdef DEBUG_VERBOSE
  14301. + CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
  14302. + #endif
  14303. + return ret;
  14304. +}
  14305. +
  14306. +int CActiveAEResample::CalcDstSampleCount(int src_samples, int dst_rate, int src_rate)
  14307. +{
  14308. + int ret = ((long long)src_samples * dst_rate + src_rate-1) / src_rate;
  14309. + #ifdef DEBUG_VERBOSE
  14310. + CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
  14311. + #endif
  14312. + return ret;
  14313. +}
  14314. +
  14315. +int CActiveAEResample::GetSrcBufferSize(int samples)
  14316. +{
  14317. + int ret = 0;
  14318. + #ifdef DEBUG_VERBOSE
  14319. + CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
  14320. + #endif
  14321. + return ret;
  14322. +}
  14323. +
  14324. +int CActiveAEResample::GetDstBufferSize(int samples)
  14325. +{
  14326. + int ret = CalcDstSampleCount(samples, m_dst_rate, m_src_rate);
  14327. + #ifdef DEBUG_VERBOSE
  14328. + CLog::Log(LOGINFO, "%s::%s = %d", CLASSNAME, __func__, ret);
  14329. + #endif
  14330. + return ret;
  14331. +}
  14332. +
  14333. +uint64_t CActiveAEResample::GetAVChannelLayout(CAEChannelInfo &info)
  14334. +{
  14335. + #ifdef DEBUG_VERBOSE
  14336. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14337. + #endif
  14338. + uint64_t channelLayout = 0;
  14339. + if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT;
  14340. + if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT;
  14341. + if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER;
  14342. + if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY;
  14343. + if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT;
  14344. + if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT;
  14345. + if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
  14346. + if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
  14347. + if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER;
  14348. + if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT;
  14349. + if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT;
  14350. + if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER;
  14351. + if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT;
  14352. + if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER;
  14353. + if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT;
  14354. + if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT;
  14355. + if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER;
  14356. + if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT;
  14357. +
  14358. + return channelLayout;
  14359. +}
  14360. +
  14361. +AVSampleFormat CActiveAEResample::GetAVSampleFormat(AEDataFormat format)
  14362. +{
  14363. + #ifdef DEBUG_VERBOSE
  14364. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14365. + #endif
  14366. + if (format == AE_FMT_U8) return AV_SAMPLE_FMT_U8;
  14367. + else if (format == AE_FMT_S16NE) return AV_SAMPLE_FMT_S16;
  14368. + else if (format == AE_FMT_S32NE) return AV_SAMPLE_FMT_S32;
  14369. + else if (format == AE_FMT_S24NE4) return AV_SAMPLE_FMT_S32;
  14370. + else if (format == AE_FMT_FLOAT) return AV_SAMPLE_FMT_FLT;
  14371. + else if (format == AE_FMT_DOUBLE) return AV_SAMPLE_FMT_DBL;
  14372. +
  14373. + else if (format == AE_FMT_U8P) return AV_SAMPLE_FMT_U8P;
  14374. + else if (format == AE_FMT_S16NEP) return AV_SAMPLE_FMT_S16P;
  14375. + else if (format == AE_FMT_S32NEP) return AV_SAMPLE_FMT_S32P;
  14376. + else if (format == AE_FMT_S24NE4P) return AV_SAMPLE_FMT_S32P;
  14377. + else if (format == AE_FMT_FLOATP) return AV_SAMPLE_FMT_FLTP;
  14378. + else if (format == AE_FMT_DOUBLEP) return AV_SAMPLE_FMT_DBLP;
  14379. +
  14380. + return AV_SAMPLE_FMT_FLT;
  14381. +}
  14382. +
  14383. +AEDataFormat CActiveAEResample::GetAESampleFormat(AVSampleFormat format, int bits)
  14384. +{
  14385. + #ifdef DEBUG_VERBOSE
  14386. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14387. + #endif
  14388. + if (format == AV_SAMPLE_FMT_U8) return AE_FMT_U8;
  14389. + else if (format == AV_SAMPLE_FMT_S16) return AE_FMT_S16NE;
  14390. + else if (format == AV_SAMPLE_FMT_S32 && bits == 32) return AE_FMT_S32NE;
  14391. + else if (format == AV_SAMPLE_FMT_S32 && bits == 24) return AE_FMT_S24NE4;
  14392. + else if (format == AV_SAMPLE_FMT_FLT) return AE_FMT_FLOAT;
  14393. + else if (format == AV_SAMPLE_FMT_DBL) return AE_FMT_DOUBLE;
  14394. +
  14395. + else if (format == AV_SAMPLE_FMT_U8P) return AE_FMT_U8P;
  14396. + else if (format == AV_SAMPLE_FMT_S16P) return AE_FMT_S16NEP;
  14397. + else if (format == AV_SAMPLE_FMT_S32P && bits == 32) return AE_FMT_S32NEP;
  14398. + else if (format == AV_SAMPLE_FMT_S32P && bits == 24) return AE_FMT_S24NE4P;
  14399. + else if (format == AV_SAMPLE_FMT_FLTP) return AE_FMT_FLOATP;
  14400. + else if (format == AV_SAMPLE_FMT_DBLP) return AE_FMT_DOUBLEP;
  14401. +
  14402. + CLog::Log(LOGERROR, "CActiveAEResample::GetAESampleFormat - format not supported");
  14403. + return AE_FMT_INVALID;
  14404. +}
  14405. +
  14406. +uint64_t CActiveAEResample::GetAVChannel(enum AEChannel aechannel)
  14407. +{
  14408. + #ifdef DEBUG_VERBOSE
  14409. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14410. + #endif
  14411. + switch (aechannel)
  14412. + {
  14413. + case AE_CH_FL: return AV_CH_FRONT_LEFT;
  14414. + case AE_CH_FR: return AV_CH_FRONT_RIGHT;
  14415. + case AE_CH_FC: return AV_CH_FRONT_CENTER;
  14416. + case AE_CH_LFE: return AV_CH_LOW_FREQUENCY;
  14417. + case AE_CH_BL: return AV_CH_BACK_LEFT;
  14418. + case AE_CH_BR: return AV_CH_BACK_RIGHT;
  14419. + case AE_CH_FLOC: return AV_CH_FRONT_LEFT_OF_CENTER;
  14420. + case AE_CH_FROC: return AV_CH_FRONT_RIGHT_OF_CENTER;
  14421. + case AE_CH_BC: return AV_CH_BACK_CENTER;
  14422. + case AE_CH_SL: return AV_CH_SIDE_LEFT;
  14423. + case AE_CH_SR: return AV_CH_SIDE_RIGHT;
  14424. + case AE_CH_TC: return AV_CH_TOP_CENTER;
  14425. + case AE_CH_TFL: return AV_CH_TOP_FRONT_LEFT;
  14426. + case AE_CH_TFC: return AV_CH_TOP_FRONT_CENTER;
  14427. + case AE_CH_TFR: return AV_CH_TOP_FRONT_RIGHT;
  14428. + case AE_CH_TBL: return AV_CH_TOP_BACK_LEFT;
  14429. + case AE_CH_TBC: return AV_CH_TOP_BACK_CENTER;
  14430. + case AE_CH_TBR: return AV_CH_TOP_BACK_RIGHT;
  14431. + default:
  14432. + return 0;
  14433. + }
  14434. +}
  14435. +
  14436. +int CActiveAEResample::GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout)
  14437. +{
  14438. + #ifdef DEBUG_VERBOSE
  14439. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14440. + #endif
  14441. + return m_dllAvUtil.av_get_channel_layout_channel_index(layout, GetAVChannel(aechannel));
  14442. +}
  14443. +
  14444. +#endif
  14445. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h
  14446. new file mode 100644
  14447. index 0000000..8371c33
  14448. --- /dev/null
  14449. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.h
  14450. @@ -0,0 +1,65 @@
  14451. +#pragma once
  14452. +/*
  14453. + * Copyright (C) 2010-2013 Team XBMC
  14454. + * http://xbmc.org
  14455. + *
  14456. + * This Program is free software; you can redistribute it and/or modify
  14457. + * it under the terms of the GNU General Public License as published by
  14458. + * the Free Software Foundation; either version 2, or (at your option)
  14459. + * any later version.
  14460. + *
  14461. + * This Program is distributed in the hope that it will be useful,
  14462. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14463. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14464. + * GNU General Public License for more details.
  14465. + *
  14466. + * You should have received a copy of the GNU General Public License
  14467. + * along with XBMC; see the file COPYING. If not, see
  14468. + * <http://www.gnu.org/licenses/>.
  14469. + *
  14470. + */
  14471. +
  14472. +#include "linux/OMXCore.h"
  14473. +
  14474. +namespace ActiveAE
  14475. +{
  14476. +
  14477. +class CActiveAEResample
  14478. +{
  14479. +public:
  14480. + CActiveAEResample();
  14481. + virtual ~CActiveAEResample();
  14482. + bool Init(uint64_t dst_chan_layout, int dst_channels, int dst_rate, AVSampleFormat dst_fmt, int dst_bits, uint64_t src_chan_layout, int src_channels, int src_rate, AVSampleFormat src_fmt, int src_bits, bool upmix, bool normalize, CAEChannelInfo *remapLayout, AEQuality quality);
  14483. + int Resample(uint8_t **dst_buffer, int dst_samples, uint8_t **src_buffer, int src_samples, double ratio);
  14484. + int64_t GetDelay(int64_t base);
  14485. + int GetBufferedSamples();
  14486. + int CalcDstSampleCount(int src_samples, int dst_rate, int src_rate);
  14487. + int GetSrcBufferSize(int samples);
  14488. + int GetDstBufferSize(int samples);
  14489. + static uint64_t GetAVChannelLayout(CAEChannelInfo &info);
  14490. +// static CAEChannelInfo GetAEChannelLayout(uint64_t layout);
  14491. + static AVSampleFormat GetAVSampleFormat(AEDataFormat format);
  14492. + static AEDataFormat GetAESampleFormat(AVSampleFormat format, int bits);
  14493. + static uint64_t GetAVChannel(enum AEChannel aechannel);
  14494. + int GetAVChannelIndex(enum AEChannel aechannel, uint64_t layout);
  14495. +
  14496. +protected:
  14497. + void DeInit();
  14498. + DllAvUtil m_dllAvUtil;
  14499. + DllSwResample m_dllSwResample;
  14500. + bool m_loaded;
  14501. + uint64_t m_src_chan_layout, m_dst_chan_layout;
  14502. + int m_src_rate, m_dst_rate;
  14503. + int m_src_channels, m_dst_channels;
  14504. + AVSampleFormat m_src_fmt, m_dst_fmt;
  14505. + int m_src_bits, m_dst_bits;
  14506. +
  14507. + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_input;
  14508. + OMX_AUDIO_PARAM_PCMMODETYPE m_pcm_output;
  14509. + COMXCoreComponent m_omx_mixer;
  14510. + bool m_Initialized;
  14511. + AVSampleFormat m_last_src_fmt, m_last_dst_fmt;
  14512. + int m_last_src_channels, m_last_dst_channels;
  14513. +};
  14514. +
  14515. +}
  14516. diff --git a/xbmc/cores/AudioEngine/Makefile.in b/xbmc/cores/AudioEngine/Makefile.in
  14517. index b49c3cc..2ba50f9 100644
  14518. --- a/xbmc/cores/AudioEngine/Makefile.in
  14519. +++ b/xbmc/cores/AudioEngine/Makefile.in
  14520. @@ -31,6 +31,7 @@ SRCS += Engines/ActiveAE/ActiveAESink.cpp
  14521. SRCS += Engines/ActiveAE/ActiveAEStream.cpp
  14522. SRCS += Engines/ActiveAE/ActiveAESound.cpp
  14523. SRCS += Engines/ActiveAE/ActiveAEResample.cpp
  14524. +SRCS += Engines/ActiveAE/ActiveAEResamplePi.cpp
  14525. SRCS += Engines/ActiveAE/ActiveAEBuffer.cpp
  14526. ifeq (@USE_ANDROID@,1)
  14527. diff --git a/xbmc/linux/OMXCore.cpp b/xbmc/linux/OMXCore.cpp
  14528. index 99e407a..8d3c86a 100644
  14529. --- a/xbmc/linux/OMXCore.cpp
  14530. +++ b/xbmc/linux/OMXCore.cpp
  14531. @@ -448,7 +448,7 @@ void COMXCoreComponent::FlushAll()
  14532. void COMXCoreComponent::FlushInput()
  14533. {
  14534. - if(!m_handle)
  14535. + if(!m_handle || m_resource_error)
  14536. return;
  14537. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  14538. @@ -470,7 +470,7 @@ void COMXCoreComponent::FlushInput()
  14539. void COMXCoreComponent::FlushOutput()
  14540. {
  14541. - if(!m_handle)
  14542. + if(!m_handle || m_resource_error)
  14543. return;
  14544. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  14545. --
  14546. 1.9.3
  14547. From 07042c916d780bf4acb742e174005aa1e38f3a13 Mon Sep 17 00:00:00 2001
  14548. From: popcornmix <popcornmix@gmail.com>
  14549. Date: Thu, 27 Mar 2014 00:22:05 +0000
  14550. Subject: [PATCH 60/94] [PiResample] Work around AE not providing correct
  14551. src_bits
  14552. ---
  14553. .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 13 +++++++++++--
  14554. 1 file changed, 11 insertions(+), 2 deletions(-)
  14555. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14556. index 1d7b425..a91e208 100644
  14557. --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14558. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14559. @@ -97,16 +97,25 @@ bool CActiveAEResample::Init(uint64_t dst_chan_layout, int dst_channels, int dst
  14560. if (!m_loaded)
  14561. return false;
  14562. + if (src_bits == 0)
  14563. + {
  14564. + if (src_fmt == AV_SAMPLE_FMT_U8) src_bits = 8;
  14565. + else if (src_fmt == AV_SAMPLE_FMT_S16) src_bits = 16;
  14566. + else if (src_fmt == AV_SAMPLE_FMT_S32) src_bits = 32;
  14567. + else if (src_fmt == AV_SAMPLE_FMT_FLT) src_bits = 32;
  14568. + }
  14569. + assert(src_bits && dst_bits);
  14570. +
  14571. m_dst_chan_layout = dst_chan_layout;
  14572. m_dst_channels = dst_channels;
  14573. m_dst_rate = dst_rate;
  14574. m_dst_fmt = dst_fmt;
  14575. - m_dst_bits = dst_bits ? dst_bits : 8;
  14576. + m_dst_bits = dst_bits;
  14577. m_src_chan_layout = src_chan_layout;
  14578. m_src_channels = src_channels;
  14579. m_src_rate = src_rate;
  14580. m_src_fmt = src_fmt;
  14581. - m_src_bits = src_bits ? src_bits : 8;
  14582. + m_src_bits = src_bits;
  14583. if (m_dst_chan_layout == 0)
  14584. m_dst_chan_layout = m_dllAvUtil.av_get_default_channel_layout(m_dst_channels);
  14585. --
  14586. 1.9.3
  14587. From 16e8c9550b1afc0a4f5c050cc10c2c19ec9cea38 Mon Sep 17 00:00:00 2001
  14588. From: popcornmix <popcornmix@gmail.com>
  14589. Date: Tue, 25 Mar 2014 19:43:07 +0000
  14590. Subject: [PATCH 61/94] [ffmpeg] Speed up wtv index creation
  14591. The index creation is O(N^2) with number of entries (typically thousands).
  14592. On a Pi this can take more than 60 seconds to execute for a recording of a few hours.
  14593. By replacing with an O(N) loop, this takes virtually zero time
  14594. ---
  14595. lib/ffmpeg/libavformat/wtvdec.c | 18 ++++++++++--------
  14596. 1 file changed, 10 insertions(+), 8 deletions(-)
  14597. diff --git a/lib/ffmpeg/libavformat/wtvdec.c b/lib/ffmpeg/libavformat/wtvdec.c
  14598. index e423370..70898bd 100644
  14599. --- a/lib/ffmpeg/libavformat/wtvdec.c
  14600. +++ b/lib/ffmpeg/libavformat/wtvdec.c
  14601. @@ -980,21 +980,23 @@ static int read_header(AVFormatContext *s)
  14602. pb = wtvfile_open(s, root, root_size, ff_timeline_table_0_entries_Events_le16);
  14603. if (pb) {
  14604. int i;
  14605. + AVIndexEntry *e = wtv->index_entries;
  14606. + AVIndexEntry *e_end = wtv->index_entries + wtv->nb_index_entries - 1;
  14607. + uint64_t last_position = 0;
  14608. while (1) {
  14609. uint64_t frame_nb = avio_rl64(pb);
  14610. uint64_t position = avio_rl64(pb);
  14611. + while (frame_nb > e->size && e <= e_end) {
  14612. + e->pos = last_position;
  14613. + e++;
  14614. + }
  14615. if (url_feof(pb))
  14616. break;
  14617. - for (i = wtv->nb_index_entries - 1; i >= 0; i--) {
  14618. - AVIndexEntry *e = wtv->index_entries + i;
  14619. - if (frame_nb > e->size)
  14620. - break;
  14621. - if (position > e->pos)
  14622. - e->pos = position;
  14623. - }
  14624. + last_position = position;
  14625. }
  14626. + e_end->pos = last_position;
  14627. wtvfile_close(pb);
  14628. - st->duration = wtv->index_entries[wtv->nb_index_entries - 1].timestamp;
  14629. + st->duration = e_end->timestamp;
  14630. }
  14631. }
  14632. }
  14633. --
  14634. 1.9.3
  14635. From c95293a4cfd39a5296b434c330c3e6e24831bb6e Mon Sep 17 00:00:00 2001
  14636. From: popcornmix <popcornmix@gmail.com>
  14637. Date: Mon, 7 Apr 2014 18:19:32 +0100
  14638. Subject: [PATCH 62/94] [rbp/omxplayer] When opening a stream don't try to
  14639. update gui so often
  14640. ---
  14641. xbmc/dialogs/GUIDialogBusy.cpp | 4 ++++
  14642. 1 file changed, 4 insertions(+)
  14643. diff --git a/xbmc/dialogs/GUIDialogBusy.cpp b/xbmc/dialogs/GUIDialogBusy.cpp
  14644. index e9ba7d3..0fdc3c2 100644
  14645. --- a/xbmc/dialogs/GUIDialogBusy.cpp
  14646. +++ b/xbmc/dialogs/GUIDialogBusy.cpp
  14647. @@ -64,7 +64,11 @@ bool CGUIDialogBusy::WaitOnEvent(CEvent &event, unsigned int displaytime /* = 10
  14648. if (dialog)
  14649. {
  14650. dialog->Show();
  14651. +#ifdef TARGET_RASPBERRY_PI
  14652. + while(!event.WaitMSec(100))
  14653. +#else
  14654. while(!event.WaitMSec(1))
  14655. +#endif
  14656. {
  14657. g_windowManager.ProcessRenderLoop(false);
  14658. if (allowCancel && dialog->IsCanceled())
  14659. --
  14660. 1.9.3
  14661. From 9420d803f17902c7d9f1e6734ab42a78c5d67572 Mon Sep 17 00:00:00 2001
  14662. From: popcornmix <popcornmix@gmail.com>
  14663. Date: Mon, 7 Apr 2014 15:28:57 +0100
  14664. Subject: [PATCH 63/94] [omxcodec] Clamp video texture at edges to avoid image
  14665. wrapping
  14666. ---
  14667. xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 ++
  14668. 1 file changed, 2 insertions(+)
  14669. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  14670. index a57abe4..e22a153 100644
  14671. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  14672. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  14673. @@ -1339,6 +1339,8 @@ void CLinuxRendererGLES::RenderOpenMax(int index, int field)
  14674. GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
  14675. glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter);
  14676. glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter);
  14677. + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  14678. + glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  14679. g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
  14680. --
  14681. 1.9.3
  14682. From 49c65c8d083952be840d8730f3fa40cfd5e0211c Mon Sep 17 00:00:00 2001
  14683. From: popcornmix <popcornmix@gmail.com>
  14684. Date: Mon, 7 Apr 2014 17:36:19 +0100
  14685. Subject: [PATCH 64/94] [PiSink] Remove unneeded header and use CAEChannelInfo
  14686. directly
  14687. ---
  14688. .../AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp | 1 -
  14689. xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 14 +++++++-------
  14690. 2 files changed, 7 insertions(+), 8 deletions(-)
  14691. diff --git a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14692. index a91e208..60c5e04 100644
  14693. --- a/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14694. +++ b/xbmc/cores/AudioEngine/Engines/ActiveAE/ActiveAEResamplePi.cpp
  14695. @@ -24,7 +24,6 @@
  14696. #include "ActiveAEResample.h"
  14697. #include "linux/RBP.h"
  14698. -#include "cores/omxplayer/PCMRemap.h"
  14699. #include "settings/Settings.h"
  14700. #include "utils/log.h"
  14701. diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  14702. index 9ce00e3..070e6eb 100644
  14703. --- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  14704. +++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  14705. @@ -78,9 +78,9 @@ static void SetAudioProps(bool stream_channels, uint32_t channel_map)
  14706. CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map);
  14707. }
  14708. -static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
  14709. +static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough)
  14710. {
  14711. - unsigned int channels = format.m_channelLayout.Count();
  14712. + unsigned int channels = channelLayout.Count();
  14713. uint32_t channel_map = 0;
  14714. if (passthrough)
  14715. return 0;
  14716. @@ -119,12 +119,12 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
  14717. // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels
  14718. // but no BR BL channels, we use the wide map in order to open only the num of channels really
  14719. // needed.
  14720. - if (format.m_channelLayout.HasChannel(AE_CH_BL) && !format.m_channelLayout.HasChannel(AE_CH_SL))
  14721. + if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL))
  14722. map = map_back;
  14723. for (unsigned int i = 0; i < channels; ++i)
  14724. {
  14725. - AEChannel c = format.m_channelLayout[i];
  14726. + AEChannel c = channelLayout[i];
  14727. unsigned int chan = 0;
  14728. if ((unsigned int)c < sizeof map_normal / sizeof *map_normal)
  14729. chan = map[(unsigned int)c];
  14730. @@ -155,9 +155,9 @@ static uint32_t GetChannelMap(AEAudioFormat &format, bool passthrough)
  14731. 0xff, // 7
  14732. 0x13, // 7.1
  14733. };
  14734. - uint8_t cea = format.m_channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels];
  14735. + uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels];
  14736. if (cea == 0xff)
  14737. - CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, format.m_channelLayout.HasChannel(AE_CH_LFE), channels);
  14738. + CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels);
  14739. channel_map |= cea << 24;
  14740. @@ -189,7 +189,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device)
  14741. format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER;
  14742. format.m_frameSamples = format.m_frames * channels;
  14743. - SetAudioProps(m_passthrough, GetChannelMap(format, m_passthrough));
  14744. + SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough));
  14745. m_format = format;
  14746. m_sinkbuffer_sec_per_byte = 1.0 / (double)(m_format.m_frameSize * m_format.m_sampleRate);
  14747. --
  14748. 1.9.3
  14749. From 6ce35e828b39e0a8f2d81cb6fb6162edd53468a8 Mon Sep 17 00:00:00 2001
  14750. From: popcornmix <popcornmix@gmail.com>
  14751. Date: Mon, 7 Apr 2014 17:37:41 +0100
  14752. Subject: [PATCH 65/94] [omxplayer] Remove PCMRemap and handle multichannel
  14753. mixing like ActiveAE does
  14754. ---
  14755. tools/buildsteps/rbpi/config-xbmc-makefile | 4 +-
  14756. tools/depends/target/alsa-lib/Makefile | 2 +-
  14757. tools/depends/target/libcec/Makefile | 2 +-
  14758. xbmc/cores/omxplayer/Makefile.in | 1 -
  14759. xbmc/cores/omxplayer/OMXAudio.cpp | 395 +++++++++-----
  14760. xbmc/cores/omxplayer/OMXAudio.h | 9 +-
  14761. xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp | 39 +-
  14762. xbmc/cores/omxplayer/OMXAudioCodecOMX.h | 5 +-
  14763. xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 4 +-
  14764. xbmc/cores/omxplayer/PCMRemap.cpp | 813 -----------------------------
  14765. xbmc/cores/omxplayer/PCMRemap.h | 151 ------
  14766. 11 files changed, 294 insertions(+), 1131 deletions(-)
  14767. delete mode 100644 xbmc/cores/omxplayer/PCMRemap.cpp
  14768. delete mode 100644 xbmc/cores/omxplayer/PCMRemap.h
  14769. diff --git a/tools/buildsteps/rbpi/config-xbmc-makefile b/tools/buildsteps/rbpi/config-xbmc-makefile
  14770. index 761a3b4..18600e2 100644
  14771. --- a/tools/buildsteps/rbpi/config-xbmc-makefile
  14772. +++ b/tools/buildsteps/rbpi/config-xbmc-makefile
  14773. @@ -12,10 +12,10 @@ CONFIGURE = cp -f $(CONFIG_SUB) $(CONFIG_GUESS) build-aux/ ;\
  14774. --disable-gl --enable-gles --enable-airplay \
  14775. --enable-airtunes --enable-libcec --enable-player=omxplayer \
  14776. --disable-sdl --disable-x11 --disable-xrandr --disable-openmax \
  14777. - --disable-optical-drive --disable-dvdcss --disable-joystick \
  14778. + --disable-optical-drive --enable-dvdcss --enable-openmax --disable-joystick \
  14779. --disable-crystalhd --disable-vtbdecoder --disable-vaapi \
  14780. --disable-vdpau --disable-projectm --disable-rsxs --disable-fishbmc \
  14781. - --disable-alsa
  14782. + --enable-alsa
  14783. all: $(SOURCE)/libxbmc.so
  14784. diff --git a/tools/depends/target/alsa-lib/Makefile b/tools/depends/target/alsa-lib/Makefile
  14785. index b03fc19..a04d933 100644
  14786. --- a/tools/depends/target/alsa-lib/Makefile
  14787. +++ b/tools/depends/target/alsa-lib/Makefile
  14788. @@ -19,7 +19,7 @@ CONFIGURE=cp -f $(CONFIG_SUB) $(CONFIG_GUESS) .; \
  14789. --with-ctl-plugins=ext \
  14790. --with-pcm-plugins="copy,linear,route,mulaw,alaw,adpcm,rate,plug,multi,file,null,empty,share,meter,hooks,lfloat,ladspa,asym,iec958,softvol,extplug,ioplug,mmap_emul" \
  14791. --disable-resmgr --enable-aload --enable-mixer --enable-pcm --disable-rawmidi --enable-hwdep --disable-seq --disable-alisp --disable-old-symbols --disable-python \
  14792. - --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --disable-shared \
  14793. + --with-softfloat=yes --with-libdl=yes --with-pthread=yes --with-librt=no --enable-shared \
  14794. LIBDYLIB=$(PLATFORM)/src/.libs/$(LIBNAME).a
  14795. diff --git a/tools/depends/target/libcec/Makefile b/tools/depends/target/libcec/Makefile
  14796. index 16fec1b..d18f1c8 100644
  14797. --- a/tools/depends/target/libcec/Makefile
  14798. +++ b/tools/depends/target/libcec/Makefile
  14799. @@ -8,7 +8,7 @@ SOURCE=$(LIBNAME)-$(VERSION)-2
  14800. ARCHIVE=$(SOURCE).tar.gz
  14801. # configuration settings
  14802. -CONFIGURE=./configure --prefix=$(PREFIX) --disable-rpi \
  14803. +CONFIGURE=./configure --prefix=$(PREFIX) --enable-rpi \
  14804. LIBDYLIB=$(PLATFORM)/src/lib/.libs/libcec.la
  14805. diff --git a/xbmc/cores/omxplayer/Makefile.in b/xbmc/cores/omxplayer/Makefile.in
  14806. index 3163282..e5cad70 100644
  14807. --- a/xbmc/cores/omxplayer/Makefile.in
  14808. +++ b/xbmc/cores/omxplayer/Makefile.in
  14809. @@ -7,7 +7,6 @@ SRCS += OMXAudioCodecOMX.cpp
  14810. SRCS += OMXPlayerAudio.cpp
  14811. SRCS += OMXPlayerVideo.cpp
  14812. SRCS += OMXImage.cpp
  14813. -SRCS += PCMRemap.cpp
  14814. LIB = omxplayer.a
  14815. diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
  14816. index 72e42ec..d9beb68 100644
  14817. --- a/xbmc/cores/omxplayer/OMXAudio.cpp
  14818. +++ b/xbmc/cores/omxplayer/OMXAudio.cpp
  14819. @@ -29,6 +29,7 @@
  14820. #include "OMXAudio.h"
  14821. #include "Application.h"
  14822. #include "utils/log.h"
  14823. +#include "linux/RBP.h"
  14824. #define CLASSNAME "COMXAudio"
  14825. @@ -40,6 +41,7 @@
  14826. #include "guilib/LocalizeStrings.h"
  14827. #include "cores/AudioEngine/Utils/AEConvert.h"
  14828. #include "cores/AudioEngine/AEFactory.h"
  14829. +#include "DllSwResample.h"
  14830. using namespace std;
  14831. @@ -404,28 +406,147 @@ bool COMXAudio::PortSettingsChanged()
  14832. return true;
  14833. }
  14834. -static unsigned count_bits(int64_t value)
  14835. +static uint64_t GetAVChannelLayout(CAEChannelInfo &info)
  14836. {
  14837. - unsigned bits = 0;
  14838. - for(;value;++bits)
  14839. - value &= value - 1;
  14840. - return bits;
  14841. + #ifdef DEBUG_VERBOSE
  14842. + CLog::Log(LOGINFO, "%s::%s", CLASSNAME, __func__);
  14843. + #endif
  14844. + uint64_t channelLayout = 0;
  14845. + if (info.HasChannel(AE_CH_FL)) channelLayout |= AV_CH_FRONT_LEFT;
  14846. + if (info.HasChannel(AE_CH_FR)) channelLayout |= AV_CH_FRONT_RIGHT;
  14847. + if (info.HasChannel(AE_CH_FC)) channelLayout |= AV_CH_FRONT_CENTER;
  14848. + if (info.HasChannel(AE_CH_LFE)) channelLayout |= AV_CH_LOW_FREQUENCY;
  14849. + if (info.HasChannel(AE_CH_BL)) channelLayout |= AV_CH_BACK_LEFT;
  14850. + if (info.HasChannel(AE_CH_BR)) channelLayout |= AV_CH_BACK_RIGHT;
  14851. + if (info.HasChannel(AE_CH_FLOC)) channelLayout |= AV_CH_FRONT_LEFT_OF_CENTER;
  14852. + if (info.HasChannel(AE_CH_FROC)) channelLayout |= AV_CH_FRONT_RIGHT_OF_CENTER;
  14853. + if (info.HasChannel(AE_CH_BC)) channelLayout |= AV_CH_BACK_CENTER;
  14854. + if (info.HasChannel(AE_CH_SL)) channelLayout |= AV_CH_SIDE_LEFT;
  14855. + if (info.HasChannel(AE_CH_SR)) channelLayout |= AV_CH_SIDE_RIGHT;
  14856. + if (info.HasChannel(AE_CH_TC)) channelLayout |= AV_CH_TOP_CENTER;
  14857. + if (info.HasChannel(AE_CH_TFL)) channelLayout |= AV_CH_TOP_FRONT_LEFT;
  14858. + if (info.HasChannel(AE_CH_TFC)) channelLayout |= AV_CH_TOP_FRONT_CENTER;
  14859. + if (info.HasChannel(AE_CH_TFR)) channelLayout |= AV_CH_TOP_FRONT_RIGHT;
  14860. + if (info.HasChannel(AE_CH_TBL)) channelLayout |= AV_CH_TOP_BACK_LEFT;
  14861. + if (info.HasChannel(AE_CH_TBC)) channelLayout |= AV_CH_TOP_BACK_CENTER;
  14862. + if (info.HasChannel(AE_CH_TBR)) channelLayout |= AV_CH_TOP_BACK_RIGHT;
  14863. +
  14864. + return channelLayout;
  14865. +}
  14866. +
  14867. +static void SetAudioProps(bool stream_channels, uint32_t channel_map)
  14868. +{
  14869. + char command[80], response[80];
  14870. +
  14871. + sprintf(command, "hdmi_stream_channels %d", stream_channels ? 1 : 0);
  14872. + vc_gencmd(response, sizeof response, command);
  14873. +
  14874. + sprintf(command, "hdmi_channel_map 0x%08x", channel_map);
  14875. + vc_gencmd(response, sizeof response, command);
  14876. +
  14877. + CLog::Log(LOGDEBUG, "%s:%s hdmi_stream_channels %d hdmi_channel_map %08x", CLASSNAME, __func__, stream_channels, channel_map);
  14878. +}
  14879. +
  14880. +static uint32_t GetChannelMap(const CAEChannelInfo &channelLayout, bool passthrough)
  14881. +{
  14882. + unsigned int channels = channelLayout.Count();
  14883. + uint32_t channel_map = 0;
  14884. + if (passthrough)
  14885. + return 0;
  14886. +
  14887. + static const unsigned char map_normal[] =
  14888. + {
  14889. + 0, //AE_CH_RAW ,
  14890. + 1, //AE_CH_FL
  14891. + 2, //AE_CH_FR
  14892. + 4, //AE_CH_FC
  14893. + 3, //AE_CH_LFE
  14894. + 7, //AE_CH_BL
  14895. + 8, //AE_CH_BR
  14896. + 1, //AE_CH_FLOC,
  14897. + 2, //AE_CH_FROC,
  14898. + 4, //AE_CH_BC,
  14899. + 5, //AE_CH_SL
  14900. + 6, //AE_CH_SR
  14901. + };
  14902. + static const unsigned char map_back[] =
  14903. + {
  14904. + 0, //AE_CH_RAW ,
  14905. + 1, //AE_CH_FL
  14906. + 2, //AE_CH_FR
  14907. + 4, //AE_CH_FC
  14908. + 3, //AE_CH_LFE
  14909. + 5, //AE_CH_BL
  14910. + 6, //AE_CH_BR
  14911. + 1, //AE_CH_FLOC,
  14912. + 2, //AE_CH_FROC,
  14913. + 4, //AE_CH_BC,
  14914. + 5, //AE_CH_SL
  14915. + 6, //AE_CH_SR
  14916. + };
  14917. + const unsigned char *map = map_normal;
  14918. + // According to CEA-861-D only RL and RR are known. In case of a format having SL and SR channels
  14919. + // but no BR BL channels, we use the wide map in order to open only the num of channels really
  14920. + // needed.
  14921. + if (channelLayout.HasChannel(AE_CH_BL) && !channelLayout.HasChannel(AE_CH_SL))
  14922. + map = map_back;
  14923. +
  14924. + for (unsigned int i = 0; i < channels; ++i)
  14925. + {
  14926. + AEChannel c = channelLayout[i];
  14927. + unsigned int chan = 0;
  14928. + if ((unsigned int)c < sizeof map_normal / sizeof *map_normal)
  14929. + chan = map[(unsigned int)c];
  14930. + if (chan > 0)
  14931. + channel_map |= (chan-1) << (3*i);
  14932. + }
  14933. + // These numbers are from Table 28 Audio InfoFrame Data byte 4 of CEA 861
  14934. + // and describe the speaker layout
  14935. + static const uint8_t cea_map[] = {
  14936. + 0xff, // 0
  14937. + 0xff, // 1
  14938. + 0x00, // 2.0
  14939. + 0x02, // 3.0
  14940. + 0x08, // 4.0
  14941. + 0x0a, // 5.0
  14942. + 0xff, // 6
  14943. + 0x12, // 7.0
  14944. + 0xff, // 8
  14945. + };
  14946. + static const uint8_t cea_map_lfe[] = {
  14947. + 0xff, // 0
  14948. + 0xff, // 1
  14949. + 0xff, // 2
  14950. + 0x01, // 2.1
  14951. + 0x03, // 3.1
  14952. + 0x09, // 4.1
  14953. + 0x0b, // 5.1
  14954. + 0xff, // 7
  14955. + 0x13, // 7.1
  14956. + };
  14957. + uint8_t cea = channelLayout.HasChannel(AE_CH_LFE) ? cea_map_lfe[channels] : cea_map[channels];
  14958. + if (cea == 0xff)
  14959. + CLog::Log(LOGERROR, "%s::%s - Unexpected CEA mapping %d,%d", CLASSNAME, __func__, channelLayout.HasChannel(AE_CH_LFE), channels);
  14960. +
  14961. + channel_map |= cea << 24;
  14962. +
  14963. + return channel_map;
  14964. }
  14965. -bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, uint64_t channelMap, bool bUsePassthrough, bool bUseHWDecode)
  14966. +bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, CAEChannelInfo channelMap, bool bUsePassthrough, bool bUseHWDecode)
  14967. {
  14968. CSingleLock lock (m_critSection);
  14969. OMX_ERRORTYPE omx_err;
  14970. Deinitialize();
  14971. - if(!m_dllAvUtil.Load())
  14972. + if (!m_dllAvUtil.Load())
  14973. return false;
  14974. m_HWDecode = bUseHWDecode;
  14975. m_Passthrough = bUsePassthrough;
  14976. - m_InputChannels = count_bits(channelMap);
  14977. + m_InputChannels = channelMap.Count();
  14978. m_format = format;
  14979. if(m_InputChannels == 0)
  14980. @@ -471,26 +592,133 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
  14981. if (!m_Passthrough)
  14982. {
  14983. - enum PCMChannels inLayout[OMX_AUDIO_MAXCHANNELS];
  14984. - enum PCMChannels outLayout[OMX_AUDIO_MAXCHANNELS];
  14985. - enum PCMLayout layout = (enum PCMLayout)std::max(0, CSettings::Get().GetInt("audiooutput.channels")-1);
  14986. + bool upmix = CSettings::Get().GetBool("audiooutput.stereoupmix");
  14987. + bool normalize = CSettings::Get().GetBool("audiooutput.normalizelevels");
  14988. + void *remapLayout = NULL;
  14989. +
  14990. + CAEChannelInfo stdLayout = (enum AEStdChLayout)CSettings::Get().GetInt("audiooutput.channels");
  14991. +
  14992. // ignore layout setting for analogue
  14993. if (CSettings::Get().GetBool("audiooutput.dualaudio") || CSettings::Get().GetString("audiooutput.audiodevice") == "PI:Analogue")
  14994. - layout = PCM_LAYOUT_2_0;
  14995. + stdLayout = AE_CH_LAYOUT_2_0;
  14996. // force out layout to stereo if input is not multichannel - it gives the receiver a chance to upmix
  14997. - if (channelMap == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT) || channelMap == AV_CH_FRONT_CENTER)
  14998. - layout = PCM_LAYOUT_2_0;
  14999. - BuildChannelMap(inLayout, channelMap);
  15000. - m_OutputChannels = BuildChannelMapCEA(outLayout, GetChannelLayout(layout));
  15001. - CPCMRemap m_remap;
  15002. - m_remap.Reset();
  15003. - /*outLayout = */m_remap.SetInputFormat (m_InputChannels, inLayout, CAEUtil::DataFormatToBits(m_format.m_dataFormat) / 8, m_format.m_sampleRate, layout);
  15004. - m_remap.SetOutputFormat(m_OutputChannels, outLayout);
  15005. - m_remap.GetDownmixMatrix(m_downmix_matrix);
  15006. - m_wave_header.dwChannelMask = channelMap;
  15007. - BuildChannelMapOMX(m_input_channels, channelMap);
  15008. - BuildChannelMapOMX(m_output_channels, GetChannelLayout(layout));
  15009. + if (m_InputChannels <= 2)
  15010. + stdLayout = AE_CH_LAYOUT_2_0;
  15011. +
  15012. + uint64_t m_dst_chan_layout = GetAVChannelLayout(stdLayout);
  15013. + uint64_t m_src_chan_layout = GetAVChannelLayout(channelMap);
  15014. + m_OutputChannels = stdLayout.Count();
  15015. +
  15016. + int m_dst_channels = m_OutputChannels;
  15017. + int m_src_channels = m_InputChannels;
  15018. + SetAudioProps(m_Passthrough, GetChannelMap(stdLayout, m_Passthrough));
  15019. +
  15020. + CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d norm:%d upmix:%d %llx:%llx", CLASSNAME, __func__, remapLayout, m_src_channels, m_dst_channels, normalize, upmix, m_src_chan_layout, m_dst_chan_layout);
  15021. +
  15022. + // this code is just uses ffmpeg to produce the 8x8 mixing matrix
  15023. + // dummy sample rate and format, as we only care about channel mapping
  15024. + DllSwResample m_dllSwResample;
  15025. + if (!m_dllSwResample.Load())
  15026. + return false;
  15027. +
  15028. + SwrContext *m_pContext = m_dllSwResample.swr_alloc_set_opts(NULL, m_dst_chan_layout, AV_SAMPLE_FMT_FLT, 48000,
  15029. + m_src_chan_layout, AV_SAMPLE_FMT_FLT, 48000, 0, NULL);
  15030. + if(!m_pContext)
  15031. + {
  15032. + CLog::Log(LOGERROR, "COMXAudio::Init - create context failed");
  15033. + return false;
  15034. + }
  15035. + // tell resampler to clamp float values
  15036. + // not required for sink stage (remapLayout == true)
  15037. + if (!remapLayout && normalize)
  15038. + {
  15039. + av_opt_set_double(m_pContext, "rematrix_maxval", 1.0, 0);
  15040. + }
  15041. +
  15042. + // stereo upmix
  15043. + if (upmix && m_src_channels == 2 && m_dst_channels > 2)
  15044. + {
  15045. + double m_rematrix[AE_CH_MAX][AE_CH_MAX];
  15046. + memset(m_rematrix, 0, sizeof(m_rematrix));
  15047. + for (int out=0; out<m_dst_channels; out++)
  15048. + {
  15049. + uint64_t out_chan = m_dllAvUtil.av_channel_layout_extract_channel(m_dst_chan_layout, out);
  15050. + switch(out_chan)
  15051. + {
  15052. + case AV_CH_FRONT_LEFT:
  15053. + case AV_CH_BACK_LEFT:
  15054. + case AV_CH_SIDE_LEFT:
  15055. + m_rematrix[out][0] = 1.0;
  15056. + break;
  15057. + case AV_CH_FRONT_RIGHT:
  15058. + case AV_CH_BACK_RIGHT:
  15059. + case AV_CH_SIDE_RIGHT:
  15060. + m_rematrix[out][1] = 1.0;
  15061. + break;
  15062. + case AV_CH_FRONT_CENTER:
  15063. + m_rematrix[out][0] = 0.5;
  15064. + m_rematrix[out][1] = 0.5;
  15065. + break;
  15066. + case AV_CH_LOW_FREQUENCY:
  15067. + m_rematrix[out][0] = 0.5;
  15068. + m_rematrix[out][1] = 0.5;
  15069. + break;
  15070. + default:
  15071. + break;
  15072. + }
  15073. + }
  15074. +
  15075. + if (m_dllSwResample.swr_set_matrix(m_pContext, (const double*)m_rematrix, AE_CH_MAX) < 0)
  15076. + {
  15077. + CLog::Log(LOGERROR, "COMXAudio::Init - setting channel matrix failed");
  15078. + return false;
  15079. + }
  15080. + }
  15081. +
  15082. + if (m_dllSwResample.swr_init(m_pContext) < 0)
  15083. + {
  15084. + CLog::Log(LOGERROR, "COMXAudio::Init - init resampler failed");
  15085. + return false;
  15086. + }
  15087. +
  15088. + const int samples = 8;
  15089. + uint8_t *output, *input;
  15090. + av_samples_alloc(&output, NULL, m_dst_channels, samples, AV_SAMPLE_FMT_FLT, 1);
  15091. + av_samples_alloc(&input , NULL, m_src_channels, samples, AV_SAMPLE_FMT_FLT, 1);
  15092. +
  15093. + // Produce "identity" samples
  15094. + float *f = (float *)input;
  15095. + for (int j=0; j < samples; j++)
  15096. + for (int i=0; i < m_src_channels; i++)
  15097. + *f++ = i == j ? 1.0f : 0.0f;
  15098. +
  15099. + int ret = m_dllSwResample.swr_convert(m_pContext, &output, samples, (const uint8_t **)&input, samples);
  15100. + if (ret < 0)
  15101. + CLog::Log(LOGERROR, "COMXAudio::Resample - resample failed");
  15102. +
  15103. + f = (float *)output;
  15104. + for (int j=0; j < 8; j++)
  15105. + {
  15106. + for (int i=0; i < m_dst_channels; i++)
  15107. + m_downmix_matrix[8*i+j] = *f++;
  15108. + for (int i=m_dst_channels; i < 8; i++)
  15109. + m_downmix_matrix[8*i+j] = 0.0f;
  15110. + }
  15111. +
  15112. + for (int j=0; j < 8; j++)
  15113. + {
  15114. + char s[128] = {}, *t=s;
  15115. + for (int i=0; i < 8; i++)
  15116. + t += sprintf(t, "% 6.2f ", m_downmix_matrix[j*8+i]);
  15117. + CLog::Log(LOGINFO, "%s::%s %s", CLASSNAME, __func__, s);
  15118. + }
  15119. + av_freep(&input);
  15120. + av_freep(&output);
  15121. + m_dllSwResample.swr_free(&m_pContext);
  15122. + m_dllSwResample.Unload();
  15123. +
  15124. + m_wave_header.dwChannelMask = m_src_chan_layout;
  15125. }
  15126. m_SampleRate = m_format.m_sampleRate;
  15127. @@ -1605,122 +1833,3 @@ void COMXAudio::CheckOutputBufferSize(void **buffer, int *oldSize, int newSize)
  15128. }
  15129. memset(*buffer, 0x0, *oldSize);
  15130. }
  15131. -
  15132. -void COMXAudio::BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout)
  15133. -{
  15134. - int index = 0;
  15135. - if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = PCM_FRONT_LEFT ;
  15136. - if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = PCM_FRONT_RIGHT ;
  15137. - if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = PCM_FRONT_CENTER ;
  15138. - if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = PCM_LOW_FREQUENCY ;
  15139. - if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = PCM_BACK_LEFT ;
  15140. - if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = PCM_BACK_RIGHT ;
  15141. - if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = PCM_FRONT_LEFT_OF_CENTER ;
  15142. - if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = PCM_FRONT_RIGHT_OF_CENTER;
  15143. - if (layout & AV_CH_BACK_CENTER ) channelMap[index++] = PCM_BACK_CENTER ;
  15144. - if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = PCM_SIDE_LEFT ;
  15145. - if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = PCM_SIDE_RIGHT ;
  15146. - if (layout & AV_CH_TOP_CENTER ) channelMap[index++] = PCM_TOP_CENTER ;
  15147. - if (layout & AV_CH_TOP_FRONT_LEFT ) channelMap[index++] = PCM_TOP_FRONT_LEFT ;
  15148. - if (layout & AV_CH_TOP_FRONT_CENTER ) channelMap[index++] = PCM_TOP_FRONT_CENTER ;
  15149. - if (layout & AV_CH_TOP_FRONT_RIGHT ) channelMap[index++] = PCM_TOP_FRONT_RIGHT ;
  15150. - if (layout & AV_CH_TOP_BACK_LEFT ) channelMap[index++] = PCM_TOP_BACK_LEFT ;
  15151. - if (layout & AV_CH_TOP_BACK_CENTER ) channelMap[index++] = PCM_TOP_BACK_CENTER ;
  15152. - if (layout & AV_CH_TOP_BACK_RIGHT ) channelMap[index++] = PCM_TOP_BACK_RIGHT ;
  15153. - while (index<OMX_AUDIO_MAXCHANNELS)
  15154. - channelMap[index++] = PCM_INVALID;
  15155. -}
  15156. -
  15157. -// See CEA spec: Table 20, Audio InfoFrame data byte 4 for the ordering here
  15158. -int COMXAudio::BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout)
  15159. -{
  15160. - int index = 0;
  15161. - if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = PCM_FRONT_LEFT;
  15162. - if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = PCM_FRONT_RIGHT;
  15163. - if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = PCM_LOW_FREQUENCY;
  15164. - if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = PCM_FRONT_CENTER;
  15165. - if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = PCM_BACK_LEFT;
  15166. - if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = PCM_BACK_RIGHT;
  15167. - if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = PCM_SIDE_LEFT;
  15168. - if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = PCM_SIDE_RIGHT;
  15169. -
  15170. - while (index<OMX_AUDIO_MAXCHANNELS)
  15171. - channelMap[index++] = PCM_INVALID;
  15172. -
  15173. - int num_channels = 0;
  15174. - for (index=0; index<OMX_AUDIO_MAXCHANNELS; index++)
  15175. - if (channelMap[index] != PCM_INVALID)
  15176. - num_channels = index+1;
  15177. - return num_channels;
  15178. -}
  15179. -
  15180. -void COMXAudio::BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE * channelMap, uint64_t layout)
  15181. -{
  15182. - int index = 0;
  15183. -
  15184. - if (layout & AV_CH_FRONT_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLF;
  15185. - if (layout & AV_CH_FRONT_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRF;
  15186. - if (layout & AV_CH_FRONT_CENTER ) channelMap[index++] = OMX_AUDIO_ChannelCF;
  15187. - if (layout & AV_CH_LOW_FREQUENCY ) channelMap[index++] = OMX_AUDIO_ChannelLFE;
  15188. - if (layout & AV_CH_BACK_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLR;
  15189. - if (layout & AV_CH_BACK_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRR;
  15190. - if (layout & AV_CH_SIDE_LEFT ) channelMap[index++] = OMX_AUDIO_ChannelLS;
  15191. - if (layout & AV_CH_SIDE_RIGHT ) channelMap[index++] = OMX_AUDIO_ChannelRS;
  15192. - if (layout & AV_CH_BACK_CENTER ) channelMap[index++] = OMX_AUDIO_ChannelCS;
  15193. - // following are not in openmax spec, but gpu does accept them
  15194. - if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)10;
  15195. - if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)11;
  15196. - if (layout & AV_CH_TOP_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)12;
  15197. - if (layout & AV_CH_TOP_FRONT_LEFT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)13;
  15198. - if (layout & AV_CH_TOP_FRONT_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)14;
  15199. - if (layout & AV_CH_TOP_FRONT_RIGHT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)15;
  15200. - if (layout & AV_CH_TOP_BACK_LEFT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)16;
  15201. - if (layout & AV_CH_TOP_BACK_CENTER ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)17;
  15202. - if (layout & AV_CH_TOP_BACK_RIGHT ) channelMap[index++] = (enum OMX_AUDIO_CHANNELTYPE)18;
  15203. -
  15204. - while (index<OMX_AUDIO_MAXCHANNELS)
  15205. - channelMap[index++] = OMX_AUDIO_ChannelNone;
  15206. -}
  15207. -
  15208. -uint64_t COMXAudio::GetChannelLayout(enum PCMLayout layout)
  15209. -{
  15210. - uint64_t layouts[] = {
  15211. - /* 2.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT,
  15212. - /* 2.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_LOW_FREQUENCY,
  15213. - /* 3.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER,
  15214. - /* 3.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_LOW_FREQUENCY,
  15215. - /* 4.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
  15216. - /* 4.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY,
  15217. - /* 5.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
  15218. - /* 5.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY,
  15219. - /* 7.0 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_SIDE_LEFT | 1<<PCM_SIDE_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT,
  15220. - /* 7.1 */ 1<<PCM_FRONT_LEFT | 1<<PCM_FRONT_RIGHT | 1<<PCM_FRONT_CENTER | 1<<PCM_SIDE_LEFT | 1<<PCM_SIDE_RIGHT | 1<<PCM_BACK_LEFT | 1<<PCM_BACK_RIGHT | 1<<PCM_LOW_FREQUENCY
  15221. - };
  15222. - return (int)layout < 10 ? layouts[(int)layout] : 0;
  15223. -}
  15224. -
  15225. -CAEChannelInfo COMXAudio::GetAEChannelLayout(uint64_t layout)
  15226. -{
  15227. - CAEChannelInfo m_channelLayout;
  15228. - m_channelLayout.Reset();
  15229. -
  15230. - if (layout & AV_CH_FRONT_LEFT ) m_channelLayout += AE_CH_FL ;
  15231. - if (layout & AV_CH_FRONT_RIGHT ) m_channelLayout += AE_CH_FR ;
  15232. - if (layout & AV_CH_FRONT_CENTER ) m_channelLayout += AE_CH_FC ;
  15233. - if (layout & AV_CH_LOW_FREQUENCY ) m_channelLayout += AE_CH_LFE ;
  15234. - if (layout & AV_CH_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
  15235. - if (layout & AV_CH_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
  15236. - if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelLayout += AE_CH_FLOC;
  15237. - if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelLayout += AE_CH_FROC;
  15238. - if (layout & AV_CH_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
  15239. - if (layout & AV_CH_SIDE_LEFT ) m_channelLayout += AE_CH_SL ;
  15240. - if (layout & AV_CH_SIDE_RIGHT ) m_channelLayout += AE_CH_SR ;
  15241. - if (layout & AV_CH_TOP_CENTER ) m_channelLayout += AE_CH_TC ;
  15242. - if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelLayout += AE_CH_TFL ;
  15243. - if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelLayout += AE_CH_TFC ;
  15244. - if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelLayout += AE_CH_TFR ;
  15245. - if (layout & AV_CH_TOP_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
  15246. - if (layout & AV_CH_TOP_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
  15247. - if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
  15248. - return m_channelLayout;
  15249. -}
  15250. diff --git a/xbmc/cores/omxplayer/OMXAudio.h b/xbmc/cores/omxplayer/OMXAudio.h
  15251. index b0264d8..a1c59da 100644
  15252. --- a/xbmc/cores/omxplayer/OMXAudio.h
  15253. +++ b/xbmc/cores/omxplayer/OMXAudio.h
  15254. @@ -38,7 +38,6 @@
  15255. #include "OMXCore.h"
  15256. #include "DllAvCodec.h"
  15257. #include "DllAvUtil.h"
  15258. -#include "PCMRemap.h"
  15259. #include "threads/CriticalSection.h"
  15260. @@ -61,7 +60,7 @@ class COMXAudio
  15261. float GetCacheTime();
  15262. float GetCacheTotal();
  15263. COMXAudio();
  15264. - bool Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, uint64_t channelMap, bool bUsePassthrough, bool bUseHWDecode);
  15265. + bool Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo &hints, CAEChannelInfo channelMap, bool bUsePassthrough, bool bUseHWDecode);
  15266. bool PortSettingsChanged();
  15267. ~COMXAudio();
  15268. @@ -99,12 +98,6 @@ class COMXAudio
  15269. unsigned int GetAudioRenderingLatency();
  15270. float GetMaxLevel(double &pts);
  15271. - void BuildChannelMap(enum PCMChannels *channelMap, uint64_t layout);
  15272. - int BuildChannelMapCEA(enum PCMChannels *channelMap, uint64_t layout);
  15273. - void BuildChannelMapOMX(enum OMX_AUDIO_CHANNELTYPE *channelMap, uint64_t layout);
  15274. - uint64_t GetChannelLayout(enum PCMLayout layout);
  15275. - CAEChannelInfo GetAEChannelLayout(uint64_t layout);
  15276. -
  15277. private:
  15278. IAudioCallback* m_pCallback;
  15279. bool m_Initialized;
  15280. diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  15281. index 7f6ef6e..5e47317 100644
  15282. --- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  15283. +++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.cpp
  15284. @@ -26,7 +26,6 @@
  15285. #include "cores/AudioEngine/Utils/AEUtil.h"
  15286. #include "settings/Settings.h"
  15287. -#include "PCMRemap.h"
  15288. // the size of the audio_render output port buffers
  15289. #define AUDIO_DECODE_OUTPUT_BUFFER (32*1024)
  15290. @@ -93,12 +92,11 @@ bool COMXAudioCodecOMX::Open(CDVDStreamInfo &hints)
  15291. m_pCodecContext->block_align = hints.blockalign;
  15292. m_pCodecContext->bit_rate = hints.bitrate;
  15293. m_pCodecContext->bits_per_coded_sample = hints.bitspersample;
  15294. - enum PCMLayout layout = (enum PCMLayout)std::max(0, CSettings::Get().GetInt("audiooutput.channels")-1);
  15295. if (hints.codec == AV_CODEC_ID_TRUEHD)
  15296. {
  15297. - if (layout == PCM_LAYOUT_2_0)
  15298. + if (CSettings::Get().GetInt("audiooutput.channels") == AE_CH_LAYOUT_2_0)
  15299. m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_STEREO;
  15300. - else if (layout <= PCM_LAYOUT_5_1)
  15301. + else if (CSettings::Get().GetInt("audiooutput.channels") == AE_CH_LAYOUT_5_1)
  15302. m_pCodecContext->request_channel_layout = AV_CH_LAYOUT_5POINT1;
  15303. }
  15304. if (m_pCodecContext->request_channel_layout)
  15305. @@ -323,7 +321,7 @@ int COMXAudioCodecOMX::GetBitRate()
  15306. return m_pCodecContext->bit_rate;
  15307. }
  15308. -static unsigned count_bits(int64_t value)
  15309. +static unsigned count_bits(uint64_t value)
  15310. {
  15311. unsigned bits = 0;
  15312. for(;value;++bits)
  15313. @@ -331,9 +329,10 @@ static unsigned count_bits(int64_t value)
  15314. return bits;
  15315. }
  15316. -uint64_t COMXAudioCodecOMX::GetChannelMap()
  15317. +void COMXAudioCodecOMX::BuildChannelMap()
  15318. {
  15319. uint64_t layout;
  15320. +
  15321. int bits = count_bits(m_pCodecContext->channel_layout);
  15322. if (bits == m_pCodecContext->channels)
  15323. layout = m_pCodecContext->channel_layout;
  15324. @@ -342,5 +341,31 @@ uint64_t COMXAudioCodecOMX::GetChannelMap()
  15325. CLog::Log(LOGINFO, "COMXAudioCodecOMX::GetChannelMap - FFmpeg reported %d channels, but the layout contains %d ignoring", m_pCodecContext->channels, bits);
  15326. layout = m_dllAvUtil.av_get_default_channel_layout(m_pCodecContext->channels);
  15327. }
  15328. - return layout;
  15329. +
  15330. + m_channelLayout.Reset();
  15331. +
  15332. + if (layout & AV_CH_FRONT_LEFT ) m_channelLayout += AE_CH_FL ;
  15333. + if (layout & AV_CH_FRONT_RIGHT ) m_channelLayout += AE_CH_FR ;
  15334. + if (layout & AV_CH_FRONT_CENTER ) m_channelLayout += AE_CH_FC ;
  15335. + if (layout & AV_CH_LOW_FREQUENCY ) m_channelLayout += AE_CH_LFE ;
  15336. + if (layout & AV_CH_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
  15337. + if (layout & AV_CH_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
  15338. + if (layout & AV_CH_FRONT_LEFT_OF_CENTER ) m_channelLayout += AE_CH_FLOC;
  15339. + if (layout & AV_CH_FRONT_RIGHT_OF_CENTER) m_channelLayout += AE_CH_FROC;
  15340. + if (layout & AV_CH_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
  15341. + if (layout & AV_CH_SIDE_LEFT ) m_channelLayout += AE_CH_SL ;
  15342. + if (layout & AV_CH_SIDE_RIGHT ) m_channelLayout += AE_CH_SR ;
  15343. + if (layout & AV_CH_TOP_CENTER ) m_channelLayout += AE_CH_TC ;
  15344. + if (layout & AV_CH_TOP_FRONT_LEFT ) m_channelLayout += AE_CH_TFL ;
  15345. + if (layout & AV_CH_TOP_FRONT_CENTER ) m_channelLayout += AE_CH_TFC ;
  15346. + if (layout & AV_CH_TOP_FRONT_RIGHT ) m_channelLayout += AE_CH_TFR ;
  15347. + if (layout & AV_CH_TOP_BACK_LEFT ) m_channelLayout += AE_CH_BL ;
  15348. + if (layout & AV_CH_TOP_BACK_CENTER ) m_channelLayout += AE_CH_BC ;
  15349. + if (layout & AV_CH_TOP_BACK_RIGHT ) m_channelLayout += AE_CH_BR ;
  15350. +}
  15351. +
  15352. +CAEChannelInfo COMXAudioCodecOMX::GetChannelMap()
  15353. +{
  15354. + BuildChannelMap();
  15355. + return m_channelLayout;
  15356. }
  15357. diff --git a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  15358. index 66e5b4a..6e6b226 100644
  15359. --- a/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  15360. +++ b/xbmc/cores/omxplayer/OMXAudioCodecOMX.h
  15361. @@ -40,7 +40,8 @@ class COMXAudioCodecOMX
  15362. int GetData(BYTE** dst, double &dts, double &pts);
  15363. void Reset();
  15364. int GetChannels();
  15365. - uint64_t GetChannelMap();
  15366. + void BuildChannelMap();
  15367. + CAEChannelInfo GetChannelMap();
  15368. int GetSampleRate();
  15369. int GetBitsPerSample();
  15370. static const char* GetName() { return "FFmpeg"; }
  15371. @@ -62,7 +63,7 @@ class COMXAudioCodecOMX
  15372. bool m_bOpenedCodec;
  15373. int m_channels;
  15374. -
  15375. + CAEChannelInfo m_channelLayout;
  15376. bool m_bFirstFrame;
  15377. bool m_bGotFrame;
  15378. bool m_bNoConcatenate;
  15379. diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  15380. index a4c11777..d3348ec 100644
  15381. --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  15382. +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  15383. @@ -567,13 +567,13 @@ bool OMXPlayerAudio::OpenDecoder()
  15384. /* GetDataFormat is setting up evrything */
  15385. m_format.m_dataFormat = GetDataFormat(m_hints);
  15386. - uint64_t channelMap = 0;
  15387. + CAEChannelInfo channelMap;
  15388. if (m_pAudioCodec && !m_passthrough)
  15389. channelMap = m_pAudioCodec->GetChannelMap();
  15390. else if (m_passthrough)
  15391. // we just want to get the channel count right to stop OMXAudio.cpp rejecting stream
  15392. // the actual layout is not used
  15393. - channelMap = (1<<m_nChannels)-1;
  15394. + channelMap = AE_CH_LAYOUT_5_1;
  15395. bool bAudioRenderOpen = m_omxAudio.Initialize(m_format, m_av_clock, m_hints, channelMap, m_passthrough, m_hw_decode);
  15396. m_codec_name = "";
  15397. diff --git a/xbmc/cores/omxplayer/PCMRemap.cpp b/xbmc/cores/omxplayer/PCMRemap.cpp
  15398. deleted file mode 100644
  15399. index f8acfcc..0000000
  15400. --- a/xbmc/cores/omxplayer/PCMRemap.cpp
  15401. +++ /dev/null
  15402. @@ -1,813 +0,0 @@
  15403. -/*
  15404. - * Copyright (C) 2005-2010 Team XBMC
  15405. - * http://xbmc.org
  15406. - *
  15407. - * This Program is free software; you can redistribute it and/or modify
  15408. - * it under the terms of the GNU General Public License as published by
  15409. - * the Free Software Foundation; either version 2, or (at your option)
  15410. - * any later version.
  15411. - *
  15412. - * This Program is distributed in the hope that it will be useful,
  15413. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15414. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15415. - * GNU General Public License for more details.
  15416. - *
  15417. - * You should have received a copy of the GNU General Public License
  15418. - * along with XBMC; see the file COPYING. If not, write to
  15419. - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  15420. - * http://www.gnu.org/copyleft/gpl.html
  15421. - *
  15422. - */
  15423. -
  15424. -#ifndef __STDC_LIMIT_MACROS
  15425. -#define __STDC_LIMIT_MACROS
  15426. -#endif
  15427. -
  15428. -#include <cstdlib>
  15429. -#include <string.h>
  15430. -#include <stdio.h>
  15431. -#include <math.h>
  15432. -
  15433. -//#include "MathUtils.h"
  15434. -#include "PCMRemap.h"
  15435. -#include "utils/log.h"
  15436. -#include "utils/StringUtils.h"
  15437. -#include "settings/Settings.h"
  15438. -#include "settings/AdvancedSettings.h"
  15439. -#ifdef _WIN32
  15440. -#include "../win32/PlatformDefs.h"
  15441. -#endif
  15442. -
  15443. -static enum PCMChannels PCMLayoutMap[PCM_MAX_LAYOUT][PCM_MAX_CH + 1] =
  15444. -{
  15445. - /* 2.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_INVALID},
  15446. - /* 2.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
  15447. - /* 3.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_INVALID},
  15448. - /* 3.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_LOW_FREQUENCY, PCM_INVALID},
  15449. - /* 4.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
  15450. - /* 4.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
  15451. - /* 5.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
  15452. - /* 5.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID},
  15453. - /* 7.0 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_SIDE_LEFT, PCM_SIDE_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_INVALID},
  15454. - /* 7.1 */ {PCM_FRONT_LEFT, PCM_FRONT_RIGHT, PCM_FRONT_CENTER, PCM_SIDE_LEFT, PCM_SIDE_RIGHT, PCM_BACK_LEFT, PCM_BACK_RIGHT, PCM_LOW_FREQUENCY, PCM_INVALID}
  15455. -};
  15456. -
  15457. -/*
  15458. - map missing output into channel @ volume level
  15459. - the order of this table is important, mix tables can not depend on channels that have not been defined yet
  15460. - eg, FC can only be mixed into FL, FR as they are the only channels that have been defined
  15461. -*/
  15462. -#define PCM_MAX_MIX 3
  15463. -static struct PCMMapInfo PCMDownmixTable[PCM_MAX_CH][PCM_MAX_MIX] =
  15464. -{
  15465. - /* PCM_FRONT_LEFT */
  15466. - {
  15467. - {PCM_INVALID}
  15468. - },
  15469. - /* PCM_FRONT_RIGHT */
  15470. - {
  15471. - {PCM_INVALID}
  15472. - },
  15473. - /* PCM_FRONT_CENTER */
  15474. - {
  15475. - {PCM_FRONT_LEFT_OF_CENTER , 1.0},
  15476. - {PCM_FRONT_RIGHT_OF_CENTER, 1.0},
  15477. - {PCM_INVALID}
  15478. - },
  15479. - /* PCM_LOW_FREQUENCY */
  15480. - {
  15481. - /*
  15482. - A/52B 7.8 paragraph 2 recomends +10db
  15483. - but due to horrible clipping when normalize
  15484. - is disabled we set this to 1.0
  15485. - */
  15486. - {PCM_FRONT_LEFT , 1.0},//3.5},
  15487. - {PCM_FRONT_RIGHT , 1.0},//3.5},
  15488. - {PCM_INVALID}
  15489. - },
  15490. - /* PCM_BACK_LEFT */
  15491. - {
  15492. - {PCM_FRONT_LEFT , 1.0},
  15493. - {PCM_INVALID}
  15494. - },
  15495. - /* PCM_BACK_RIGHT */
  15496. - {
  15497. - {PCM_FRONT_RIGHT , 1.0},
  15498. - {PCM_INVALID}
  15499. - },
  15500. - /* PCM_FRONT_LEFT_OF_CENTER */
  15501. - {
  15502. - {PCM_FRONT_LEFT , 1.0},
  15503. - {PCM_FRONT_CENTER , 1.0, true},
  15504. - {PCM_INVALID}
  15505. - },
  15506. - /* PCM_FRONT_RIGHT_OF_CENTER */
  15507. - {
  15508. - {PCM_FRONT_RIGHT , 1.0},
  15509. - {PCM_FRONT_CENTER , 1.0, true},
  15510. - {PCM_INVALID}
  15511. - },
  15512. - /* PCM_BACK_CENTER */
  15513. - {
  15514. - {PCM_BACK_LEFT , 1.0},
  15515. - {PCM_BACK_RIGHT , 1.0},
  15516. - {PCM_INVALID}
  15517. - },
  15518. - /* PCM_SIDE_LEFT */
  15519. - {
  15520. - {PCM_FRONT_LEFT , 1.0},
  15521. - {PCM_BACK_LEFT , 1.0},
  15522. - {PCM_INVALID}
  15523. - },
  15524. - /* PCM_SIDE_RIGHT */
  15525. - {
  15526. - {PCM_FRONT_RIGHT , 1.0},
  15527. - {PCM_BACK_RIGHT , 1.0},
  15528. - {PCM_INVALID}
  15529. - },
  15530. - /* PCM_TOP_FRONT_LEFT */
  15531. - {
  15532. - {PCM_FRONT_LEFT , 1.0},
  15533. - {PCM_INVALID}
  15534. - },
  15535. - /* PCM_TOP_FRONT_RIGHT */
  15536. - {
  15537. - {PCM_FRONT_RIGHT , 1.0},
  15538. - {PCM_INVALID}
  15539. - },
  15540. - /* PCM_TOP_FRONT_CENTER */
  15541. - {
  15542. - {PCM_TOP_FRONT_LEFT , 1.0},
  15543. - {PCM_TOP_FRONT_RIGHT , 1.0},
  15544. - {PCM_INVALID}
  15545. - },
  15546. - /* PCM_TOP_CENTER */
  15547. - {
  15548. - {PCM_TOP_FRONT_LEFT , 1.0},
  15549. - {PCM_TOP_FRONT_RIGHT , 1.0},
  15550. - {PCM_INVALID}
  15551. - },
  15552. - /* PCM_TOP_BACK_LEFT */
  15553. - {
  15554. - {PCM_BACK_LEFT , 1.0},
  15555. - {PCM_INVALID}
  15556. - },
  15557. - /* PCM_TOP_BACK_RIGHT */
  15558. - {
  15559. - {PCM_BACK_RIGHT , 1.0},
  15560. - {PCM_INVALID}
  15561. - },
  15562. - /* PCM_TOP_BACK_CENTER */
  15563. - {
  15564. - {PCM_TOP_BACK_LEFT , 1.0},
  15565. - {PCM_TOP_BACK_RIGHT , 1.0},
  15566. - {PCM_INVALID}
  15567. - }
  15568. -};
  15569. -
  15570. -CPCMRemap::CPCMRemap() :
  15571. - m_inSet (false),
  15572. - m_outSet (false),
  15573. - m_inChannels (0),
  15574. - m_outChannels (0),
  15575. - m_inSampleSize(0),
  15576. - m_ignoreLayout(false),
  15577. - m_buf(NULL),
  15578. - m_bufsize(0),
  15579. - m_attenuation (1.0),
  15580. - m_attenuationInc(0.0),
  15581. - m_attenuationMin(1.0),
  15582. - m_sampleRate (48000.0), //safe default
  15583. - m_holdCounter (0),
  15584. - m_limiterEnabled(false)
  15585. -{
  15586. - Dispose();
  15587. -}
  15588. -
  15589. -CPCMRemap::~CPCMRemap()
  15590. -{
  15591. - Dispose();
  15592. -}
  15593. -
  15594. -void CPCMRemap::Dispose()
  15595. -{
  15596. - free(m_buf);
  15597. - m_buf = NULL;
  15598. - m_bufsize = 0;
  15599. -}
  15600. -
  15601. -/* resolves the channels recursively and returns the new index of tablePtr */
  15602. -struct PCMMapInfo* CPCMRemap::ResolveChannel(enum PCMChannels channel, float level, bool ifExists, std::vector<enum PCMChannels> path, struct PCMMapInfo *tablePtr)
  15603. -{
  15604. - if (channel == PCM_INVALID) return tablePtr;
  15605. -
  15606. - /* if its a 1 to 1 mapping, return */
  15607. - if (m_useable[channel])
  15608. - {
  15609. - tablePtr->channel = channel;
  15610. - tablePtr->level = level;
  15611. -
  15612. - ++tablePtr;
  15613. - tablePtr->channel = PCM_INVALID;
  15614. - return tablePtr;
  15615. - } else
  15616. - if (ifExists)
  15617. - level /= 2;
  15618. -
  15619. - struct PCMMapInfo *info;
  15620. - std::vector<enum PCMChannels>::iterator itt;
  15621. -
  15622. - for(info = PCMDownmixTable[channel]; info->channel != PCM_INVALID; ++info)
  15623. - {
  15624. - /* make sure we are not about to recurse into ourself */
  15625. - bool found = false;
  15626. - for(itt = path.begin(); itt != path.end(); ++itt)
  15627. - if (*itt == info->channel)
  15628. - {
  15629. - found = true;
  15630. - break;
  15631. - }
  15632. -
  15633. - if (found)
  15634. - continue;
  15635. -
  15636. - path.push_back(channel);
  15637. - float l = (info->level * (level / 100)) * 100;
  15638. - tablePtr = ResolveChannel(info->channel, l, info->ifExists, path, tablePtr);
  15639. - path.pop_back();
  15640. - }
  15641. -
  15642. - return tablePtr;
  15643. -}
  15644. -
  15645. -/*
  15646. - Builds a lookup table without extra adjustments, useful if we simply
  15647. - want to find out which channels are active.
  15648. - For final adjustments, BuildMap() is used.
  15649. -*/
  15650. -void CPCMRemap::ResolveChannels()
  15651. -{
  15652. - unsigned int in_ch, out_ch;
  15653. - bool hasSide = false;
  15654. - bool hasBack = false;
  15655. -
  15656. - memset(m_useable, 0, sizeof(m_useable));
  15657. -
  15658. - if (!m_outSet)
  15659. - {
  15660. - /* Output format is not known yet, assume the full configured map.
  15661. - * Note that m_ignoreLayout-using callers normally ignore the result of
  15662. - * this function when !m_outSet, when it is called only for an advice for
  15663. - * the caller of SetInputFormat about the best possible output map, and
  15664. - * they can still set their output format arbitrarily in their call to
  15665. - * SetOutputFormat. */
  15666. - for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
  15667. - m_useable[*chan] = true;
  15668. - }
  15669. - else if (m_ignoreLayout)
  15670. - {
  15671. - for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
  15672. - m_useable[m_outMap[out_ch]] = true;
  15673. - }
  15674. - else
  15675. - {
  15676. - /* figure out what channels we have and can use */
  15677. - for(enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
  15678. - {
  15679. - for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
  15680. - if (m_outMap[out_ch] == *chan)
  15681. - {
  15682. - m_useable[*chan] = true;
  15683. - break;
  15684. - }
  15685. - }
  15686. - }
  15687. -
  15688. - /* force mono audio to front left and front right */
  15689. - if (!m_ignoreLayout && m_inChannels == 1 && m_inMap[0] == PCM_FRONT_CENTER
  15690. - && m_useable[PCM_FRONT_LEFT] && m_useable[PCM_FRONT_RIGHT])
  15691. - {
  15692. - CLog::Log(LOGDEBUG, "CPCMRemap: Mapping mono audio to front left and front right");
  15693. - m_useable[PCM_FRONT_CENTER] = false;
  15694. - m_useable[PCM_FRONT_LEFT_OF_CENTER] = false;
  15695. - m_useable[PCM_FRONT_RIGHT_OF_CENTER] = false;
  15696. - }
  15697. -
  15698. - /* see if our input has side/back channels */
  15699. - for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
  15700. - switch(m_inMap[in_ch])
  15701. - {
  15702. - case PCM_SIDE_LEFT:
  15703. - case PCM_SIDE_RIGHT:
  15704. - hasSide = true;
  15705. - break;
  15706. -
  15707. - case PCM_BACK_LEFT:
  15708. - case PCM_BACK_RIGHT:
  15709. - hasBack = true;
  15710. - break;
  15711. -
  15712. - default:;
  15713. - }
  15714. -
  15715. - /* if our input has side, and not back channels, and our output doesnt have side channels */
  15716. - if (hasSide && !hasBack && (!m_useable[PCM_SIDE_LEFT] || !m_useable[PCM_SIDE_RIGHT]))
  15717. - {
  15718. - CLog::Log(LOGDEBUG, "CPCMRemap: Forcing side channel map to back channels");
  15719. - for(in_ch = 0; in_ch < m_inChannels; ++in_ch)
  15720. - if (m_inMap[in_ch] == PCM_SIDE_LEFT ) m_inMap[in_ch] = PCM_BACK_LEFT;
  15721. - else if (m_inMap[in_ch] == PCM_SIDE_RIGHT) m_inMap[in_ch] = PCM_BACK_RIGHT;
  15722. - }
  15723. -
  15724. - /* resolve all the channels */
  15725. - struct PCMMapInfo table[PCM_MAX_CH + 1], *info, *dst;
  15726. - std::vector<enum PCMChannels> path;
  15727. -
  15728. - for (int i = 0; i < PCM_MAX_CH + 1; i++)
  15729. - {
  15730. - for (int j = 0; j < PCM_MAX_CH + 1; j++)
  15731. - m_lookupMap[i][j].channel = PCM_INVALID;
  15732. - }
  15733. -
  15734. - memset(m_counts, 0, sizeof(m_counts));
  15735. - for(in_ch = 0; in_ch < m_inChannels; ++in_ch) {
  15736. -
  15737. - for (int i = 0; i < PCM_MAX_CH + 1; i++)
  15738. - table[i].channel = PCM_INVALID;
  15739. -
  15740. - ResolveChannel(m_inMap[in_ch], 1.0f, false, path, table);
  15741. - for(info = table; info->channel != PCM_INVALID; ++info)
  15742. - {
  15743. - /* find the end of the table */
  15744. - for(dst = m_lookupMap[info->channel]; dst->channel != PCM_INVALID; ++dst);
  15745. -
  15746. - /* append it to the table and set its input offset */
  15747. - dst->channel = m_inMap[in_ch];
  15748. - dst->in_offset = in_ch * 2;
  15749. - dst->level = info->level;
  15750. - m_counts[dst->channel]++;
  15751. - }
  15752. - }
  15753. -}
  15754. -
  15755. -/*
  15756. - builds a lookup table to convert from the input mapping to the output
  15757. - mapping, this decreases the amount of work per sample to remap it.
  15758. -*/
  15759. -void CPCMRemap::BuildMap()
  15760. -{
  15761. - struct PCMMapInfo *dst;
  15762. - unsigned int out_ch;
  15763. -
  15764. - if (!m_inSet || !m_outSet) return;
  15765. -
  15766. - m_inStride = m_inSampleSize * m_inChannels ;
  15767. - m_outStride = m_inSampleSize * m_outChannels;
  15768. -
  15769. - /* see if we need to normalize the levels */
  15770. - bool dontnormalize = !CSettings::Get().GetBool("audiooutput.normalizelevels");
  15771. - CLog::Log(LOGDEBUG, "CPCMRemap: Downmix normalization is %s", (dontnormalize ? "disabled" : "enabled"));
  15772. -
  15773. - ResolveChannels();
  15774. -
  15775. - /* convert the levels into RMS values */
  15776. - float loudest = 0.0;
  15777. - bool hasLoudest = false;
  15778. -
  15779. - for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
  15780. - {
  15781. - float scale = 0;
  15782. - int count = 0;
  15783. - for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
  15784. - {
  15785. - dst->copy = false;
  15786. - dst->level = dst->level / sqrt((float)m_counts[dst->channel]);
  15787. - scale += dst->level;
  15788. - ++count;
  15789. - }
  15790. -
  15791. - /* if there is only 1 channel to mix, and the level is 1.0, then just copy the channel */
  15792. - dst = m_lookupMap[m_outMap[out_ch]];
  15793. - if (count == 1 && dst->level > 0.99 && dst->level < 1.01)
  15794. - dst->copy = true;
  15795. -
  15796. - /* normalize the levels if it is turned on */
  15797. - if (!dontnormalize)
  15798. - for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
  15799. - {
  15800. - dst->level /= scale;
  15801. - /* find the loudest output level we have that is not 1-1 */
  15802. - if (dst->level < 1.0 && loudest < dst->level)
  15803. - {
  15804. - loudest = dst->level;
  15805. - hasLoudest = true;
  15806. - }
  15807. - }
  15808. - }
  15809. -
  15810. - /* adjust the channels that are too loud */
  15811. - for(out_ch = 0; out_ch < m_outChannels; ++out_ch)
  15812. - {
  15813. - CStdString s = "", f;
  15814. - for(dst = m_lookupMap[m_outMap[out_ch]]; dst->channel != PCM_INVALID; ++dst)
  15815. - {
  15816. - if (hasLoudest && dst->copy)
  15817. - {
  15818. - dst->level = loudest;
  15819. - dst->copy = false;
  15820. - }
  15821. -
  15822. - f = StringUtils::Format("%s(%f%s) ", PCMChannelStr(dst->channel).c_str(), dst->level, dst->copy ? "*" : "");
  15823. - s += f;
  15824. - }
  15825. - CLog::Log(LOGDEBUG, "CPCMRemap: %s = %s\n", PCMChannelStr(m_outMap[out_ch]).c_str(), s.c_str());
  15826. - }
  15827. -}
  15828. -
  15829. -void CPCMRemap::DumpMap(CStdString info, unsigned int channels, enum PCMChannels *channelMap)
  15830. -{
  15831. - if (channelMap == NULL)
  15832. - {
  15833. - CLog::Log(LOGINFO, "CPCMRemap: %s channel map: NULL", info.c_str());
  15834. - return;
  15835. - }
  15836. -
  15837. - CStdString mapping;
  15838. - for(unsigned int i = 0; i < channels; ++i)
  15839. - mapping += ((i == 0) ? "" : ",") + PCMChannelStr(channelMap[i]);
  15840. -
  15841. - CLog::Log(LOGINFO, "CPCMRemap: %s channel map: %s\n", info.c_str(), mapping.c_str());
  15842. -}
  15843. -
  15844. -void CPCMRemap::Reset()
  15845. -{
  15846. - m_inSet = false;
  15847. - m_outSet = false;
  15848. - Dispose();
  15849. -}
  15850. -
  15851. -/* sets the input format, and returns the requested channel layout */
  15852. -enum PCMChannels *CPCMRemap::SetInputFormat(unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate, PCMLayout layout)
  15853. -{
  15854. - m_inChannels = channels;
  15855. - m_inSampleSize = sampleSize;
  15856. - m_sampleRate = sampleRate;
  15857. - m_inSet = channelMap != NULL;
  15858. - if (channelMap)
  15859. - memcpy(m_inMap, channelMap, sizeof(enum PCMChannels) * channels);
  15860. -
  15861. - /* get the audio layout, and count the channels in it */
  15862. - m_channelLayout = layout;
  15863. - if (m_channelLayout >= PCM_MAX_LAYOUT) m_channelLayout = PCM_LAYOUT_2_0;
  15864. -
  15865. -
  15866. - DumpMap("I", channels, channelMap);
  15867. - BuildMap();
  15868. -
  15869. - /* now remove the empty channels from PCMLayoutMap;
  15870. - * we don't perform upmixing so we want the minimum amount of those */
  15871. - if (channelMap) {
  15872. - if (!m_outSet)
  15873. - ResolveChannels(); /* Do basic channel resolving to find out the empty channels;
  15874. - * If m_outSet == true, this was done already by BuildMap() above */
  15875. - int i = 0;
  15876. - for (enum PCMChannels *chan = PCMLayoutMap[m_channelLayout]; *chan != PCM_INVALID; ++chan)
  15877. - if (m_lookupMap[*chan][0].channel != PCM_INVALID) {
  15878. - /* something is mapped here, so add the channel */
  15879. - m_layoutMap[i++] = *chan;
  15880. - }
  15881. - m_layoutMap[i] = PCM_INVALID;
  15882. - } else
  15883. - memcpy(m_layoutMap, PCMLayoutMap[m_channelLayout], sizeof(PCMLayoutMap[m_channelLayout]));
  15884. -
  15885. - m_attenuation = 1.0;
  15886. - m_attenuationInc = 1.0;
  15887. - m_holdCounter = 0;
  15888. -
  15889. - return m_layoutMap;
  15890. -}
  15891. -
  15892. -/* sets the output format supported by the audio renderer */
  15893. -void CPCMRemap::SetOutputFormat(unsigned int channels, enum PCMChannels *channelMap, bool ignoreLayout/* = false */)
  15894. -{
  15895. - m_outChannels = channels;
  15896. - m_outSet = channelMap != NULL;
  15897. - m_ignoreLayout = ignoreLayout;
  15898. - if (channelMap)
  15899. - memcpy(m_outMap, channelMap, sizeof(enum PCMChannels) * channels);
  15900. -
  15901. - DumpMap("O", channels, channelMap);
  15902. - BuildMap();
  15903. -
  15904. - m_attenuation = 1.0;
  15905. - m_attenuationInc = 1.0;
  15906. - m_holdCounter = 0;
  15907. -}
  15908. -
  15909. -#if 0
  15910. -void CPCMRemap::Remap(void *data, void *out, unsigned int samples, long drc)
  15911. -{
  15912. - float gain = 1.0f;
  15913. - if (drc > 0)
  15914. - gain = pow(10.0f, (float)drc / 2000.0f);
  15915. -
  15916. - Remap(data, out, samples, gain);
  15917. -}
  15918. -
  15919. -/* remap the supplied data into out, which must be pre-allocated */
  15920. -void CPCMRemap::Remap(void *data, void *out, unsigned int samples, float gain /*= 1.0f*/)
  15921. -{
  15922. - CheckBufferSize(samples * m_outChannels * sizeof(float));
  15923. -
  15924. - //set output buffer to 0
  15925. - memset(out, 0, samples * m_outChannels * m_inSampleSize);
  15926. -
  15927. - //set intermediate buffer to 0
  15928. - memset(m_buf, 0, m_bufsize);
  15929. -
  15930. - ProcessInput(data, out, samples, gain);
  15931. - AddGain(m_buf, samples * m_outChannels, gain);
  15932. - ProcessLimiter(samples, gain);
  15933. - ProcessOutput(out, samples, gain);
  15934. -}
  15935. -
  15936. -void CPCMRemap::CheckBufferSize(int size)
  15937. -{
  15938. - if (m_bufsize < size)
  15939. - {
  15940. - m_bufsize = size;
  15941. - m_buf = (float*)realloc(m_buf, m_bufsize);
  15942. - }
  15943. -}
  15944. -
  15945. -void CPCMRemap::ProcessInput(void* data, void* out, unsigned int samples, float gain)
  15946. -{
  15947. - for (unsigned int ch = 0; ch < m_outChannels; ch++)
  15948. - {
  15949. - struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
  15950. - if (info->channel == PCM_INVALID)
  15951. - continue;
  15952. -
  15953. - if (info->copy && gain == 1.0f) //do direct copy
  15954. - {
  15955. - uint8_t* src = (uint8_t*)data + info->in_offset;
  15956. - uint8_t* dst = (uint8_t*)out + ch * m_inSampleSize;
  15957. - uint8_t* dstend = dst + samples * m_outStride;
  15958. - while (dst != dstend)
  15959. - {
  15960. - *(int16_t*)dst = *(int16_t*)src;
  15961. - src += m_inStride;
  15962. - dst += m_outStride;
  15963. - }
  15964. - }
  15965. - else //needs some volume change or mixing, put into intermediate buffer
  15966. - {
  15967. - for(; info->channel != PCM_INVALID; info++)
  15968. - {
  15969. - uint8_t* src = (uint8_t*)data + info->in_offset;
  15970. - float* dst = m_buf + ch;
  15971. - float* dstend = dst + samples * m_outChannels;
  15972. - while (dst != dstend)
  15973. - {
  15974. - *dst += (float)(*(int16_t*)src) * info->level;
  15975. - src += m_inStride;
  15976. - dst += m_outChannels;
  15977. - }
  15978. - }
  15979. - }
  15980. - }
  15981. -}
  15982. -
  15983. -void CPCMRemap::AddGain(float* buf, unsigned int samples, float gain)
  15984. -{
  15985. - if (gain != 1.0f) //needs a gain change
  15986. - {
  15987. - float* ptr = m_buf;
  15988. - float* end = m_buf + samples;
  15989. - while (ptr != end)
  15990. - *(ptr++) *= gain;
  15991. - }
  15992. -}
  15993. -
  15994. -void CPCMRemap::ProcessLimiter(unsigned int samples, float gain)
  15995. -{
  15996. - //check total gain for each output channel
  15997. - float highestgain = 1.0f;
  15998. - for (unsigned int ch = 0; ch < m_outChannels; ch++)
  15999. - {
  16000. - struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
  16001. - if (info->channel == PCM_INVALID)
  16002. - continue;
  16003. -
  16004. - float chgain = 0.0f;
  16005. - for(; info->channel != PCM_INVALID; info++)
  16006. - chgain += info->level * gain;
  16007. -
  16008. - if (chgain > highestgain)
  16009. - highestgain = chgain;
  16010. - }
  16011. -
  16012. - m_attenuationMin = 1.0f;
  16013. -
  16014. - //if one of the channels can clip, enable a limiter
  16015. - if (highestgain > 1.0001f)
  16016. - {
  16017. - m_attenuationMin = m_attenuation;
  16018. -
  16019. - if (!m_limiterEnabled)
  16020. - {
  16021. - CLog::Log(LOGDEBUG, "CPCMRemap:: max gain: %f, enabling limiter", highestgain);
  16022. - m_limiterEnabled = true;
  16023. - }
  16024. -
  16025. - for (unsigned int i = 0; i < samples; i++)
  16026. - {
  16027. - //for each collection of samples, get the highest absolute value
  16028. - float maxAbs = 0.0f;
  16029. - for (unsigned int outch = 0; outch < m_outChannels; outch++)
  16030. - {
  16031. - float absval = fabs(m_buf[i * m_outChannels + outch]) / 32768.0f;
  16032. - if (maxAbs < absval)
  16033. - maxAbs = absval;
  16034. - }
  16035. -
  16036. - //if attenuatedAbs is higher than 1.0f, audio is clipping
  16037. - float attenuatedAbs = maxAbs * m_attenuation;
  16038. - if (attenuatedAbs > 1.0f)
  16039. - {
  16040. - //set m_attenuation so that m_attenuation * sample is the maximum output value
  16041. - m_attenuation = 1.0f / maxAbs;
  16042. - if (m_attenuation < m_attenuationMin)
  16043. - m_attenuationMin = m_attenuation;
  16044. - //value to add to m_attenuation to make it 1.0f
  16045. - m_attenuationInc = 1.0f - m_attenuation;
  16046. - //amount of samples to hold m_attenuation
  16047. - m_holdCounter = MathUtils::round_int(m_sampleRate * g_advancedSettings.m_limiterHold);
  16048. - }
  16049. - else if (m_attenuation < 1.0f && attenuatedAbs > 0.95f)
  16050. - {
  16051. - //if we're attenuating and we get within 5% of clipping, hold m_attenuation
  16052. - m_attenuationInc = 1.0f - m_attenuation;
  16053. - m_holdCounter = MathUtils::round_int(m_sampleRate * g_advancedSettings.m_limiterHold);
  16054. - }
  16055. -
  16056. - //apply attenuation
  16057. - for (unsigned int outch = 0; outch < m_outChannels; outch++)
  16058. - m_buf[i * m_outChannels + outch] *= m_attenuation;
  16059. -
  16060. - if (m_holdCounter)
  16061. - {
  16062. - //hold m_attenuation
  16063. - m_holdCounter--;
  16064. - }
  16065. - else if (m_attenuationInc > 0.0f)
  16066. - {
  16067. - //move m_attenuation to 1.0 in g_advancedSettings.m_limiterRelease seconds
  16068. - m_attenuation += m_attenuationInc / m_sampleRate / g_advancedSettings.m_limiterRelease;
  16069. - if (m_attenuation > 1.0f)
  16070. - {
  16071. - m_attenuation = 1.0f;
  16072. - m_attenuationInc = 0.0f;
  16073. - }
  16074. - }
  16075. - }
  16076. - }
  16077. - else
  16078. - {
  16079. - if (m_limiterEnabled)
  16080. - {
  16081. - CLog::Log(LOGDEBUG, "CPCMRemap:: max gain: %f, disabling limiter", highestgain);
  16082. - m_limiterEnabled = false;
  16083. - }
  16084. -
  16085. - //reset the limiter
  16086. - m_attenuation = 1.0f;
  16087. - m_attenuationInc = 0.0f;
  16088. - m_holdCounter = 0;
  16089. - }
  16090. -}
  16091. -
  16092. -void CPCMRemap::ProcessOutput(void* out, unsigned int samples, float gain)
  16093. -{
  16094. - //copy from intermediate buffer to output
  16095. - for (unsigned int ch = 0; ch < m_outChannels; ch++)
  16096. - {
  16097. - struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
  16098. - if (info->channel == PCM_INVALID)
  16099. - continue;
  16100. -
  16101. - if (!info->copy || gain != 1.0f)
  16102. - {
  16103. - float* src = m_buf + ch;
  16104. - uint8_t* dst = (uint8_t*)out + ch * m_inSampleSize;
  16105. - uint8_t* dstend = dst + samples * m_outStride;
  16106. -
  16107. - while(dst != dstend)
  16108. - {
  16109. - *(int16_t*)dst = MathUtils::round_int(std::min(std::max(*src, (float)INT16_MIN), (float)INT16_MAX));
  16110. - src += m_outChannels;
  16111. - dst += m_outStride;
  16112. - }
  16113. - }
  16114. - }
  16115. -}
  16116. -
  16117. -bool CPCMRemap::CanRemap()
  16118. -{
  16119. - return (m_inSet && m_outSet);
  16120. -}
  16121. -
  16122. -int CPCMRemap::InBytesToFrames(int bytes)
  16123. -{
  16124. - return bytes / m_inSampleSize / m_inChannels;
  16125. -}
  16126. -
  16127. -int CPCMRemap::FramesToOutBytes(int frames)
  16128. -{
  16129. - return frames * m_inSampleSize * m_outChannels;
  16130. -}
  16131. -
  16132. -int CPCMRemap::FramesToInBytes(int frames)
  16133. -{
  16134. - return frames * m_inSampleSize * m_inChannels;
  16135. -}
  16136. -#endif
  16137. -CStdString CPCMRemap::PCMChannelStr(enum PCMChannels ename)
  16138. -{
  16139. - const char* PCMChannelName[] =
  16140. - {
  16141. - "FL",
  16142. - "FR",
  16143. - "CE",
  16144. - "LFE",
  16145. - "BL",
  16146. - "BR",
  16147. - "FLOC",
  16148. - "FROC",
  16149. - "BC",
  16150. - "SL",
  16151. - "SR",
  16152. - "TFL",
  16153. - "TFR",
  16154. - "TFC",
  16155. - "TC",
  16156. - "TBL",
  16157. - "TBR",
  16158. - "TBC"
  16159. - };
  16160. -
  16161. - int namepos = (int)ename;
  16162. - CStdString namestr;
  16163. -
  16164. - if (namepos < 0 || namepos >= (int)(sizeof(PCMChannelName) / sizeof(const char*)))
  16165. - namestr = StringUtils::Format("UNKNOWN CHANNEL:%i", namepos);
  16166. - else
  16167. - namestr = PCMChannelName[namepos];
  16168. -
  16169. - return namestr;
  16170. -}
  16171. -#if 0
  16172. -CStdString CPCMRemap::PCMLayoutStr(enum PCMLayout ename)
  16173. -{
  16174. - const char* PCMLayoutName[] =
  16175. - {
  16176. - "2.0",
  16177. - "2.1",
  16178. - "3.0",
  16179. - "3.1",
  16180. - "4.0",
  16181. - "4.1",
  16182. - "5.0",
  16183. - "5.1",
  16184. - "7.0",
  16185. - "7.1"
  16186. - };
  16187. -
  16188. - int namepos = (int)ename;
  16189. - CStdString namestr;
  16190. -
  16191. - if (namepos < 0 || namepos >= (int)(sizeof(PCMLayoutName) / sizeof(const char*)))
  16192. - namestr.Format("UNKNOWN LAYOUT:%i", namepos);
  16193. - else
  16194. - namestr = PCMLayoutName[namepos];
  16195. -
  16196. - return namestr;
  16197. -}
  16198. -#endif
  16199. -
  16200. -
  16201. -void CPCMRemap::GetDownmixMatrix(float *downmix)
  16202. -{
  16203. - for (int i=0; i<8*8; i++)
  16204. - downmix[i] = 0.0f;
  16205. -
  16206. - for (unsigned int ch = 0; ch < m_outChannels; ch++)
  16207. - {
  16208. - struct PCMMapInfo *info = m_lookupMap[m_outMap[ch]];
  16209. - if (info->channel == PCM_INVALID)
  16210. - continue;
  16211. -
  16212. - for(; info->channel != PCM_INVALID; info++)
  16213. - downmix[8*ch + (info->in_offset>>1)] = info->level;
  16214. - }
  16215. -}
  16216. diff --git a/xbmc/cores/omxplayer/PCMRemap.h b/xbmc/cores/omxplayer/PCMRemap.h
  16217. deleted file mode 100644
  16218. index a273cd1..0000000
  16219. --- a/xbmc/cores/omxplayer/PCMRemap.h
  16220. +++ /dev/null
  16221. @@ -1,151 +0,0 @@
  16222. -#ifndef __PCM_REMAP__H__
  16223. -#define __PCM_REMAP__H__
  16224. -
  16225. -/*
  16226. - * Copyright (C) 2005-2010 Team XBMC
  16227. - * http://xbmc.org
  16228. - *
  16229. - * This Program is free software; you can redistribute it and/or modify
  16230. - * it under the terms of the GNU General Public License as published by
  16231. - * the Free Software Foundation; either version 2, or (at your option)
  16232. - * any later version.
  16233. - *
  16234. - * This Program is distributed in the hope that it will be useful,
  16235. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16236. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16237. - * GNU General Public License for more details.
  16238. - *
  16239. - * You should have received a copy of the GNU General Public License
  16240. - * along with XBMC; see the file COPYING. If not, write to
  16241. - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  16242. - * http://www.gnu.org/copyleft/gpl.html
  16243. - *
  16244. - */
  16245. -
  16246. -#include <stdint.h>
  16247. -#include <vector>
  16248. -#include "utils/StdString.h"
  16249. -
  16250. -#define PCM_MAX_CH 18
  16251. -enum PCMChannels
  16252. -{
  16253. - PCM_INVALID = -1,
  16254. - PCM_FRONT_LEFT,
  16255. - PCM_FRONT_RIGHT,
  16256. - PCM_FRONT_CENTER,
  16257. - PCM_LOW_FREQUENCY,
  16258. - PCM_BACK_LEFT,
  16259. - PCM_BACK_RIGHT,
  16260. - PCM_FRONT_LEFT_OF_CENTER,
  16261. - PCM_FRONT_RIGHT_OF_CENTER,
  16262. - PCM_BACK_CENTER,
  16263. - PCM_SIDE_LEFT,
  16264. - PCM_SIDE_RIGHT,
  16265. - PCM_TOP_FRONT_LEFT,
  16266. - PCM_TOP_FRONT_RIGHT,
  16267. - PCM_TOP_FRONT_CENTER,
  16268. - PCM_TOP_CENTER,
  16269. - PCM_TOP_BACK_LEFT,
  16270. - PCM_TOP_BACK_RIGHT,
  16271. - PCM_TOP_BACK_CENTER
  16272. -};
  16273. -
  16274. -#define PCM_MAX_LAYOUT 10
  16275. -enum PCMLayout
  16276. -{
  16277. - PCM_LAYOUT_2_0 = 0,
  16278. - PCM_LAYOUT_2_1,
  16279. - PCM_LAYOUT_3_0,
  16280. - PCM_LAYOUT_3_1,
  16281. - PCM_LAYOUT_4_0,
  16282. - PCM_LAYOUT_4_1,
  16283. - PCM_LAYOUT_5_0,
  16284. - PCM_LAYOUT_5_1,
  16285. - PCM_LAYOUT_7_0,
  16286. - PCM_LAYOUT_7_1
  16287. -};
  16288. -
  16289. -struct PCMMapInfo
  16290. -{
  16291. - enum PCMChannels channel;
  16292. - float level;
  16293. - bool ifExists;
  16294. - int in_offset;
  16295. - bool copy;
  16296. -};
  16297. -
  16298. -//! Channels remapper class
  16299. -/*!
  16300. - The usual set-up process:
  16301. - - user calls SetInputFormat with the input channels information
  16302. - - SetInputFormat responds with a channelmap corresponding to the speaker
  16303. - layout that the user has configured, with empty (according to information
  16304. - calculated from the input channelmap) channels removed
  16305. - - user uses this information to create the desired output channelmap,
  16306. - and calls SetOutputFormat to set it (if the channelmap contains channels
  16307. - that do not exist in the configured speaker layout, they will contain
  16308. - only silence unless ignoreLayout is true)
  16309. - */
  16310. -
  16311. -class CPCMRemap
  16312. -{
  16313. -protected:
  16314. - bool m_inSet, m_outSet;
  16315. - enum PCMLayout m_channelLayout;
  16316. - unsigned int m_inChannels, m_outChannels;
  16317. - unsigned int m_inSampleSize;
  16318. - enum PCMChannels m_inMap [PCM_MAX_CH];
  16319. - enum PCMChannels m_outMap[PCM_MAX_CH];
  16320. - enum PCMChannels m_layoutMap[PCM_MAX_CH + 1];
  16321. -
  16322. - bool m_ignoreLayout;
  16323. - bool m_useable [PCM_MAX_CH];
  16324. - int m_inStride, m_outStride;
  16325. - struct PCMMapInfo m_lookupMap[PCM_MAX_CH + 1][PCM_MAX_CH + 1];
  16326. - int m_counts[PCM_MAX_CH];
  16327. -
  16328. - float* m_buf;
  16329. - int m_bufsize;
  16330. - float m_attenuation;
  16331. - float m_attenuationInc;
  16332. - float m_attenuationMin; //lowest attenuation value during a call of Remap(), used for the codec info
  16333. - float m_sampleRate;
  16334. - unsigned int m_holdCounter;
  16335. - bool m_limiterEnabled;
  16336. - bool m_dontnormalize;
  16337. -
  16338. - struct PCMMapInfo* ResolveChannel(enum PCMChannels channel, float level, bool ifExists, std::vector<enum PCMChannels> path, struct PCMMapInfo *tablePtr);
  16339. - void ResolveChannels(); //!< Partial BuildMap(), just enough to see which output channels are active
  16340. - void BuildMap();
  16341. - void DumpMap(CStdString info, int unsigned channels, enum PCMChannels *channelMap);
  16342. - void Dispose();
  16343. - CStdString PCMChannelStr(enum PCMChannels ename);
  16344. - CStdString PCMLayoutStr(enum PCMLayout ename);
  16345. -
  16346. - void CheckBufferSize(int size);
  16347. - void ProcessInput(void* data, void* out, unsigned int samples, float gain);
  16348. - void AddGain(float* buf, unsigned int samples, float gain);
  16349. - void ProcessLimiter(unsigned int samples, float gain);
  16350. - void ProcessOutput(void* out, unsigned int samples, float gain);
  16351. -
  16352. -public:
  16353. -
  16354. - CPCMRemap();
  16355. - ~CPCMRemap();
  16356. -
  16357. - void Reset();
  16358. - enum PCMChannels *SetInputFormat (unsigned int channels, enum PCMChannels *channelMap, unsigned int sampleSize, unsigned int sampleRate, PCMLayout layout);
  16359. - void SetOutputFormat(unsigned int channels, enum PCMChannels *channelMap, bool ignoreLayout = false);
  16360. -#if 0
  16361. - void Remap(void *data, void *out, unsigned int samples, long drc);
  16362. - void Remap(void *data, void *out, unsigned int samples, float gain = 1.0f);
  16363. - bool CanRemap();
  16364. - int InBytesToFrames (int bytes );
  16365. - int FramesToOutBytes(int frames);
  16366. - int FramesToInBytes (int frames);
  16367. -#endif
  16368. - float GetCurrentAttenuation() { return m_attenuationMin; }
  16369. - void GetDownmixMatrix(float *downmix);
  16370. -};
  16371. -
  16372. -#endif
  16373. --
  16374. 1.9.3
  16375. From f642e8eac4fb16039ce662a8a170908efd43ebf8 Mon Sep 17 00:00:00 2001
  16376. From: popcornmix <popcornmix@gmail.com>
  16377. Date: Thu, 10 Apr 2014 17:19:18 +0100
  16378. Subject: [PATCH 66/94] [omxplayer] Remove unused framerate functions
  16379. ---
  16380. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 4 +---
  16381. xbmc/linux/OMXClock.cpp | 35 ---------------------------------
  16382. xbmc/linux/OMXClock.h | 4 ----
  16383. 3 files changed, 1 insertion(+), 42 deletions(-)
  16384. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16385. index a5620da..019f4b2 100644
  16386. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16387. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16388. @@ -527,7 +527,7 @@ bool OMXPlayerVideo::OpenDecoder()
  16389. return false;
  16390. if (m_hints.fpsrate && m_hints.fpsscale)
  16391. - m_fFrameRate = DVD_TIME_BASE / OMXClock::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
  16392. + m_fFrameRate = DVD_TIME_BASE / CDVDCodecUtils::NormalizeFrameduration((double)DVD_TIME_BASE * m_hints.fpsscale / m_hints.fpsrate);
  16393. else
  16394. m_fFrameRate = 25;
  16395. @@ -564,8 +564,6 @@ bool OMXPlayerVideo::OpenDecoder()
  16396. sprintf(command, "hdmi_ntsc_freqs %d", bNtscFreq);
  16397. CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder fps: %f %s\n", m_fFrameRate, command);
  16398. m_DllBcmHost.vc_gencmd(response, sizeof response, command);
  16399. -
  16400. - m_av_clock->SetRefreshRate(m_fFrameRate);
  16401. }
  16402. // start from assuming all recent frames had valid pts
  16403. diff --git a/xbmc/linux/OMXClock.cpp b/xbmc/linux/OMXClock.cpp
  16404. index bee7bac..c631ab6 100644
  16405. --- a/xbmc/linux/OMXClock.cpp
  16406. +++ b/xbmc/linux/OMXClock.cpp
  16407. @@ -39,7 +39,6 @@ OMXClock::OMXClock()
  16408. {
  16409. m_pause = false;
  16410. - m_fps = 25.0f;
  16411. m_omx_speed = DVD_PLAYSPEED_NORMAL;
  16412. m_WaitMask = 0;
  16413. m_eState = OMX_TIME_ClockStateStopped;
  16414. @@ -565,38 +564,4 @@ int64_t OMXClock::CurrentHostFrequency(void)
  16415. return( (int64_t)1000000000L );
  16416. }
  16417. -int OMXClock::GetRefreshRate(double* interval)
  16418. -{
  16419. - if(!interval)
  16420. - return false;
  16421. -
  16422. - *interval = m_fps;
  16423. - return true;
  16424. -}
  16425. -
  16426. -double OMXClock::NormalizeFrameduration(double frameduration)
  16427. -{
  16428. - //if the duration is within 20 microseconds of a common duration, use that
  16429. - const double durations[] = {DVD_TIME_BASE * 1.001 / 24.0, DVD_TIME_BASE / 24.0, DVD_TIME_BASE / 25.0,
  16430. - DVD_TIME_BASE * 1.001 / 30.0, DVD_TIME_BASE / 30.0, DVD_TIME_BASE / 50.0,
  16431. - DVD_TIME_BASE * 1.001 / 60.0, DVD_TIME_BASE / 60.0};
  16432. -
  16433. - double lowestdiff = DVD_TIME_BASE;
  16434. - int selected = -1;
  16435. - for (size_t i = 0; i < sizeof(durations) / sizeof(durations[0]); i++)
  16436. - {
  16437. - double diff = fabs(frameduration - durations[i]);
  16438. - if (diff < DVD_MSEC_TO_TIME(0.02) && diff < lowestdiff)
  16439. - {
  16440. - selected = i;
  16441. - lowestdiff = diff;
  16442. - }
  16443. - }
  16444. -
  16445. - if (selected != -1)
  16446. - return durations[selected];
  16447. - else
  16448. - return frameduration;
  16449. -}
  16450. -
  16451. #endif
  16452. diff --git a/xbmc/linux/OMXClock.h b/xbmc/linux/OMXClock.h
  16453. index f83074a..7bb6d4d 100644
  16454. --- a/xbmc/linux/OMXClock.h
  16455. +++ b/xbmc/linux/OMXClock.h
  16456. @@ -50,7 +50,6 @@ class OMXClock
  16457. protected:
  16458. bool m_pause;
  16459. pthread_mutex_t m_lock;
  16460. - double m_fps;
  16461. int m_omx_speed;
  16462. OMX_U32 m_WaitMask;
  16463. OMX_TIME_CLOCKSTATE m_eState;
  16464. @@ -91,9 +90,6 @@ class OMXClock
  16465. static int64_t CurrentHostCounter(void);
  16466. static int64_t CurrentHostFrequency(void);
  16467. - int GetRefreshRate(double* interval = NULL);
  16468. - void SetRefreshRate(double fps) { m_fps = fps; };
  16469. -
  16470. static double NormalizeFrameduration(double frameduration);
  16471. };
  16472. --
  16473. 1.9.3
  16474. From 652d09aff0c0ed4cab08ab7ebbe0da37118c53ba Mon Sep 17 00:00:00 2001
  16475. From: popcornmix <popcornmix@gmail.com>
  16476. Date: Sun, 30 Mar 2014 15:54:34 +0100
  16477. Subject: [PATCH 67/94] [omxplayer] Make the sharpness control act as a
  16478. sharpness control.
  16479. This fixes scaling kernel as Mitchell Netravali, and varies sharpness over range B=[5/3,0] C=[-1/3,1/2]
  16480. ---
  16481. xbmc/cores/omxplayer/OMXPlayer.cpp | 338 +++++++++++++++++++++++++++++++++++++
  16482. 1 file changed, 338 insertions(+)
  16483. diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp
  16484. index 2515fa1..b09e8e0 100644
  16485. --- a/xbmc/cores/omxplayer/OMXPlayer.cpp
  16486. +++ b/xbmc/cores/omxplayer/OMXPlayer.cpp
  16487. @@ -1051,6 +1051,334 @@ bool COMXPlayer::IsBetterStream(COMXCurrentStream& current, CDemuxStream* stream
  16488. return false;
  16489. }
  16490. +static void SetSharpness(float sharpness)
  16491. +{
  16492. + const int16_t mitchells[][32] =
  16493. + {
  16494. + { // B=1.66667 C=-0.33333
  16495. + 0, 3, 8, 15, 24, 35, 49, 55, 70, 92,100,107,109,113,113,114,114,113,113,109,107,100, 92, 70, 55, 49, 35, 24, 15, 8, 3, 0,
  16496. + },
  16497. + { // B=1.64000 C=-0.32000
  16498. + 0, 3, 7, 14, 24, 34, 48, 54, 69, 91,100,107,111,114,116,116,116,116,114,111,107,100, 91, 69, 54, 48, 34, 24, 14, 7, 3, 0,
  16499. + },
  16500. + { // B=1.61333 C=-0.30667
  16501. + 0, 3, 7, 14, 23, 34, 47, 53, 68, 90, 99,107,112,115,118,118,118,118,115,112,107, 99, 90, 68, 53, 47, 34, 23, 14, 7, 3, 0,
  16502. + },
  16503. + { // B=1.58667 C=-0.29333
  16504. + 0, 2, 7, 14, 22, 33, 46, 52, 67, 89, 99,107,113,117,119,121,121,119,117,113,107, 99, 89, 67, 52, 46, 33, 22, 14, 7, 2, 0,
  16505. + },
  16506. + { // B=1.56000 C=-0.28000
  16507. + 0, 2, 7, 13, 22, 32, 45, 51, 66, 88, 98,107,114,119,121,123,123,121,119,114,107, 98, 88, 66, 51, 45, 32, 22, 13, 7, 2, 0,
  16508. + },
  16509. + { // B=1.53333 C=-0.26667
  16510. + 0, 2, 7, 12, 21, 31, 44, 50, 65, 87, 98,108,114,120,123,125,125,123,120,114,108, 98, 87, 65, 50, 44, 31, 21, 12, 7, 2, 0,
  16511. + },
  16512. + { // B=1.50667 C=-0.25333
  16513. + 0, 2, 6, 12, 20, 30, 43, 49, 64, 86, 98,108,116,122,125,127,127,125,122,116,108, 98, 86, 64, 49, 43, 30, 20, 12, 6, 2, 0,
  16514. + },
  16515. + { // B=1.48000 C=-0.24000
  16516. + 0, 2, 6, 12, 19, 29, 42, 47, 63, 85, 98,108,117,123,127,130,130,127,123,117,108, 98, 85, 63, 47, 42, 29, 19, 12, 6, 2, 0,
  16517. + },
  16518. + { // B=1.45333 C=-0.22667
  16519. + 0, 2, 6, 11, 19, 28, 41, 46, 62, 85, 97,108,118,125,129,132,132,129,125,118,108, 97, 85, 62, 46, 41, 28, 19, 11, 6, 2, 0,
  16520. + },
  16521. + { // B=1.42667 C=-0.21333
  16522. + 0, 2, 5, 11, 18, 28, 40, 45, 61, 84, 97,108,119,126,131,134,134,131,126,119,108, 97, 84, 61, 45, 40, 28, 18, 11, 5, 2, 0,
  16523. + },
  16524. + { // B=1.40000 C=-0.20000
  16525. + 0, 2, 5, 10, 18, 27, 39, 44, 60, 84, 96,109,119,127,134,136,136,134,127,119,109, 96, 84, 60, 44, 39, 27, 18, 10, 5, 2, 0,
  16526. + },
  16527. + { // B=1.37333 C=-0.18667
  16528. + 0, 1, 5, 10, 17, 26, 38, 43, 58, 82, 96,109,120,129,135,139,139,135,129,120,109, 96, 82, 58, 43, 38, 26, 17, 10, 5, 1, 0,
  16529. + },
  16530. + { // B=1.34667 C=-0.17333
  16531. + 0, 2, 4, 10, 16, 25, 37, 42, 57, 81, 96,109,121,131,137,141,141,137,131,121,109, 96, 81, 57, 42, 37, 25, 16, 10, 4, 2, 0,
  16532. + },
  16533. + { // B=1.32000 C=-0.16000
  16534. + 0, 1, 4, 9, 15, 24, 36, 41, 56, 81, 95,110,122,132,139,143,143,139,132,122,110, 95, 81, 56, 41, 36, 24, 15, 9, 4, 1, 0,
  16535. + },
  16536. + { // B=1.29333 C=-0.14667
  16537. + 0, 1, 4, 8, 15, 23, 35, 40, 55, 80, 95,110,123,133,141,146,146,141,133,123,110, 95, 80, 55, 40, 35, 23, 15, 8, 4, 1, 0,
  16538. + },
  16539. + { // B=1.26667 C=-0.13333
  16540. + 0, 1, 4, 8, 14, 22, 33, 38, 54, 79, 95,110,124,135,143,148,148,143,135,124,110, 95, 79, 54, 38, 33, 22, 14, 8, 4, 1, 0,
  16541. + },
  16542. + { // B=1.24000 C=-0.12000
  16543. + 0, 1, 4, 7, 14, 21, 33, 37, 53, 78, 94,110,125,136,145,150,150,145,136,125,110, 94, 78, 53, 37, 33, 21, 14, 7, 4, 1, 0,
  16544. + },
  16545. + { // B=1.21333 C=-0.10667
  16546. + 0, 1, 3, 7, 13, 20, 32, 36, 52, 77, 94,110,127,138,147,152,152,147,138,127,110, 94, 77, 52, 36, 32, 20, 13, 7, 3, 1, 0,
  16547. + },
  16548. + { // B=1.18667 C=-0.09333
  16549. + 0, 1, 3, 7, 12, 20, 30, 35, 51, 77, 93,111,125,140,149,155,155,149,140,125,111, 93, 77, 51, 35, 30, 20, 12, 7, 3, 1, 0,
  16550. + },
  16551. + { // B=1.16000 C=-0.08000
  16552. + 0, 1, 3, 6, 11, 19, 29, 34, 50, 76, 93,111,128,141,151,157,157,151,141,128,111, 93, 76, 50, 34, 29, 19, 11, 6, 3, 1, 0,
  16553. + },
  16554. + { // B=1.13333 C=-0.06667
  16555. + 0, 1, 3, 5, 11, 18, 28, 33, 49, 75, 93,111,129,143,153,159,159,153,143,129,111, 93, 75, 49, 33, 28, 18, 11, 5, 3, 1, 0,
  16556. + },
  16557. + { // B=1.10667 C=-0.05333
  16558. + 0, 1, 2, 5, 10, 17, 27, 32, 48, 74, 93,111,130,144,155,161,161,155,144,130,111, 93, 74, 48, 32, 27, 17, 10, 5, 2, 1, 0,
  16559. + },
  16560. + { // B=1.08000 C=-0.04000
  16561. + 0, 1, 2, 5, 9, 16, 26, 31, 46, 73, 92,112,130,145,157,164,164,157,145,130,112, 92, 73, 46, 31, 26, 16, 9, 5, 2, 1, 0,
  16562. + },
  16563. + { // B=1.05333 C=-0.02667
  16564. + 0, 0, 2, 4, 9, 15, 25, 29, 45, 72, 92,112,131,147,159,166,166,159,147,131,112, 92, 72, 45, 29, 25, 15, 9, 4, 2, 0, 0,
  16565. + },
  16566. + { // B=1.02667 C=-0.01333
  16567. + 0, 0, 1, 4, 8, 14, 24, 28, 44, 72, 92,112,132,148,161,168,168,161,148,132,112, 92, 72, 44, 28, 24, 14, 8, 4, 1, 0, 0,
  16568. + },
  16569. + { // B=1.00000 C=0.00000
  16570. + 0, 0, 1, 4, 7, 14, 23, 27, 43, 71, 91,112,133,150,163,170,170,163,150,133,112, 91, 71, 43, 27, 23, 14, 7, 4, 1, 0, 0,
  16571. + },
  16572. + { // B=0.97333 C=0.01333
  16573. + 0, 0, 1, 3, 7, 12, 22, 26, 42, 70, 91,113,133,152,165,173,173,165,152,133,113, 91, 70, 42, 26, 22, 12, 7, 3, 1, 0, 0,
  16574. + },
  16575. + { // B=0.94667 C=0.02667
  16576. + 0, 0, 1, 2, 6, 12, 21, 25, 41, 69, 90,113,135,153,167,175,175,167,153,135,113, 90, 69, 41, 25, 21, 12, 6, 2, 1, 0, 0,
  16577. + },
  16578. + { // B=0.92000 C=0.04000
  16579. + 0, 0, 0, 2, 5, 11, 20, 24, 40, 68, 90,113,136,154,169,177,177,169,154,136,113, 90, 68, 40, 24, 20, 11, 5, 2, 0, 0, 0,
  16580. + },
  16581. + { // B=0.89333 C=0.05333
  16582. + 0, 0, 0, 1, 5, 10, 19, 23, 39, 67, 90,114,136,156,171,179,179,171,156,136,114, 90, 67, 39, 23, 19, 10, 5, 1, 0, 0, 0,
  16583. + },
  16584. + { // B=0.86667 C=0.06667
  16585. + 0, 0, 0, 1, 4, 9, 18, 22, 38, 66, 89,114,137,157,173,182,182,173,157,137,114, 89, 66, 38, 22, 18, 9, 4, 1, 0, 0, 0,
  16586. + },
  16587. + { // B=0.84000 C=0.08000
  16588. + 0, 0, -1, 1, 3, 9, 17, 21, 37, 65, 89,114,138,159,175,184,184,175,159,138,114, 89, 65, 37, 21, 17, 9, 3, 1, -1, 0, 0,
  16589. + },
  16590. + { // B=0.81333 C=0.09333
  16591. + 0, 0, -1, 0, 3, 7, 16, 19, 36, 65, 89,114,139,160,177,186,186,177,160,139,114, 89, 65, 36, 19, 16, 7, 3, 0, -1, 0, 0,
  16592. + },
  16593. + { // B=0.78667 C=0.10667
  16594. + 0, -1, -1, 0, 2, 6, 15, 18, 35, 64, 88,115,139,162,179,188,188,179,162,139,115, 88, 64, 35, 18, 15, 6, 2, 0, -1, -1, 0,
  16595. + },
  16596. + { // B=0.76000 C=0.12000
  16597. + 0, -1, -1, -1, 1, 6, 14, 17, 33, 63, 88,115,141,163,181,191,191,181,163,141,115, 88, 63, 33, 17, 14, 6, 1, -1, -1, -1, 0,
  16598. + },
  16599. + { // B=0.73333 C=0.13333
  16600. + 0, -1, -1, -1, 0, 5, 13, 16, 32, 62, 87,115,142,165,183,193,193,183,165,142,115, 87, 62, 32, 16, 13, 5, 0, -1, -1, -1, 0,
  16601. + },
  16602. + { // B=0.70667 C=0.14667
  16603. + 0, -1, -1, -2, 0, 4, 12, 15, 31, 61, 87,115,143,166,185,195,195,185,166,143,115, 87, 61, 31, 15, 12, 4, 0, -2, -1, -1, 0,
  16604. + },
  16605. + { // B=0.68000 C=0.16000
  16606. + 0, -1, -2, -2, -1, 3, 11, 14, 30, 61, 87,116,142,168,187,197,197,187,168,142,116, 87, 61, 30, 14, 11, 3, -1, -2, -2, -1, 0,
  16607. + },
  16608. + { // B=0.65333 C=0.17333
  16609. + 0, -1, -2, -3, -1, 2, 10, 13, 29, 60, 86,116,144,169,189,200,200,189,169,144,116, 86, 60, 29, 13, 10, 2, -1, -3, -2, -1, 0,
  16610. + },
  16611. + { // B=0.62667 C=0.18667
  16612. + 0, -1, -3, -3, -2, 1, 9, 12, 28, 59, 86,116,145,171,191,202,202,191,171,145,116, 86, 59, 28, 12, 9, 1, -2, -3, -3, -1, 0,
  16613. + },
  16614. + { // B=0.60000 C=0.20000
  16615. + 0, -1, -3, -3, -3, 0, 8, 10, 27, 58, 86,116,146,172,193,204,204,193,172,146,116, 86, 58, 27, 10, 8, 0, -3, -3, -3, -1, 0,
  16616. + },
  16617. + { // B=0.57333 C=0.21333
  16618. + 0, -1, -3, -4, -3, -1, 7, 9, 26, 57, 86,116,147,174,194,207,207,194,174,147,116, 86, 57, 26, 9, 7, -1, -3, -4, -3, -1, 0,
  16619. + },
  16620. + { // B=0.54667 C=0.22667
  16621. + 0, -2, -3, -5, -4, -1, 5, 8, 25, 57, 85,117,148,176,196,209,209,196,176,148,117, 85, 57, 25, 8, 5, -1, -4, -5, -3, -2, 0,
  16622. + },
  16623. + { // B=0.52000 C=0.24000
  16624. + 0, -1, -4, -5, -5, -2, 4, 7, 24, 55, 85,117,149,177,199,211,211,199,177,149,117, 85, 55, 24, 7, 4, -2, -5, -5, -4, -1, 0,
  16625. + },
  16626. + { // B=0.49333 C=0.25333
  16627. + 0, -2, -4, -5, -6, -3, 3, 6, 23, 55, 84,117,150,178,200,214,214,200,178,150,117, 84, 55, 23, 6, 3, -3, -6, -5, -4, -2, 0,
  16628. + },
  16629. + { // B=0.46667 C=0.26667
  16630. + 0, -2, -4, -6, -6, -4, 2, 6, 22, 54, 84,118,150,180,202,216,216,202,180,150,118, 84, 54, 22, 6, 2, -4, -6, -6, -4, -2, 0,
  16631. + },
  16632. + { // B=0.44000 C=0.28000
  16633. + 0, -2, -4, -6, -7, -5, 2, 5, 21, 53, 83,118,150,181,205,218,218,205,181,150,118, 83, 53, 21, 5, 2, -5, -7, -6, -4, -2, 0,
  16634. + },
  16635. + { // B=0.41333 C=0.29333
  16636. + 0, -2, -4, -7, -7, -6, 0, 5, 20, 53, 83,118,152,183,207,220,220,207,183,152,118, 83, 53, 20, 5, 0, -6, -7, -7, -4, -2, 0,
  16637. + },
  16638. + { // B=0.38667 C=0.30667
  16639. + 0, -2, -5, -7, -8, -7, -1, 4, 19, 52, 83,118,153,185,208,223,223,208,185,153,118, 83, 52, 19, 4, -1, -7, -8, -7, -5, -2, 0,
  16640. + },
  16641. + { // B=0.36000 C=0.32000
  16642. + 0, -2, -5, -8, -8, -8, -2, 3, 19, 51, 83,118,155,186,210,225,225,210,186,155,118, 83, 51, 19, 3, -2, -8, -8, -8, -5, -2, 0,
  16643. + },
  16644. + { // B=0.33333 C=0.33333
  16645. + 0, -2, -6, -8,-10, -8, -3, 2, 18, 50, 82,119,155,187,213,227,227,213,187,155,119, 82, 50, 18, 2, -3, -8,-10, -8, -6, -2, 0,
  16646. + },
  16647. + { // B=0.32667 C=0.33667
  16648. + 0, -2, -6, -8,-10, -8, -3, 2, 18, 49, 82,119,155,188,213,228,228,213,188,155,119, 82, 49, 18, 2, -3, -8,-10, -8, -6, -2, 0,
  16649. + },
  16650. + { // B=0.32000 C=0.34000
  16651. + 0, -2, -6, -8,-10, -9, -3, 2, 18, 49, 82,119,155,188,214,228,228,214,188,155,119, 82, 49, 18, 2, -3, -9,-10, -8, -6, -2, 0,
  16652. + },
  16653. + { // B=0.31333 C=0.34333
  16654. + 0, -2, -6, -8,-10, -9, -4, 1, 18, 49, 82,119,155,188,214,229,229,214,188,155,119, 82, 49, 18, 1, -4, -9,-10, -8, -6, -2, 0,
  16655. + },
  16656. + { // B=0.30667 C=0.34667
  16657. + 0, -2, -6, -9,-10, -9, -4, 1, 18, 49, 82,119,156,189,214,229,229,214,189,156,119, 82, 49, 18, 1, -4, -9,-10, -9, -6, -2, 0,
  16658. + },
  16659. + { // B=0.30000 C=0.35000
  16660. + 0, -3, -5, -9,-10,-10, -4, 1, 18, 49, 82,119,156,189,215,230,230,215,189,156,119, 82, 49, 18, 1, -4,-10,-10, -9, -5, -3, 0,
  16661. + },
  16662. + { // B=0.29333 C=0.35333
  16663. + 0, -2, -6, -9,-10,-10, -4, 1, 17, 48, 82,119,156,190,215,231,231,215,190,156,119, 82, 48, 17, 1, -4,-10,-10, -9, -6, -2, 0,
  16664. + },
  16665. + { // B=0.28667 C=0.35667
  16666. + 0, -2, -6, -9,-11,-10, -5, 1, 17, 48, 82,119,157,190,216,231,231,216,190,157,119, 82, 48, 17, 1, -5,-10,-11, -9, -6, -2, 0,
  16667. + },
  16668. + { // B=0.28000 C=0.36000
  16669. + 0, -3, -6, -9,-11,-10, -5, 0, 17, 48, 82,119,157,190,217,231,231,217,190,157,119, 82, 48, 17, 0, -5,-10,-11, -9, -6, -3, 0,
  16670. + },
  16671. + { // B=0.27333 C=0.36333
  16672. + 0, -3, -6, -9,-11,-11, -5, 0, 17, 48, 82,119,157,191,217,232,232,217,191,157,119, 82, 48, 17, 0, -5,-11,-11, -9, -6, -3, 0,
  16673. + },
  16674. + { // B=0.26667 C=0.36667
  16675. + 0, -3, -6, -9,-11,-11, -5, 0, 17, 48, 81,119,157,191,217,233,233,217,191,157,119, 81, 48, 17, 0, -5,-11,-11, -9, -6, -3, 0,
  16676. + },
  16677. + { // B=0.26000 C=0.37000
  16678. + 0, -3, -6,-10,-11,-11, -5, 0, 16, 47, 81,120,156,191,218,233,233,218,191,156,120, 81, 47, 16, 0, -5,-11,-11,-10, -6, -3, 0,
  16679. + },
  16680. + { // B=0.25333 C=0.37333
  16681. + 0, -3, -6, -9,-12,-11, -6, 0, 16, 47, 81,119,158,192,218,234,234,218,192,158,119, 81, 47, 16, 0, -6,-11,-12, -9, -6, -3, 0,
  16682. + },
  16683. + { // B=0.24667 C=0.37667
  16684. + 0, -3, -6,-10,-12,-11, -6, 0, 16, 47, 81,120,157,192,219,234,234,219,192,157,120, 81, 47, 16, 0, -6,-11,-12,-10, -6, -3, 0,
  16685. + },
  16686. + { // B=0.24000 C=0.38000
  16687. + 0, -3, -6,-10,-12,-12, -6, -1, 16, 47, 81,120,158,193,219,235,235,219,193,158,120, 81, 47, 16, -1, -6,-12,-12,-10, -6, -3, 0,
  16688. + },
  16689. + { // B=0.23333 C=0.38333
  16690. + 0, -3, -6,-10,-12,-12, -6, -1, 16, 46, 81,120,158,193,220,236,236,220,193,158,120, 81, 46, 16, -1, -6,-12,-12,-10, -6, -3, 0,
  16691. + },
  16692. + { // B=0.22667 C=0.38667
  16693. + 0, -3, -6,-10,-12,-12, -7, -1, 15, 47, 80,120,158,194,220,236,236,220,194,158,120, 80, 47, 15, -1, -7,-12,-12,-10, -6, -3, 0,
  16694. + },
  16695. + { // B=0.22000 C=0.39000
  16696. + 0, -3, -6,-10,-13,-12, -7, -1, 15, 46, 80,120,159,194,221,237,237,221,194,159,120, 80, 46, 15, -1, -7,-12,-13,-10, -6, -3, 0,
  16697. + },
  16698. + { // B=0.21333 C=0.39333
  16699. + 0, -3, -6,-10,-13,-12, -8, -1, 15, 46, 80,120,159,194,221,237,237,221,194,159,120, 80, 46, 15, -1, -8,-12,-13,-10, -6, -3, 0,
  16700. + },
  16701. + { // B=0.20667 C=0.39667
  16702. + 0, -3, -7,-10,-13,-12, -8, -2, 15, 46, 80,120,159,194,222,238,238,222,194,159,120, 80, 46, 15, -2, -8,-12,-13,-10, -7, -3, 0,
  16703. + },
  16704. + { // B=0.20000 C=0.40000
  16705. + 0, -3, -7,-10,-13,-13, -8, -2, 15, 45, 81,120,159,195,222,238,238,222,195,159,120, 81, 45, 15, -2, -8,-13,-13,-10, -7, -3, 0,
  16706. + },
  16707. + { // B=0.19333 C=0.40333
  16708. + 0, -3, -7,-11,-13,-13, -8, -2, 15, 45, 81,120,160,195,223,239,239,223,195,160,120, 81, 45, 15, -2, -8,-13,-13,-11, -7, -3, 0,
  16709. + },
  16710. + { // B=0.18667 C=0.40667
  16711. + 0, -3, -7,-10,-14,-13, -9, -2, 14, 45, 80,120,160,196,223,240,240,223,196,160,120, 80, 45, 14, -2, -9,-13,-14,-10, -7, -3, 0,
  16712. + },
  16713. + { // B=0.18000 C=0.41000
  16714. + 0, -3, -7,-11,-13,-13, -9, -2, 14, 45, 80,120,160,196,224,240,240,224,196,160,120, 80, 45, 14, -2, -9,-13,-13,-11, -7, -3, 0,
  16715. + },
  16716. + { // B=0.17333 C=0.41333
  16717. + 0, -3, -7,-11,-13,-14, -9, -3, 14, 45, 80,120,160,196,225,240,240,225,196,160,120, 80, 45, 14, -3, -9,-14,-13,-11, -7, -3, 0,
  16718. + },
  16719. + { // B=0.16667 C=0.41667
  16720. + 0, -3, -7,-11,-14,-14, -9, -3, 14, 44, 80,120,161,197,225,241,241,225,197,161,120, 80, 44, 14, -3, -9,-14,-14,-11, -7, -3, 0,
  16721. + },
  16722. + { // B=0.16000 C=0.42000
  16723. + 0, -3, -7,-11,-14,-14,-10, -3, 14, 44, 80,120,161,197,225,242,242,225,197,161,120, 80, 44, 14, -3,-10,-14,-14,-11, -7, -3, 0,
  16724. + },
  16725. + { // B=0.15333 C=0.42333
  16726. + 0, -3, -7,-11,-14,-14,-10, -3, 13, 44, 80,120,161,197,226,242,242,226,197,161,120, 80, 44, 13, -3,-10,-14,-14,-11, -7, -3, 0,
  16727. + },
  16728. + { // B=0.14667 C=0.42667
  16729. + 0, -3, -7,-11,-15,-14,-10, -4, 14, 43, 80,120,163,198,226,243,243,226,198,163,120, 80, 43, 14, -4,-10,-14,-15,-11, -7, -3, 0,
  16730. + },
  16731. + { // B=0.14000 C=0.43000
  16732. + 0, -3, -7,-12,-14,-15,-10, -4, 14, 43, 80,120,163,198,227,243,243,227,198,163,120, 80, 43, 14, -4,-10,-15,-14,-12, -7, -3, 0,
  16733. + },
  16734. + { // B=0.13333 C=0.43333
  16735. + 0, -3, -7,-12,-14,-15,-11, -4, 13, 43, 79,121,161,199,227,244,244,227,199,161,121, 79, 43, 13, -4,-11,-15,-14,-12, -7, -3, 0,
  16736. + },
  16737. + { // B=0.12667 C=0.43667
  16738. + 0, -3, -7,-12,-14,-15,-11, -4, 13, 43, 79,120,163,199,228,245,245,228,199,163,120, 79, 43, 13, -4,-11,-15,-14,-12, -7, -3, 0,
  16739. + },
  16740. + { // B=0.12000 C=0.44000
  16741. + 0, -3, -7,-12,-15,-15,-12, -5, 13, 43, 79,121,162,199,228,245,245,228,199,162,121, 79, 43, 13, -5,-12,-15,-15,-12, -7, -3, 0,
  16742. + },
  16743. + { // B=0.11333 C=0.44333
  16744. + 0, -3, -7,-12,-15,-16,-11, -5, 13, 42, 79,121,162,200,229,246,246,229,200,162,121, 79, 42, 13, -5,-11,-16,-15,-12, -7, -3, 0,
  16745. + },
  16746. + { // B=0.10667 C=0.44667
  16747. + 0, -3, -8,-12,-15,-16,-12, -5, 13, 42, 79,121,162,200,229,246,246,229,200,162,121, 79, 42, 13, -5,-12,-16,-15,-12, -8, -3, 0,
  16748. + },
  16749. + { // B=0.10000 C=0.45000
  16750. + 0, -3, -8,-12,-16,-16,-12, -6, 13, 42, 79,121,163,200,230,247,247,230,200,163,121, 79, 42, 13, -6,-12,-16,-16,-12, -8, -3, 0,
  16751. + },
  16752. + { // B=0.09333 C=0.45333
  16753. + 0, -3, -8,-12,-16,-16,-13, -5, 12, 42, 79,121,163,201,230,248,248,230,201,163,121, 79, 42, 12, -5,-13,-16,-16,-12, -8, -3, 0,
  16754. + },
  16755. + { // B=0.08667 C=0.45667
  16756. + 0, -3, -8,-12,-16,-16,-13, -5, 12, 41, 79,121,163,201,231,248,248,231,201,163,121, 79, 41, 12, -5,-13,-16,-16,-12, -8, -3, 0,
  16757. + },
  16758. + { // B=0.08000 C=0.46000
  16759. + 0, -3, -8,-12,-16,-17,-13, -6, 12, 41, 79,121,163,201,232,248,248,232,201,163,121, 79, 41, 12, -6,-13,-17,-16,-12, -8, -3, 0,
  16760. + },
  16761. + { // B=0.07333 C=0.46333
  16762. + 0, -3, -8,-13,-16,-17,-13, -6, 12, 41, 79,121,164,202,232,249,249,232,202,164,121, 79, 41, 12, -6,-13,-17,-16,-13, -8, -3, 0,
  16763. + },
  16764. + { // B=0.06667 C=0.46667
  16765. + 0, -3, -8,-13,-16,-17,-14, -6, 11, 41, 79,121,164,202,233,249,249,233,202,164,121, 79, 41, 11, -6,-14,-17,-16,-13, -8, -3, 0,
  16766. + },
  16767. + { // B=0.06000 C=0.47000
  16768. + 0, -3, -8,-13,-16,-18,-14, -6, 11, 40, 79,121,164,203,233,250,250,233,203,164,121, 79, 40, 11, -6,-14,-18,-16,-13, -8, -3, 0,
  16769. + },
  16770. + { // B=0.05333 C=0.47333
  16771. + 0, -3, -8,-13,-17,-18,-14, -6, 11, 40, 79,121,165,203,233,251,251,233,203,165,121, 79, 40, 11, -6,-14,-18,-17,-13, -8, -3, 0,
  16772. + },
  16773. + { // B=0.04667 C=0.47667
  16774. + 0, -4, -8,-13,-17,-18,-14, -7, 11, 40, 79,121,166,203,234,251,251,234,203,166,121, 79, 40, 11, -7,-14,-18,-17,-13, -8, -4, 0,
  16775. + },
  16776. + { // B=0.04000 C=0.48000
  16777. + 0, -4, -8,-13,-17,-18,-14, -7, 11, 40, 78,121,166,204,234,251,251,234,204,166,121, 78, 40, 11, -7,-14,-18,-17,-13, -8, -4, 0,
  16778. + },
  16779. + { // B=0.03333 C=0.48333
  16780. + 0, -4, -8,-14,-17,-18,-15, -7, 11, 40, 78,122,164,204,235,252,252,235,204,164,122, 78, 40, 11, -7,-15,-18,-17,-14, -8, -4, 0,
  16781. + },
  16782. + { // B=0.02667 C=0.48667
  16783. + 0, -4, -8,-14,-17,-19,-15, -7, 10, 40, 78,122,164,205,235,253,253,235,205,164,122, 78, 40, 10, -7,-15,-19,-17,-14, -8, -4, 0,
  16784. + },
  16785. + { // B=0.02000 C=0.49000
  16786. + 0, -4, -8,-14,-17,-19,-15, -7, 10, 39, 78,122,164,205,236,253,253,236,205,164,122, 78, 39, 10, -7,-15,-19,-17,-14, -8, -4, 0,
  16787. + },
  16788. + { // B=0.01333 C=0.49333
  16789. + 0, -4, -8,-14,-18,-19,-16, -7, 9, 40, 78,122,165,205,236,254,254,236,205,165,122, 78, 40, 9, -7,-16,-19,-18,-14, -8, -4, 0,
  16790. + },
  16791. + { // B=0.00667 C=0.49667
  16792. + 0, -4, -9,-14,-18,-19,-15, -8, 10, 39, 78,122,166,206,236,254,254,236,206,166,122, 78, 39, 10, -8,-15,-19,-18,-14, -9, -4, 0,
  16793. + },
  16794. + { // B=0.00000 C=0.50000
  16795. + 0, -4, -8,-14,-18,-19,-16, -8, 9, 39, 77,122,166,206,237,255,255,237,206,166,122, 77, 39, 9, -8,-16,-19,-18,-14, -8, -4, 0,
  16796. + },
  16797. + };
  16798. + int index = (sharpness + 1.0f) * 50.0f + 0.5f;
  16799. + if (index >=0 && index <= 100)
  16800. + {
  16801. + const int16_t *coef = mitchells[index];
  16802. +
  16803. + char command[33*12];
  16804. + char response[33*12];
  16805. + unsigned int len = sprintf(command, "scaling_kernel ");
  16806. + for (int i=0; i < 32; i++) {
  16807. + if (len + 12 < sizeof command)
  16808. + len += sprintf(command+len, "%d ", coef[i]);
  16809. + }
  16810. + // no interpolate flag
  16811. + if (len + 12 < sizeof command)
  16812. + len += sprintf(command+len, " %d", 0);
  16813. + //printf("%i: %s\n", index, command);
  16814. + vc_gencmd(response, sizeof response, command);
  16815. + }
  16816. +}
  16817. +
  16818. void COMXPlayer::Process()
  16819. {
  16820. bool bOmxWaitVideo = false;
  16821. @@ -1183,6 +1511,8 @@ void COMXPlayer::Process()
  16822. SetCaching(CACHESTATE_FLUSH);
  16823. EDEINTERLACEMODE current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
  16824. + float current_sharpness = CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness;
  16825. + SetSharpness(current_sharpness);
  16826. while (!m_bAbortRequest)
  16827. {
  16828. @@ -1214,6 +1544,13 @@ void COMXPlayer::Process()
  16829. current_deinterlace = CMediaSettings::Get().GetCurrentVideoSettings().m_DeinterlaceMode;
  16830. }
  16831. + // if sharpness setting has changed, we should update it
  16832. + if (current_sharpness != CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness)
  16833. + {
  16834. + current_sharpness = CMediaSettings::Get().GetCurrentVideoSettings().m_Sharpness;
  16835. + SetSharpness(current_sharpness);
  16836. + }
  16837. +
  16838. m_video_fifo = (int)(100.0*(m_omxPlayerVideo.GetDecoderBufferSize()-m_omxPlayerVideo.GetDecoderFreeSpace())/m_omxPlayerVideo.GetDecoderBufferSize());
  16839. m_audio_fifo = (int)(100.0*audio_fifo/m_omxPlayerAudio.GetCacheTotal());
  16840. @@ -4577,6 +4914,7 @@ void COMXPlayer::GetRenderFeatures(std::vector<int> &renderFeatures)
  16841. renderFeatures.push_back(RENDERFEATURE_CROP);
  16842. renderFeatures.push_back(RENDERFEATURE_PIXEL_RATIO);
  16843. renderFeatures.push_back(RENDERFEATURE_ZOOM);
  16844. + renderFeatures.push_back(RENDERFEATURE_SHARPNESS);
  16845. }
  16846. void COMXPlayer::GetDeinterlaceMethods(std::vector<int> &deinterlaceMethods)
  16847. --
  16848. 1.9.3
  16849. From 97a3f2347e45eee8f960a2190891d4bd9de3dda0 Mon Sep 17 00:00:00 2001
  16850. From: popcornmix <popcornmix@gmail.com>
  16851. Date: Thu, 10 Apr 2014 17:24:51 +0100
  16852. Subject: [PATCH 68/94] [rpi] Include ntsc frequencies in list of supported
  16853. resolutions
  16854. ---
  16855. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 8 ------
  16856. xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 35 ++++++++++++++++++++++++-
  16857. xbmc/windowing/egl/WinSystemEGL.cpp | 3 ++-
  16858. 3 files changed, 36 insertions(+), 10 deletions(-)
  16859. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16860. index 019f4b2..b8a3871 100644
  16861. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16862. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16863. @@ -556,14 +556,6 @@ bool OMXPlayerVideo::OpenDecoder()
  16864. m_omxVideo.GetDecoderName().c_str() , m_hints.width, m_hints.height, m_hints.profile, m_fFrameRate);
  16865. m_codecname = m_omxVideo.GetDecoderName();
  16866. -
  16867. - // if we are closer to ntsc version of framerate, let gpu know
  16868. - int iFrameRate = (int)(m_fFrameRate + 0.5f);
  16869. - bool bNtscFreq = fabs(m_fFrameRate * 1001.0f / 1000.0f - iFrameRate) < fabs(m_fFrameRate - iFrameRate);
  16870. - char response[80], command[80];
  16871. - sprintf(command, "hdmi_ntsc_freqs %d", bNtscFreq);
  16872. - CLog::Log(LOGINFO, "OMXPlayerVideo::OpenDecoder fps: %f %s\n", m_fFrameRate, command);
  16873. - m_DllBcmHost.vc_gencmd(response, sizeof response, command);
  16874. }
  16875. // start from assuming all recent frames had valid pts
  16876. diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  16877. index dc47095..21b8cc4 100644
  16878. --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  16879. +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  16880. @@ -20,6 +20,7 @@
  16881. #include "system.h"
  16882. #include <EGL/egl.h>
  16883. +#include <math.h>
  16884. #include "EGLNativeTypeRaspberryPI.h"
  16885. #include "utils/log.h"
  16886. #include "guilib/gui3d.h"
  16887. @@ -236,6 +237,18 @@ bool CEGLNativeTypeRaspberryPI::SetNativeResolution(const RESOLUTION_INFO &res)
  16888. property.param2 = 0;
  16889. vc_tv_hdmi_set_property(&property);
  16890. }
  16891. +
  16892. + HDMI_PROPERTY_PARAM_T property;
  16893. + property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
  16894. + // if we are closer to ntsc version of framerate, let gpu know
  16895. + int iFrameRate = (int)(res.fRefreshRate + 0.5f);
  16896. + if (fabsf(res.fRefreshRate * (1001.0f / 1000.0f) - iFrameRate) < fabsf(res.fRefreshRate - iFrameRate))
  16897. + property.param1 = HDMI_PIXEL_CLOCK_TYPE_NTSC;
  16898. + else
  16899. + property.param1 = HDMI_PIXEL_CLOCK_TYPE_PAL;
  16900. + property.param2 = 0;
  16901. + vc_tv_hdmi_set_property(&property);
  16902. +
  16903. int success = m_DllBcmHost->vc_tv_hdmi_power_on_explicit_new(HDMI_MODE_HDMI, GETFLAGS_GROUP(res.dwFlags), GETFLAGS_MODE(res.dwFlags));
  16904. if (success == 0)
  16905. @@ -442,7 +455,10 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &r
  16906. m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  16907. m_desktopRes.fPixelRatio *= 0.5;
  16908. }
  16909. - m_desktopRes.fRefreshRate = (float)tv_state.display.hdmi.frame_rate;
  16910. + HDMI_PROPERTY_PARAM_T property;
  16911. + property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
  16912. + vc_tv_hdmi_get_property(&property);
  16913. + m_desktopRes.fRefreshRate = property.param1 == HDMI_PIXEL_CLOCK_TYPE_NTSC ? tv_state.display.hdmi.frame_rate * (1000.0f/1001.0f) : tv_state.display.hdmi.frame_rate;
  16914. }
  16915. else // sdtv
  16916. {
  16917. @@ -576,6 +592,12 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  16918. res.iSubtitles = (int)(0.965 * res.iHeight);
  16919. AddUniqueResolution(res, resolutions);
  16920. + if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  16921. + {
  16922. + RESOLUTION_INFO res2 = res;
  16923. + res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f);
  16924. + AddUniqueResolution(res2, resolutions);
  16925. + }
  16926. // Also add 3D versions of modes
  16927. if (tv->struct_3d_mask & HDMI_3D_STRUCT_SIDE_BY_SIDE_HALF_HORIZONTAL)
  16928. @@ -590,6 +612,11 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  16929. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  16930. AddUniqueResolution(res2, resolutions);
  16931. + if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  16932. + {
  16933. + res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f);
  16934. + AddUniqueResolution(res2, resolutions);
  16935. + }
  16936. }
  16937. if (tv->struct_3d_mask & HDMI_3D_STRUCT_TOP_AND_BOTTOM)
  16938. {
  16939. @@ -603,6 +630,12 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  16940. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  16941. AddUniqueResolution(res2, resolutions);
  16942. + if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  16943. + {
  16944. + res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f);
  16945. + AddUniqueResolution(res2, resolutions);
  16946. + }
  16947. +
  16948. }
  16949. }
  16950. }
  16951. diff --git a/xbmc/windowing/egl/WinSystemEGL.cpp b/xbmc/windowing/egl/WinSystemEGL.cpp
  16952. index 0c32947..258a293 100644
  16953. --- a/xbmc/windowing/egl/WinSystemEGL.cpp
  16954. +++ b/xbmc/windowing/egl/WinSystemEGL.cpp
  16955. @@ -34,6 +34,7 @@
  16956. #include "EGLWrapper.h"
  16957. #include "EGLQuirks.h"
  16958. #include <vector>
  16959. +#include <float.h>
  16960. ////////////////////////////////////////////////////////////////////////////////////////////
  16961. CWinSystemEGL::CWinSystemEGL() : CWinSystemBase()
  16962. {
  16963. @@ -399,7 +400,7 @@ void CWinSystemEGL::UpdateResolutions()
  16964. resDesktop.iScreenWidth == resolutions[i].iScreenWidth &&
  16965. resDesktop.iScreenHeight == resolutions[i].iScreenHeight &&
  16966. (resDesktop.dwFlags & D3DPRESENTFLAG_MODEMASK) == (resolutions[i].dwFlags & D3DPRESENTFLAG_MODEMASK) &&
  16967. - resDesktop.fRefreshRate == resolutions[i].fRefreshRate)
  16968. + fabs(resDesktop.fRefreshRate - resolutions[i].fRefreshRate) < FLT_EPSILON)
  16969. {
  16970. ResDesktop = res_index;
  16971. }
  16972. --
  16973. 1.9.3
  16974. From 6e000e35a42863a9db644692246c43300e4ab948 Mon Sep 17 00:00:00 2001
  16975. From: popcornmix <popcornmix@gmail.com>
  16976. Date: Thu, 10 Apr 2014 17:26:20 +0100
  16977. Subject: [PATCH 69/94] [omxplayer] Allow a framerate callback from GPU to
  16978. trigger a hdmi mode change
  16979. ---
  16980. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 8 +++++---
  16981. xbmc/cores/omxplayer/OMXPlayerVideo.h | 4 ++--
  16982. xbmc/cores/omxplayer/OMXVideo.cpp | 35 +++++++++++++++++----------------
  16983. xbmc/cores/omxplayer/OMXVideo.h | 2 +-
  16984. 4 files changed, 26 insertions(+), 23 deletions(-)
  16985. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16986. index b8a3871..e9010b1 100644
  16987. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16988. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  16989. @@ -694,7 +694,7 @@ void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect,
  16990. player->SetVideoRect(SrcRect, DestRect);
  16991. }
  16992. -void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, float display_aspect)
  16993. +void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, float framerate, float display_aspect)
  16994. {
  16995. RESOLUTION res = g_graphicsContext.GetVideoResolution();
  16996. uint32_t video_width = CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth;
  16997. @@ -743,6 +743,8 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
  16998. else if( display_aspect != 0.0f )
  16999. iDisplayWidth = (int) (iDisplayHeight * display_aspect);
  17000. + m_fFrameRate = DVD_TIME_BASE / CDVDCodecUtils::NormalizeFrameduration((double)DVD_TIME_BASE / framerate);
  17001. +
  17002. CLog::Log(LOGDEBUG,"%s - change configuration. video:%dx%d. framerate: %4.2f. %dx%d format: BYPASS",
  17003. __FUNCTION__, video_width, video_height, m_fFrameRate, iDisplayWidth, iDisplayHeight);
  17004. @@ -757,9 +759,9 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
  17005. g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
  17006. }
  17007. -void OMXPlayerVideo::ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float display_aspect)
  17008. +void OMXPlayerVideo::ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float framerate, float display_aspect)
  17009. {
  17010. OMXPlayerVideo *player = static_cast<OMXPlayerVideo*>(ctx);
  17011. - player->ResolutionUpdateCallBack(width, height, display_aspect);
  17012. + player->ResolutionUpdateCallBack(width, height, framerate, display_aspect);
  17013. }
  17014. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17015. index b49748f..33564dd 100644
  17016. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17017. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17018. @@ -125,7 +125,7 @@ class OMXPlayerVideo : public CThread
  17019. int GetFreeSpace();
  17020. void SetVideoRect(const CRect &SrcRect, const CRect &DestRect);
  17021. static void RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect);
  17022. - void ResolutionUpdateCallBack(uint32_t width, uint32_t height, float pixel_aspect);
  17023. - static void ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float pixel_aspect);
  17024. + void ResolutionUpdateCallBack(uint32_t width, uint32_t height, float framerate, float pixel_aspect);
  17025. + static void ResolutionUpdateCallBack(void *ctx, uint32_t width, uint32_t height, float framerate, float pixel_aspect);
  17026. };
  17027. #endif
  17028. diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp
  17029. index 66a351d..10a7530 100644
  17030. --- a/xbmc/cores/omxplayer/OMXVideo.cpp
  17031. +++ b/xbmc/cores/omxplayer/OMXVideo.cpp
  17032. @@ -171,6 +171,22 @@ bool COMXVideo::PortSettingsChanged()
  17033. CLog::Log(LOGERROR, "%s::%s - error m_omx_decoder.GetParameter(OMX_IndexParamBrcmPixelAspectRatio) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  17034. }
  17035. + OMX_CONFIG_INTERLACETYPE interlace;
  17036. + OMX_INIT_STRUCTURE(interlace);
  17037. + interlace.nPortIndex = m_omx_decoder.GetOutputPort();
  17038. + omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
  17039. +
  17040. + if(m_deinterlace_request == VS_DEINTERLACEMODE_FORCE)
  17041. + m_deinterlace = true;
  17042. + else if(m_deinterlace_request == VS_DEINTERLACEMODE_OFF)
  17043. + m_deinterlace = false;
  17044. + else
  17045. + m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
  17046. +
  17047. + CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  17048. + port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
  17049. + port_image.format.video.xFramerate / (float)(1<<16), interlace.eMode, m_deinterlace);
  17050. +
  17051. // let OMXPlayerVideo know about resolution so it can inform RenderManager
  17052. if (m_res_callback)
  17053. {
  17054. @@ -178,7 +194,8 @@ bool COMXVideo::PortSettingsChanged()
  17055. if (pixel_aspect.nX && pixel_aspect.nY)
  17056. display_aspect = (float)pixel_aspect.nX * port_image.format.video.nFrameWidth /
  17057. ((float)pixel_aspect.nY * port_image.format.video.nFrameHeight);
  17058. - m_res_callback(m_res_ctx, port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight, display_aspect);
  17059. + m_res_callback(m_res_ctx, port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
  17060. + port_image.format.video.xFramerate / (float)(1<<16), display_aspect);
  17061. }
  17062. if (m_settings_changed)
  17063. @@ -187,27 +204,11 @@ bool COMXVideo::PortSettingsChanged()
  17064. return true;
  17065. }
  17066. - OMX_CONFIG_INTERLACETYPE interlace;
  17067. - OMX_INIT_STRUCTURE(interlace);
  17068. - interlace.nPortIndex = m_omx_decoder.GetOutputPort();
  17069. - omx_err = m_omx_decoder.GetConfig(OMX_IndexConfigCommonInterlace, &interlace);
  17070. -
  17071. - if(m_deinterlace_request == VS_DEINTERLACEMODE_FORCE)
  17072. - m_deinterlace = true;
  17073. - else if(m_deinterlace_request == VS_DEINTERLACEMODE_OFF)
  17074. - m_deinterlace = false;
  17075. - else
  17076. - m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
  17077. -
  17078. if(!m_omx_render.Initialize("OMX.broadcom.video_render", OMX_IndexParamVideoInit))
  17079. return false;
  17080. m_omx_render.ResetEos();
  17081. - CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  17082. - port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
  17083. - port_image.format.video.xFramerate / (float)(1<<16), interlace.eMode, m_deinterlace);
  17084. -
  17085. if(!m_omx_sched.Initialize("OMX.broadcom.video_scheduler", OMX_IndexParamVideoInit))
  17086. return false;
  17087. diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h
  17088. index d69f854..fd23e70 100644
  17089. --- a/xbmc/cores/omxplayer/OMXVideo.h
  17090. +++ b/xbmc/cores/omxplayer/OMXVideo.h
  17091. @@ -38,7 +38,7 @@
  17092. #define CLASSNAME "COMXVideo"
  17093. -typedef void (*ResolutionUpdateCallBackFn)(void *ctx, uint32_t width, uint32_t height, float display_aspect);
  17094. +typedef void (*ResolutionUpdateCallBackFn)(void *ctx, uint32_t width, uint32_t height, float framerate, float display_aspect);
  17095. class COMXVideo
  17096. {
  17097. --
  17098. 1.9.3
  17099. From 7d8653f297a2aeea7b10bf36732892878ae89334 Mon Sep 17 00:00:00 2001
  17100. From: popcornmix <popcornmix@gmail.com>
  17101. Date: Fri, 11 Apr 2014 19:01:26 +0100
  17102. Subject: [PATCH 70/94] [omxplayer] Request to be notified about framerate
  17103. changes
  17104. ---
  17105. xbmc/cores/omxplayer/OMXVideo.cpp | 14 ++++++++++++--
  17106. 1 file changed, 12 insertions(+), 2 deletions(-)
  17107. diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp
  17108. index 10a7530..148b16f 100644
  17109. --- a/xbmc/cores/omxplayer/OMXVideo.cpp
  17110. +++ b/xbmc/cores/omxplayer/OMXVideo.cpp
  17111. @@ -183,7 +183,7 @@ bool COMXVideo::PortSettingsChanged()
  17112. else
  17113. m_deinterlace = interlace.eMode != OMX_InterlaceProgressive;
  17114. - CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  17115. + CLog::Log(LOGDEBUG, "%s::%s - %dx%d@%.2f interlace:%d deinterlace:%d", CLASSNAME, __func__,
  17116. port_image.format.video.nFrameWidth, port_image.format.video.nFrameHeight,
  17117. port_image.format.video.xFramerate / (float)(1<<16), interlace.eMode, m_deinterlace);
  17118. @@ -558,7 +558,17 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, EDEINTERLACEMODE de
  17119. CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err);
  17120. return false;
  17121. }
  17122. -
  17123. + // request portsettingschanged on refresh rate change
  17124. + if (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") == ADJUST_REFRESHRATE_ALWAYS)
  17125. + {
  17126. + notifications.nIndex = OMX_IndexParamPortDefinition;
  17127. + omx_err = m_omx_decoder.SetParameter((OMX_INDEXTYPE)OMX_IndexConfigRequestCallback, &notifications);
  17128. + if (omx_err != OMX_ErrorNone)
  17129. + {
  17130. + CLog::Log(LOGERROR, "COMXVideo::Open OMX_IndexConfigRequestCallback error (0%08x)\n", omx_err);
  17131. + //return false;
  17132. + }
  17133. + }
  17134. OMX_PARAM_BRCMVIDEODECODEERRORCONCEALMENTTYPE concanParam;
  17135. OMX_INIT_STRUCTURE(concanParam);
  17136. if(g_advancedSettings.m_omxDecodeStartWithValidFrame)
  17137. --
  17138. 1.9.3
  17139. From 12a54cc9ca0c0500f1d86173df0c8466270bd766 Mon Sep 17 00:00:00 2001
  17140. From: popcornmix <popcornmix@gmail.com>
  17141. Date: Mon, 14 Apr 2014 17:04:57 +0100
  17142. Subject: [PATCH 71/94] [omxplayer] Support stereo view modes with scaling
  17143. The Pi only supported a single view rectangle, which is sufficient for all mono view modes,
  17144. but only supports a subset of stereo modes.
  17145. To work around this, the scaling rectangles were ignored in 3D modes and 3D video was treated as unscaled.
  17146. While this worked or square pixel, 16:9 content on a 16:9 display, it went wrong is various other conditions.
  17147. @sraue reported that mono view of SBS/TAB content wasn't scaled correctly, and other forum reports
  17148. aspect ratio errors in widescreen 3D videos.
  17149. As it wasn't trivial to work around these bug reports, I've added a new stereo flags to the firmware
  17150. that allows a second display region to be created for the second eye, allowing scaling to work.
  17151. I've been through the video stereo modes (none, sbs, tab) and the display stereo modes (mono, sbs, tab)
  17152. and all the zoom modes, and compared the scaling to xbmc on windows and all seem to match
  17153. Requires udpated firmware.
  17154. ---
  17155. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 103 +++++++++++++++++++++-----------
  17156. xbmc/cores/omxplayer/OMXPlayerVideo.h | 4 +-
  17157. xbmc/cores/omxplayer/OMXVideo.cpp | 45 ++++++++------
  17158. xbmc/cores/omxplayer/OMXVideo.h | 3 +-
  17159. 4 files changed, 100 insertions(+), 55 deletions(-)
  17160. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17161. index e9010b1..d5f3bec 100644
  17162. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17163. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17164. @@ -97,6 +97,9 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
  17165. m_src_rect.SetRect(0, 0, 0, 0);
  17166. m_dst_rect.SetRect(0, 0, 0, 0);
  17167. + m_video_stereo_mode = RENDER_STEREO_MODE_OFF;
  17168. + m_display_stereo_mode = RENDER_STEREO_MODE_OFF;
  17169. + m_StereoInvert = false;
  17170. m_started = false;
  17171. m_iCurrentPts = DVD_NOPTS_VALUE;
  17172. m_nextOverlay = DVD_NOPTS_VALUE;
  17173. @@ -120,6 +123,9 @@ bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints)
  17174. // force SetVideoRect to be called initially
  17175. m_src_rect.SetRect(0, 0, 0, 0);
  17176. m_dst_rect.SetRect(0, 0, 0, 0);
  17177. + m_video_stereo_mode = RENDER_STEREO_MODE_OFF;
  17178. + m_display_stereo_mode = RENDER_STEREO_MODE_OFF;
  17179. + m_StereoInvert = false;
  17180. if (!m_DllBcmHost.Load())
  17181. return false;
  17182. @@ -634,58 +640,85 @@ int OMXPlayerVideo::GetFreeSpace()
  17183. void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRect)
  17184. {
  17185. - CRect SrcRect = InSrcRect, DestRect = InDestRect;
  17186. + // we get called twice a frame for left/right. Can ignore the rights.
  17187. + if (g_graphicsContext.GetStereoView() == RENDER_STEREO_VIEW_RIGHT)
  17188. + return;
  17189. - // in 3d modes skip this - we get called as the gui switches from left eye to right eye
  17190. + CRect SrcRect = InSrcRect, DestRect = InDestRect;
  17191. unsigned flags = GetStereoModeFlags(GetStereoMode());
  17192. -
  17193. - if (CONF_FLAGS_STEREO_MODE_MASK(flags))
  17194. - {
  17195. - if (g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_MONO)
  17196. - {
  17197. - if (GetStereoMode() == "left_right")
  17198. - SrcRect.SetRect(0, 0, m_hints.width>>1, m_hints.height);
  17199. - else if (GetStereoMode() == "right_left")
  17200. - SrcRect.SetRect(m_hints.width>>1, 0, m_hints.width, m_hints.height);
  17201. - else if (GetStereoMode() == "top_bottom")
  17202. - SrcRect.SetRect(0, 0, m_hints.width, m_hints.height>>1);
  17203. - else if (GetStereoMode() == "bottom_top")
  17204. - SrcRect.SetRect(0, m_hints.height>>1, m_hints.width, m_hints.height);
  17205. - }
  17206. - else
  17207. - SrcRect.SetRect(0, 0, m_hints.width, m_hints.height);
  17208. - // interpreted as fullscreen
  17209. - DestRect.SetRect(0, 0, 0, 0);
  17210. - }
  17211. + RENDER_STEREO_MODE video_stereo_mode = (flags & CONF_FLAGS_STEREO_MODE_SBS) ? RENDER_STEREO_MODE_SPLIT_VERTICAL :
  17212. + (flags & CONF_FLAGS_STEREO_MODE_TAB) ? RENDER_STEREO_MODE_SPLIT_HORIZONTAL : RENDER_STEREO_MODE_OFF;
  17213. + bool stereo_invert = (flags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false;
  17214. + RENDER_STEREO_MODE display_stereo_mode = g_graphicsContext.GetStereoMode();
  17215. // check if destination rect or video view mode has changed
  17216. - if (m_dst_rect != DestRect || m_src_rect != SrcRect)
  17217. - {
  17218. - m_src_rect = SrcRect;
  17219. - m_dst_rect = DestRect;
  17220. - }
  17221. - else
  17222. - {
  17223. + if (!(m_dst_rect != DestRect) && !(m_src_rect != SrcRect) && m_video_stereo_mode == video_stereo_mode && m_display_stereo_mode == display_stereo_mode && m_StereoInvert == stereo_invert)
  17224. return;
  17225. - }
  17226. +
  17227. + CLog::Log(LOGDEBUG, "OMXPlayerVideo::%s %d,%d,%d,%d -> %d,%d,%d,%d (%d,%d,%d,%d,%s)", __func__,
  17228. + (int)SrcRect.x1, (int)SrcRect.y1, (int)SrcRect.x2, (int)SrcRect.y2,
  17229. + (int)DestRect.x1, (int)DestRect.y1, (int)DestRect.x2, (int)DestRect.y2,
  17230. + video_stereo_mode, display_stereo_mode, CMediaSettings::Get().GetCurrentVideoSettings().m_StereoInvert, g_graphicsContext.GetStereoView(), OMXPlayerVideo::GetStereoMode().c_str());
  17231. +
  17232. + m_src_rect = SrcRect;
  17233. + m_dst_rect = DestRect;
  17234. + m_video_stereo_mode = video_stereo_mode;
  17235. + m_display_stereo_mode = display_stereo_mode;
  17236. + m_StereoInvert = stereo_invert;
  17237. // might need to scale up m_dst_rect to display size as video decodes
  17238. // to separate video plane that is at display size.
  17239. RESOLUTION res = g_graphicsContext.GetVideoResolution();
  17240. CRect gui(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iWidth, CDisplaySettings::Get().GetResolutionInfo(res).iHeight);
  17241. CRect display(0, 0, CDisplaySettings::Get().GetResolutionInfo(res).iScreenWidth, CDisplaySettings::Get().GetResolutionInfo(res).iScreenHeight);
  17242. - CRect dst_rect(m_dst_rect);
  17243. +
  17244. + switch (video_stereo_mode)
  17245. + {
  17246. + case RENDER_STEREO_MODE_SPLIT_VERTICAL:
  17247. + // optimisation - use simpler display mode in common case of unscaled 3d with same display mode
  17248. + if (video_stereo_mode == display_stereo_mode && DestRect.x1 == 0.0f && DestRect.x2 * 2.0f == gui.Width() && !stereo_invert)
  17249. + {
  17250. + SrcRect.x2 *= 2.0f;
  17251. + DestRect.x2 *= 2.0f;
  17252. + video_stereo_mode = RENDER_STEREO_MODE_OFF;
  17253. + display_stereo_mode = RENDER_STEREO_MODE_OFF;
  17254. + }
  17255. + else if (stereo_invert)
  17256. + {
  17257. + SrcRect.x1 += m_hints.width / 2;
  17258. + SrcRect.x2 += m_hints.width / 2;
  17259. + }
  17260. + break;
  17261. +
  17262. + case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
  17263. + // optimisation - use simpler display mode in common case of unscaled 3d with same display mode
  17264. + if (video_stereo_mode == display_stereo_mode && DestRect.y1 == 0.0f && DestRect.y2 * 2.0f == gui.Height() && !stereo_invert)
  17265. + {
  17266. + SrcRect.y2 *= 2.0f;
  17267. + DestRect.y2 *= 2.0f;
  17268. + video_stereo_mode = RENDER_STEREO_MODE_OFF;
  17269. + display_stereo_mode = RENDER_STEREO_MODE_OFF;
  17270. + }
  17271. + else if (stereo_invert)
  17272. + {
  17273. + SrcRect.y1 += m_hints.height / 2;
  17274. + SrcRect.y2 += m_hints.height / 2;
  17275. + }
  17276. + break;
  17277. +
  17278. + default: break;
  17279. + }
  17280. if (gui != display)
  17281. {
  17282. float xscale = display.Width() / gui.Width();
  17283. float yscale = display.Height() / gui.Height();
  17284. - dst_rect.x1 *= xscale;
  17285. - dst_rect.x2 *= xscale;
  17286. - dst_rect.y1 *= yscale;
  17287. - dst_rect.y2 *= yscale;
  17288. + DestRect.x1 *= xscale;
  17289. + DestRect.x2 *= xscale;
  17290. + DestRect.y1 *= yscale;
  17291. + DestRect.y2 *= yscale;
  17292. }
  17293. - m_omxVideo.SetVideoRect(SrcRect, dst_rect);
  17294. + m_omxVideo.SetVideoRect(SrcRect, DestRect, video_stereo_mode, display_stereo_mode);
  17295. }
  17296. void OMXPlayerVideo::RenderUpdateCallBack(const void *ctx, const CRect &SrcRect, const CRect &DestRect)
  17297. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17298. index 33564dd..6f19395 100644
  17299. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17300. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  17301. @@ -69,7 +69,9 @@ class OMXPlayerVideo : public CThread
  17302. CRect m_src_rect;
  17303. CRect m_dst_rect;
  17304. -
  17305. + RENDER_STEREO_MODE m_video_stereo_mode;
  17306. + RENDER_STEREO_MODE m_display_stereo_mode;
  17307. + bool m_StereoInvert;
  17308. uint32_t m_history_valid_pts;
  17309. DllBcmHost m_DllBcmHost;
  17310. diff --git a/xbmc/cores/omxplayer/OMXVideo.cpp b/xbmc/cores/omxplayer/OMXVideo.cpp
  17311. index 148b16f..dceb8bf 100644
  17312. --- a/xbmc/cores/omxplayer/OMXVideo.cpp
  17313. +++ b/xbmc/cores/omxplayer/OMXVideo.cpp
  17314. @@ -836,7 +836,7 @@ void COMXVideo::Reset(void)
  17315. }
  17316. ///////////////////////////////////////////////////////////////////////////////////////////
  17317. -void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect)
  17318. +void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode)
  17319. {
  17320. CSingleLock lock (m_critSection);
  17321. if(!m_is_open)
  17322. @@ -846,27 +846,36 @@ void COMXVideo::SetVideoRect(const CRect& SrcRect, const CRect& DestRect)
  17323. OMX_INIT_STRUCTURE(configDisplay);
  17324. configDisplay.nPortIndex = m_omx_render.GetInputPort();
  17325. - configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT);
  17326. - configDisplay.dest_rect.x_offset = (int)(DestRect.x1+0.5f);
  17327. - configDisplay.dest_rect.y_offset = (int)(DestRect.y1+0.5f);
  17328. - configDisplay.dest_rect.width = (int)(DestRect.Width()+0.5f);
  17329. - configDisplay.dest_rect.height = (int)(DestRect.Height()+0.5f);
  17330. -
  17331. - configDisplay.src_rect.x_offset = (int)(SrcRect.x1+0.5f);
  17332. - configDisplay.src_rect.y_offset = (int)(SrcRect.y1+0.5f);
  17333. - configDisplay.src_rect.width = (int)(SrcRect.Width()+0.5f);
  17334. - configDisplay.src_rect.height = (int)(SrcRect.Height()+0.5f);
  17335. -
  17336. - if (configDisplay.dest_rect.width == 0 || configDisplay.dest_rect.height == 0)
  17337. - configDisplay.fullscreen = OMX_TRUE;
  17338. + configDisplay.set = (OMX_DISPLAYSETTYPE)(OMX_DISPLAY_SET_DEST_RECT|OMX_DISPLAY_SET_SRC_RECT|OMX_DISPLAY_SET_FULLSCREEN|OMX_DISPLAY_SET_NOASPECT|OMX_DISPLAY_SET_MODE);
  17339. + configDisplay.dest_rect.x_offset = lrintf(DestRect.x1);
  17340. + configDisplay.dest_rect.y_offset = lrintf(DestRect.y1);
  17341. + configDisplay.dest_rect.width = lrintf(DestRect.Width());
  17342. + configDisplay.dest_rect.height = lrintf(DestRect.Height());
  17343. +
  17344. + configDisplay.src_rect.x_offset = lrintf(SrcRect.x1);
  17345. + configDisplay.src_rect.y_offset = lrintf(SrcRect.y1);
  17346. + configDisplay.src_rect.width = lrintf(SrcRect.Width());
  17347. + configDisplay.src_rect.height = lrintf(SrcRect.Height());
  17348. +
  17349. + configDisplay.fullscreen = OMX_FALSE;
  17350. + configDisplay.noaspect = OMX_TRUE;
  17351. +
  17352. + if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
  17353. + configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_TOP;
  17354. + else if (video_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
  17355. + configDisplay.mode = OMX_DISPLAY_MODE_STEREO_TOP_TO_LEFT;
  17356. + else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
  17357. + configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_TOP;
  17358. + else if (video_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && display_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
  17359. + configDisplay.mode = OMX_DISPLAY_MODE_STEREO_LEFT_TO_LEFT;
  17360. else
  17361. - configDisplay.noaspect = OMX_TRUE;
  17362. + configDisplay.mode = OMX_DISPLAY_MODE_LETTERBOX;
  17363. m_omx_render.SetConfig(OMX_IndexConfigDisplayRegion, &configDisplay);
  17364. - CLog::Log(LOGDEBUG, "dest_rect.x_offset %d dest_rect.y_offset %d dest_rect.width %d dest_rect.height %d\n",
  17365. - configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset,
  17366. - configDisplay.dest_rect.width, configDisplay.dest_rect.height);
  17367. + CLog::Log(LOGDEBUG, "%s::%s %d,%d,%d,%d -> %d,%d,%d,%d mode:%d", CLASSNAME, __func__,
  17368. + configDisplay.src_rect.x_offset, configDisplay.src_rect.y_offset, configDisplay.src_rect.width, configDisplay.src_rect.height,
  17369. + configDisplay.dest_rect.x_offset, configDisplay.dest_rect.y_offset, configDisplay.dest_rect.width, configDisplay.dest_rect.height, configDisplay.mode);
  17370. }
  17371. int COMXVideo::GetInputBufferSize()
  17372. diff --git a/xbmc/cores/omxplayer/OMXVideo.h b/xbmc/cores/omxplayer/OMXVideo.h
  17373. index fd23e70..226000e 100644
  17374. --- a/xbmc/cores/omxplayer/OMXVideo.h
  17375. +++ b/xbmc/cores/omxplayer/OMXVideo.h
  17376. @@ -32,6 +32,7 @@
  17377. #include "DVDDemuxers/DVDDemux.h"
  17378. #include "xbmc/settings/VideoSettings.h"
  17379. #include "threads/CriticalSection.h"
  17380. +#include "xbmc/rendering/RenderSystem.h"
  17381. #include <string>
  17382. #define VIDEO_BUFFERS 60
  17383. @@ -58,7 +59,7 @@ class COMXVideo
  17384. void Reset(void);
  17385. void SetDropState(bool bDrop);
  17386. std::string GetDecoderName() { return m_video_codec_name; };
  17387. - void SetVideoRect(const CRect& SrcRect, const CRect& DestRect);
  17388. + void SetVideoRect(const CRect& SrcRect, const CRect& DestRect, RENDER_STEREO_MODE video_mode, RENDER_STEREO_MODE display_mode);
  17389. int GetInputBufferSize();
  17390. void SubmitEOS();
  17391. bool IsEOS();
  17392. --
  17393. 1.9.3
  17394. From 716400b7b3cf13c6546bba6a0d0a2f47825f9117 Mon Sep 17 00:00:00 2001
  17395. From: popcornmix <popcornmix@gmail.com>
  17396. Date: Wed, 16 Apr 2014 21:18:06 +0100
  17397. Subject: [PATCH 72/94] [omxplayer] Don't propagate 3d flags based on supported
  17398. 3d modes
  17399. ---
  17400. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 29 ++++-------------------------
  17401. 1 file changed, 4 insertions(+), 25 deletions(-)
  17402. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17403. index d5f3bec..e9f86f3 100644
  17404. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17405. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17406. @@ -736,36 +736,15 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
  17407. unsigned flags = 0;
  17408. ERenderFormat format = RENDER_FMT_BYPASS;
  17409. + /* figure out steremode expected based on user settings and hints */
  17410. + unsigned int stereo_flags = GetStereoModeFlags(GetStereoMode());
  17411. +
  17412. if(m_bAllowFullscreen)
  17413. {
  17414. flags |= CONF_FLAGS_FULLSCREEN;
  17415. m_bAllowFullscreen = false; // only allow on first configure
  17416. }
  17417. -
  17418. - flags |= GetStereoModeFlags(GetStereoMode());
  17419. -
  17420. - if(flags & CONF_FLAGS_STEREO_MODE_SBS)
  17421. - {
  17422. - if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DSBS))
  17423. - CLog::Log(LOGNOTICE, "3DSBS movie found");
  17424. - else
  17425. - {
  17426. - flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
  17427. - CLog::Log(LOGNOTICE, "3DSBS movie found but not supported");
  17428. - }
  17429. - }
  17430. - else if(flags & CONF_FLAGS_STEREO_MODE_TAB)
  17431. - {
  17432. - if(g_Windowing.Support3D(video_width, video_height, D3DPRESENTFLAG_MODE3DTB))
  17433. - CLog::Log(LOGNOTICE, "3DTB movie found");
  17434. - else
  17435. - {
  17436. - flags &= ~CONF_FLAGS_STEREO_MODE_MASK(~0);
  17437. - CLog::Log(LOGNOTICE, "3DTB movie found but not supported");
  17438. - }
  17439. - }
  17440. - else
  17441. - CLog::Log(LOGNOTICE, "not a 3D movie");
  17442. + flags |= stereo_flags;
  17443. unsigned int iDisplayWidth = width;
  17444. unsigned int iDisplayHeight = height;
  17445. --
  17446. 1.9.3
  17447. From 7f2220746d9efeb3e8cfc4524479a615db5b710c Mon Sep 17 00:00:00 2001
  17448. From: popcornmix <popcornmix@gmail.com>
  17449. Date: Thu, 17 Apr 2014 13:00:52 +0100
  17450. Subject: [PATCH 73/94] [graphics] Don't set stereo mode based on resolution
  17451. The resolution change should follow stereo mode
  17452. ---
  17453. xbmc/guilib/GraphicContext.cpp | 22 ----------------------
  17454. 1 file changed, 22 deletions(-)
  17455. diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
  17456. index 5bffdf5..7e4fdd4 100644
  17457. --- a/xbmc/guilib/GraphicContext.cpp
  17458. +++ b/xbmc/guilib/GraphicContext.cpp
  17459. @@ -418,28 +418,6 @@ void CGraphicContext::SetVideoResolution(RESOLUTION res, bool forceUpdate)
  17460. Lock();
  17461. RESOLUTION_INFO info_org = CDisplaySettings::Get().GetResolutionInfo(res);
  17462. - RESOLUTION_INFO info_last = CDisplaySettings::Get().GetResolutionInfo(lastRes);
  17463. -
  17464. - RENDER_STEREO_MODE stereo_mode = m_stereoMode;
  17465. -
  17466. - // if the new mode is an actual stereo mode, switch to that
  17467. - // if the old mode was an actual stereo mode, switch to no 3d mode
  17468. - if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DTB)
  17469. - stereo_mode = RENDER_STEREO_MODE_SPLIT_HORIZONTAL;
  17470. - else if (info_org.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
  17471. - stereo_mode = RENDER_STEREO_MODE_SPLIT_VERTICAL;
  17472. - else if ((info_last.dwFlags & D3DPRESENTFLAG_MODE3DSBS) != 0
  17473. - || (info_last.dwFlags & D3DPRESENTFLAG_MODE3DTB) != 0)
  17474. - stereo_mode = RENDER_STEREO_MODE_OFF;
  17475. -
  17476. - if(stereo_mode != m_stereoMode)
  17477. - {
  17478. - m_stereoView = RENDER_STEREO_VIEW_OFF;
  17479. - m_stereoMode = stereo_mode;
  17480. - m_nextStereoMode = stereo_mode;
  17481. - CSettings::Get().SetInt("videoscreen.stereoscopicmode", (int)m_stereoMode);
  17482. - }
  17483. -
  17484. RESOLUTION_INFO info_mod = GetResInfo(res);
  17485. m_iScreenWidth = info_mod.iWidth;
  17486. --
  17487. 1.9.3
  17488. From 7885d90283809ccbcdb9c39809682dfc099049c4 Mon Sep 17 00:00:00 2001
  17489. From: popcornmix <popcornmix@gmail.com>
  17490. Date: Thu, 17 Apr 2014 13:01:51 +0100
  17491. Subject: [PATCH 74/94] [graphics] Allow switching to a more suitable 3D
  17492. resolution
  17493. ---
  17494. xbmc/guilib/GraphicContext.cpp | 41 ++++++++++++++++++++++++++++++++++++++++-
  17495. xbmc/guilib/GraphicContext.h | 1 +
  17496. 2 files changed, 41 insertions(+), 1 deletion(-)
  17497. diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
  17498. index 7e4fdd4..886b612 100644
  17499. --- a/xbmc/guilib/GraphicContext.cpp
  17500. +++ b/xbmc/guilib/GraphicContext.cpp
  17501. @@ -35,6 +35,7 @@
  17502. #include "utils/JobManager.h"
  17503. #include "video/VideoReferenceClock.h"
  17504. #include "cores/IPlayer.h"
  17505. +#include <float.h>
  17506. using namespace std;
  17507. @@ -459,6 +460,44 @@ RESOLUTION CGraphicContext::GetVideoResolution() const
  17508. return m_Resolution;
  17509. }
  17510. +RESOLUTION CGraphicContext::Get3DVideoResolution(RENDER_STEREO_MODE mode) const
  17511. +{
  17512. + RESOLUTION best = m_Resolution;
  17513. + RESOLUTION_INFO curr = CDisplaySettings::Get().GetResolutionInfo(best);
  17514. +
  17515. + // Find closest refresh rate
  17516. + for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
  17517. + {
  17518. + const RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo((RESOLUTION)i);
  17519. +
  17520. + //discard resolutions that are not the same width and height (and interlaced/3D flags)
  17521. + //or have a too low refreshrate
  17522. + if (info.iScreenWidth != curr.iScreenWidth
  17523. + || info.iScreenHeight != curr.iScreenHeight
  17524. + || info.iScreen != curr.iScreen
  17525. + || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED)
  17526. + || fabs(info.fRefreshRate - curr.fRefreshRate) >= FLT_EPSILON)
  17527. + continue;
  17528. +
  17529. + if (mode == RENDER_STEREO_MODE_SPLIT_VERTICAL && info.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
  17530. + {
  17531. + best = (RESOLUTION)i;
  17532. + break;
  17533. + }
  17534. + else if (mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL && info.dwFlags & D3DPRESENTFLAG_MODE3DTB)
  17535. + {
  17536. + best = (RESOLUTION)i;
  17537. + break;
  17538. + }
  17539. + else if ((mode == RENDER_STEREO_MODE_OFF || mode == RENDER_STEREO_MODE_MONO) && !(info.dwFlags & (D3DPRESENTFLAG_MODE3DSBS|D3DPRESENTFLAG_MODE3DTB)))
  17540. + {
  17541. + best = (RESOLUTION)i;
  17542. + break;
  17543. + }
  17544. + }
  17545. + return best;
  17546. +}
  17547. +
  17548. void CGraphicContext::ResetOverscan(RESOLUTION_INFO &res)
  17549. {
  17550. res.Overscan.left = 0;
  17551. @@ -996,7 +1035,7 @@ void CGraphicContext::Flip(const CDirtyRegionList& dirty)
  17552. if(m_stereoMode != m_nextStereoMode)
  17553. {
  17554. m_stereoMode = m_nextStereoMode;
  17555. - SetVideoResolution(GetVideoResolution(), true);
  17556. + SetVideoResolution(Get3DVideoResolution(m_stereoMode), true);
  17557. g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_RENDERER_RESET);
  17558. }
  17559. }
  17560. diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
  17561. index 0a27643..df55e92 100644
  17562. --- a/xbmc/guilib/GraphicContext.h
  17563. +++ b/xbmc/guilib/GraphicContext.h
  17564. @@ -108,6 +108,7 @@ class CGraphicContext : public CCriticalSection,
  17565. bool IsValidResolution(RESOLUTION res);
  17566. void SetVideoResolution(RESOLUTION res, bool forceUpdate = false);
  17567. RESOLUTION GetVideoResolution() const;
  17568. + RESOLUTION Get3DVideoResolution(RENDER_STEREO_MODE mode) const;
  17569. void ResetOverscan(RESOLUTION res, OVERSCAN &overscan);
  17570. void ResetOverscan(RESOLUTION_INFO &resinfo);
  17571. void ResetScreenParameters(RESOLUTION res);
  17572. --
  17573. 1.9.3
  17574. From 49438256c57d11b415f6a90f653857e7fae16a1d Mon Sep 17 00:00:00 2001
  17575. From: popcornmix <popcornmix@gmail.com>
  17576. Date: Thu, 17 Apr 2014 13:38:55 +0100
  17577. Subject: [PATCH 75/94] [3D] Support switching to 3D resolutions
  17578. Include matching 3D flags (SBS/TAB) in the score of a resolution to switch to, to enable switching to 3d modes.
  17579. Also remove the old code that treated 3D modes differently when assigning a score.
  17580. ---
  17581. xbmc/cores/VideoRenderers/BaseRenderer.cpp | 47 +++++++++++-------------------
  17582. 1 file changed, 17 insertions(+), 30 deletions(-)
  17583. diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17584. index 970b822..9ca1be1 100644
  17585. --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17586. +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17587. @@ -222,10 +222,14 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
  17588. RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RESOLUTION current, float& weight)
  17589. {
  17590. RESOLUTION_INFO curr = g_graphicsContext.GetResInfo(current);
  17591. + RENDER_STEREO_MODE stereo_mode = g_graphicsContext.GetStereoMode();
  17592. float fRefreshRate = fps;
  17593. - float last_diff = fRefreshRate;
  17594. + int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
  17595. + if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ||
  17596. + !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(curr.dwFlags & D3DPRESENTFLAG_MODE3DTB))
  17597. + c_weight += 1000;
  17598. // Find closest refresh rate
  17599. for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
  17600. @@ -241,40 +245,23 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES
  17601. || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001)
  17602. continue;
  17603. - // For 3D choose the closest refresh rate
  17604. - if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
  17605. - {
  17606. - float diff = (info.fRefreshRate - fRefreshRate);
  17607. - if(diff < 0)
  17608. - diff *= -1.0f;
  17609. + int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
  17610. - if(diff < last_diff)
  17611. - {
  17612. - last_diff = diff;
  17613. - current = (RESOLUTION)i;
  17614. - curr = info;
  17615. - }
  17616. - }
  17617. - else
  17618. - {
  17619. - int c_weight = MathUtils::round_int(RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
  17620. - int i_weight = MathUtils::round_int(RefreshWeight(info.fRefreshRate, fRefreshRate * multiplier) * 1000.0);
  17621. + if (!(stereo_mode == RENDER_STEREO_MODE_SPLIT_VERTICAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) ||
  17622. + !(stereo_mode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL) != !(info.dwFlags & D3DPRESENTFLAG_MODE3DTB))
  17623. + i_weight += 1000;
  17624. - // Closer the better, prefer higher refresh rate if the same
  17625. - if ((i_weight < c_weight)
  17626. - || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate))
  17627. - {
  17628. - current = (RESOLUTION)i;
  17629. - curr = info;
  17630. - }
  17631. + // Closer the better, prefer higher refresh rate if the same
  17632. + if ((i_weight < c_weight)
  17633. + || (i_weight == c_weight && info.fRefreshRate > curr.fRefreshRate))
  17634. + {
  17635. + current = (RESOLUTION)i;
  17636. + curr = info;
  17637. + c_weight = i_weight;
  17638. }
  17639. }
  17640. - // For 3D overwrite weight
  17641. - if(CONF_FLAGS_STEREO_MODE_MASK(m_iFlags))
  17642. - weight = 0;
  17643. - else
  17644. - weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier);
  17645. + weight = RefreshWeight(curr.fRefreshRate, fRefreshRate * multiplier);
  17646. return current;
  17647. }
  17648. --
  17649. 1.9.3
  17650. From bd077947037288550a8e68efed630a3477a16564 Mon Sep 17 00:00:00 2001
  17651. From: popcornmix <popcornmix@gmail.com>
  17652. Date: Wed, 23 Apr 2014 00:05:07 +0100
  17653. Subject: [PATCH 76/94] [graphics] Make pixel ratio for 3d modes consistent
  17654. Note: Use the stored stereo flags from lists of resolutions.
  17655. Use current stereo mode for current resolution.
  17656. ---
  17657. xbmc/cores/VideoRenderers/BaseRenderer.cpp | 10 ++++----
  17658. xbmc/guilib/GraphicContext.cpp | 32 ++++++++++---------------
  17659. xbmc/guilib/GraphicContext.h | 4 ++--
  17660. xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 8 -------
  17661. 4 files changed, 19 insertions(+), 35 deletions(-)
  17662. diff --git a/xbmc/cores/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17663. index 9ca1be1..6bf42bf 100644
  17664. --- a/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17665. +++ b/xbmc/cores/VideoRenderers/BaseRenderer.cpp
  17666. @@ -119,7 +119,7 @@ bool CBaseRenderer::FindResolutionFromOverride(float fps, float& weight, bool fa
  17667. for (size_t j = (int)RES_DESKTOP; j < CDisplaySettings::Get().ResolutionInfoSize(); j++)
  17668. {
  17669. - RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j);
  17670. + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)j, false);
  17671. if (info.iScreenWidth == curr.iScreenWidth
  17672. && info.iScreenHeight == curr.iScreenHeight
  17673. @@ -179,7 +179,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
  17674. //get the resolution with the refreshrate closest to 60 hertz
  17675. for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
  17676. {
  17677. - RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
  17678. + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false);
  17679. if (MathUtils::round_int(info.fRefreshRate) == 60
  17680. && info.iScreenWidth == curr.iScreenWidth
  17681. @@ -200,7 +200,7 @@ void CBaseRenderer::FindResolutionFromFpsMatch(float fps, float& weight)
  17682. CLog::Log(LOGDEBUG, "60 hertz refreshrate not available, choosing highest");
  17683. for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
  17684. {
  17685. - RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
  17686. + RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false);
  17687. if (info.fRefreshRate > curr.fRefreshRate
  17688. && info.iScreenWidth == curr.iScreenWidth
  17689. @@ -234,14 +234,14 @@ RESOLUTION CBaseRenderer::FindClosestResolution(float fps, float multiplier, RES
  17690. // Find closest refresh rate
  17691. for (size_t i = (int)RES_DESKTOP; i < CDisplaySettings::Get().ResolutionInfoSize(); i++)
  17692. {
  17693. - const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i);
  17694. + const RESOLUTION_INFO info = g_graphicsContext.GetResInfo((RESOLUTION)i, false);
  17695. //discard resolutions that are not the same width and height (and interlaced/3D flags)
  17696. //or have a too low refreshrate
  17697. if (info.iScreenWidth != curr.iScreenWidth
  17698. || info.iScreenHeight != curr.iScreenHeight
  17699. || info.iScreen != curr.iScreen
  17700. - || (info.dwFlags & D3DPRESENTFLAG_MODEMASK) != (curr.dwFlags & D3DPRESENTFLAG_MODEMASK)
  17701. + || (info.dwFlags & D3DPRESENTFLAG_INTERLACED) != (curr.dwFlags & D3DPRESENTFLAG_INTERLACED)
  17702. || info.fRefreshRate < (fRefreshRate * multiplier / 1.001) - 0.001)
  17703. continue;
  17704. diff --git a/xbmc/guilib/GraphicContext.cpp b/xbmc/guilib/GraphicContext.cpp
  17705. index 886b612..40a6362 100644
  17706. --- a/xbmc/guilib/GraphicContext.cpp
  17707. +++ b/xbmc/guilib/GraphicContext.cpp
  17708. @@ -707,32 +707,26 @@ void CGraphicContext::ApplyStateBlock()
  17709. g_Windowing.ApplyStateBlock();
  17710. }
  17711. -const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const
  17712. +const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res, bool use_current_3d /*= true*/) const
  17713. {
  17714. RESOLUTION_INFO info = CDisplaySettings::Get().GetResolutionInfo(res);
  17715. - if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL)
  17716. + if(use_current_3d ? m_stereoMode == RENDER_STEREO_MODE_SPLIT_HORIZONTAL : (info.dwFlags & D3DPRESENTFLAG_MODE3DTB))
  17717. {
  17718. - if((info.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
  17719. - {
  17720. - info.fPixelRatio /= 2;
  17721. - info.iBlanking = 0;
  17722. - info.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  17723. - }
  17724. + info.fPixelRatio /= 2;
  17725. + info.iBlanking = 0;
  17726. + info.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  17727. info.iHeight = (info.iHeight - info.iBlanking) / 2;
  17728. info.Overscan.top /= 2;
  17729. info.Overscan.bottom = (info.Overscan.bottom - info.iBlanking) / 2;
  17730. info.iSubtitles = (info.iSubtitles - info.iBlanking) / 2;
  17731. }
  17732. - if(m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL)
  17733. + if(use_current_3d ? m_stereoMode == RENDER_STEREO_MODE_SPLIT_VERTICAL : (info.dwFlags & D3DPRESENTFLAG_MODE3DSBS))
  17734. {
  17735. - if((info.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0)
  17736. - {
  17737. - info.fPixelRatio *= 2;
  17738. - info.iBlanking = 0;
  17739. - info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  17740. - }
  17741. + info.fPixelRatio *= 2;
  17742. + info.iBlanking = 0;
  17743. + info.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  17744. info.iWidth = (info.iWidth - info.iBlanking) / 2;
  17745. info.Overscan.left /= 2;
  17746. info.Overscan.right = (info.Overscan.right - info.iBlanking) / 2;
  17747. @@ -740,7 +734,7 @@ const RESOLUTION_INFO CGraphicContext::GetResInfo(RESOLUTION res) const
  17748. return info;
  17749. }
  17750. -void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info)
  17751. +void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info, bool use_current_3d /*= true*/)
  17752. {
  17753. RESOLUTION_INFO& curr = CDisplaySettings::Get().GetResolutionInfo(res);
  17754. curr.Overscan = info.Overscan;
  17755. @@ -750,16 +744,14 @@ void CGraphicContext::SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info)
  17756. if(info.dwFlags & D3DPRESENTFLAG_MODE3DSBS)
  17757. {
  17758. curr.Overscan.right = info.Overscan.right * 2 + info.iBlanking;
  17759. - if((curr.dwFlags & D3DPRESENTFLAG_MODE3DSBS) == 0)
  17760. - curr.fPixelRatio /= 2.0;
  17761. + curr.fPixelRatio /= 2.0;
  17762. }
  17763. if(info.dwFlags & D3DPRESENTFLAG_MODE3DTB)
  17764. {
  17765. curr.Overscan.bottom = info.Overscan.bottom * 2 + info.iBlanking;
  17766. curr.iSubtitles = info.iSubtitles * 2 + info.iBlanking;
  17767. - if((curr.dwFlags & D3DPRESENTFLAG_MODE3DTB) == 0)
  17768. - curr.fPixelRatio *= 2.0;
  17769. + curr.fPixelRatio *= 2.0;
  17770. }
  17771. }
  17772. diff --git a/xbmc/guilib/GraphicContext.h b/xbmc/guilib/GraphicContext.h
  17773. index df55e92..c77f2ff 100644
  17774. --- a/xbmc/guilib/GraphicContext.h
  17775. +++ b/xbmc/guilib/GraphicContext.h
  17776. @@ -124,8 +124,8 @@ class CGraphicContext : public CCriticalSection,
  17777. {
  17778. return GetResInfo(m_Resolution);
  17779. }
  17780. - const RESOLUTION_INFO GetResInfo(RESOLUTION res) const;
  17781. - void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info);
  17782. + const RESOLUTION_INFO GetResInfo(RESOLUTION res, bool use_current_3d = true) const;
  17783. + void SetResInfo(RESOLUTION res, const RESOLUTION_INFO& info, bool use_current_3d = true);
  17784. /* \brief Get UI scaling information from a given resolution to the screen resolution.
  17785. Takes account of overscan and UI zooming.
  17786. diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  17787. index 21b8cc4..f57b22b 100644
  17788. --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  17789. +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  17790. @@ -446,15 +446,9 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &r
  17791. m_desktopRes.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv_state.display.hdmi.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
  17792. // Also add 3D flags
  17793. if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_SBS_HALF)
  17794. - {
  17795. m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  17796. - m_desktopRes.fPixelRatio *= 2.0;
  17797. - }
  17798. else if (tv_state.display.hdmi.format_3d == HDMI_3D_FORMAT_TB_HALF)
  17799. - {
  17800. m_desktopRes.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  17801. - m_desktopRes.fPixelRatio *= 0.5;
  17802. - }
  17803. HDMI_PROPERTY_PARAM_T property;
  17804. property.property = HDMI_PROPERTY_PIXEL_CLOCK_TYPE;
  17805. vc_tv_hdmi_get_property(&property);
  17806. @@ -605,7 +599,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  17807. RESOLUTION_INFO res2 = res;
  17808. res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  17809. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  17810. - res2.fPixelRatio *= 2.0f;
  17811. SetResolutionString(res2);
  17812. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  17813. @@ -623,7 +616,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  17814. RESOLUTION_INFO res2 = res;
  17815. res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  17816. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  17817. - res2.fPixelRatio *= 0.5f;
  17818. SetResolutionString(res2);
  17819. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  17820. --
  17821. 1.9.3
  17822. From 7464b116a5db0be0c2b50314fcf703529d6f646e Mon Sep 17 00:00:00 2001
  17823. From: popcornmix <popcornmix@gmail.com>
  17824. Date: Wed, 23 Apr 2014 21:07:51 +0100
  17825. Subject: [PATCH 77/94] [PiSink] More attempts to reduce underrun audio
  17826. glitches with multichannl and high samplerate
  17827. ---
  17828. xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp | 79 +++++++++++--------------------
  17829. 1 file changed, 27 insertions(+), 52 deletions(-)
  17830. diff --git a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  17831. index 070e6eb..133b9f6 100644
  17832. --- a/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  17833. +++ b/xbmc/cores/AudioEngine/Sinks/AESinkPi.cpp
  17834. @@ -186,7 +186,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device)
  17835. unsigned int sample_size = CAEUtil::DataFormatToBits(format.m_dataFormat) >> 3;
  17836. format.m_frameSize = sample_size * channels;
  17837. format.m_sampleRate = std::max(8000U, std::min(192000U, format.m_sampleRate));
  17838. - format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER;
  17839. + format.m_frames = format.m_sampleRate * AUDIO_PLAYBUFFER / NUM_OMX_BUFFERS;
  17840. format.m_frameSamples = format.m_frames * channels;
  17841. SetAudioProps(m_passthrough, GetChannelMap(format.m_channelLayout, m_passthrough));
  17842. @@ -232,7 +232,7 @@ bool CAESinkPi::Initialize(AEAudioFormat &format, std::string &device)
  17843. CLog::Log(LOGERROR, "%s:%s - error get OMX_IndexParamPortDefinition (input) omx_err(0x%08x)", CLASSNAME, __func__, omx_err);
  17844. port_param.nBufferCountActual = std::max((unsigned int)port_param.nBufferCountMin, (unsigned int)NUM_OMX_BUFFERS);
  17845. - port_param.nBufferSize = m_format.m_frameSize * m_format.m_frames / port_param.nBufferCountActual;
  17846. + port_param.nBufferSize = m_format.m_frameSize * m_format.m_frames;
  17847. omx_err = m_omx_render.SetParameter(OMX_IndexParamPortDefinition, &port_param);
  17848. if (omx_err != OMX_ErrorNone)
  17849. @@ -308,63 +308,38 @@ double CAESinkPi::GetCacheTotal()
  17850. unsigned int CAESinkPi::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
  17851. {
  17852. - unsigned int sent = 0;
  17853. -
  17854. - if (!m_Initialized)
  17855. + if (!m_Initialized || !frames)
  17856. return frames;
  17857. OMX_ERRORTYPE omx_err = OMX_ErrorNone;
  17858. OMX_BUFFERHEADERTYPE *omx_buffer = NULL;
  17859. - while (sent < frames)
  17860. +
  17861. + double delay = GetDelay();
  17862. + if (delay <= 0.0 && m_submitted)
  17863. + CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames);
  17864. +
  17865. + omx_buffer = m_omx_render.GetInputBuffer(1000);
  17866. + if (omx_buffer == NULL)
  17867. {
  17868. - double delay = GetDelay();
  17869. - double ideal_submission_time = AUDIO_PLAYBUFFER - delay;
  17870. - // ideal amount of audio we'd like submit (to make delay match AUDIO_PLAYBUFFER)
  17871. - int timeout = blocking ? 1000 : 0;
  17872. - int ideal_submission_samples = ideal_submission_time / (m_sinkbuffer_sec_per_byte * m_format.m_frameSize);
  17873. - // if we are almost full then sleep (to avoid repeatedly sending a few samples)
  17874. - bool too_laggy = ideal_submission_time < 0.25 * AUDIO_PLAYBUFFER;
  17875. - int sleeptime = (int)(AUDIO_PLAYBUFFER * 0.25 * 1000.0);
  17876. - if (too_laggy)
  17877. - {
  17878. - if (blocking)
  17879. - {
  17880. - Sleep(sleeptime);
  17881. - continue;
  17882. - }
  17883. - break;
  17884. - }
  17885. - omx_buffer = m_omx_render.GetInputBuffer(timeout);
  17886. - if (omx_buffer == NULL)
  17887. - {
  17888. - if (blocking)
  17889. - CLog::Log(LOGERROR, "COMXAudio::Decode timeout");
  17890. - break;
  17891. - }
  17892. -
  17893. - unsigned int space = omx_buffer->nAllocLen / m_format.m_frameSize;
  17894. - unsigned int samples = std::min(std::min(space, (unsigned int)ideal_submission_samples), frames - sent);
  17895. -
  17896. - omx_buffer->nFilledLen = samples * m_format.m_frameSize;
  17897. - omx_buffer->nTimeStamp = ToOMXTime(0);
  17898. - omx_buffer->nFlags = 0;
  17899. - memcpy(omx_buffer->pBuffer, (uint8_t *)data + sent * m_format.m_frameSize, omx_buffer->nFilledLen);
  17900. -
  17901. - sent += samples;
  17902. -
  17903. - if (sent == frames)
  17904. - omx_buffer->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME;
  17905. -
  17906. - if (delay <= 0.0 && m_submitted)
  17907. - CLog::Log(LOGNOTICE, "%s:%s Underrun (delay:%.2f frames:%d)", CLASSNAME, __func__, delay, frames);
  17908. -
  17909. - omx_err = m_omx_render.EmptyThisBuffer(omx_buffer);
  17910. - if (omx_err != OMX_ErrorNone)
  17911. - CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err);
  17912. - m_submitted++;
  17913. + CLog::Log(LOGERROR, "CAESinkPi::AddPackets timeout");
  17914. + return 0;
  17915. }
  17916. - return sent;
  17917. + omx_buffer->nFilledLen = frames * m_format.m_frameSize;
  17918. + // must be true
  17919. + assert(omx_buffer->nFilledLen <= omx_buffer->nAllocLen);
  17920. + omx_buffer->nTimeStamp = ToOMXTime(0);
  17921. + omx_buffer->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
  17922. + memcpy(omx_buffer->pBuffer, data, omx_buffer->nFilledLen);
  17923. +
  17924. + omx_err = m_omx_render.EmptyThisBuffer(omx_buffer);
  17925. + if (omx_err != OMX_ErrorNone)
  17926. + CLog::Log(LOGERROR, "%s:%s frames=%d err=%x", CLASSNAME, __func__, frames, omx_err);
  17927. + m_submitted++;
  17928. + delay = GetDelay();
  17929. + if (delay > AUDIO_PLAYBUFFER)
  17930. + Sleep((int)(1000.0f * (delay - AUDIO_PLAYBUFFER)));
  17931. + return frames;
  17932. }
  17933. void CAESinkPi::Drain()
  17934. --
  17935. 1.9.3
  17936. From 508c32de290d09c429d73b2497408b930550f1a3 Mon Sep 17 00:00:00 2001
  17937. From: popcornmix <popcornmix@gmail.com>
  17938. Date: Wed, 23 Apr 2014 22:36:01 +0100
  17939. Subject: [PATCH 78/94] [omxplayer] Fix for aspect ratio of portrait videos
  17940. ---
  17941. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 10 ++++++++++
  17942. 1 file changed, 10 insertions(+)
  17943. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17944. index e9f86f3..7e2c644 100644
  17945. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17946. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  17947. @@ -651,6 +651,16 @@ void OMXPlayerVideo::SetVideoRect(const CRect &InSrcRect, const CRect &InDestRec
  17948. bool stereo_invert = (flags & CONF_FLAGS_STEREO_CADANCE_RIGHT_LEFT) ? true : false;
  17949. RENDER_STEREO_MODE display_stereo_mode = g_graphicsContext.GetStereoMode();
  17950. + // fix up transposed video
  17951. + if (m_hints.orientation == 90 || m_hints.orientation == 270)
  17952. + {
  17953. + float diff = (DestRect.Height() - DestRect.Width()) * 0.5f;
  17954. + DestRect.x1 -= diff;
  17955. + DestRect.x2 += diff;
  17956. + DestRect.y1 += diff;
  17957. + DestRect.y2 -= diff;
  17958. + }
  17959. +
  17960. // check if destination rect or video view mode has changed
  17961. if (!(m_dst_rect != DestRect) && !(m_src_rect != SrcRect) && m_video_stereo_mode == video_stereo_mode && m_display_stereo_mode == display_stereo_mode && m_StereoInvert == stereo_invert)
  17962. return;
  17963. --
  17964. 1.9.3
  17965. From fe9fea7a1aac545aa601b71aae01651bc42a5376 Mon Sep 17 00:00:00 2001
  17966. From: popcornmix <popcornmix@gmail.com>
  17967. Date: Tue, 22 Apr 2014 12:23:23 +0100
  17968. Subject: [PATCH 79/94] [omxplayer] Make dvdplayer the default for dvd images
  17969. ---
  17970. xbmc/cores/omxplayer/omxplayer_advancedsettings.xml | 2 +-
  17971. 1 file changed, 1 insertion(+), 1 deletion(-)
  17972. diff --git a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
  17973. index 77c6a15..51c0daf 100644
  17974. --- a/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
  17975. +++ b/xbmc/cores/omxplayer/omxplayer_advancedsettings.xml
  17976. @@ -2,6 +2,6 @@
  17977. <advancedsettings>
  17978. <video>
  17979. <defaultplayer>omxplayer</defaultplayer>
  17980. - <defaultdvdplayer>omxplayer</defaultdvdplayer>
  17981. + <defaultdvdplayer>dvdplayer</defaultdvdplayer>
  17982. </video>
  17983. </advancedsettings>
  17984. --
  17985. 1.9.3
  17986. From f417d7d303eaa5113edba8ba562cb61ed8a6c59a Mon Sep 17 00:00:00 2001
  17987. From: popcornmix <popcornmix@gmail.com>
  17988. Date: Sat, 26 Apr 2014 17:27:52 +0100
  17989. Subject: [PATCH 80/94] [cec] Don't suspend pi on tv switch off - it can't wake
  17990. up
  17991. ---
  17992. system/peripherals.xml | 2 +-
  17993. 1 file changed, 1 insertion(+), 1 deletion(-)
  17994. diff --git a/system/peripherals.xml b/system/peripherals.xml
  17995. index a906628..9b5271a 100644
  17996. --- a/system/peripherals.xml
  17997. +++ b/system/peripherals.xml
  17998. @@ -16,7 +16,7 @@
  17999. <setting key="send_inactive_source" type="bool" value="1" label="36025" order="5" />
  18000. <setting key="cec_standby_screensaver" type="bool" value="0" label="36009" order="6" />
  18001. <setting key="cec_wake_screensaver" type="bool" value="1" label="36010" order="7" />
  18002. - <setting key="standby_pc_on_tv_standby" type="enum" value="13011" label="36029" order="8" lvalues="36028|13005|13011" />
  18003. + <setting key="standby_pc_on_tv_standby" type="enum" value="36028" label="36029" order="8" lvalues="36028|13005|13011" />
  18004. <setting key="standby_tv_on_pc_standby" type="bool" value="1" label="36026" order="9" />
  18005. <setting key="use_tv_menu_language" type="bool" value="1" label="36018" order="10" />
  18006. <setting key="pause_playback_on_deactivate" type="bool" value="1" label="36033" order="11" />
  18007. --
  18008. 1.9.3
  18009. From 0563f1df1295ac5600fd330fb201e854ad900e02 Mon Sep 17 00:00:00 2001
  18010. From: popcornmix <popcornmix@gmail.com>
  18011. Date: Sat, 12 Apr 2014 17:57:19 +0100
  18012. Subject: [PATCH 81/94] [omxplayer] Ignore occasionally valid pts values, they
  18013. cause live tv stutter
  18014. ---
  18015. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 2 +-
  18016. 1 file changed, 1 insertion(+), 1 deletion(-)
  18017. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18018. index 7e2c644..b3786f6 100644
  18019. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18020. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18021. @@ -490,7 +490,7 @@ void OMXPlayerVideo::Process()
  18022. // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts
  18023. m_history_valid_pts = (m_history_valid_pts << 1) | (pPacket->pts != DVD_NOPTS_VALUE);
  18024. double pts = pPacket->pts;
  18025. - if(pPacket->pts == DVD_NOPTS_VALUE && count_bits(m_history_valid_pts & 0xffff) < 4)
  18026. + if(count_bits(m_history_valid_pts & 0xffff) < 4)
  18027. pts = pPacket->dts;
  18028. if (pts != DVD_NOPTS_VALUE)
  18029. --
  18030. 1.9.3
  18031. From cddc5f27f9aa11dfb65e16ec1f84a809cf79c68b Mon Sep 17 00:00:00 2001
  18032. From: popcornmix <popcornmix@gmail.com>
  18033. Date: Wed, 7 May 2014 14:54:41 +0100
  18034. Subject: [PATCH 82/94] [Pi] Fix naming of refresh rates to avoid lost
  18035. calibration settings
  18036. ---
  18037. xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 13 ++++---------
  18038. xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h | 2 +-
  18039. 2 files changed, 5 insertions(+), 10 deletions(-)
  18040. diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  18041. index f57b22b..5b26b20 100644
  18042. --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  18043. +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  18044. @@ -58,6 +58,7 @@
  18045. # define DLOG(fmt, args...)
  18046. #endif
  18047. +static void SetResolutionString(RESOLUTION_INFO &res);
  18048. CEGLNativeTypeRaspberryPI::CEGLNativeTypeRaspberryPI()
  18049. {
  18050. @@ -194,8 +195,9 @@ int CEGLNativeTypeRaspberryPI::FindMatchingResolution(const RESOLUTION_INFO &res
  18051. #endif
  18052. #if defined(TARGET_RASPBERRY_PI)
  18053. -int CEGLNativeTypeRaspberryPI::AddUniqueResolution(const RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions)
  18054. +int CEGLNativeTypeRaspberryPI::AddUniqueResolution(RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions)
  18055. {
  18056. + SetResolutionString(res);
  18057. int i = FindMatchingResolution(res, resolutions);
  18058. if (i>=0)
  18059. { // don't replace a progressive resolution with an interlaced one of same resolution
  18060. @@ -467,10 +469,7 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &r
  18061. m_desktopRes.fPixelRatio = get_display_aspect_ratio((SDTV_ASPECT_T)tv_state.display.sdtv.display_options.aspect) / ((float)m_desktopRes.iScreenWidth / (float)m_desktopRes.iScreenHeight);
  18062. }
  18063. - m_desktopRes.strMode = StringUtils::Format("%dx%d", m_desktopRes.iScreenWidth, m_desktopRes.iScreenHeight);
  18064. -
  18065. - if((int)m_desktopRes.fRefreshRate > 1)
  18066. - SetResolutionString(m_desktopRes);
  18067. + SetResolutionString(m_desktopRes);
  18068. m_initDesktopRes = false;
  18069. @@ -578,8 +577,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  18070. res.iScreenHeight = tv->height;
  18071. res.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res.iScreenWidth / (float)res.iScreenHeight);
  18072. - SetResolutionString(res);
  18073. -
  18074. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f) %s%s:%x\n", i, res.strMode.c_str(), res.fPixelRatio,
  18075. tv->native ? "N" : "", tv->scan_mode ? "I" : "", tv->code);
  18076. @@ -599,7 +596,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  18077. RESOLUTION_INFO res2 = res;
  18078. res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  18079. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  18080. - SetResolutionString(res2);
  18081. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  18082. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  18083. @@ -616,7 +612,6 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  18084. RESOLUTION_INFO res2 = res;
  18085. res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  18086. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  18087. - SetResolutionString(res2);
  18088. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  18089. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  18090. diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h
  18091. index d1ebb81..59401f5 100644
  18092. --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h
  18093. +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.h
  18094. @@ -71,6 +71,6 @@ class CEGLNativeTypeRaspberryPI : public CEGLNativeType
  18095. void DestroyDispmaxWindow();
  18096. int FindMatchingResolution(const RESOLUTION_INFO &res, const std::vector<RESOLUTION_INFO> &resolutions);
  18097. - int AddUniqueResolution(const RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions);
  18098. + int AddUniqueResolution(RESOLUTION_INFO &res, std::vector<RESOLUTION_INFO> &resolutions);
  18099. #endif
  18100. };
  18101. --
  18102. 1.9.3
  18103. From a4c36a4925e780b63d9821fb04504453ac982205 Mon Sep 17 00:00:00 2001
  18104. From: popcornmix <popcornmix@gmail.com>
  18105. Date: Sat, 10 May 2014 11:40:41 +0100
  18106. Subject: [PATCH 83/94] [omxplayer] Skip out of submit loop when closing.
  18107. Avoids a permanent hang at EOF when using IPTV streams
  18108. ---
  18109. xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 7 +++++--
  18110. xbmc/cores/omxplayer/OMXPlayerAudio.h | 1 +
  18111. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 7 +++++--
  18112. xbmc/cores/omxplayer/OMXPlayerVideo.h | 1 +
  18113. 4 files changed, 12 insertions(+), 4 deletions(-)
  18114. diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  18115. index d3348ec..4435d22 100644
  18116. --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  18117. +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp
  18118. @@ -89,6 +89,7 @@ OMXPlayerAudio::OMXPlayerAudio(OMXClock *av_clock, CDVDMessageQueue& parent)
  18119. m_hw_decode = false;
  18120. m_silence = false;
  18121. m_flush = false;
  18122. + m_bClose = false;
  18123. }
  18124. @@ -145,11 +146,13 @@ void OMXPlayerAudio::OpenStream(CDVDStreamInfo &hints, COMXAudioCodecOMX *codec)
  18125. m_format.m_dataFormat = GetDataFormat(m_hints);
  18126. m_format.m_sampleRate = 0;
  18127. m_format.m_channelLayout = 0;
  18128. + m_bClose = false;
  18129. }
  18130. bool OMXPlayerAudio::CloseStream(bool bWaitForBuffers)
  18131. {
  18132. // wait until buffers are empty
  18133. + m_bClose = true;
  18134. if (bWaitForBuffers && m_speed > 0) m_messageQueue.WaitUntilEmpty();
  18135. m_messageQueue.Abort();
  18136. @@ -259,8 +262,8 @@ bool OMXPlayerAudio::Decode(DemuxPacket *pkt, bool bDropPacket)
  18137. while(!m_bStop)
  18138. {
  18139. - // discard if flushing as clocks may be stopped and we'll never submit it
  18140. - if(m_flush)
  18141. + // discard if flushing or closing as clocks may be stopped and we'll never submit it
  18142. + if(m_flush || m_bClose)
  18143. break;
  18144. if(m_omxAudio.GetSpace() < (unsigned int)decoded_size)
  18145. diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.h b/xbmc/cores/omxplayer/OMXPlayerAudio.h
  18146. index 685a686..7b55e48 100644
  18147. --- a/xbmc/cores/omxplayer/OMXPlayerAudio.h
  18148. +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.h
  18149. @@ -70,6 +70,7 @@ class OMXPlayerAudio : public CThread
  18150. bool m_DecoderOpen;
  18151. bool m_bad_state;
  18152. + bool m_bClose;
  18153. virtual void OnStartup();
  18154. virtual void OnExit();
  18155. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18156. index b3786f6..61b884e 100644
  18157. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18158. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  18159. @@ -104,6 +104,7 @@ OMXPlayerVideo::OMXPlayerVideo(OMXClock *av_clock,
  18160. m_iCurrentPts = DVD_NOPTS_VALUE;
  18161. m_nextOverlay = DVD_NOPTS_VALUE;
  18162. m_flush = false;
  18163. + m_bClose = false;
  18164. m_history_valid_pts = 0;
  18165. }
  18166. @@ -118,6 +119,7 @@ bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints)
  18167. m_hdmi_clock_sync = (CSettings::Get().GetInt("videoplayer.adjustrefreshrate") != ADJUST_REFRESHRATE_OFF);
  18168. m_started = false;
  18169. m_flush = false;
  18170. + m_bClose = false;
  18171. m_stalled = m_messageQueue.GetPacketCount(CDVDMsg::DEMUXER_PACKET) == 0;
  18172. m_nextOverlay = DVD_NOPTS_VALUE;
  18173. // force SetVideoRect to be called initially
  18174. @@ -161,6 +163,7 @@ bool OMXPlayerVideo::OpenStream(CDVDStreamInfo &hints, COMXVideo *codec)
  18175. bool OMXPlayerVideo::CloseStream(bool bWaitForBuffers)
  18176. {
  18177. // wait until buffers are empty
  18178. + m_bClose = true;
  18179. if (bWaitForBuffers && m_speed > 0) m_messageQueue.WaitUntilEmpty();
  18180. m_messageQueue.Abort();
  18181. @@ -469,8 +472,8 @@ void OMXPlayerVideo::Process()
  18182. while (!m_bStop)
  18183. {
  18184. - // discard if flushing as clocks may be stopped and we'll never submit it
  18185. - if (m_flush)
  18186. + // discard if flushing or closing as clocks may be stopped and we'll never submit it
  18187. + if (m_flush || m_bClose)
  18188. break;
  18189. if((int)m_omxVideo.GetFreeSpace() < pPacket->iSize)
  18190. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  18191. index 6f19395..8eff32f 100644
  18192. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.h
  18193. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h
  18194. @@ -66,6 +66,7 @@ class OMXPlayerVideo : public CThread
  18195. float m_fForcedAspectRatio;
  18196. unsigned m_flags;
  18197. + bool m_bClose;
  18198. CRect m_src_rect;
  18199. CRect m_dst_rect;
  18200. --
  18201. 1.9.3
  18202. From b90562b8ffc29c1d9e037e94b0c92b3b0b67413b Mon Sep 17 00:00:00 2001
  18203. From: xbmc <fernetmenta@online.de>
  18204. Date: Mon, 28 May 2012 10:34:39 +0200
  18205. Subject: [PATCH 84/94] videoplayer: adapt lateness detection and dropping to
  18206. buffering
  18207. ---
  18208. xbmc/cores/VideoRenderers/RenderManager.cpp | 16 +-
  18209. xbmc/cores/VideoRenderers/RenderManager.h | 12 +-
  18210. .../dvdplayer/DVDCodecs/Video/DVDVideoCodec.h | 38 +++-
  18211. .../DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp | 41 +++++
  18212. .../DVDCodecs/Video/DVDVideoCodecFFmpeg.h | 7 +
  18213. xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 197 +++++++++++++++++----
  18214. xbmc/cores/dvdplayer/DVDPlayerVideo.h | 23 +++
  18215. 7 files changed, 296 insertions(+), 38 deletions(-)
  18216. diff --git a/xbmc/cores/VideoRenderers/RenderManager.cpp b/xbmc/cores/VideoRenderers/RenderManager.cpp
  18217. index 3503988..4ca74f8 100644
  18218. --- a/xbmc/cores/VideoRenderers/RenderManager.cpp
  18219. +++ b/xbmc/cores/VideoRenderers/RenderManager.cpp
  18220. @@ -286,6 +286,8 @@ bool CXBMCRenderManager::Configure(unsigned int width, unsigned int height, unsi
  18221. m_bIsStarted = true;
  18222. m_bReconfigured = true;
  18223. m_presentstep = PRESENT_IDLE;
  18224. + m_presentpts = DVD_NOPTS_VALUE;
  18225. + m_sleeptime = 1.0;
  18226. m_presentevent.notifyAll();
  18227. m_firstFlipPage = false; // tempfix
  18228. @@ -629,7 +631,7 @@ void CXBMCRenderManager::SetViewMode(int iViewMode)
  18229. m_pRenderer->SetViewMode(iViewMode);
  18230. }
  18231. -void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
  18232. +void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0LL*/, double pts /* = 0 */, int source /*= -1*/, EFIELDSYNC sync /*= FS_NONE*/)
  18233. {
  18234. { CSharedLock lock(m_sharedSection);
  18235. @@ -697,6 +699,7 @@ void CXBMCRenderManager::FlipPage(volatile bool& bStop, double timestamp /* = 0L
  18236. m.timestamp = timestamp;
  18237. m.presentfield = sync;
  18238. m.presentmethod = presentmethod;
  18239. + m.pts = pts;
  18240. requeue(m_queued, m_free);
  18241. /* signal to any waiters to check state */
  18242. @@ -1065,6 +1068,8 @@ void CXBMCRenderManager::PrepareNextRender()
  18243. m_discard.push_back(m_presentsource);
  18244. m_presentsource = idx;
  18245. m_queued.pop_front();
  18246. + m_sleeptime = m_Queue[idx].timestamp - clocktime;
  18247. + m_presentpts = m_Queue[idx].pts;
  18248. m_presentevent.notifyAll();
  18249. }
  18250. }
  18251. @@ -1081,3 +1086,12 @@ void CXBMCRenderManager::DiscardBuffer()
  18252. m_presentstep = PRESENT_IDLE;
  18253. m_presentevent.notifyAll();
  18254. }
  18255. +
  18256. +bool CXBMCRenderManager::GetStats(double &sleeptime, double &pts, int &bufferLevel)
  18257. +{
  18258. + CSingleLock lock(m_presentlock);
  18259. + sleeptime = m_sleeptime;
  18260. + pts = m_presentpts;
  18261. + bufferLevel = m_queued.size() + m_discard.size();
  18262. + return true;
  18263. +}
  18264. diff --git a/xbmc/cores/VideoRenderers/RenderManager.h b/xbmc/cores/VideoRenderers/RenderManager.h
  18265. index c469795..949c652b 100644
  18266. --- a/xbmc/cores/VideoRenderers/RenderManager.h
  18267. +++ b/xbmc/cores/VideoRenderers/RenderManager.h
  18268. @@ -98,10 +98,11 @@ class CXBMCRenderManager
  18269. *
  18270. * @param bStop reference to stop flag of calling thread
  18271. * @param timestamp of frame delivered with AddVideoPicture
  18272. + * @param pts used for lateness detection
  18273. * @param source depreciated
  18274. * @param sync signals frame, top, or bottom field
  18275. */
  18276. - void FlipPage(volatile bool& bStop, double timestamp = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
  18277. + void FlipPage(volatile bool& bStop, double timestamp = 0.0, double pts = 0.0, int source = -1, EFIELDSYNC sync = FS_NONE);
  18278. unsigned int PreInit();
  18279. void UnInit();
  18280. bool Flush();
  18281. @@ -176,6 +177,12 @@ class CXBMCRenderManager
  18282. int WaitForBuffer(volatile bool& bStop, int timeout = 100);
  18283. /**
  18284. + * Can be called by player for lateness detection. This is done best by
  18285. + * looking at the end of the queue.
  18286. + */
  18287. + bool GetStats(double &sleeptime, double &pts, int &bufferLevel);
  18288. +
  18289. + /**
  18290. * Video player call this on flush in oder to discard any queued frames
  18291. */
  18292. void DiscardBuffer();
  18293. @@ -222,6 +229,7 @@ class CXBMCRenderManager
  18294. struct SPresent
  18295. {
  18296. + double pts;
  18297. double timestamp;
  18298. EFIELDSYNC presentfield;
  18299. EPRESENTMETHOD presentmethod;
  18300. @@ -233,6 +241,8 @@ class CXBMCRenderManager
  18301. ERenderFormat m_format;
  18302. + double m_sleeptime;
  18303. + double m_presentpts;
  18304. double m_presentcorr;
  18305. double m_presenterr;
  18306. double m_errorbuff[ERRORBUFFSIZE];
  18307. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  18308. index dc047d7..c09939c 100644
  18309. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  18310. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h
  18311. @@ -129,6 +129,10 @@ struct DVDVideoUserData
  18312. #define DVP_FLAG_NOSKIP 0x00000010 // indicate this picture should never be dropped
  18313. #define DVP_FLAG_DROPPED 0x00000020 // indicate that this picture has been dropped in decoder stage, will have no data
  18314. +#define DVP_FLAG_DROPDEINT 0x00000040 // indicate that this picture was requested to have been dropped in deint stage
  18315. +#define DVP_FLAG_NO_POSTPROC 0x00000100 // see GetCodecStats
  18316. +#define DVP_FLAG_DRAIN 0x00000200 // see GetCodecStats
  18317. +
  18318. // DVP_FLAG 0x00000100 - 0x00000f00 is in use by libmpeg2!
  18319. #define DVP_QSCALE_UNKNOWN 0
  18320. @@ -146,6 +150,8 @@ class CDVDCodecOptions;
  18321. #define VC_PICTURE 0x00000004 // the decoder got a picture, call Decode(NULL, 0) again to parse the rest of the data
  18322. #define VC_USERDATA 0x00000008 // the decoder found some userdata, call Decode(NULL, 0) again to parse the rest of the data
  18323. #define VC_FLUSHED 0x00000010 // the decoder lost it's state, we need to restart decoding again
  18324. +#define VC_DROPPED 0x00000020 // needed to identify if a picture was dropped
  18325. +
  18326. class CDVDVideoCodec
  18327. {
  18328. public:
  18329. @@ -263,7 +269,6 @@ class CDVDVideoCodec
  18330. return 0;
  18331. }
  18332. -
  18333. /**
  18334. * Number of references to old pictures that are allowed to
  18335. * be retained when calling decode on the next demux packet
  18336. @@ -280,4 +285,35 @@ class CDVDVideoCodec
  18337. * Interact with user settings so that user disabled codecs are disabled
  18338. */
  18339. static bool IsCodecDisabled(DVDCodecAvailableType* map, unsigned int size, AVCodecID id);
  18340. +
  18341. + /* For calculation of dropping requirements player asks for some information.
  18342. + *
  18343. + * - pts : right after decoder, used to detect gaps (dropped frames in decoder)
  18344. + * - droppedPics : indicates if decoder has dropped a picture
  18345. + * -1 means that decoder has no info on this.
  18346. + *
  18347. + * If codec does not implement this method, pts of decoded frame at input
  18348. + * video player is used. In case decoder does post-proc and de-interlacing there
  18349. + * may be quite some frames queued up between exit decoder and entry player.
  18350. + */
  18351. + virtual bool GetCodecStats(double &pts, int &droppedPics)
  18352. + {
  18353. + droppedPics= -1;
  18354. + return false;
  18355. + }
  18356. +
  18357. + /**
  18358. + * Codec can be informed by player with the following flags:
  18359. + *
  18360. + * DVP_FLAG_NO_POSTPROC : if speed is not normal the codec can switch off
  18361. + * postprocessing and de-interlacing
  18362. + *
  18363. + * DVP_FLAG_DRAIN : codecs may do postprocessing and de-interlacing.
  18364. + * If video buffers in RenderManager are about to run dry,
  18365. + * this is signaled to codec. Codec can wait for post-proc
  18366. + * to be finished instead of returning empty and getting another
  18367. + * packet.
  18368. + *
  18369. + */
  18370. + virtual void SetCodecControl(int flags) {}
  18371. };
  18372. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
  18373. index 9b6a34d..81fe0cf 100644
  18374. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
  18375. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
  18376. @@ -164,6 +164,7 @@ CDVDVideoCodecFFmpeg::CDVDVideoCodecFFmpeg() : CDVDVideoCodec()
  18377. m_iLastKeyframe = 0;
  18378. m_dts = DVD_NOPTS_VALUE;
  18379. m_started = false;
  18380. + m_decoderPts = DVD_NOPTS_VALUE;
  18381. }
  18382. CDVDVideoCodecFFmpeg::~CDVDVideoCodecFFmpeg()
  18383. @@ -355,6 +356,14 @@ void CDVDVideoCodecFFmpeg::SetDropState(bool bDrop)
  18384. {
  18385. if( m_pCodecContext )
  18386. {
  18387. + if (bDrop && m_pHardware && m_pHardware->CanSkipDeint())
  18388. + {
  18389. + m_requestSkipDeint = true;
  18390. + bDrop = false;
  18391. + }
  18392. + else
  18393. + m_requestSkipDeint = false;
  18394. +
  18395. // i don't know exactly how high this should be set
  18396. // couldn't find any good docs on it. think it varies
  18397. // from codec to codec on what it does
  18398. @@ -556,6 +565,7 @@ int CDVDVideoCodecFFmpeg::Decode(uint8_t* pData, int iSize, double dts, double p
  18399. void CDVDVideoCodecFFmpeg::Reset()
  18400. {
  18401. m_started = false;
  18402. + m_decoderPts = DVD_NOPTS_VALUE;
  18403. m_iLastKeyframe = m_pCodecContext->has_b_frames;
  18404. m_dllAvCodec.avcodec_flush_buffers(m_pCodecContext);
  18405. @@ -665,6 +675,22 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(DVDVideoPicture* pDvdVideoPicture)
  18406. else
  18407. pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
  18408. + if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE)
  18409. + m_decoderPts = pDvdVideoPicture->pts;
  18410. + else
  18411. + m_decoderPts = m_dts;
  18412. +
  18413. + if (m_requestSkipDeint)
  18414. + {
  18415. + pDvdVideoPicture->iFlags |= DVP_FLAG_DROPDEINT;
  18416. + m_skippedDeint = 1;
  18417. + }
  18418. + else
  18419. + m_skippedDeint = 0;
  18420. +
  18421. + m_requestSkipDeint = false;
  18422. + pDvdVideoPicture->iFlags |= m_codecControlFlags;
  18423. +
  18424. if(!m_started)
  18425. pDvdVideoPicture->iFlags |= DVP_FLAG_DROPPED;
  18426. @@ -924,3 +950,18 @@ unsigned CDVDVideoCodecFFmpeg::GetAllowedReferences()
  18427. else
  18428. return 0;
  18429. }
  18430. +
  18431. +bool CDVDVideoCodecFFmpeg::GetCodecStats(double &pts, int &droppedPics)
  18432. +{
  18433. + pts = m_decoderPts;
  18434. + if (m_skippedDeint)
  18435. + droppedPics = m_skippedDeint;
  18436. + else
  18437. + droppedPics = -1;
  18438. + return true;
  18439. +}
  18440. +
  18441. +void CDVDVideoCodecFFmpeg::SetCodecControl(int flags)
  18442. +{
  18443. + m_codecControlFlags = flags;
  18444. +}
  18445. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
  18446. index 2287031..827c9507 100644
  18447. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
  18448. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.h
  18449. @@ -45,6 +45,7 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
  18450. virtual int Check (AVCodecContext* avctx) = 0;
  18451. virtual void Reset () {}
  18452. virtual unsigned GetAllowedReferences() { return 0; }
  18453. + virtual bool CanSkipDeint() {return false; }
  18454. virtual const std::string Name() = 0;
  18455. virtual CCriticalSection* Section() { return NULL; }
  18456. };
  18457. @@ -62,6 +63,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
  18458. virtual const char* GetName() { return m_name.c_str(); }; // m_name is never changed after open
  18459. virtual unsigned GetConvergeCount();
  18460. virtual unsigned GetAllowedReferences();
  18461. + virtual bool GetCodecStats(double &pts, int &droppedPics);
  18462. + virtual void SetCodecControl(int flags);
  18463. bool IsHardwareAllowed() { return !m_bSoftware; }
  18464. IHardwareDecoder * GetHardware() { return m_pHardware; };
  18465. @@ -127,4 +130,8 @@ class CDVDVideoCodecFFmpeg : public CDVDVideoCodec
  18466. double m_dts;
  18467. bool m_started;
  18468. std::vector<PixelFormat> m_formats;
  18469. + double m_decoderPts, m_decoderInterval;
  18470. + int m_skippedDeint;
  18471. + bool m_requestSkipDeint;
  18472. + int m_codecControlFlags;
  18473. };
  18474. diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18475. index fddb7f7..181ff74 100644
  18476. --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18477. +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18478. @@ -38,6 +38,7 @@
  18479. #include "DVDCodecs/DVDCodecs.h"
  18480. #include "DVDCodecs/Overlay/DVDOverlayCodecCC.h"
  18481. #include "DVDCodecs/Overlay/DVDOverlaySSA.h"
  18482. +#include "guilib/GraphicContext.h"
  18483. #include <sstream>
  18484. #include <iomanip>
  18485. #include <numeric>
  18486. @@ -320,8 +321,10 @@ void CDVDPlayerVideo::Process()
  18487. int iDropped = 0; //frames dropped in a row
  18488. bool bRequestDrop = false;
  18489. + int iDropDirective;
  18490. m_videoStats.Start();
  18491. + m_droppingStats.Reset();
  18492. while (!m_bStop)
  18493. {
  18494. @@ -436,6 +439,7 @@ void CDVDPlayerVideo::Process()
  18495. picture.iFlags &= ~DVP_FLAG_ALLOCATED;
  18496. m_packets.clear();
  18497. m_started = false;
  18498. + m_droppingStats.Reset();
  18499. }
  18500. else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush())
  18501. {
  18502. @@ -448,6 +452,7 @@ void CDVDPlayerVideo::Process()
  18503. //we need to recalculate the framerate
  18504. //TODO: this needs to be set on a streamchange instead
  18505. ResetFrameRateCalc();
  18506. + m_droppingStats.Reset();
  18507. m_stalled = true;
  18508. m_started = false;
  18509. @@ -467,6 +472,7 @@ void CDVDPlayerVideo::Process()
  18510. m_iNrOfPicturesNotToSkip = 0;
  18511. if (m_pVideoCodec)
  18512. m_pVideoCodec->SetSpeed(m_speed);
  18513. + m_droppingStats.Reset();
  18514. }
  18515. else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED))
  18516. {
  18517. @@ -515,6 +521,28 @@ void CDVDPlayerVideo::Process()
  18518. m_iNrOfPicturesNotToSkip = 1;
  18519. }
  18520. + bRequestDrop = false;
  18521. + iDropDirective = CalcDropRequirement(pts);
  18522. + if (iDropDirective & EOS_VERYLATE)
  18523. + {
  18524. + if (m_bAllowDrop)
  18525. + {
  18526. + m_pullupCorrection.Flush();
  18527. + bRequestDrop = true;
  18528. + }
  18529. + }
  18530. + int codecControl = 0;
  18531. + if (iDropDirective & EOS_BUFFER_LEVEL)
  18532. + codecControl |= DVP_FLAG_DRAIN;
  18533. + if (m_speed > DVD_PLAYSPEED_NORMAL)
  18534. + codecControl |= DVP_FLAG_NO_POSTPROC;
  18535. + m_pVideoCodec->SetCodecControl(codecControl);
  18536. + if (iDropDirective & EOS_DROPPED)
  18537. + {
  18538. + m_iDroppedFrames++;
  18539. + iDropped++;
  18540. + }
  18541. +
  18542. if (m_messageQueue.GetDataSize() == 0
  18543. || m_speed < 0)
  18544. {
  18545. @@ -567,15 +595,7 @@ void CDVDPlayerVideo::Process()
  18546. }
  18547. m_videoStats.AddSampleBytes(pPacket->iSize);
  18548. - // assume decoder dropped a picture if it didn't give us any
  18549. - // picture from a demux packet, this should be reasonable
  18550. - // for libavformat as a demuxer as it normally packetizes
  18551. - // pictures when they come from demuxer
  18552. - if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE))
  18553. - {
  18554. - m_iDroppedFrames++;
  18555. - iDropped++;
  18556. - }
  18557. +
  18558. // reset the request, the following while loop may break before
  18559. // setting the flag to a new value
  18560. bRequestDrop = false;
  18561. @@ -1185,33 +1205,12 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
  18562. m_FlipTimeStamp += max(0.0, iSleepTime);
  18563. m_FlipTimeStamp += iFrameDuration;
  18564. - if (iSleepTime <= 0 && m_speed)
  18565. - m_iLateFrames++;
  18566. - else
  18567. - m_iLateFrames = 0;
  18568. -
  18569. - // ask decoder to drop frames next round, as we are very late
  18570. - if(m_iLateFrames > 10)
  18571. + if ((pPicture->iFlags & DVP_FLAG_DROPPED))
  18572. {
  18573. - if (!(pPicture->iFlags & DVP_FLAG_NOSKIP))
  18574. - {
  18575. - //if we're calculating the framerate,
  18576. - //don't drop frames until we've calculated a stable framerate
  18577. - if (m_bAllowDrop || m_speed != DVD_PLAYSPEED_NORMAL)
  18578. - {
  18579. - result |= EOS_VERYLATE;
  18580. - m_pullupCorrection.Flush(); //dropped frames mess up the pattern, so just flush it
  18581. - }
  18582. - m_iDroppedRequest++;
  18583. - }
  18584. - }
  18585. - else
  18586. - {
  18587. - m_iDroppedRequest = 0;
  18588. - }
  18589. -
  18590. - if( (pPicture->iFlags & DVP_FLAG_DROPPED) )
  18591. + m_droppingStats.AddOutputDropGain(pts, 1/m_fFrameRate);
  18592. + CLog::Log(LOGDEBUG,"%s - dropped in output", __FUNCTION__);
  18593. return result | EOS_DROPPED;
  18594. + }
  18595. // set fieldsync if picture is interlaced
  18596. EFIELDSYNC mDisplayField = FS_NONE;
  18597. @@ -1244,7 +1243,7 @@ int CDVDPlayerVideo::OutputPicture(const DVDVideoPicture* src, double pts)
  18598. if (index < 0)
  18599. return EOS_DROPPED;
  18600. - g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, -1, mDisplayField);
  18601. + g_renderManager.FlipPage(CThread::m_bStop, (iCurrentClock + iSleepTime) / DVD_TIME_BASE, pts, -1, mDisplayField);
  18602. return result;
  18603. #else
  18604. @@ -1544,3 +1543,131 @@ void CDVDPlayerVideo::CalcFrameRate()
  18605. m_iFrameRateCount = 0;
  18606. }
  18607. }
  18608. +
  18609. +int CDVDPlayerVideo::CalcDropRequirement(double pts)
  18610. +{
  18611. + int result = 0;
  18612. + double iSleepTime;
  18613. + double iDecoderPts, iRenderPts;
  18614. + double iInterval;
  18615. + double iGain;
  18616. + double iLateness;
  18617. + bool bNewFrame;
  18618. + int iDroppedPics = -1;
  18619. + int iBufferLevel;
  18620. +
  18621. + // get decoder stats
  18622. + if (!m_pVideoCodec->GetCodecStats(iDecoderPts, iDroppedPics))
  18623. + iDecoderPts = pts;
  18624. + if (iDecoderPts == DVD_NOPTS_VALUE)
  18625. + iDecoderPts = pts;
  18626. +
  18627. + // get render stats
  18628. + g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel);
  18629. +
  18630. + if (iBufferLevel < 0)
  18631. + result |= EOS_BUFFER_LEVEL;
  18632. + else if (iBufferLevel < 2)
  18633. + {
  18634. + result |= EOS_BUFFER_LEVEL;
  18635. + CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - hurry: %d", iBufferLevel);
  18636. + }
  18637. +
  18638. + bNewFrame = iDecoderPts != m_droppingStats.m_lastDecoderPts;
  18639. +
  18640. + iInterval = 1/m_fFrameRate*(double)DVD_TIME_BASE;
  18641. +
  18642. + m_FlipTimeStamp = m_pClock->GetAbsoluteClock() + max(0.0, iSleepTime) + iInterval;
  18643. +
  18644. + if (m_stalled)
  18645. + m_iCurrentPts = DVD_NOPTS_VALUE;
  18646. + else
  18647. + m_iCurrentPts = iRenderPts - max(0.0, iSleepTime);
  18648. +
  18649. + if (m_droppingStats.m_lastDecoderPts > 0
  18650. + && bNewFrame
  18651. + && m_bAllowDrop)
  18652. + {
  18653. + iGain = (iDecoderPts - m_droppingStats.m_lastDecoderPts - iInterval)/(double)DVD_TIME_BASE;
  18654. + if (iDroppedPics > 0)
  18655. + {
  18656. + CDroppingStats::CGain gain;
  18657. + gain.gain = iDroppedPics * 1/m_fFrameRate;
  18658. + gain.pts = iDecoderPts;
  18659. + m_droppingStats.m_gain.push_back(gain);
  18660. + m_droppingStats.m_totalGain += gain.gain;
  18661. + result |= EOS_DROPPED;
  18662. + m_droppingStats.m_dropRequests = 0;
  18663. + CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped pictures, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain);
  18664. + }
  18665. + else if (iDroppedPics < 0 && iGain > 1/m_fFrameRate)
  18666. + {
  18667. + CDroppingStats::CGain gain;
  18668. + gain.gain = iGain;
  18669. + gain.pts = iDecoderPts;
  18670. + m_droppingStats.m_gain.push_back(gain);
  18671. + m_droppingStats.m_totalGain += iGain;
  18672. + result |= EOS_DROPPED;
  18673. + m_droppingStats.m_dropRequests = 0;
  18674. + CLog::Log(LOGDEBUG,"CDVDPlayerVideo::CalcDropRequirement - dropped in decoder, Sleeptime: %f, Bufferlevel: %d, Gain: %f", iSleepTime, iBufferLevel, iGain);
  18675. + }
  18676. + }
  18677. + m_droppingStats.m_lastDecoderPts = iDecoderPts;
  18678. +
  18679. + // subtract gains
  18680. + while (!m_droppingStats.m_gain.empty() &&
  18681. + iRenderPts >= m_droppingStats.m_gain.front().pts)
  18682. + {
  18683. + m_droppingStats.m_totalGain -= m_droppingStats.m_gain.front().gain;
  18684. + m_droppingStats.m_gain.pop_front();
  18685. + }
  18686. +
  18687. + // calculate lateness
  18688. + iLateness = iSleepTime + m_droppingStats.m_totalGain;
  18689. + if (iLateness < 0 && m_speed)
  18690. + {
  18691. + if (bNewFrame)
  18692. + m_droppingStats.m_lateFrames++;
  18693. +
  18694. + // if lateness is smaller than frametime, we observe this state
  18695. + // for 10 cycles
  18696. + if (m_droppingStats.m_lateFrames > 10 || iLateness < -2/m_fFrameRate)
  18697. + {
  18698. + // is frame allowed to skip
  18699. + if (m_iNrOfPicturesNotToSkip <= 0)
  18700. + {
  18701. + if (bNewFrame || m_droppingStats.m_dropRequests < 5)
  18702. + {
  18703. + result |= EOS_VERYLATE;
  18704. + }
  18705. + m_droppingStats.m_dropRequests++;
  18706. + }
  18707. + }
  18708. + }
  18709. + else
  18710. + {
  18711. + m_droppingStats.m_dropRequests = 0;
  18712. + m_droppingStats.m_lateFrames = 0;
  18713. + }
  18714. + m_droppingStats.m_lastRenderPts = iRenderPts;
  18715. + return result;
  18716. +}
  18717. +
  18718. +void CDroppingStats::Reset()
  18719. +{
  18720. + m_gain.clear();
  18721. + m_totalGain = 0;
  18722. + m_lastDecoderPts = 0;
  18723. + m_lastRenderPts = 0;
  18724. + m_lateFrames = 0;
  18725. + m_dropRequests = 0;
  18726. +}
  18727. +
  18728. +void CDroppingStats::AddOutputDropGain(double pts, double frametime)
  18729. +{
  18730. + CDroppingStats::CGain gain;
  18731. + gain.gain = frametime;
  18732. + gain.pts = pts;
  18733. + m_gain.push_back(gain);
  18734. + m_totalGain += frametime;
  18735. +}
  18736. diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18737. index f8ad541..186e271 100644
  18738. --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18739. +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18740. @@ -36,6 +36,25 @@ class CDVDOverlayCodecCC;
  18741. #define VIDEO_PICTURE_QUEUE_SIZE 1
  18742. +class CDroppingStats
  18743. +{
  18744. +public:
  18745. + void Reset();
  18746. + void AddOutputDropGain(double pts, double frametime);
  18747. + struct CGain
  18748. + {
  18749. + double gain;
  18750. + double pts;
  18751. + };
  18752. + std::deque<CGain> m_gain;
  18753. + double m_totalGain;
  18754. + double m_lastDecoderPts;
  18755. + double m_lastRenderPts;
  18756. + unsigned int m_lateFrames;
  18757. + unsigned int m_dropRequests;
  18758. +};
  18759. +
  18760. +
  18761. class CDVDPlayerVideo : public CThread
  18762. {
  18763. public:
  18764. @@ -104,6 +123,7 @@ class CDVDPlayerVideo : public CThread
  18765. #define EOS_ABORT 1
  18766. #define EOS_DROPPED 2
  18767. #define EOS_VERYLATE 4
  18768. +#define EOS_BUFFER_LEVEL 8
  18769. void AutoCrop(DVDVideoPicture* pPicture);
  18770. void AutoCrop(DVDVideoPicture *pPicture, RECT &crop);
  18771. @@ -129,6 +149,7 @@ class CDVDPlayerVideo : public CThread
  18772. void ResetFrameRateCalc();
  18773. void CalcFrameRate();
  18774. + int CalcDropRequirement(double pts);
  18775. double m_fFrameRate; //framerate of the video currently playing
  18776. bool m_bCalcFrameRate; //if we should calculate the framerate from the timestamps
  18777. @@ -182,5 +203,7 @@ class CDVDPlayerVideo : public CThread
  18778. CPullupCorrection m_pullupCorrection;
  18779. std::list<DVDMessageListItem> m_packets;
  18780. +
  18781. + CDroppingStats m_droppingStats;
  18782. };
  18783. --
  18784. 1.9.3
  18785. From 16d2c2ee305eb2cd3ec42fd0aad474dbf356d75d Mon Sep 17 00:00:00 2001
  18786. From: xbmc <fernetmenta@online.de>
  18787. Date: Sun, 2 Sep 2012 16:05:21 +0200
  18788. Subject: [PATCH 85/94] video player: present correct pts to user for a/v sync
  18789. (after buffering in renderer)
  18790. ---
  18791. xbmc/cores/dvdplayer/DVDPlayerVideo.cpp | 16 ++++++++++++++++
  18792. xbmc/cores/dvdplayer/DVDPlayerVideo.h | 2 +-
  18793. 2 files changed, 17 insertions(+), 1 deletion(-)
  18794. diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18795. index 181ff74..01757cc 100644
  18796. --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18797. +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.cpp
  18798. @@ -1463,6 +1463,22 @@ void CDVDPlayerVideo::ResetFrameRateCalc()
  18799. g_advancedSettings.m_videoFpsDetect == 0;
  18800. }
  18801. +double CDVDPlayerVideo::GetCurrentPts()
  18802. +{
  18803. + double iSleepTime, iRenderPts;
  18804. + int iBufferLevel;
  18805. +
  18806. + // get render stats
  18807. + g_renderManager.GetStats(iSleepTime, iRenderPts, iBufferLevel);
  18808. +
  18809. + if( m_stalled )
  18810. + iRenderPts = DVD_NOPTS_VALUE;
  18811. + else
  18812. + iRenderPts = iRenderPts - max(0.0, iSleepTime);
  18813. +
  18814. + return iRenderPts;
  18815. +}
  18816. +
  18817. #define MAXFRAMERATEDIFF 0.01
  18818. #define MAXFRAMESERR 1000
  18819. diff --git a/xbmc/cores/dvdplayer/DVDPlayerVideo.h b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18820. index 186e271..59c7f09 100644
  18821. --- a/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18822. +++ b/xbmc/cores/dvdplayer/DVDPlayerVideo.h
  18823. @@ -100,7 +100,7 @@ class CDVDPlayerVideo : public CThread
  18824. bool InitializedOutputDevice();
  18825. - double GetCurrentPts() { return m_iCurrentPts; }
  18826. + double GetCurrentPts();
  18827. int GetPullupCorrection() { return m_pullupCorrection.GetPatternLength(); }
  18828. double GetOutputDelay(); /* returns the expected delay, from that a packet is put in queue */
  18829. --
  18830. 1.9.3
  18831. From afa38b57afee02720263e2db79d20e1411461433 Mon Sep 17 00:00:00 2001
  18832. From: popcornmix <popcornmix@gmail.com>
  18833. Date: Mon, 12 May 2014 23:06:43 +0100
  18834. Subject: [PATCH 86/94] [omxcodec] Updates to work better with dropping and
  18835. lateness detection
  18836. ---
  18837. .../DVDCodecs/Video/DVDVideoCodecOpenMax.cpp | 5 ++
  18838. .../DVDCodecs/Video/DVDVideoCodecOpenMax.h | 1 +
  18839. .../dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 95 ++++++++++++++++------
  18840. .../cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h | 9 +-
  18841. 4 files changed, 84 insertions(+), 26 deletions(-)
  18842. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  18843. index ef10555..8323497 100644
  18844. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  18845. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.cpp
  18846. @@ -91,4 +91,9 @@ bool CDVDVideoCodecOpenMax::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
  18847. return m_omx_decoder->ClearPicture(pDvdVideoPicture);
  18848. }
  18849. +bool CDVDVideoCodecOpenMax::GetCodecStats(double &pts, int &droppedPics)
  18850. +{
  18851. + return m_omx_decoder->GetCodecStats(pts, droppedPics);
  18852. +}
  18853. +
  18854. #endif
  18855. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  18856. index b7c0c1b..4f243df 100644
  18857. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  18858. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecOpenMax.h
  18859. @@ -41,6 +41,7 @@ class CDVDVideoCodecOpenMax : public CDVDVideoCodec
  18860. virtual unsigned GetAllowedReferences();
  18861. virtual void SetDropState(bool bDrop);
  18862. virtual const char* GetName(void);
  18863. + virtual bool GetCodecStats(double &pts, int &droppedPics);
  18864. protected:
  18865. OpenMaxVideoPtr m_omx_decoder;
  18866. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  18867. index 71d19af..93cf521 100644
  18868. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  18869. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  18870. @@ -37,6 +37,7 @@
  18871. #include "ApplicationMessenger.h"
  18872. #include "Application.h"
  18873. #include "threads/Atomics.h"
  18874. +#include "guilib/GUIWindowManager.h"
  18875. #include <IL/OMX_Core.h>
  18876. #include <IL/OMX_Component.h>
  18877. @@ -57,6 +58,7 @@
  18878. #define OMX_BUFFERFLAG_PTS_INVALID (1<<28)
  18879. #define OMX_BUFFERFLAG_DROPPED (1<<29)
  18880. +#define OMX_BUFFERFLAG_FIRST_FIELD (1<<30)
  18881. COpenMaxVideoBuffer::COpenMaxVideoBuffer(COpenMaxVideo *omv)
  18882. : m_omv(omv), m_refs(0)
  18883. @@ -139,8 +141,11 @@ COpenMaxVideo::COpenMaxVideo()
  18884. m_deinterlace = false;
  18885. m_deinterlace_request = VS_DEINTERLACEMODE_OFF;
  18886. - m_deinterlace_second_field = false;
  18887. m_startframe = false;
  18888. + m_decoderPts = DVD_NOPTS_VALUE;
  18889. + m_droppedPics = 0;
  18890. + m_decode_frame_number = 1;
  18891. + m_skipDeinterlaceFields = false;
  18892. }
  18893. COpenMaxVideo::~COpenMaxVideo()
  18894. @@ -369,7 +374,10 @@ void COpenMaxVideo::Dispose()
  18895. m_finished = true;
  18896. pthread_mutex_unlock(&m_omx_output_mutex);
  18897. if (done)
  18898. + {
  18899. + assert(m_dts_queue.empty());
  18900. m_myself.reset();
  18901. + }
  18902. }
  18903. void COpenMaxVideo::SetDropState(bool bDrop)
  18904. @@ -730,6 +738,7 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  18905. omx_buffer->nFilledLen = (demuxer_bytes > omx_buffer->nAllocLen) ? omx_buffer->nAllocLen : demuxer_bytes;
  18906. omx_buffer->nTimeStamp = ToOMXTime((uint64_t)(pts == DVD_NOPTS_VALUE) ? 0 : pts);
  18907. omx_buffer->pAppPrivate = omx_buffer;
  18908. + omx_buffer->pMarkData = (OMX_PTR)m_decode_frame_number;
  18909. memcpy(omx_buffer->pBuffer, demuxer_content, omx_buffer->nFilledLen);
  18910. demuxer_bytes -= omx_buffer->nFilledLen;
  18911. @@ -742,12 +751,18 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  18912. omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
  18913. if (pts == DVD_NOPTS_VALUE) // hijack an omx flag to indicate there wasn't a real timestamp - it will be returned with the picture (but otherwise ignored)
  18914. omx_buffer->nFlags |= OMX_BUFFERFLAG_PTS_INVALID;
  18915. - if (m_drop_state) // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored)
  18916. + if (m_drop_state)
  18917. + {
  18918. + // hijack an omx flag to signal this frame to be dropped - it will be returned with the picture (but otherwise ignored)
  18919. omx_buffer->nFlags |= OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED;
  18920. + m_droppedPics += m_deinterlace ? 2:1;
  18921. + }
  18922. + // always set this flag on input. It won't be set on second field of interlaced video.
  18923. + omx_buffer->nFlags |= OMX_BUFFERFLAG_FIRST_FIELD;
  18924. #if defined(OMX_DEBUG_VERBOSE)
  18925. - CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x",
  18926. - CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags);
  18927. + CLog::Log(LOGDEBUG, "%s::%s - %-6d dts:%.3f pts:%.3f flags:%x frame:%d",
  18928. + CLASSNAME, __func__, omx_buffer->nFilledLen, dts == DVD_NOPTS_VALUE ? 0.0 : dts*1e-6, pts == DVD_NOPTS_VALUE ? 0.0 : pts*1e-6, omx_buffer->nFlags, (int)omx_buffer->pMarkData);
  18929. #endif
  18930. omx_err = m_omx_decoder.EmptyThisBuffer(omx_buffer);
  18931. @@ -758,13 +773,16 @@ int COpenMaxVideo::Decode(uint8_t* pData, int iSize, double dts, double pts)
  18932. }
  18933. if (demuxer_bytes == 0)
  18934. {
  18935. + m_decode_frame_number++;
  18936. m_startframe = true;
  18937. #ifdef DTS_QUEUE
  18938. if (!m_drop_state)
  18939. {
  18940. // only push if we are successful with feeding OMX_EmptyThisBuffer
  18941. + pthread_mutex_lock(&m_omx_output_mutex);
  18942. m_dts_queue.push(dts);
  18943. assert(m_dts_queue.size() < 32);
  18944. + pthread_mutex_unlock(&m_omx_output_mutex);
  18945. }
  18946. #endif
  18947. if (buffer_to_free)
  18948. @@ -840,13 +858,18 @@ void COpenMaxVideo::Reset(void)
  18949. SetDropState(true);
  18950. SetDropState(false);
  18951. #ifdef DTS_QUEUE
  18952. + pthread_mutex_lock(&m_omx_output_mutex);
  18953. while (!m_dts_queue.empty())
  18954. m_dts_queue.pop();
  18955. + pthread_mutex_unlock(&m_omx_output_mutex);
  18956. #endif
  18957. while (!m_demux_queue.empty())
  18958. m_demux_queue.pop();
  18959. m_startframe = false;
  18960. + m_decoderPts = DVD_NOPTS_VALUE;
  18961. + m_droppedPics = 0;
  18962. + m_decode_frame_number = 1;
  18963. }
  18964. @@ -928,26 +951,17 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  18965. }
  18966. }
  18967. -#ifdef DTS_QUEUE
  18968. - if (!m_deinterlace_second_field)
  18969. - {
  18970. - assert(!m_dts_queue.empty());
  18971. - pDvdVideoPicture->dts = m_dts_queue.front();
  18972. - m_dts_queue.pop();
  18973. - }
  18974. - if (m_deinterlace)
  18975. - m_deinterlace_second_field = !m_deinterlace_second_field;
  18976. -#endif
  18977. // nTimeStamp is in microseconds
  18978. + pDvdVideoPicture->dts = buffer->dts;
  18979. pDvdVideoPicture->pts = FromOMXTime(buffer->omx_buffer->nTimeStamp);
  18980. pDvdVideoPicture->openMaxBuffer->Acquire();
  18981. pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
  18982. if (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_PTS_INVALID)
  18983. pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
  18984. #if defined(OMX_DEBUG_VERBOSE)
  18985. - CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__,
  18986. + CLog::Log(LOGINFO, "%s::%s dts:%.3f pts:%.3f flags:%x:%x frame:%d openMaxBuffer:%p omx_buffer:%p egl_image:%p texture_id:%x", CLASSNAME, __func__,
  18987. pDvdVideoPicture->dts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->dts*1e-6, pDvdVideoPicture->pts == DVD_NOPTS_VALUE ? 0.0 : pDvdVideoPicture->pts*1e-6,
  18988. - pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id);
  18989. + pDvdVideoPicture->iFlags, buffer->omx_buffer->nFlags, (int)buffer->omx_buffer->pMarkData, pDvdVideoPicture->openMaxBuffer, pDvdVideoPicture->openMaxBuffer->omx_buffer, pDvdVideoPicture->openMaxBuffer->egl_image, pDvdVideoPicture->openMaxBuffer->texture_id);
  18990. #endif
  18991. assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED)));
  18992. }
  18993. @@ -956,6 +970,12 @@ bool COpenMaxVideo::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  18994. CLog::Log(LOGERROR, "%s::%s - called but m_omx_output_ready is empty", CLASSNAME, __func__);
  18995. return false;
  18996. }
  18997. +
  18998. + if (pDvdVideoPicture->pts != DVD_NOPTS_VALUE)
  18999. + m_decoderPts = pDvdVideoPicture->pts;
  19000. + else
  19001. + m_decoderPts = pDvdVideoPicture->dts; // xxx is DVD_NOPTS_VALUE better?
  19002. +
  19003. return true;
  19004. }
  19005. @@ -970,25 +990,54 @@ bool COpenMaxVideo::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
  19006. return true;
  19007. }
  19008. +bool COpenMaxVideo::GetCodecStats(double &pts, int &droppedPics)
  19009. +{
  19010. + pts = m_decoderPts;
  19011. + droppedPics = m_droppedPics;
  19012. + m_droppedPics = 0;
  19013. + CLog::Log(LOGDEBUG, "%s::%s - pts:%.0f droppedPics:%d", CLASSNAME, __func__, pts, droppedPics);
  19014. + return true;
  19015. +}
  19016. +
  19017. // DecoderFillBufferDone -- OpenMax output buffer has been filled
  19018. OMX_ERRORTYPE COpenMaxVideo::DecoderFillBufferDone(
  19019. OMX_HANDLETYPE hComponent,
  19020. OMX_BUFFERHEADERTYPE* pBuffer)
  19021. {
  19022. COpenMaxVideoBuffer *buffer = (COpenMaxVideoBuffer*)pBuffer->pAppPrivate;
  19023. + bool skipDeinterlaceFields = m_skipDeinterlaceFields || g_windowManager.HasDialogOnScreen();
  19024. #if defined(OMX_DEBUG_VERBOSE)
  19025. - CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x",
  19026. - CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags);
  19027. + CLog::Log(LOGDEBUG, "%s::%s - %p (%p,%p) buffer_size(%u), pts:%.3f flags:%x frame:%d win:%x",
  19028. + CLASSNAME, __func__, buffer, pBuffer, buffer->omx_buffer, pBuffer->nFilledLen, (double)FromOMXTime(buffer->omx_buffer->nTimeStamp)*1e-6, buffer->omx_buffer->nFlags, (int)buffer->omx_buffer->pMarkData, skipDeinterlaceFields);
  19029. #endif
  19030. assert(!(buffer->omx_buffer->nFlags & (OMX_BUFFERFLAG_DECODEONLY | OMX_BUFFERFLAG_DROPPED)));
  19031. - // queue output omx buffer to ready list.
  19032. - pthread_mutex_lock(&m_omx_output_mutex);
  19033. - buffer->m_aspect_ratio = m_aspect_ratio;
  19034. - m_omx_output_ready.push(buffer);
  19035. - pthread_mutex_unlock(&m_omx_output_mutex);
  19036. +
  19037. + // flags have OMX_BUFFERFLAG_FIRST_FIELD set if this is a direct result of a submitted frame,
  19038. + // clear for second field of deinterlaced frame. They are zero when frame is returned due to a flush.
  19039. +#ifdef DTS_QUEUE
  19040. + if ((!m_deinterlace || (buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_FIRST_FIELD)) && buffer->omx_buffer->nFlags)
  19041. + {
  19042. + pthread_mutex_lock(&m_omx_output_mutex);
  19043. + assert(!m_dts_queue.empty());
  19044. + buffer->dts = m_dts_queue.front();
  19045. + m_dts_queue.pop();
  19046. + pthread_mutex_unlock(&m_omx_output_mutex);
  19047. + }
  19048. +#endif
  19049. + if (m_drop_state || (m_deinterlace && skipDeinterlaceFields && !(buffer->omx_buffer->nFlags & OMX_BUFFERFLAG_FIRST_FIELD)))
  19050. + {
  19051. + ReturnOpenMaxBuffer(buffer);
  19052. + }
  19053. + else
  19054. + {
  19055. + buffer->m_aspect_ratio = m_aspect_ratio;
  19056. + pthread_mutex_lock(&m_omx_output_mutex);
  19057. + m_omx_output_ready.push(buffer);
  19058. + pthread_mutex_unlock(&m_omx_output_mutex);
  19059. + }
  19060. return OMX_ErrorNone;
  19061. }
  19062. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  19063. index f234f6d..adf53b5 100644
  19064. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  19065. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.h
  19066. @@ -57,6 +57,7 @@ class COpenMaxVideoBuffer
  19067. int height;
  19068. float m_aspect_ratio;
  19069. int index;
  19070. + double dts;
  19071. // used for egl based rendering if active
  19072. EGLImageKHR egl_image;
  19073. @@ -87,6 +88,7 @@ class COpenMaxVideo
  19074. virtual unsigned GetAllowedReferences() { return 2; }
  19075. virtual void SetDropState(bool bDrop);
  19076. virtual const char* GetName(void) { return (const char*)m_pFormatName; }
  19077. + virtual bool GetCodecStats(double &pts, int &droppedPics);
  19078. // OpenMax decoder callback routines.
  19079. OMX_ERRORTYPE DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE* pBuffer);
  19080. @@ -142,10 +144,11 @@ class COpenMaxVideo
  19081. bool m_deinterlace;
  19082. EDEINTERLACEMODE m_deinterlace_request;
  19083. - bool m_deinterlace_second_field;
  19084. -
  19085. bool m_startframe;
  19086. -
  19087. + unsigned int m_decode_frame_number;
  19088. + double m_decoderPts;
  19089. + unsigned int m_droppedPics;
  19090. + bool m_skipDeinterlaceFields;
  19091. bool PortSettingsChanged();
  19092. bool SendDecoderConfig(uint8_t *extradata, int extrasize);
  19093. bool NaluFormatStartCodes(enum AVCodecID codec, uint8_t *extradata, int extrasize);
  19094. --
  19095. 1.9.3
  19096. From 4dd2fcf0f479b6b18dac9a496ddf1788b82388f2 Mon Sep 17 00:00:00 2001
  19097. From: popcornmix <popcornmix@gmail.com>
  19098. Date: Sun, 11 May 2014 16:13:45 +0100
  19099. Subject: [PATCH 87/94] [rbp] Add config.txt settings to log file
  19100. ---
  19101. xbmc/linux/RBP.cpp | 8 +++++++-
  19102. 1 file changed, 7 insertions(+), 1 deletion(-)
  19103. diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
  19104. index 49dcbb8..9a5e9cb 100644
  19105. --- a/xbmc/linux/RBP.cpp
  19106. +++ b/xbmc/linux/RBP.cpp
  19107. @@ -79,11 +79,17 @@ bool CRBP::Initialize()
  19108. void CRBP::LogFirmwareVerison()
  19109. {
  19110. - char response[160];
  19111. + char response[1024];
  19112. m_DllBcmHost->vc_gencmd(response, sizeof response, "version");
  19113. response[sizeof(response) - 1] = '\0';
  19114. CLog::Log(LOGNOTICE, "Raspberry PI firmware version: %s", response);
  19115. CLog::Log(LOGNOTICE, "ARM mem: %dMB GPU mem: %dMB MPG2:%d WVC1:%d", m_arm_mem, m_gpu_mem, m_codec_mpg2_enabled, m_codec_wvc1_enabled);
  19116. + m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config int");
  19117. + response[sizeof(response) - 1] = '\0';
  19118. + CLog::Log(LOGNOTICE, "Config:\n%s", response);
  19119. + m_DllBcmHost->vc_gencmd(response, sizeof response, "get_config str");
  19120. + response[sizeof(response) - 1] = '\0';
  19121. + CLog::Log(LOGNOTICE, "Config:\n%s", response);
  19122. }
  19123. void CRBP::GetDisplaySize(int &width, int &height)
  19124. --
  19125. 1.9.3
  19126. From eb2cba833f1399befcbd60901f3d97a08e3a2781 Mon Sep 17 00:00:00 2001
  19127. From: Alex Deryskyba <alex@codesnake.com>
  19128. Date: Thu, 8 May 2014 18:54:54 +0300
  19129. Subject: [PATCH 88/94] Reset display region when video stream properties
  19130. change
  19131. Currently when video stream properties change, e.g. when user switches to next or previous Live TV channel, and has the same frame width and height, the COMXVideo::SetVideoRect() method is not called, causing the video to play back with default source and destination rectangles, not respecting the user-defined zoom settings.
  19132. This commit fixes the issue.
  19133. ---
  19134. xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 3 +++
  19135. 1 file changed, 3 insertions(+)
  19136. diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  19137. index 61b884e..eaa1e34 100644
  19138. --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  19139. +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp
  19140. @@ -781,6 +781,9 @@ void OMXPlayerVideo::ResolutionUpdateCallBack(uint32_t width, uint32_t height, f
  19141. return;
  19142. }
  19143. + m_src_rect.SetRect(0, 0, 0, 0);
  19144. + m_dst_rect.SetRect(0, 0, 0, 0);
  19145. +
  19146. g_renderManager.RegisterRenderUpdateCallBack((const void*)this, RenderUpdateCallBack);
  19147. }
  19148. --
  19149. 1.9.3
  19150. From 7c369ba5ec4e700f5c06e1caa20095bc26e61195 Mon Sep 17 00:00:00 2001
  19151. From: popcornmix <popcornmix@gmail.com>
  19152. Date: Wed, 28 May 2014 23:44:11 +0100
  19153. Subject: [PATCH 89/94] [omxplayer] Fix for mapping of multichannel PCM audio
  19154. ---
  19155. xbmc/cores/omxplayer/OMXAudio.cpp | 11 ++++++++---
  19156. 1 file changed, 8 insertions(+), 3 deletions(-)
  19157. diff --git a/xbmc/cores/omxplayer/OMXAudio.cpp b/xbmc/cores/omxplayer/OMXAudio.cpp
  19158. index d9beb68..75eff26 100644
  19159. --- a/xbmc/cores/omxplayer/OMXAudio.cpp
  19160. +++ b/xbmc/cores/omxplayer/OMXAudio.cpp
  19161. @@ -606,13 +606,18 @@ bool COMXAudio::Initialize(AEAudioFormat format, OMXClock *clock, CDVDStreamInfo
  19162. if (m_InputChannels <= 2)
  19163. stdLayout = AE_CH_LAYOUT_2_0;
  19164. - uint64_t m_dst_chan_layout = GetAVChannelLayout(stdLayout);
  19165. +
  19166. + CAEChannelInfo resolvedMap = channelMap;
  19167. + resolvedMap.ResolveChannels(stdLayout);
  19168. + uint64_t m_dst_chan_layout = GetAVChannelLayout(resolvedMap);
  19169. uint64_t m_src_chan_layout = GetAVChannelLayout(channelMap);
  19170. - m_OutputChannels = stdLayout.Count();
  19171. +
  19172. + m_InputChannels = channelMap.Count();
  19173. + m_OutputChannels = resolvedMap.Count();
  19174. int m_dst_channels = m_OutputChannels;
  19175. int m_src_channels = m_InputChannels;
  19176. - SetAudioProps(m_Passthrough, GetChannelMap(stdLayout, m_Passthrough));
  19177. + SetAudioProps(m_Passthrough, GetChannelMap(resolvedMap, m_Passthrough));
  19178. CLog::Log(LOGINFO, "%s::%s remap:%p chan:%d->%d norm:%d upmix:%d %llx:%llx", CLASSNAME, __func__, remapLayout, m_src_channels, m_dst_channels, normalize, upmix, m_src_chan_layout, m_dst_chan_layout);
  19179. --
  19180. 1.9.3
  19181. From 458ec80741e4aa1ae95fe616f5953e1268a4802e Mon Sep 17 00:00:00 2001
  19182. From: popcornmix <popcornmix@gmail.com>
  19183. Date: Fri, 30 May 2014 14:15:10 +0100
  19184. Subject: [PATCH 90/94] [pi] Fix for logged resolutions
  19185. ---
  19186. xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp | 15 +++++----------
  19187. 1 file changed, 5 insertions(+), 10 deletions(-)
  19188. diff --git a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  19189. index 5b26b20..a3edf0e 100644
  19190. --- a/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  19191. +++ b/xbmc/windowing/egl/EGLNativeTypeRaspberryPI.cpp
  19192. @@ -483,10 +483,8 @@ bool CEGLNativeTypeRaspberryPI::ProbeResolutions(std::vector<RESOLUTION_INFO> &r
  19193. if(resolutions.size() == 0)
  19194. {
  19195. - RESOLUTION_INFO res;
  19196. - CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags);
  19197. -
  19198. AddUniqueResolution(m_desktopRes, resolutions);
  19199. + CLog::Log(LOGDEBUG, "EGL probe resolution %s:%x\n", m_desktopRes.strMode.c_str(), m_desktopRes.dwFlags);
  19200. }
  19201. if(resolutions.size() < 2)
  19202. @@ -576,13 +574,12 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  19203. res.iScreenWidth = tv->width;
  19204. res.iScreenHeight = tv->height;
  19205. res.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res.iScreenWidth / (float)res.iScreenHeight);
  19206. + res.iSubtitles = (int)(0.965 * res.iHeight);
  19207. + AddUniqueResolution(res, resolutions);
  19208. CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f) %s%s:%x\n", i, res.strMode.c_str(), res.fPixelRatio,
  19209. tv->native ? "N" : "", tv->scan_mode ? "I" : "", tv->code);
  19210. - res.iSubtitles = (int)(0.965 * res.iHeight);
  19211. -
  19212. - AddUniqueResolution(res, resolutions);
  19213. if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  19214. {
  19215. RESOLUTION_INFO res2 = res;
  19216. @@ -596,11 +593,10 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  19217. RESOLUTION_INFO res2 = res;
  19218. res2.dwFlags |= D3DPRESENTFLAG_MODE3DSBS;
  19219. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  19220. - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  19221. -
  19222. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  19223. AddUniqueResolution(res2, resolutions);
  19224. + CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  19225. if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  19226. {
  19227. res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f);
  19228. @@ -612,11 +608,10 @@ void CEGLNativeTypeRaspberryPI::GetSupportedModes(HDMI_RES_GROUP_T group, std::v
  19229. RESOLUTION_INFO res2 = res;
  19230. res2.dwFlags |= D3DPRESENTFLAG_MODE3DTB;
  19231. res2.fPixelRatio = get_display_aspect_ratio((HDMI_ASPECT_T)tv->aspect_ratio) / ((float)res2.iScreenWidth / (float)res2.iScreenHeight);
  19232. - CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  19233. -
  19234. res2.iSubtitles = (int)(0.965 * res2.iHeight);
  19235. AddUniqueResolution(res2, resolutions);
  19236. + CLog::Log(LOGDEBUG, "EGL mode %d: %s (%.2f)\n", i, res2.strMode.c_str(), res2.fPixelRatio);
  19237. if (tv->frame_rate == 24 || tv->frame_rate == 30 || tv->frame_rate == 60)
  19238. {
  19239. res2.fRefreshRate = (float)tv->frame_rate * (1000.0f/1001.0f);
  19240. --
  19241. 1.9.3
  19242. From 9eb0d69eb1f319421780025cefe6df3ade40c4dc Mon Sep 17 00:00:00 2001
  19243. From: popcornmix <popcornmix@gmail.com>
  19244. Date: Sat, 7 Jun 2014 16:55:41 +0100
  19245. Subject: [PATCH 91/94] [omx] Remove logging for texture jobs
  19246. This causes a lot of log spam which hasn't proved useful so far.
  19247. ---
  19248. xbmc/cores/omxplayer/OMXImage.cpp | 5 -----
  19249. 1 file changed, 5 deletions(-)
  19250. diff --git a/xbmc/cores/omxplayer/OMXImage.cpp b/xbmc/cores/omxplayer/OMXImage.cpp
  19251. index 262a004..d529b20 100644
  19252. --- a/xbmc/cores/omxplayer/OMXImage.cpp
  19253. +++ b/xbmc/cores/omxplayer/OMXImage.cpp
  19254. @@ -210,13 +210,11 @@ bool COMXImage::SendMessage(bool (*callback)(EGLDisplay egl_display, EGLContext
  19255. mess.sync.Reset();
  19256. {
  19257. CSingleLock lock(m_texqueue_lock);
  19258. - CLog::Log(LOGDEBUG, "%s: texture job: %p:%p", __func__, &mess, mess.callback);
  19259. m_texqueue.push(&mess);
  19260. m_texqueue_cond.notifyAll();
  19261. }
  19262. // wait for function to have finished (in texture thread)
  19263. mess.sync.Wait();
  19264. - CLog::Log(LOGDEBUG, "%s: texture job done: %p:%p = %d", __func__, &mess, mess.callback, mess.result);
  19265. // need to ensure texture thread has returned from mess.sync.Set() before we exit and free tex
  19266. CSingleLock lock(m_texqueue_lock);
  19267. return mess.result;
  19268. @@ -429,15 +427,12 @@ void COMXImage::Process()
  19269. struct callbackinfo *mess = m_texqueue.front();
  19270. m_texqueue.pop();
  19271. lock.Leave();
  19272. - CLog::Log(LOGDEBUG, "%s: texture job: %p:%p:%p", __func__, mess, mess->callback, mess->cookie);
  19273. mess->result = mess->callback(g_Windowing.GetEGLDisplay(), GetEGLContext(), mess->cookie);
  19274. - CLog::Log(LOGDEBUG, "%s: texture job about to Set: %p:%p:%p", __func__, mess, mess->callback, mess->cookie);
  19275. {
  19276. CSingleLock lock(m_texqueue_lock);
  19277. mess->sync.Set();
  19278. }
  19279. - CLog::Log(LOGDEBUG, "%s: texture job: %p done", __func__, mess);
  19280. }
  19281. }
  19282. }
  19283. --
  19284. 1.9.3
  19285. From 4c7a42273416f4053a5bb90755ea45cc0a5f7a0b Mon Sep 17 00:00:00 2001
  19286. From: popcornmix <popcornmix@gmail.com>
  19287. Date: Sun, 15 Jun 2014 13:20:53 +0100
  19288. Subject: [PATCH 92/94] gles: Avoid crash when capturing snapshot when using
  19289. dvdplayer
  19290. Note: snapshot will be blank, but that's better than crashing
  19291. ---
  19292. xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 2 ++
  19293. 1 file changed, 2 insertions(+)
  19294. diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  19295. index e22a153..0cff2c5 100644
  19296. --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  19297. +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
  19298. @@ -1600,7 +1600,9 @@ bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
  19299. return false;
  19300. // If rendered directly by the hardware
  19301. +#ifndef TARGET_RASPBERRY_PI
  19302. if (m_renderMethod & RENDER_BYPASS)
  19303. +#endif
  19304. {
  19305. capture->BeginRender();
  19306. capture->EndRender();
  19307. --
  19308. 1.9.3
  19309. From 9805b1c9b218f8ba15c41752cc88f6e8bc3223ad Mon Sep 17 00:00:00 2001
  19310. From: popcornmix <popcornmix@gmail.com>
  19311. Date: Wed, 28 May 2014 18:30:51 +0100
  19312. Subject: [PATCH 93/94] [omxcodec] Reduce GPU memory use by 2 video frames
  19313. ---
  19314. xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp | 14 ++++++++++++++
  19315. 1 file changed, 14 insertions(+)
  19316. diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  19317. index 93cf521..cc45570 100644
  19318. --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  19319. +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/OpenMaxVideo.cpp
  19320. @@ -308,6 +308,20 @@ bool COpenMaxVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, OpenM
  19321. return false;
  19322. }
  19323. + {
  19324. + // as we aren't tunnelled to display, we can save memory by setting extrabuffers to 0
  19325. + OMX_PARAM_U32TYPE extra_buffers;
  19326. + OMX_INIT_STRUCTURE(extra_buffers);
  19327. + extra_buffers.nU32 = 0;
  19328. +
  19329. + omx_err = m_omx_decoder.SetParameter(OMX_IndexParamBrcmExtraBuffers, &extra_buffers);
  19330. + if(omx_err != OMX_ErrorNone)
  19331. + {
  19332. + CLog::Log(LOGERROR, "COMXVideo::Open error OMX_IndexParamBrcmExtraBuffers omx_err(0x%08x)\n", omx_err);
  19333. + return false;
  19334. + }
  19335. + }
  19336. +
  19337. // request portsettingschanged on aspect ratio change
  19338. OMX_CONFIG_REQUESTCALLBACKTYPE notifications;
  19339. OMX_INIT_STRUCTURE(notifications);
  19340. --
  19341. 1.9.3
  19342. From 1b49a6f5b1655918e26d84ca4260fc249c00022f Mon Sep 17 00:00:00 2001
  19343. From: popcornmix <popcornmix@gmail.com>
  19344. Date: Wed, 18 Jun 2014 23:11:28 +0100
  19345. Subject: [PATCH 94/94] [rbp] Reduce GPU memory use when limited
  19346. Switching from default triple buffered output to double buffered saves 8M with 1080p GUI.
  19347. This may slightly reduce framerate, but is likely to be minimal.
  19348. Assume if gpu_mem is set below the default 128M that this memory reduction is wanted
  19349. ---
  19350. xbmc/linux/RBP.cpp | 3 +++
  19351. 1 file changed, 3 insertions(+)
  19352. diff --git a/xbmc/linux/RBP.cpp b/xbmc/linux/RBP.cpp
  19353. index 9a5e9cb..50d5186 100644
  19354. --- a/xbmc/linux/RBP.cpp
  19355. +++ b/xbmc/linux/RBP.cpp
  19356. @@ -72,6 +72,9 @@ bool CRBP::Initialize()
  19357. if (vc_gencmd(response, sizeof response, "codec_enabled WVC1") == 0)
  19358. m_codec_wvc1_enabled = strcmp("WVC1=enabled", response) == 0;
  19359. + if (m_gpu_mem < 128)
  19360. + setenv("V3D_DOUBLE_BUFFER", "1", 1);
  19361. +
  19362. g_OMXImage.Initialize();
  19363. m_omx_image_init = true;
  19364. return true;
  19365. --
  19366. 1.9.3