1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "media/filters/source_buffer_stream.h"
- #include <stddef.h>
- #include <stdint.h>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/logging.h"
- #include "base/numerics/safe_conversions.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_split.h"
- #include "base/strings/string_util.h"
- #include "base/test/scoped_feature_list.h"
- #include "base/time/time.h"
- #include "media/base/data_buffer.h"
- #include "media/base/decoder_buffer.h"
- #include "media/base/media_log.h"
- #include "media/base/media_switches.h"
- #include "media/base/media_util.h"
- #include "media/base/mock_media_log.h"
- #include "media/base/test_helpers.h"
- #include "media/base/text_track_config.h"
- #include "media/base/timestamp_constants.h"
- #include "media/base/webvtt_util.h"
- #include "media/filters/source_buffer_range.h"
- #include "testing/gtest/include/gtest/gtest.h"
- using ::testing::HasSubstr;
- using ::testing::InSequence;
- using ::testing::StrictMock;
- namespace {
- enum class TimeGranularity { kMicrosecond, kMillisecond };
- } // namespace
- namespace media {
- typedef StreamParser::BufferQueue BufferQueue;
- static const int kDefaultFramesPerSecond = 30;
- static const int kDefaultKeyframesPerSecond = 6;
- static const uint8_t kDataA = 0x11;
- static const uint8_t kDataB = 0x33;
- static const int kDataSize = 1;
- // Matchers for verifying common media log entry strings.
- MATCHER_P(ContainsTrackBufferExhaustionSkipLog, skip_milliseconds, "") {
- return CONTAINS_STRING(arg,
- "Media append that overlapped current playback "
- "position may cause time gap in playing VIDEO stream "
- "because the next keyframe is " +
- base::NumberToString(skip_milliseconds) +
- "ms beyond last overlapped frame. Media may "
- "appear temporarily frozen.");
- }
- #define EXPECT_STATUS_FOR_STREAM_OP(status_suffix, operation) \
- { EXPECT_EQ(SourceBufferStreamStatus::status_suffix, stream_->operation); }
- class SourceBufferStreamTest : public testing::Test {
- public:
- SourceBufferStreamTest(const SourceBufferStreamTest&) = delete;
- SourceBufferStreamTest& operator=(const SourceBufferStreamTest&) = delete;
- protected:
- SourceBufferStreamTest() {
- video_config_ = TestVideoConfig::Normal();
- SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
- ResetStream<>(video_config_);
- }
- template <typename ConfigT>
- void ResetStream(const ConfigT& config) {
- stream_ = std::make_unique<SourceBufferStream>(config, &media_log_);
- }
- void SetMemoryLimit(size_t buffers_of_data) {
- stream_->set_memory_limit(buffers_of_data * kDataSize);
- }
- void SetStreamInfo(int frames_per_second, int keyframes_per_second) {
- frames_per_second_ = frames_per_second;
- keyframes_per_second_ = keyframes_per_second;
- frame_duration_ = ConvertToFrameDuration(frames_per_second);
- }
- void SetTextStream() {
- video_config_ = TestVideoConfig::Invalid();
- TextTrackConfig config(kTextSubtitles, "", "", "");
- ResetStream<>(config);
- SetStreamInfo(2, 2);
- }
- void SetAudioStream() {
- video_config_ = TestVideoConfig::Invalid();
- audio_config_.Initialize(AudioCodec::kVorbis, kSampleFormatPlanarF32,
- CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(),
- EncryptionScheme::kUnencrypted, base::TimeDelta(),
- 0);
- ResetStream<>(audio_config_);
- // Equivalent to 2ms per frame.
- SetStreamInfo(500, 500);
- }
- void NewCodedFrameGroupAppend(int starting_position, int number_of_buffers) {
- AppendBuffers(starting_position, number_of_buffers, true, base::TimeDelta(),
- &kDataA, kDataSize);
- }
- void NewCodedFrameGroupAppend(int starting_position,
- int number_of_buffers,
- const uint8_t* data) {
- AppendBuffers(starting_position, number_of_buffers, true, base::TimeDelta(),
- data, kDataSize);
- }
- void NewCodedFrameGroupAppend_OffsetFirstBuffer(
- int starting_position,
- int number_of_buffers,
- base::TimeDelta first_buffer_offset) {
- AppendBuffers(starting_position, number_of_buffers, true,
- first_buffer_offset, &kDataA, kDataSize);
- }
- void AppendBuffers(int starting_position, int number_of_buffers) {
- AppendBuffers(starting_position, number_of_buffers, false,
- base::TimeDelta(), &kDataA, kDataSize);
- }
- void AppendBuffers(int starting_position,
- int number_of_buffers,
- const uint8_t* data) {
- AppendBuffers(starting_position, number_of_buffers, false,
- base::TimeDelta(), data, kDataSize);
- }
- void NewCodedFrameGroupAppend(const std::string& buffers_to_append) {
- AppendBuffers(buffers_to_append, true, kNoTimestamp, false);
- }
- void NewCodedFrameGroupAppend(base::TimeDelta start_timestamp,
- const std::string& buffers_to_append) {
- AppendBuffers(buffers_to_append, true, start_timestamp, false);
- }
- void AppendBuffers(const std::string& buffers_to_append) {
- AppendBuffers(buffers_to_append, false, kNoTimestamp, false);
- }
- void NewCodedFrameGroupAppendOneByOne(const std::string& buffers_to_append) {
- AppendBuffers(buffers_to_append, true, kNoTimestamp, true);
- }
- void AppendBuffersOneByOne(const std::string& buffers_to_append) {
- AppendBuffers(buffers_to_append, false, kNoTimestamp, true);
- }
- void Seek(int position) { stream_->Seek(position * frame_duration_); }
- void SeekToTimestampMs(int64_t timestamp_ms) {
- stream_->Seek(base::Milliseconds(timestamp_ms));
- }
- bool GarbageCollect(base::TimeDelta media_time, int new_data_size) {
- return stream_->GarbageCollectIfNeeded(media_time, new_data_size);
- }
- bool GarbageCollectWithPlaybackAtBuffer(int position, int new_data_buffers) {
- return GarbageCollect(position * frame_duration_,
- new_data_buffers * kDataSize);
- }
- void RemoveInMs(int start, int end, int duration) {
- Remove(base::Milliseconds(start), base::Milliseconds(end),
- base::Milliseconds(duration));
- }
- void Remove(base::TimeDelta start, base::TimeDelta end,
- base::TimeDelta duration) {
- stream_->Remove(start, end, duration);
- }
- void SignalStartOfCodedFrameGroup(base::TimeDelta start_timestamp) {
- stream_->OnStartOfCodedFrameGroup(start_timestamp);
- }
- int GetRemovalRangeInMs(int start, int end, int bytes_to_free,
- int* removal_end) {
- base::TimeDelta removal_end_timestamp = base::Milliseconds(*removal_end);
- int bytes_removed = stream_->GetRemovalRange(
- base::Milliseconds(start), base::Milliseconds(end), bytes_to_free,
- &removal_end_timestamp);
- *removal_end = removal_end_timestamp.InMilliseconds();
- return bytes_removed;
- }
- void CheckExpectedRanges(const std::string& expected) {
- Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
- std::stringstream ss;
- ss << "{ ";
- for (size_t i = 0; i < r.size(); ++i) {
- int64_t start = r.start(i).IntDiv(frame_duration_);
- int64_t end = r.end(i).IntDiv(frame_duration_) - 1;
- ss << "[" << start << "," << end << ") ";
- }
- ss << "}";
- EXPECT_EQ(expected, ss.str());
- }
- void CheckExpectedRangesByTimestamp(
- const std::string& expected,
- TimeGranularity granularity = TimeGranularity::kMillisecond) {
- Ranges<base::TimeDelta> r = stream_->GetBufferedTime();
- std::stringstream ss;
- ss << "{ ";
- for (size_t i = 0; i < r.size(); ++i) {
- auto conversion = (granularity == TimeGranularity::kMillisecond)
- ? &base::TimeDelta::InMilliseconds
- : &base::TimeDelta::InMicroseconds;
- int64_t start = (r.start(i).*conversion)();
- int64_t end = (r.end(i).*conversion)();
- ss << "[" << start << "," << end << ") ";
- }
- ss << "}";
- EXPECT_EQ(expected, ss.str());
- }
- void CheckExpectedRangeEndTimes(const std::string& expected) {
- std::stringstream ss;
- ss << "{ ";
- for (const auto& r : stream_->ranges_) {
- base::TimeDelta highest_pts = r->GetEndTimestamp();
- base::TimeDelta end_time = r->GetBufferedEndTimestamp();
- ss << "<" << highest_pts.InMilliseconds() << ","
- << end_time.InMilliseconds() << "> ";
- }
- ss << "}";
- EXPECT_EQ(expected, ss.str());
- }
- void CheckIsNextInPTSSequenceWithFirstRange(int64_t pts_in_ms,
- bool expectation) {
- ASSERT_GE(stream_->ranges_.size(), 1u);
- const auto& range_ptr = *(stream_->ranges_.begin());
- EXPECT_EQ(expectation, range_ptr->IsNextInPresentationSequence(
- base::Milliseconds(pts_in_ms)));
- }
- void CheckExpectedBuffers(
- int starting_position, int ending_position) {
- CheckExpectedBuffers(starting_position, ending_position, false, NULL, 0);
- }
- void CheckExpectedBuffers(
- int starting_position, int ending_position, bool expect_keyframe) {
- CheckExpectedBuffers(starting_position, ending_position, expect_keyframe,
- NULL, 0);
- }
- void CheckExpectedBuffers(int starting_position,
- int ending_position,
- const uint8_t* data) {
- CheckExpectedBuffers(starting_position, ending_position, false, data,
- kDataSize);
- }
- void CheckExpectedBuffers(int starting_position,
- int ending_position,
- const uint8_t* data,
- bool expect_keyframe) {
- CheckExpectedBuffers(starting_position, ending_position, expect_keyframe,
- data, kDataSize);
- }
- void CheckExpectedBuffers(int starting_position,
- int ending_position,
- bool expect_keyframe,
- const uint8_t* expected_data,
- int expected_size) {
- int current_position = starting_position;
- for (; current_position <= ending_position; current_position++) {
- scoped_refptr<StreamParserBuffer> buffer;
- SourceBufferStreamStatus status = stream_->GetNextBuffer(&buffer);
- EXPECT_NE(status, SourceBufferStreamStatus::kConfigChange);
- if (status != SourceBufferStreamStatus::kSuccess)
- break;
- if (expect_keyframe && current_position == starting_position)
- EXPECT_TRUE(buffer->is_key_frame());
- if (expected_data) {
- const uint8_t* actual_data = buffer->data();
- const int actual_size = buffer->data_size();
- EXPECT_EQ(expected_size, actual_size);
- for (int i = 0; i < std::min(actual_size, expected_size); i++) {
- EXPECT_EQ(expected_data[i], actual_data[i]);
- }
- }
- EXPECT_EQ(
- base::ClampFloor(buffer->GetDecodeTimestamp() / frame_duration_),
- current_position);
- }
- EXPECT_EQ(ending_position + 1, current_position);
- }
- void CheckExpectedBuffers(
- const std::string& expected,
- TimeGranularity granularity = TimeGranularity::kMillisecond) {
- std::vector<std::string> timestamps = base::SplitString(
- expected, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::stringstream ss;
- const SourceBufferStreamType type = stream_->GetType();
- for (size_t i = 0; i < timestamps.size(); i++) {
- scoped_refptr<StreamParserBuffer> buffer;
- SourceBufferStreamStatus status = stream_->GetNextBuffer(&buffer);
- if (i > 0)
- ss << " ";
- if (status == SourceBufferStreamStatus::kConfigChange) {
- switch (type) {
- case SourceBufferStreamType::kVideo:
- stream_->GetCurrentVideoDecoderConfig();
- break;
- case SourceBufferStreamType::kAudio:
- stream_->GetCurrentAudioDecoderConfig();
- break;
- case SourceBufferStreamType::kText:
- stream_->GetCurrentTextTrackConfig();
- break;
- }
- EXPECT_EQ("C", timestamps[i]);
- ss << "C";
- continue;
- }
- EXPECT_EQ(SourceBufferStreamStatus::kSuccess, status);
- if (status != SourceBufferStreamStatus::kSuccess)
- break;
- if (granularity == TimeGranularity::kMillisecond)
- ss << buffer->timestamp().InMilliseconds();
- else
- ss << buffer->timestamp().InMicroseconds();
- if (buffer->GetDecodeTimestamp() !=
- DecodeTimestamp::FromPresentationTime(buffer->timestamp())) {
- if (granularity == TimeGranularity::kMillisecond)
- ss << "|" << buffer->GetDecodeTimestamp().InMilliseconds();
- else
- ss << "|" << buffer->GetDecodeTimestamp().InMicroseconds();
- }
- // Check duration if expected timestamp contains it.
- if (timestamps[i].find('D') != std::string::npos) {
- ss << "D" << buffer->duration().InMilliseconds();
- }
- // Check duration estimation if expected timestamp contains it.
- if (timestamps[i].find('E') != std::string::npos &&
- buffer->is_duration_estimated()) {
- ss << "E";
- }
- // Handle preroll buffers.
- if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) {
- ASSERT_TRUE(buffer->is_key_frame());
- scoped_refptr<StreamParserBuffer> preroll_buffer;
- preroll_buffer.swap(buffer);
- // When a preroll buffer is encountered we should be able to request one
- // more buffer. The first buffer should match the timestamp and config
- // of the second buffer, except that its discard_padding() should be its
- // duration.
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- ASSERT_EQ(buffer->GetConfigId(), preroll_buffer->GetConfigId());
- ASSERT_EQ(buffer->track_id(), preroll_buffer->track_id());
- ASSERT_EQ(buffer->timestamp(), preroll_buffer->timestamp());
- ASSERT_EQ(buffer->GetDecodeTimestamp(),
- preroll_buffer->GetDecodeTimestamp());
- ASSERT_EQ(kInfiniteDuration, preroll_buffer->discard_padding().first);
- ASSERT_EQ(base::TimeDelta(), preroll_buffer->discard_padding().second);
- ASSERT_TRUE(buffer->is_key_frame());
- ss << "P";
- } else if (buffer->is_key_frame()) {
- ss << "K";
- }
- }
- EXPECT_EQ(expected, ss.str());
- }
- void CheckNoNextBuffer() {
- scoped_refptr<StreamParserBuffer> buffer;
- EXPECT_STATUS_FOR_STREAM_OP(kNeedBuffer, GetNextBuffer(&buffer));
- }
- void CheckEOSReached() {
- scoped_refptr<StreamParserBuffer> buffer;
- EXPECT_STATUS_FOR_STREAM_OP(kEndOfStream, GetNextBuffer(&buffer));
- }
- void CheckVideoConfig(const VideoDecoderConfig& config) {
- const VideoDecoderConfig& actual = stream_->GetCurrentVideoDecoderConfig();
- EXPECT_TRUE(actual.Matches(config))
- << "Expected: " << config.AsHumanReadableString()
- << "\nActual: " << actual.AsHumanReadableString();
- }
- void CheckAudioConfig(const AudioDecoderConfig& config) {
- const AudioDecoderConfig& actual = stream_->GetCurrentAudioDecoderConfig();
- EXPECT_TRUE(actual.Matches(config))
- << "Expected: " << config.AsHumanReadableString()
- << "\nActual: " << actual.AsHumanReadableString();
- }
- base::TimeDelta frame_duration() const { return frame_duration_; }
- StrictMock<MockMediaLog> media_log_;
- std::unique_ptr<SourceBufferStream> stream_;
- VideoDecoderConfig video_config_;
- AudioDecoderConfig audio_config_;
- private:
- DemuxerStream::Type GetStreamType() {
- switch (stream_->GetType()) {
- case SourceBufferStreamType::kAudio:
- return DemuxerStream::AUDIO;
- case SourceBufferStreamType::kVideo:
- return DemuxerStream::VIDEO;
- case SourceBufferStreamType::kText:
- return DemuxerStream::TEXT;
- default:
- NOTREACHED();
- return DemuxerStream::UNKNOWN;
- }
- }
- base::TimeDelta ConvertToFrameDuration(int frames_per_second) {
- return base::Seconds(1) / frames_per_second;
- }
- void AppendBuffers(int starting_position,
- int number_of_buffers,
- bool begin_coded_frame_group,
- base::TimeDelta first_buffer_offset,
- const uint8_t* data,
- int size) {
- if (begin_coded_frame_group) {
- stream_->OnStartOfCodedFrameGroup(starting_position * frame_duration_);
- }
- int keyframe_interval = frames_per_second_ / keyframes_per_second_;
- BufferQueue queue;
- for (int i = 0; i < number_of_buffers; i++) {
- int position = starting_position + i;
- bool is_keyframe = position % keyframe_interval == 0;
- // Track ID is meaningless to these tests.
- scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom(
- data, size, is_keyframe, GetStreamType(), 0);
- base::TimeDelta timestamp = frame_duration_ * position;
- if (i == 0)
- timestamp += first_buffer_offset;
- buffer->SetDecodeTimestamp(
- DecodeTimestamp::FromPresentationTime(timestamp));
- // Simulate an IBB...BBP pattern in which all B-frames reference both
- // the I- and P-frames. For a GOP with playback order 12345, this would
- // result in a decode timestamp order of 15234.
- base::TimeDelta presentation_timestamp;
- if (is_keyframe) {
- presentation_timestamp = timestamp;
- } else if ((position - 1) % keyframe_interval == 0) {
- // This is the P-frame (first frame following the I-frame)
- presentation_timestamp =
- (timestamp + frame_duration_ * (keyframe_interval - 2));
- } else {
- presentation_timestamp = timestamp - frame_duration_;
- }
- buffer->set_timestamp(presentation_timestamp);
- buffer->set_duration(frame_duration_);
- queue.push_back(buffer);
- }
- if (!queue.empty())
- stream_->Append(queue);
- }
- void UpdateLastBufferDuration(DecodeTimestamp current_dts,
- BufferQueue* buffers) {
- if (buffers->empty() || buffers->back()->duration().is_positive())
- return;
- DecodeTimestamp last_dts = buffers->back()->GetDecodeTimestamp();
- DCHECK(current_dts >= last_dts);
- buffers->back()->set_duration(current_dts - last_dts);
- }
- // StringToBufferQueue() allows for the generation of StreamParserBuffers from
- // coded strings of timestamps separated by spaces.
- //
- // Supported syntax (options must be in this order):
- // pp[u][|dd[u]][Dzz][E][P][K]
- //
- // pp:
- // Generates a StreamParserBuffer with decode and presentation timestamp xx.
- // E.g., "0 1 2 3".
- // pp is interpreted as milliseconds, unless suffixed with "u", in which case
- // pp is interpreted as microseconds.
- //
- // pp|dd:
- // Generates a StreamParserBuffer with presentation timestamp pp and decode
- // timestamp dd. E.g., "0|0 3|1 1|2 2|3". dd is interpreted as milliseconds,
- // unless suffixed with "u", in which case dd is interpreted as microseconds.
- //
- // Dzz[u]
- // Explicitly describe the duration of the buffer. zz specifies the duration
- // in milliseconds (or in microseconds if suffixed with "u"). If the duration
- // isn't specified with this syntax, the duration is derived using the
- // timestamp delta between this buffer and the next buffer. If not specified,
- // the final buffer will simply copy the duration of the previous buffer. If
- // the queue only contains 1 buffer then the duration must be explicitly
- // specified with this format.
- // E.g. "0D10 10D20"
- //
- // E:
- // Indicates that the buffer should be marked as containing an *estimated*
- // duration. E.g., "0D20E 20 25E 30"
- //
- // P:
- // Indicates the buffer with will also have a preroll buffer
- // associated with it. The preroll buffer will just be dummy data.
- // E.g. "0P 5 10"
- //
- // K:
- // Indicates the buffer is a keyframe. E.g., "0K 1|2K 2|4D2K 6 8".
- BufferQueue StringToBufferQueue(const std::string& buffers_to_append) {
- std::vector<std::string> timestamps = base::SplitString(
- buffers_to_append, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- CHECK_GT(timestamps.size(), 0u);
- BufferQueue buffers;
- for (size_t i = 0; i < timestamps.size(); i++) {
- bool is_keyframe = false;
- bool has_preroll = false;
- bool is_duration_estimated = false;
- if (base::EndsWith(timestamps[i], "K", base::CompareCase::SENSITIVE)) {
- is_keyframe = true;
- // Remove the "K" off of the token.
- timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
- }
- // Handle preroll buffers.
- if (base::EndsWith(timestamps[i], "P", base::CompareCase::SENSITIVE)) {
- is_keyframe = true;
- has_preroll = true;
- // Remove the "P" off of the token.
- timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
- }
- if (base::EndsWith(timestamps[i], "E", base::CompareCase::SENSITIVE)) {
- is_duration_estimated = true;
- // Remove the "E" off of the token.
- timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
- }
- int duration_in_us = -1;
- size_t duration_pos = timestamps[i].find('D');
- if (duration_pos != std::string::npos) {
- bool is_duration_us = false; // Default to millisecond interpretation.
- if (base::EndsWith(timestamps[i], "u", base::CompareCase::SENSITIVE)) {
- is_duration_us = true;
- timestamps[i] = timestamps[i].substr(0, timestamps[i].length() - 1);
- }
- CHECK(base::StringToInt(timestamps[i].substr(duration_pos + 1),
- &duration_in_us));
- if (!is_duration_us)
- duration_in_us *= base::Time::kMicrosecondsPerMillisecond;
- timestamps[i] = timestamps[i].substr(0, duration_pos);
- }
- std::vector<std::string> buffer_timestamp_strings = base::SplitString(
- timestamps[i], "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (buffer_timestamp_strings.size() == 1)
- buffer_timestamp_strings.push_back(buffer_timestamp_strings[0]);
- CHECK_EQ(2u, buffer_timestamp_strings.size());
- std::vector<base::TimeDelta> buffer_timestamps;
- // Parse PTS, then DTS into TimeDeltas.
- for (size_t j = 0; j < 2; ++j) {
- int us = 0;
- bool is_us = false; // Default to millisecond interpretation.
- if (base::EndsWith(buffer_timestamp_strings[j], "u",
- base::CompareCase::SENSITIVE)) {
- is_us = true;
- buffer_timestamp_strings[j] = buffer_timestamp_strings[j].substr(
- 0, buffer_timestamp_strings[j].length() - 1);
- }
- CHECK(base::StringToInt(buffer_timestamp_strings[j], &us));
- if (!is_us)
- us *= base::Time::kMicrosecondsPerMillisecond;
- buffer_timestamps.push_back(base::Microseconds(us));
- }
- // Create buffer. Track ID is meaningless to these tests
- scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom(
- &kDataA, kDataSize, is_keyframe, GetStreamType(), 0);
- buffer->set_timestamp(buffer_timestamps[0]);
- if (is_duration_estimated)
- buffer->set_is_duration_estimated(true);
- if (buffer_timestamps[1] != buffer_timestamps[0]) {
- buffer->SetDecodeTimestamp(
- DecodeTimestamp::FromPresentationTime(buffer_timestamps[1]));
- }
- if (duration_in_us >= 0)
- buffer->set_duration(base::Microseconds(duration_in_us));
- // Simulate preroll buffers by just generating another buffer and sticking
- // it as the preroll.
- if (has_preroll) {
- scoped_refptr<StreamParserBuffer> preroll_buffer =
- StreamParserBuffer::CopyFrom(&kDataA, kDataSize, is_keyframe,
- GetStreamType(), 0);
- preroll_buffer->set_duration(frame_duration_);
- buffer->SetPrerollBuffer(preroll_buffer);
- }
- UpdateLastBufferDuration(buffer->GetDecodeTimestamp(), &buffers);
- buffers.push_back(buffer);
- }
- // If the last buffer doesn't have a duration, assume it is the
- // same as the second to last buffer.
- if (buffers.size() >= 2 && buffers.back()->duration() == kNoTimestamp) {
- buffers.back()->set_duration(
- buffers[buffers.size() - 2]->duration());
- }
- return buffers;
- }
- void AppendBuffers(const std::string& buffers_to_append,
- bool start_new_coded_frame_group,
- base::TimeDelta coded_frame_group_start_timestamp,
- bool one_by_one) {
- BufferQueue buffers = StringToBufferQueue(buffers_to_append);
- if (start_new_coded_frame_group) {
- base::TimeDelta start_timestamp = coded_frame_group_start_timestamp;
- base::TimeDelta buffers_start_timestamp = buffers[0]->timestamp();
- if (start_timestamp == kNoTimestamp)
- start_timestamp = buffers_start_timestamp;
- else
- ASSERT_TRUE(start_timestamp <= buffers_start_timestamp);
- stream_->OnStartOfCodedFrameGroup(start_timestamp);
- }
- if (!one_by_one) {
- stream_->Append(buffers);
- return;
- }
- // Append each buffer one by one.
- for (size_t i = 0; i < buffers.size(); i++) {
- BufferQueue wrapper;
- wrapper.push_back(buffers[i]);
- stream_->Append(wrapper);
- }
- }
- int frames_per_second_;
- int keyframes_per_second_;
- base::TimeDelta frame_duration_;
- };
- TEST_F(SourceBufferStreamTest, Append_SingleRange) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 14);
- }
- TEST_F(SourceBufferStreamTest, Append_SingleRange_OneBufferAtATime) {
- // Append 15 buffers starting at position 0, one buffer at a time.
- NewCodedFrameGroupAppend(0, 1);
- for (int i = 1; i < 15; i++)
- AppendBuffers(i, 1);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 14);
- }
- TEST_F(SourceBufferStreamTest, Append_DisjointRanges) {
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 5);
- // Append 10 buffers at positions 15 through 24.
- NewCodedFrameGroupAppend(15, 10);
- // Check expected ranges.
- CheckExpectedRanges("{ [0,4) [15,24) }");
- // Check buffers in ranges.
- Seek(0);
- CheckExpectedBuffers(0, 4);
- Seek(15);
- CheckExpectedBuffers(15, 24);
- }
- TEST_F(SourceBufferStreamTest, Append_AdjacentRanges) {
- // Append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10);
- // Append 11 buffers at positions 15 through 25.
- NewCodedFrameGroupAppend(15, 11);
- // Append 5 buffers at positions 10 through 14 to bridge the gap.
- NewCodedFrameGroupAppend(10, 5);
- // Check expected range.
- CheckExpectedRanges("{ [0,25) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 25);
- }
- TEST_F(SourceBufferStreamTest, Complete_Overlap) {
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5);
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 14);
- }
- TEST_F(SourceBufferStreamTest,
- Complete_Overlap_AfterGroupTimestampAndBeforeFirstBufferTimestamp) {
- // Append a coded frame group with a start timestamp of 0, but the first
- // buffer starts at 30ms. This can happen in muxed content where the
- // audio starts before the first frame.
- NewCodedFrameGroupAppend(base::Milliseconds(0), "30K 60K 90K 120K");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Completely overlap the old buffers, with a coded frame group that starts
- // after the old coded frame group start timestamp, but before the timestamp
- // of the first buffer in the coded frame group.
- NewCodedFrameGroupAppend("20K 50K 80K 110D10K");
- // Verify that the buffered ranges are updated properly and we don't crash.
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("20K 50K 80K 110K 120K");
- }
- TEST_F(SourceBufferStreamTest, Complete_Overlap_EdgeCase) {
- // Make each frame a keyframe so that it's okay to overlap frames at any point
- // (instead of needing to respect keyframe boundaries).
- SetStreamInfo(30, 30);
- // Append 6 buffers at positions 6 through 11.
- NewCodedFrameGroupAppend(6, 6);
- // Append 8 buffers at positions 5 through 12.
- NewCodedFrameGroupAppend(5, 8);
- // Check expected range.
- CheckExpectedRanges("{ [5,12) }");
- // Check buffers in range.
- Seek(5);
- CheckExpectedBuffers(5, 12);
- }
- TEST_F(SourceBufferStreamTest, Start_Overlap) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 5);
- // Append 6 buffers at positions 10 through 15.
- NewCodedFrameGroupAppend(10, 6);
- // Check expected range.
- CheckExpectedRanges("{ [5,15) }");
- // Check buffers in range.
- Seek(5);
- CheckExpectedBuffers(5, 15);
- }
- TEST_F(SourceBufferStreamTest, End_Overlap) {
- // Append 10 buffers at positions 10 through 19.
- NewCodedFrameGroupAppend(10, 10);
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10);
- // Check expected range.
- CheckExpectedRanges("{ [5,19) }");
- // Check buffers in range.
- Seek(5);
- CheckExpectedBuffers(5, 19);
- }
- // Using position based test API:
- // DTS : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
- // PTS : 0 4 1 2 3 5 9 6 7 8 10 14 11 12 13 15 19 16 17 18 20
- // old : A a a a a A a a a a
- // new : B b b b b B b b
- // after: B b b b b B b b A a a a a
- TEST_F(SourceBufferStreamTest, End_Overlap_Several) {
- // Append 10 buffers at positions 10 through 19 (DTS and PTS).
- NewCodedFrameGroupAppend(10, 10, &kDataA);
- // Append 8 buffers at positions 5 through 12 (DTS); 5 through 14 (PTS) with
- // partial second GOP.
- NewCodedFrameGroupAppend(5, 8, &kDataB);
- // Check expected ranges: stream should not have kept buffers at DTS 13,14;
- // PTS 12,13 because the keyframe on which they depended (10, PTS=DTS) was
- // overwritten. Note that partial second GOP of B includes PTS [10,14), DTS
- // [10,12). These are continuous with the overlapped original range's next GOP
- // at (15, PTS=DTS).
- // Unlike the rest of the position based test API used in this case, these
- // range expectation strings are the actual timestamps (divided by
- // frame_duration_).
- CheckExpectedRanges("{ [5,19) }");
- // Check buffers in range.
- Seek(5);
- CheckExpectedBuffers(5, 12, &kDataB);
- // No seek is necessary (1 continuous range).
- CheckExpectedBuffers(15, 19, &kDataA);
- CheckNoNextBuffer();
- }
- // Test an end overlap edge case where a single buffer overlaps the
- // beginning of a range.
- // old : 0K 30 60 90 120K 150
- // new : 0K
- // after: 0K 120K 150
- // track:
- TEST_F(SourceBufferStreamTest, End_Overlap_SingleBuffer) {
- // Seek to start of stream.
- SeekToTimestampMs(0);
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- NewCodedFrameGroupAppend("0D30K");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- CheckExpectedBuffers("0K 120K 150");
- CheckNoNextBuffer();
- }
- // Using position based test API:
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A a A a A a
- // new : B b b b b B b b b b B b b b b B b b b b B b b b b B b b b b
- // after == new
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Several) {
- // Append 2 buffers at positions 5 through 6 (DTS); 5 through 9 (PTS) partial
- // GOP.
- NewCodedFrameGroupAppend(5, 2, &kDataA);
- // Append 2 buffers at positions 15 through 16 (DTS); 15 through 19 (PTS)
- // partial GOP.
- NewCodedFrameGroupAppend(15, 2, &kDataA);
- // Append 2 buffers at positions 25 through 26 (DTS); 25 through 29 (PTS)
- // partial GOP.
- NewCodedFrameGroupAppend(25, 2, &kDataA);
- // Check expected ranges. Unlike the rest of the position based test API used
- // in this case, these range expectation strings are the actual timestamps
- // (divided by frame_duration_).
- CheckExpectedRanges("{ [5,9) [15,19) [25,29) }");
- // Append buffers at positions 0 through 29 (DTS and PTS).
- NewCodedFrameGroupAppend(0, 30, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,29) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 29, &kDataB);
- }
- // Using position based test API:
- // DTS:0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
- // PTS:0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9
- // old: A a A a A a A a
- // new:B b b b b B b b b b B b b b b B b b b b B b b b b B b b b b B b b b b
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Several_Then_Merge) {
- // Append 2 buffers at positions 5 through 6 (DTS); 5 through 9 (PTS) partial
- // GOP.
- NewCodedFrameGroupAppend(5, 2, &kDataA);
- // Append 2 buffers at positions 10 through 11 (DTS); 15 through 19 (PTS)
- // partial GOP.
- NewCodedFrameGroupAppend(15, 2, &kDataA);
- // Append 2 buffers at positions 25 through 26 (DTS); 25 through 29 (PTS)
- // partial GOP.
- NewCodedFrameGroupAppend(25, 2, &kDataA);
- // Append 2 buffers at positions 35 through 36 (DTS); 35 through 39 (PTS)
- // partial GOP.
- NewCodedFrameGroupAppend(35, 2, &kDataA);
- // Append buffers at positions 0 through 34 (DTS and PTS).
- NewCodedFrameGroupAppend(0, 35, &kDataB);
- // Check expected ranges. Unlike the rest of the position based test API used
- // in this case, these range expectation strings are the actual timestamps
- // (divided by frame_duration_).
- CheckExpectedRanges("{ [0,39) }");
- // Check buffers in range.
- Seek(0);
- CheckExpectedBuffers(0, 34, &kDataB);
- CheckExpectedBuffers(35, 36, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to buffer at position 5.
- Seek(5);
- // Replace old data with new data.
- NewCodedFrameGroupAppend(5, 10, &kDataB);
- // Check ranges are correct.
- CheckExpectedRanges("{ [5,14) }");
- // Check that data has been replaced with new data.
- CheckExpectedBuffers(5, 14, &kDataB);
- }
- // This test is testing that a client can append data to SourceBufferStream that
- // overlaps the range from which the client is currently grabbing buffers. We
- // would expect that the SourceBufferStream would return old data until it hits
- // the keyframe of the new data, after which it will return the new data.
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_TrackBuffer) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to buffer at position 5 and get next buffer.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Do a complete overlap by appending 20 buffers at positions 0 through 19.
- NewCodedFrameGroupAppend(0, 20, &kDataB);
- // Check range is correct.
- CheckExpectedRanges("{ [0,19) }");
- // Expect old data up until next keyframe in new data.
- CheckExpectedBuffers(6, 9, &kDataA);
- CheckExpectedBuffers(10, 10, &kDataB, true);
- // Expect rest of data to be new.
- CheckExpectedBuffers(11, 19, &kDataB);
- // Seek back to beginning; all data should be new.
- Seek(0);
- CheckExpectedBuffers(0, 19, &kDataB);
- // Check range continues to be correct.
- CheckExpectedRanges("{ [0,19) }");
- }
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_EdgeCase) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to buffer at position 5 and get next buffer.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Replace existing data with new data.
- NewCodedFrameGroupAppend(5, 10, &kDataB);
- // Check ranges are correct.
- CheckExpectedRanges("{ [5,14) }");
- // Expect old data up until next keyframe in new data.
- CheckExpectedBuffers(6, 9, &kDataA);
- CheckExpectedBuffers(10, 10, &kDataB, true);
- // Expect rest of data to be new.
- CheckExpectedBuffers(11, 14, &kDataB);
- // Seek back to beginning; all data should be new.
- Seek(5);
- CheckExpectedBuffers(5, 14, &kDataB);
- // Check range continues to be correct.
- CheckExpectedRanges("{ [5,14) }");
- }
- TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_Multiple) {
- static const uint8_t kDataC = 0x55;
- static const uint8_t kDataD = 0x77;
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataA);
- // Seek to buffer at position 5 and get next buffer.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Replace existing data with new data.
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Then replace it again with different data.
- NewCodedFrameGroupAppend(5, 5, &kDataC);
- // Now append 5 new buffers at positions 10 through 14.
- NewCodedFrameGroupAppend(10, 5, &kDataC);
- // Now replace all the data entirely.
- NewCodedFrameGroupAppend(5, 10, &kDataD);
- // Expect buffers 6 through 9 to be DataA, and the remaining
- // buffers to be kDataD.
- CheckExpectedBuffers(6, 9, &kDataA);
- CheckExpectedBuffers(10, 14, &kDataD);
- // At this point we cannot fulfill request.
- CheckNoNextBuffer();
- // Seek back to beginning; all data should be new.
- Seek(5);
- CheckExpectedBuffers(5, 14, &kDataD);
- }
- TEST_F(SourceBufferStreamTest, Start_Overlap_Selected) {
- // Append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataA);
- // Seek to position 5, then add buffers to overlap data at that position.
- Seek(5);
- NewCodedFrameGroupAppend(5, 10, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Because we seeked to a keyframe, the next buffers should all be new data.
- CheckExpectedBuffers(5, 14, &kDataB);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 4, &kDataA);
- CheckExpectedBuffers(5, 14, &kDataB);
- }
- TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_TrackBuffer) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15, &kDataA);
- // Seek to 10 and get buffer.
- Seek(10);
- CheckExpectedBuffers(10, 10, &kDataA);
- // Now append 10 buffers of new data at positions 10 through 19.
- NewCodedFrameGroupAppend(10, 10, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,19) }");
- // The next 4 buffers should be a from the old buffer, followed by a keyframe
- // from the new data.
- CheckExpectedBuffers(11, 14, &kDataA);
- CheckExpectedBuffers(15, 15, &kDataB, true);
- // The rest of the buffers should be new data.
- CheckExpectedBuffers(16, 19, &kDataB);
- // Now seek to the beginning; positions 0 through 9 should be the original
- // data, positions 10 through 19 should be the new data.
- Seek(0);
- CheckExpectedBuffers(0, 9, &kDataA);
- CheckExpectedBuffers(10, 19, &kDataB);
- // Make sure range is still correct.
- CheckExpectedRanges("{ [0,19) }");
- }
- TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_EdgeCase) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- Seek(10);
- CheckExpectedBuffers(10, 10, &kDataA);
- // Now replace the last 5 buffers with new data.
- NewCodedFrameGroupAppend(10, 5, &kDataB);
- // The next 4 buffers should be the origial data, held in the track buffer.
- CheckExpectedBuffers(11, 14, &kDataA);
- // The next buffer is at position 15, so we should fail to fulfill the
- // request.
- CheckNoNextBuffer();
- // Now append data at 15 through 19 and check to make sure it's correct.
- NewCodedFrameGroupAppend(15, 5, &kDataB);
- CheckExpectedBuffers(15, 19, &kDataB);
- // Seek to beginning of buffered range and check buffers.
- Seek(5);
- CheckExpectedBuffers(5, 9, &kDataA);
- CheckExpectedBuffers(10, 19, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [5,19) }");
- }
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer is a keyframe that's being overlapped by new
- // buffers.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : *A*a a a a A a a a a
- // new : B b b b b B b b b b
- // after: B b b b b*B*b b b b A a a a a
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 5.
- Seek(5);
- // Now append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Because we seeked to a keyframe, the next buffers should be new.
- CheckExpectedBuffers(5, 9, &kDataB);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 9, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- }
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is after the newly appended buffers.
- //
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : |A a a a a A a a*a*a|
- // new : B b b b b B b b b b
- // after: |B b b b b B b b b b A a a*a*a|
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_1) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 10, then move to position 13.
- Seek(10);
- CheckExpectedBuffers(10, 12, &kDataA);
- // Now append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Make sure rest of data is as expected.
- CheckExpectedBuffers(13, 14, &kDataA);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 9, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- }
- // Using position based test API:
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is after the newly appended buffers.
- //
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A a a a a A a a*a*a
- // new : B b b b b B b b
- // after: B b b b b B b b A a a*a*a
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_2) {
- // Append 10 buffers at positions 5 through 14 (DTS and PTS, 2 full GOPs)
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 10, then move to position 13.
- Seek(10);
- CheckExpectedBuffers(10, 12, &kDataA);
- // Now append 8 buffers at positions 0 through 7 (DTS); 0 through 9 (PTS) with
- // partial second GOP.
- NewCodedFrameGroupAppend(0, 8, &kDataB);
- // Check expected ranges: stream should not have kept buffers at DTS 8,9;
- // PTS 7,8 because the keyframe on which they depended (5, PTS=DTS) was
- // overwritten. Note that partial second GOP of B includes PTS [5,9), DTS
- // [5,7). These are continuous with the overlapped original range's next GOP
- // at (10, PTS=DTS).
- // Unlike the rest of the position based test API used in this case, these
- // range expectation strings are the actual timestamps (divided by
- // frame_duration_).
- CheckExpectedRanges("{ [0,14) }");
- // Make sure rest of data is as expected.
- CheckExpectedBuffers(13, 14, &kDataA);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 7, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // Using position based test API:
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is after the newly appended buffers.
- //
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A a a*a*a A a a a a
- // new : B b b b b B b b
- // after: B b b b b B b b A a a a a
- // track: a a
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_3) {
- // Append 10 buffers at positions 5 through 14 (DTS and PTS, 2 full GOPs)
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 5, then move to position 8.
- Seek(5);
- CheckExpectedBuffers(5, 7, &kDataA);
- // Now append 8 buffers at positions 0 through 7 (DTS); 0 through 9 (PTS) with
- // partial second GOP.
- NewCodedFrameGroupAppend(0, 8, &kDataB);
- // Check expected ranges: stream should not have kept buffers at DTS 8,9;
- // PTS 7,8 because the keyframe on which they depended (5, PTS=DTS) was
- // overwritten. However, they were in the GOP being read from, so were put
- // into the track buffer. Note that partial second GOP of B includes PTS
- // [5,9), DTS [5,7). These are continuous with the overlapped original range's
- // next GOP at (10, PTS=DTS).
- // Unlike the rest of the position based test API used in this case, these
- // range expectation strings are the actual timestamps (divided by
- // frame_duration_).
- CheckExpectedRanges("{ [0,14) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(8, 9, &kDataA);
- // The buffer immediately after the track buffer should be a keyframe.
- CheckExpectedBuffers(10, 10, &kDataA, true);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 7, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is overlapped by the new buffers.
- //
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : |A a a*a*a A a a a a|
- // new : B b b b b B b b b b
- // after: |B b b b b B b b b b A a a a a|
- // track: |a a|
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_1) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 5, then move to position 8.
- Seek(5);
- CheckExpectedBuffers(5, 7, &kDataA);
- // Now append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(8, 9, &kDataA);
- // The buffer immediately after the track buffer should be a keyframe.
- CheckExpectedBuffers(10, 10, &kDataA, true);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 9, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- }
- // Using position based test API:
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is overlapped by the new buffers.
- //
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A*a*a a a A a a a a
- // new : B b b b b B b
- // after: B b b b b B b A a a a a
- // track: a a a a
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_2) {
- // Append 10 buffers at positions 5 through 14 (PTS and DTS, 2 full GOPs).
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to position 5, then move to position 6.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Now append 7 buffers at positions 0 through 6 (DTS); 0 through 9 (PTS) with
- // partial second GOP.
- NewCodedFrameGroupAppend(0, 7, &kDataB);
- // Check expected ranges: stream should not have kept buffers at DTS 7,8,9;
- // PTS 6,7,8 because the keyframe on which they depended (5, PTS=DTS) was
- // overwritten. However, they were in the GOP being read from, so were put
- // into the track buffer. Note that partial second GOP of B includes PTS
- // [5,9), DTS [5,6). These are continuous with the overlapped original range's
- // next GOP at (10, PTS=DTS).
- // Unlike the rest of the position based test API used in this case, these
- // range expectation strings are the actual timestamps (divided by
- // frame_duration_).
- CheckExpectedRanges("{ [0,14) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(6, 9, &kDataA);
- // The buffer immediately after the track buffer should be a keyframe.
- CheckExpectedBuffers(10, 10, &kDataA, true);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 6, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // Using position based test API:
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next buffer in the range is overlapped by the new buffers.
- // In this particular case, the next keyframe after the track buffer is in the
- // range with the new buffers.
- //
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A*a*a a a A a a a a A a a a a
- // new : B b b b b B b b b b B
- // after: B b b b b B b b b b B A a a a a
- // track: a a a a
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_3) {
- // Append 15 buffers at positions 5 through 19 (PTS and DTS, 3 full GOPs).
- NewCodedFrameGroupAppend(5, 15, &kDataA);
- // Seek to position 5, then move to position 6.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Now append 11 buffers at positions 0 through 10 (PTS and DTS, 2 full GOPs
- // and just the keyframe of a third GOP).
- NewCodedFrameGroupAppend(0, 11, &kDataB);
- // Check expected ranges: stream should not have kept buffers at 11-14 (DTS
- // and PTS) because the keyframe on which they depended (10, PTS=DTS) was
- // overwritten. The GOP being read from was overwritten, so track buffer
- // should contain DTS 6-9 (PTS 9,6,7,8). Note that the partial third GOP of B
- // includes (10, PTS=DTS). This partial GOP is continuous with the overlapped
- // original range's next GOP at (15, PTS=DTS).
- // Unlike the rest of the position based test API used in this case, these
- // range expectation strings are the actual timestamps (divided by
- // frame_duration_).
- CheckExpectedRanges("{ [0,19) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(6, 9, &kDataA);
- // The buffer immediately after the track buffer should be a keyframe
- // from the new data.
- CheckExpectedBuffers(10, 10, &kDataB, true);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 10, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(15, 19, &kDataA);
- }
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and there is no keyframe after the end of the new buffers.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : |A*a*a a a|
- // new : B b b b b B
- // after: |B b b b b B|
- // track: |a a a a|
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew) {
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataA);
- // Seek to position 5, then move to position 6.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Now append 6 buffers at positions 0 through 5.
- NewCodedFrameGroupAppend(0, 6, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,5) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(6, 9, &kDataA);
- // Now there's no data to fulfill the request.
- CheckNoNextBuffer();
- // Let's fill in the gap, buffers 6 through 10.
- AppendBuffers(6, 5, &kDataB);
- // We should be able to get the next buffer.
- CheckExpectedBuffers(10, 10, &kDataB);
- }
- // Using position based test API:
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and there is no keyframe after the end of the new buffers, then more
- // buffers end-overlap the beginning.
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0
- // old : A a a a a A*a*
- // new : B b b b b B b b b b B
- // after: B b b b b B b b b b B
- // new : A a a a a A
- // after: A a a a a A B b b b b B
- // track: a
- // new : B b b b b B
- // after: A a a a a A B b b b b B b b b b B
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew2) {
- // Append 7 buffers at positions 10 through 16 (DTS); 10 through 19 (PTS) with
- // a partial second GOP.
- NewCodedFrameGroupAppend(10, 7, &kDataA);
- // Seek to position 15, then move to position 16.
- Seek(15);
- CheckExpectedBuffers(15, 15, &kDataA);
- // Now append 11 buffers at positions 5 through 15 (PTS and DTS), 2 full GOPs
- // and just the keyframe of a third GOP.
- NewCodedFrameGroupAppend(5, 11, &kDataB);
- // Check expected ranges: stream should not have kept buffer at DTS 16, PTS 19
- // because the keyframe it depended on (15, PTS=DTS) was overwritten.
- // The GOP being read from was overwritten, so track buffer
- // should contain DTS 16, PTS 19.
- // Unlike the rest of the position based test API used in this case,
- // CheckExpectedRanges() uses expectation strings containing actual timestamps
- // (divided by frame_duration_).
- CheckExpectedRanges("{ [5,15) }");
- // Now do another end-overlap. Append one full GOP plus keyframe of 2nd. Note
- // that this new keyframe at (5, PTS=DTS) is continuous with the overlapped
- // range's next GOP (B) at (10, PTS=DTS).
- NewCodedFrameGroupAppend(0, 6, &kDataA);
- CheckExpectedRanges("{ [0,15) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(16, 16, &kDataA);
- // Now there's no data to fulfill the request.
- CheckNoNextBuffer();
- // Add data to the end of the range in the position just read from the track
- // buffer. The stream should not be able to fulfill the next read
- // until we've added a keyframe continuous beyond this point.
- NewCodedFrameGroupAppend(15, 1, &kDataB);
- CheckNoNextBuffer();
- for (int i = 16; i <= 19; i++) {
- AppendBuffers(i, 1, &kDataB);
- CheckNoNextBuffer();
- }
- // Now append a keyframe at PTS=DTS=20.
- AppendBuffers(20, 1, &kDataB);
- // The buffer at position 16 (PTS 19) in track buffer is adjacent to the next
- // keyframe, so no warning should be emitted on that track buffer exhaustion.
- // We should be able to get the next buffer (no longer from the track buffer).
- CheckExpectedBuffers(20, 20, &kDataB, true);
- CheckNoNextBuffer();
- // Make sure all data is correct.
- CheckExpectedRanges("{ [0,20) }");
- Seek(0);
- CheckExpectedBuffers(0, 5, &kDataA);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 20, &kDataB);
- CheckNoNextBuffer();
- }
- // This test covers the case where new buffers end-overlap an existing, selected
- // range, and the next keyframe in a separate range.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : |A*a*a a a| |A a a a a|
- // new : B b b b b B
- // after: |B b b b b B| |A a a a a|
- // track: |a a a a|
- TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew3) {
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataA);
- // Append 5 buffers at positions 15 through 19.
- NewCodedFrameGroupAppend(15, 5, &kDataA);
- // Check expected range.
- CheckExpectedRanges("{ [5,9) [15,19) }");
- // Seek to position 5, then move to position 6.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Now append 6 buffers at positions 0 through 5.
- NewCodedFrameGroupAppend(0, 6, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,5) [15,19) }");
- // Check for data in the track buffer.
- CheckExpectedBuffers(6, 9, &kDataA);
- // Now there's no data to fulfill the request.
- CheckNoNextBuffer();
- // Let's fill in the gap, buffers 6 through 14.
- AppendBuffers(6, 9, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,19) }");
- // We should be able to get the next buffer.
- CheckExpectedBuffers(10, 14, &kDataB);
- // We should be able to get the next buffer.
- CheckExpectedBuffers(15, 19, &kDataA);
- }
- // This test covers the case when new buffers overlap the middle of a selected
- // range. This tests the case when there is precise overlap of an existing GOP,
- // and the next buffer is a keyframe.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : A a a a a*A*a a a a A a a a a
- // new : B b b b b
- // after: A a a a a*B*b b b b A a a a a
- TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_1) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15, &kDataA);
- // Seek to position 5.
- Seek(5);
- // Now append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Check for next data; should be new data.
- CheckExpectedBuffers(5, 9, &kDataB);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 4, &kDataA);
- CheckExpectedBuffers(5, 9, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // This test covers the case when new buffers overlap the middle of a selected
- // range. This tests the case when there is precise overlap of an existing GOP,
- // and the next buffer is a non-keyframe in a GOP after the new buffers.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : A a a a a A a a a a A*a*a a a
- // new : B b b b b
- // after: A a a a a B b b b b A*a*a a a
- TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_2) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15, &kDataA);
- // Seek to 10 then move to position 11.
- Seek(10);
- CheckExpectedBuffers(10, 10, &kDataA);
- // Now append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Make sure data is correct.
- CheckExpectedBuffers(11, 14, &kDataA);
- CheckNoNextBuffer();
- Seek(0);
- CheckExpectedBuffers(0, 4, &kDataA);
- CheckExpectedBuffers(5, 9, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // This test covers the case when new buffers overlap the middle of a selected
- // range. This tests the case when only a partial GOP is appended, that append
- // is merged into the overlapped range, and the next buffer is before the new
- // buffers.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : A a*a*a a A a a a a A a a a a
- // new : B
- // after: A a*a*a a B A a a a a
- TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_3) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15, &kDataA);
- // Seek to beginning then move to position 2.
- Seek(0);
- CheckExpectedBuffers(0, 1, &kDataA);
- // Now append 1 buffer at position 5 (just the keyframe of a GOP).
- NewCodedFrameGroupAppend(5, 1, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Make sure data is correct.
- CheckExpectedBuffers(2, 4, &kDataA);
- CheckExpectedBuffers(5, 5, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- // Seek to the beginning and recheck data in case track buffer erroneously
- // became involved.
- Seek(0);
- CheckExpectedBuffers(0, 4, &kDataA);
- CheckExpectedBuffers(5, 5, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- // This test covers the case when new buffers overlap the middle of a selected
- // range. This tests the case when only a partial GOP is appended, and the next
- // buffer is after the new buffers, and comes from the track buffer until the
- // next GOP in the original buffers.
- // index: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
- // old : A a a a a A a a*a*a A a a a a
- // new : B
- // after: A a a a a B A a a a a
- // track: a a
- TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_4) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15, &kDataA);
- // Seek to 5 then move to position 8.
- Seek(5);
- CheckExpectedBuffers(5, 7, &kDataA);
- // Now append 1 buffer at position 5.
- NewCodedFrameGroupAppend(5, 1, &kDataB);
- // Check expected range.
- CheckExpectedRanges("{ [0,14) }");
- // Buffers 8 and 9 should be in the track buffer.
- CheckExpectedBuffers(8, 9, &kDataA);
- // The buffer immediately after the track buffer should be a keyframe.
- CheckExpectedBuffers(10, 10, &kDataA, true);
- // Make sure all data is correct.
- Seek(0);
- CheckExpectedBuffers(0, 4, &kDataA);
- CheckExpectedBuffers(5, 5, &kDataB);
- // No seek should be necessary (1 continuous range).
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne) {
- // Append 5 buffers starting at 10ms, 30ms apart.
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100 130");
- // The range ends at 160, accounting for the last buffer's duration.
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Overlap with 10 buffers starting at the beginning, appended one at a
- // time.
- NewCodedFrameGroupAppend(0, 1, &kDataB);
- for (int i = 1; i < 10; i++)
- AppendBuffers(i, 1, &kDataB);
- // All data should be replaced.
- Seek(0);
- CheckExpectedRanges("{ [0,9) }");
- CheckExpectedBuffers(0, 9, &kDataB);
- }
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_DeleteGroup) {
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100 130K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Seek to 130ms.
- SeekToTimestampMs(130);
- // Overlap with a new coded frame group from 0 to 130ms.
- NewCodedFrameGroupAppendOneByOne("0K 120D10");
- // Next buffer should still be 130ms.
- CheckExpectedBuffers("130K");
- // Check the final buffers is correct.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 120 130K");
- }
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_BetweenCodedFrameGroups) {
- // Append 5 buffers starting at 110ms, 30ms apart.
- NewCodedFrameGroupAppendOneByOne("110K 140 170 200 230");
- CheckExpectedRangesByTimestamp("{ [110,260) }");
- // Now append 2 coded frame groups from 0ms to 210ms, 30ms apart. Note that
- // the
- // old keyframe 110ms falls in between these two groups.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90");
- NewCodedFrameGroupAppendOneByOne("120K 150 180 210");
- CheckExpectedRangesByTimestamp("{ [0,240) }");
- // Check the final buffers is correct; the keyframe at 110ms should be
- // deleted.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 30 60 90 120K 150 180 210");
- }
- // old : 10K 40 *70* 100K 125 130K
- // new : 0K 30 60 90 120K
- // after: 0K 30 60 90 *120K* 130K
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer) {
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(50));
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K 125 130D30K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 130ms.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120D10K");
- CheckExpectedRangesByTimestamp("{ [0,160) }");
- // Should return frame 70ms from the track buffer, then switch
- // to the new data at 120K, then switch back to the old data at 130K. The
- // frame at 125ms that depended on keyframe 100ms should have been deleted.
- CheckExpectedBuffers("70 120K 130K");
- // Check the final result: should not include data from the track buffer.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 30 60 90 120K 130K");
- }
- // Overlap the next keyframe after the end of the track buffer with a new
- // keyframe.
- // old : 10K 40 *70* 100K 125 130K
- // new : 0K 30 60 90 120K
- // after: 0K 30 60 90 *120K* 130K
- // track: 70
- // new : 110K 130
- // after: 0K 30 60 90 *110K* 130
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer2) {
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(40));
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K 125 130D30K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms; 70ms and 100ms go in
- // track
- // buffer.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120D10K");
- CheckExpectedRangesByTimestamp("{ [0,160) }");
- // Now overlap the keyframe at 120ms.
- NewCodedFrameGroupAppendOneByOne("110K 130");
- // Should return frame 70ms from the track buffer. Then it should
- // return the keyframe after the track buffer, which is at 110ms.
- CheckExpectedBuffers("70 110K 130");
- }
- // Overlap the next keyframe after the end of the track buffer without a
- // new keyframe.
- // old : 10K 40 *70* 100K 125 130K
- // new : 0K 30 60 90 120K
- // after: 0K 30 60 90 *120K* 130K
- // track: 70
- // new : 50K 80 110 140
- // after: 0K 30 50K 80 110 140 * (waiting for keyframe)
- // track: 70
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer3) {
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(80));
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K 125 130D30K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms; 70ms goes in track
- // buffer.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120D10K");
- CheckExpectedRangesByTimestamp("{ [0,160) }");
- // Now overlap the keyframe at 120ms and 130ms.
- NewCodedFrameGroupAppendOneByOne("50K 80 110 140");
- CheckExpectedRangesByTimestamp("{ [0,170) }");
- // Should have all the buffers from the track buffer, then stall.
- CheckExpectedBuffers("70");
- CheckNoNextBuffer();
- // Appending a keyframe should fulfill the read.
- AppendBuffersOneByOne("150D30K");
- CheckExpectedBuffers("150K");
- CheckNoNextBuffer();
- }
- // Overlap the next keyframe after the end of the track buffer with a keyframe
- // that comes before the end of the track buffer.
- // old : 10K 40 *70* 100K 125 130K
- // new : 0K 30 60 90 120K
- // after: 0K 30 60 90 *120K* 130K
- // track: 70
- // new : 80K 110 140
- // after: 0K 30 60 *80K* 110 140
- // track: 70
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer4) {
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K 125 130D30K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms; 70ms and 100ms go in
- // track
- // buffer.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120D10K");
- CheckExpectedRangesByTimestamp("{ [0,160) }");
- // Now append a keyframe at 80ms.
- NewCodedFrameGroupAppendOneByOne("80K 110 140");
- CheckExpectedBuffers("70 80K 110 140");
- CheckNoNextBuffer();
- }
- // Overlap the next keyframe after the end of the track buffer with a keyframe
- // that comes before the end of the track buffer, when the selected stream was
- // waiting for the next keyframe.
- // old : 10K 40 *70* 100K
- // new : 0K 30 60 90 120
- // after: 0K 30 60 90 120 * (waiting for keyframe)
- // track: 70
- // new : 80K 110 140
- // after: 0K 30 60 *80K* 110 140
- // track: 70
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer5) {
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K");
- CheckExpectedRangesByTimestamp("{ [10,130) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms; 70ms goes in track
- // buffer.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Now append a keyframe at 80ms.
- NewCodedFrameGroupAppendOneByOne("80K 110 140");
- CheckExpectedBuffers("70 80K 110 140");
- CheckNoNextBuffer();
- }
- // Test that appending to a different range while there is data in
- // the track buffer doesn't affect the selected range or track buffer state.
- // old : 10K 40 *70* 100K 125 130K ... 200K 230
- // new : 0K 30 60 90 120K
- // after: 0K 30 60 90 *120K* 130K ... 200K 230
- // track: 70
- // old : 0K 30 60 90 *120K* 130K ... 200K 230
- // new : 260K 290
- // after: 0K 30 60 90 *120K* 130K ... 200K 230 260K 290
- // track: 70
- TEST_F(SourceBufferStreamTest, Overlap_OneByOne_TrackBuffer6) {
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(50));
- NewCodedFrameGroupAppendOneByOne("10K 40 70 100K 125 130D30K");
- NewCodedFrameGroupAppendOneByOne("200K 230");
- CheckExpectedRangesByTimestamp("{ [10,160) [200,260) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms.
- NewCodedFrameGroupAppendOneByOne("0K 30 60 90 120D10K");
- CheckExpectedRangesByTimestamp("{ [0,160) [200,260) }");
- // Verify that 70 gets read out of the track buffer.
- CheckExpectedBuffers("70");
- // Append more data to the unselected range.
- NewCodedFrameGroupAppendOneByOne("260K 290");
- CheckExpectedRangesByTimestamp("{ [0,160) [200,320) }");
- CheckExpectedBuffers("120K 130K");
- CheckNoNextBuffer();
- // Check the final result: should not include data from the track buffer.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 30 60 90 120K 130K");
- CheckNoNextBuffer();
- }
- // Test that overlap-appending with a GOP that begins with time of next track
- // buffer frame drops that track buffer frame and buffers the new GOP correctly.
- // append : 10K 40 70 100
- // read the first two buffers
- // after : 10K 40 *70* 100
- //
- // append : 0K 30 60 90 120
- // after : 0K 30 60 90 120
- // track : *70* 100
- //
- // read the buffer at 70ms from track
- // after : 0K 30 60 90 120
- // track : *100*
- //
- // append : 100K 130
- // after : 0K 30 60 90 *100K* 130
- // track : (empty)
- // 100K, not 100, should be the next buffer read.
- TEST_F(SourceBufferStreamTest,
- Overlap_That_Prunes_All_of_Previous_TrackBuffer) {
- NewCodedFrameGroupAppend("10K 40 70 100");
- CheckExpectedRangesByTimestamp("{ [10,130) }");
- // Seek to 70ms.
- SeekToTimestampMs(70);
- CheckExpectedBuffers("10K 40");
- // Overlap with a new coded frame group from 0 to 120ms, leaving the original
- // nonkeyframes at 70ms and 100ms in the track buffer.
- NewCodedFrameGroupAppend("0K 30 60 90 120");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Verify that 70 gets read out of the track buffer, leaving the nonkeyframe
- // at 100ms in the track buffer.
- CheckExpectedBuffers("70");
- // Overlap with a coded frame group having a keyframe at 100ms. This should
- // clear the track buffer and serve that keyframe, not the original
- // nonkeyframe at time 100ms on the next read call.
- NewCodedFrameGroupAppend("100K 130");
- CheckExpectedRangesByTimestamp("{ [0,160) }");
- CheckExpectedBuffers("100K 130");
- CheckNoNextBuffer();
- // Check the final result: should not include data from the track buffer.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 30 60 90 100K 130");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Seek_Keyframe) {
- // Append 6 buffers at positions 0 through 5.
- NewCodedFrameGroupAppend(0, 6);
- // Seek to beginning.
- Seek(0);
- CheckExpectedBuffers(0, 5, true);
- }
- TEST_F(SourceBufferStreamTest, Seek_NonKeyframe) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15);
- // Seek to buffer at position 13.
- Seek(13);
- // Expect seeking back to the nearest keyframe.
- CheckExpectedBuffers(10, 14, true);
- // Seek to buffer at position 3.
- Seek(3);
- // Expect seeking back to the nearest keyframe.
- CheckExpectedBuffers(0, 3, true);
- }
- TEST_F(SourceBufferStreamTest, Seek_NotBuffered) {
- // Seek to beginning.
- SeekToTimestampMs(0);
- // Try to get buffer; nothing's appended.
- CheckNoNextBuffer();
- // Append 1 buffer at time 0, duration 10ms.
- NewCodedFrameGroupAppend("0D10K");
- // Confirm we can read it back.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K");
- // Try to get buffer out of range.
- SeekToTimestampMs(10);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Seek_InBetweenTimestamps) {
- // Append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10);
- base::TimeDelta bump = frame_duration() / 4;
- CHECK(bump.is_positive());
- // Seek to buffer a little after position 5.
- stream_->Seek(5 * frame_duration() + bump);
- CheckExpectedBuffers(5, 5, true);
- // Seek to buffer a little before position 5.
- stream_->Seek(5 * frame_duration() - bump);
- CheckExpectedBuffers(0, 0, true);
- }
- // This test will do a complete overlap of an existing range in order to add
- // buffers to the track buffers. Then the test does a seek to another part of
- // the stream. The SourceBufferStream should clear its internal track buffer in
- // response to the Seek().
- TEST_F(SourceBufferStreamTest, Seek_After_TrackBuffer_Filled) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10, &kDataA);
- // Seek to buffer at position 5 and get next buffer.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Do a complete overlap by appending 20 buffers at positions 0 through 19.
- NewCodedFrameGroupAppend(0, 20, &kDataB);
- // Check range is correct.
- CheckExpectedRanges("{ [0,19) }");
- // Seek to beginning; all data should be new.
- Seek(0);
- CheckExpectedBuffers(0, 19, &kDataB);
- // Check range continues to be correct.
- CheckExpectedRanges("{ [0,19) }");
- }
- TEST_F(SourceBufferStreamTest, Seek_StartOfGroup) {
- base::TimeDelta bump = frame_duration() / 4;
- CHECK(bump.is_positive());
- // Append 5 buffers at position (5 + |bump|) through 9, where the coded frame
- // group begins at position 5.
- Seek(5);
- NewCodedFrameGroupAppend_OffsetFirstBuffer(5, 5, bump);
- scoped_refptr<StreamParserBuffer> buffer;
- // GetNextBuffer() should return the next buffer at position (5 + |bump|).
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- EXPECT_EQ(buffer->GetDecodeTimestamp(),
- DecodeTimestamp::FromPresentationTime(5 * frame_duration() + bump));
- // Check rest of buffers.
- CheckExpectedBuffers(6, 9);
- // Seek to position 15.
- Seek(15);
- // Append 5 buffers at positions (15 + |bump|) through 19, where the coded
- // frame group begins at 15.
- NewCodedFrameGroupAppend_OffsetFirstBuffer(15, 5, bump);
- // GetNextBuffer() should return the next buffer at position (15 + |bump|).
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- EXPECT_EQ(buffer->GetDecodeTimestamp(), DecodeTimestamp::FromPresentationTime(
- 15 * frame_duration() + bump));
- // Check rest of buffers.
- CheckExpectedBuffers(16, 19);
- }
- TEST_F(SourceBufferStreamTest, Seek_BeforeStartOfGroup) {
- // Append 10 buffers at positions 5 through 14.
- NewCodedFrameGroupAppend(5, 10);
- // Seek to a time before the first buffer in the range.
- Seek(0);
- // Should return buffers from the beginning of the range.
- CheckExpectedBuffers(5, 14);
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_CompleteOverlap) {
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 4);
- // Append 5 buffers at positions 10 through 14, and seek to the beginning of
- // this range.
- NewCodedFrameGroupAppend(10, 5);
- Seek(10);
- // Now seek to the beginning of the first range.
- Seek(0);
- // Completely overlap the old seek point.
- NewCodedFrameGroupAppend(5, 15);
- // The GetNextBuffer() call should respect the 2nd seek point.
- CheckExpectedBuffers(0, 0);
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_CompleteOverlap_Pending) {
- // Append 2 buffers at positions 0 through 1.
- NewCodedFrameGroupAppend(0, 2);
- // Append 5 buffers at positions 15 through 19 and seek to beginning of the
- // range.
- NewCodedFrameGroupAppend(15, 5);
- Seek(15);
- // Now seek position 5.
- Seek(5);
- // Completely overlap the old seek point.
- NewCodedFrameGroupAppend(10, 15);
- // The seek at position 5 should still be pending.
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_MiddleOverlap) {
- // Append 1 buffer at position 0, duration 10ms.
- NewCodedFrameGroupAppend("0D10K");
- // Append 3 IPBBB GOPs starting at 50ms.
- NewCodedFrameGroupAppend(
- "50K 90|60 60|70 70|80 80|90 "
- "100K 140|110 110|120 120|130 130|140 "
- "150K 190|160 160|170 170|180 180|190");
- SeekToTimestampMs(150);
- // Now seek to the beginning of the stream.
- SeekToTimestampMs(0);
- // Overlap the middle of the last range with a partial GOP, just a keyframe.
- NewCodedFrameGroupAppend("100D10K");
- CheckExpectedRangesByTimestamp("{ [0,10) [50,200) }");
- // The GetNextBuffer() call should respect the 2nd seek point.
- CheckExpectedBuffers("0K");
- CheckNoNextBuffer();
- // Check the data in the second range.
- SeekToTimestampMs(50);
- CheckExpectedBuffers(
- "50K 90|60 60|70 70|80 80|90 100K 150K 190|160 160|170 170|180 180|190");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_MiddleOverlap_Pending) {
- // Append 1 buffer at position 0, duration 10ms.
- NewCodedFrameGroupAppend("0D10K");
- // Append 3 IPBBB GOPs starting at 50ms. Then seek to 150ms.
- NewCodedFrameGroupAppend(
- "50K 90|60 60|70 70|80 80|90 "
- "100K 140|110 110|120 120|130 130|140 "
- "150K 190|160 160|170 170|180 180|190");
- SeekToTimestampMs(150);
- // Now seek to unbuffered time 20ms.
- SeekToTimestampMs(20);
- // Overlap the middle of the last range with a partial GOP, just a keyframe.
- NewCodedFrameGroupAppend("100D10K");
- CheckExpectedRangesByTimestamp("{ [0,10) [50,200) }");
- // The seek to 20ms should still be pending.
- CheckNoNextBuffer();
- // Check the data in both ranges.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K");
- CheckNoNextBuffer();
- SeekToTimestampMs(50);
- CheckExpectedBuffers(
- "50K 90|60 60|70 70|80 80|90 100K 150K 190|160 160|170 170|180 180|190");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_StartOverlap) {
- // Append 2 buffers at positions 0 through 1.
- NewCodedFrameGroupAppend(0, 2);
- // Append 15 buffers at positions 5 through 19 and seek to position 15.
- NewCodedFrameGroupAppend(5, 15);
- Seek(15);
- // Now seek to the beginning of the stream.
- Seek(0);
- // Start overlap the old seek point.
- NewCodedFrameGroupAppend(10, 10);
- // The GetNextBuffer() call should respect the 2nd seek point.
- CheckExpectedBuffers(0, 0);
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_StartOverlap_Pending) {
- // Append 2 buffers at positions 0 through 1.
- NewCodedFrameGroupAppend(0, 2);
- // Append 15 buffers at positions 10 through 24 and seek to position 20.
- NewCodedFrameGroupAppend(10, 15);
- Seek(20);
- // Now seek to position 5.
- Seek(5);
- // Start overlap the old seek point.
- NewCodedFrameGroupAppend(15, 10);
- // The seek at time 0 should still be pending.
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_EndOverlap) {
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 4);
- // Append 15 buffers at positions 10 through 24 and seek to start of range.
- NewCodedFrameGroupAppend(10, 15);
- Seek(10);
- // Now seek to the beginning of the stream.
- Seek(0);
- // End overlap the old seek point.
- NewCodedFrameGroupAppend(5, 10);
- // The GetNextBuffer() call should respect the 2nd seek point.
- CheckExpectedBuffers(0, 0);
- }
- TEST_F(SourceBufferStreamTest, OldSeekPoint_EndOverlap_Pending) {
- // Append 2 buffers at positions 0 through 1.
- NewCodedFrameGroupAppend(0, 2);
- // Append 15 buffers at positions 15 through 29 and seek to start of range.
- NewCodedFrameGroupAppend(15, 15);
- Seek(15);
- // Now seek to position 5
- Seek(5);
- // End overlap the old seek point.
- NewCodedFrameGroupAppend(10, 10);
- // The seek at time 5 should still be pending.
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, GetNextBuffer_AfterMerges) {
- // Append 5 buffers at positions 10 through 14.
- NewCodedFrameGroupAppend(10, 5);
- // Seek to buffer at position 12.
- Seek(12);
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5);
- // Make sure ranges are merged.
- CheckExpectedRanges("{ [5,14) }");
- // Make sure the next buffer is correct.
- CheckExpectedBuffers(10, 10);
- // Append 5 buffers at positions 15 through 19.
- NewCodedFrameGroupAppend(15, 5);
- CheckExpectedRanges("{ [5,19) }");
- // Make sure the remaining next buffers are correct.
- CheckExpectedBuffers(11, 14);
- }
- TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenAppend) {
- // Append 4 buffers at positions 0 through 3.
- NewCodedFrameGroupAppend(0, 4);
- // Seek to buffer at position 0 and get all buffers.
- Seek(0);
- CheckExpectedBuffers(0, 3);
- // Next buffer is at position 4, so should not be able to fulfill request.
- CheckNoNextBuffer();
- // Append 2 buffers at positions 4 through 5.
- AppendBuffers(4, 2);
- CheckExpectedBuffers(4, 5);
- }
- // This test covers the case where new buffers start-overlap a range whose next
- // buffer is not buffered.
- TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenStartOverlap) {
- // Append 10 buffers at positions 0 through 9 and exhaust the buffers.
- NewCodedFrameGroupAppend(0, 10, &kDataA);
- Seek(0);
- CheckExpectedBuffers(0, 9, &kDataA);
- // Next buffer is at position 10, so should not be able to fulfill request.
- CheckNoNextBuffer();
- // Append 6 buffers at positons 5 through 10. This is to test that doing a
- // start-overlap successfully fulfills the read at position 10, even though
- // position 10 was unbuffered.
- NewCodedFrameGroupAppend(5, 6, &kDataB);
- CheckExpectedBuffers(10, 10, &kDataB);
- // Then add 5 buffers from positions 11 though 15.
- AppendBuffers(11, 5, &kDataB);
- // Check the next 4 buffers are correct, which also effectively seeks to
- // position 15.
- CheckExpectedBuffers(11, 14, &kDataB);
- // Replace the next buffer at position 15 with another start overlap.
- NewCodedFrameGroupAppend(15, 2, &kDataA);
- CheckExpectedBuffers(15, 16, &kDataA);
- }
- // Tests a start overlap that occurs right at the timestamp of the last output
- // buffer that was returned by GetNextBuffer(). This test verifies that
- // GetNextBuffer() skips to second GOP in the newly appended data instead
- // of returning two buffers with the same timestamp.
- TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenStartOverlap2) {
- NewCodedFrameGroupAppend("0K 30 60 90 120");
- Seek(0);
- CheckExpectedBuffers("0K 30 60 90 120");
- CheckNoNextBuffer();
- // Append a keyframe with the same timestamp as the last buffer output.
- NewCodedFrameGroupAppend("120D30K");
- CheckNoNextBuffer();
- // Append the rest of the coded frame group and make sure that buffers are
- // returned from the first GOP after 120.
- AppendBuffers("150 180 210K 240");
- CheckExpectedBuffers("210K 240");
- // Seek to the beginning and verify the contents of the source buffer.
- Seek(0);
- CheckExpectedBuffers("0K 30 60 90 120K 150 180 210K 240");
- CheckNoNextBuffer();
- }
- // This test covers the case where new buffers completely overlap a range
- // whose next buffer is not buffered.
- TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenCompleteOverlap) {
- // Append 5 buffers at positions 10 through 14 and exhaust the buffers.
- NewCodedFrameGroupAppend(10, 5, &kDataA);
- Seek(10);
- CheckExpectedBuffers(10, 14, &kDataA);
- // Next buffer is at position 15, so should not be able to fulfill request.
- CheckNoNextBuffer();
- // Do a complete overlap and test that this successfully fulfills the read
- // at position 15.
- NewCodedFrameGroupAppend(5, 11, &kDataB);
- CheckExpectedBuffers(15, 15, &kDataB);
- // Then add 5 buffers from positions 16 though 20.
- AppendBuffers(16, 5, &kDataB);
- // Check the next 4 buffers are correct, which also effectively seeks to
- // position 20.
- CheckExpectedBuffers(16, 19, &kDataB);
- // Do a complete overlap and replace the buffer at position 20.
- NewCodedFrameGroupAppend(0, 21, &kDataA);
- CheckExpectedBuffers(20, 20, &kDataA);
- }
- // This test covers the case where a range is stalled waiting for its next
- // buffer, then an end-overlap causes the end of the range to be deleted.
- TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenEndOverlap) {
- // Append 5 buffers at positions 10 through 14 and exhaust the buffers.
- NewCodedFrameGroupAppend(10, 5, &kDataA);
- Seek(10);
- CheckExpectedBuffers(10, 14, &kDataA);
- CheckExpectedRanges("{ [10,14) }");
- // Next buffer is at position 15, so should not be able to fulfill request.
- CheckNoNextBuffer();
- // Do an end overlap that causes the latter half of the range to be deleted.
- NewCodedFrameGroupAppend(5, 6, &kDataB);
- CheckNoNextBuffer();
- CheckExpectedRanges("{ [5,10) }");
- // Fill in the gap. Getting the next buffer should still stall at position 15.
- for (int i = 11; i <= 14; i++) {
- AppendBuffers(i, 1, &kDataB);
- CheckNoNextBuffer();
- }
- // Append the buffer at position 15 and check to make sure all is correct.
- AppendBuffers(15, 1);
- CheckExpectedBuffers(15, 15);
- CheckExpectedRanges("{ [5,15) }");
- }
- // This test is testing the "next buffer" logic after a complete overlap. In
- // this scenario, when the track buffer is exhausted, there is no buffered data
- // to fulfill the request. The SourceBufferStream should be able to fulfill the
- // request when the data is later appended, and should not lose track of the
- // "next buffer" position.
- TEST_F(SourceBufferStreamTest, GetNextBuffer_Overlap_Selected_Complete) {
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataA);
- // Seek to buffer at position 5 and get next buffer.
- Seek(5);
- CheckExpectedBuffers(5, 5, &kDataA);
- // Replace existing data with new data.
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Expect old data up until next keyframe in new data.
- CheckExpectedBuffers(6, 9, &kDataA);
- // Next buffer is at position 10, so should not be able to fulfill the
- // request.
- CheckNoNextBuffer();
- // Now add 5 new buffers at positions 10 through 14.
- AppendBuffers(10, 5, &kDataB);
- CheckExpectedBuffers(10, 14, &kDataB);
- }
- TEST_F(SourceBufferStreamTest, PresentationTimestampIndependence) {
- // Append 20 buffers at position 0.
- NewCodedFrameGroupAppend(0, 20);
- Seek(0);
- int last_keyframe_idx = -1;
- base::TimeDelta last_keyframe_presentation_timestamp;
- base::TimeDelta last_p_frame_presentation_timestamp;
- // Check for IBB...BBP pattern.
- for (int i = 0; i < 20; i++) {
- scoped_refptr<StreamParserBuffer> buffer;
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- if (buffer->is_key_frame()) {
- EXPECT_EQ(DecodeTimestamp::FromPresentationTime(buffer->timestamp()),
- buffer->GetDecodeTimestamp());
- last_keyframe_idx = i;
- last_keyframe_presentation_timestamp = buffer->timestamp();
- } else if (i == last_keyframe_idx + 1) {
- ASSERT_NE(last_keyframe_idx, -1);
- last_p_frame_presentation_timestamp = buffer->timestamp();
- EXPECT_LT(last_keyframe_presentation_timestamp,
- last_p_frame_presentation_timestamp);
- } else {
- EXPECT_GT(buffer->timestamp(), last_keyframe_presentation_timestamp);
- EXPECT_LT(buffer->timestamp(), last_p_frame_presentation_timestamp);
- EXPECT_LT(DecodeTimestamp::FromPresentationTime(buffer->timestamp()),
- buffer->GetDecodeTimestamp());
- }
- }
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFront) {
- // Set memory limit to 20 buffers.
- SetMemoryLimit(20);
- // Append 20 buffers at positions 0 through 19.
- NewCodedFrameGroupAppend(0, 1, &kDataA);
- for (int i = 1; i < 20; i++)
- AppendBuffers(i, 1, &kDataA);
- // GC should be a no-op, since we are just under memory limit.
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedRanges("{ [0,19) }");
- Seek(0);
- CheckExpectedBuffers(0, 19, &kDataA);
- // Seek to the middle of the stream.
- Seek(10);
- // We are about to append 5 new buffers and current playback position is 10,
- // so the GC algorithm should be able to delete some old data from the front.
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(10, 5));
- CheckExpectedRanges("{ [5,19) }");
- // Append 5 buffers to the end of the stream.
- AppendBuffers(20, 5, &kDataA);
- CheckExpectedRanges("{ [5,24) }");
- CheckExpectedBuffers(10, 24, &kDataA);
- Seek(5);
- CheckExpectedBuffers(5, 9, &kDataA);
- }
- TEST_F(SourceBufferStreamTest,
- GarbageCollection_DeleteFront_PreserveSeekedGOP) {
- // Set memory limit to 15 buffers.
- SetMemoryLimit(15);
- NewCodedFrameGroupAppend("0K 10 20 30 40 50K 60 70 80 90");
- NewCodedFrameGroupAppend("1000K 1010 1020 1030 1040");
- // GC should be a no-op, since we are just under memory limit.
- EXPECT_TRUE(GarbageCollect(base::TimeDelta(), 0));
- CheckExpectedRangesByTimestamp("{ [0,100) [1000,1050) }");
- // Seek to the near the end of the first range
- SeekToTimestampMs(95);
- // We are about to append 7 new buffers and current playback position is at
- // the end of the last GOP in the first range, so the GC algorithm should be
- // able to delete some old data from the front, but must not collect the last
- // GOP in that first range. Neither can it collect the last appended GOP
- // (which is the entire second range), so GC should return false since it
- // couldn't collect enough.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(95), 7));
- CheckExpectedRangesByTimestamp("{ [50,100) [1000,1050) }");
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontGOPsAtATime) {
- // Set memory limit to 20 buffers.
- SetMemoryLimit(20);
- // Append 20 buffers at positions 0 through 19.
- NewCodedFrameGroupAppend(0, 20, &kDataA);
- // Seek to position 10.
- Seek(10);
- CheckExpectedRanges("{ [0,19) }");
- // Add one buffer to put the memory over the cap.
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(10, 1));
- AppendBuffers(20, 1, &kDataA);
- // GC should have deleted the first 5 buffers so that the range still begins
- // with a keyframe.
- CheckExpectedRanges("{ [5,20) }");
- CheckExpectedBuffers(10, 20, &kDataA);
- Seek(5);
- CheckExpectedBuffers(5, 9, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteBack) {
- // Set memory limit to 5 buffers.
- SetMemoryLimit(5);
- // Append 5 buffers at positions 15 through 19.
- NewCodedFrameGroupAppend(15, 5, &kDataA);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 5, &kDataA);
- CheckExpectedRanges("{ [0,4) [15,19) }");
- // Seek to position 0.
- Seek(0);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- // Should leave the first 5 buffers from 0 to 4.
- CheckExpectedRanges("{ [0,4) }");
- CheckExpectedBuffers(0, 4, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteFrontAndBack) {
- // Set memory limit to 3 buffers.
- SetMemoryLimit(3);
- // Seek to position 15.
- Seek(15);
- // Append 40 buffers at positions 0 through 39.
- NewCodedFrameGroupAppend(0, 40, &kDataA);
- // GC will try to keep data between current playback position and last append
- // position. This will ensure that the last append position is 19 and will
- // allow GC algorithm to collect data outside of the range [15,19)
- NewCodedFrameGroupAppend(15, 5, &kDataA);
- CheckExpectedRanges("{ [0,39) }");
- // Should leave the GOP containing the current playback position 15 and the
- // last append position 19. GC returns false, since we are still above limit.
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(15, 0));
- CheckExpectedRanges("{ [15,19) }");
- CheckExpectedBuffers(15, 19, &kDataA);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteSeveralRanges) {
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 5);
- // Append 5 buffers at positions 10 through 14.
- NewCodedFrameGroupAppend(10, 5);
- // Append 5 buffers at positions 20 through 24.
- NewCodedFrameGroupAppend(20, 5);
- // Append 5 buffers at positions 40 through 44.
- NewCodedFrameGroupAppend(40, 5);
- CheckExpectedRanges("{ [0,4) [10,14) [20,24) [40,44) }");
- // Seek to position 20.
- Seek(20);
- CheckExpectedBuffers(20, 20);
- // Set memory limit to 1 buffer.
- SetMemoryLimit(1);
- // Append 5 buffers at positions 30 through 34.
- NewCodedFrameGroupAppend(30, 5);
- // We will have more than 1 buffer left, GC will fail
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(20, 0));
- // Should have deleted all buffer ranges before the current buffer and after
- // last GOP
- CheckExpectedRanges("{ [20,24) [30,34) }");
- CheckExpectedBuffers(21, 24);
- CheckNoNextBuffer();
- // Continue appending into the last range to make sure it didn't break.
- AppendBuffers(35, 10);
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(20, 0));
- // Should save everything between read head and last appended
- CheckExpectedRanges("{ [20,24) [30,44) }");
- // Make sure appending before and after the ranges didn't somehow break.
- SetMemoryLimit(100);
- NewCodedFrameGroupAppend(0, 10);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(20, 0));
- CheckExpectedRanges("{ [0,9) [20,24) [30,44) }");
- Seek(0);
- CheckExpectedBuffers(0, 9);
- NewCodedFrameGroupAppend(90, 10);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedRanges("{ [0,9) [20,24) [30,44) [90,99) }");
- Seek(30);
- CheckExpectedBuffers(30, 44);
- CheckNoNextBuffer();
- Seek(90);
- CheckExpectedBuffers(90, 99);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppend) {
- // Set memory limit to 10 buffers.
- SetMemoryLimit(10);
- // Append 1 GOP starting at 310ms, 30ms apart.
- NewCodedFrameGroupAppend("310K 340 370");
- // Append 2 GOPs starting at 490ms, 30ms apart.
- NewCodedFrameGroupAppend("490K 520 550 580K 610 640");
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedRangesByTimestamp("{ [310,400) [490,670) }");
- // Seek to the GOP at 580ms.
- SeekToTimestampMs(580);
- // Append 2 GOPs before the existing ranges.
- // So the ranges before GC are "{ [100,280) [310,400) [490,670) }".
- NewCodedFrameGroupAppend("100K 130 160 190K 220 250K");
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(580), 0));
- // Should save the newly appended GOPs.
- CheckExpectedRangesByTimestamp("{ [100,280) [580,670) }");
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_DeleteAfterLastAppendMerged) {
- // Set memory limit to 10 buffers.
- SetMemoryLimit(10);
- // Append 3 GOPs starting at 400ms, 30ms apart.
- NewCodedFrameGroupAppend("400K 430 460 490K 520 550 580K 610 640");
- // Seek to the GOP at 580ms.
- SeekToTimestampMs(580);
- // Append 2 GOPs starting at 220ms, and they will be merged with the existing
- // range. So the range before GC is "{ [220,670) }".
- NewCodedFrameGroupAppend("220K 250 280 310K 340 370");
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(580), 0));
- // Should save the newly appended GOPs.
- CheckExpectedRangesByTimestamp("{ [220,400) [580,670) }");
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_NoSeek) {
- // Set memory limit to 20 buffers.
- SetMemoryLimit(20);
- // Append 25 buffers at positions 0 through 24.
- NewCodedFrameGroupAppend(0, 25, &kDataA);
- // If playback is still in the first GOP (starting at 0), GC should fail.
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(2, 0));
- CheckExpectedRanges("{ [0,24) }");
- // As soon as playback position moves past the first GOP, it should be removed
- // and after removing the first GOP we are under memory limit.
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(5, 0));
- CheckExpectedRanges("{ [5,24) }");
- CheckNoNextBuffer();
- Seek(5);
- CheckExpectedBuffers(5, 24, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_PendingSeek) {
- // Append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataA);
- // Append 5 buffers at positions 25 through 29.
- NewCodedFrameGroupAppend(25, 5, &kDataA);
- // Seek to position 15.
- Seek(15);
- CheckNoNextBuffer();
- CheckExpectedRanges("{ [0,9) [25,29) }");
- // Set memory limit to 5 buffers.
- SetMemoryLimit(5);
- // Append 5 buffers as positions 30 to 34 to trigger GC.
- AppendBuffers(30, 5, &kDataA);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(30, 0));
- // The current algorithm will delete from the beginning until the memory is
- // under cap.
- CheckExpectedRanges("{ [30,34) }");
- // Expand memory limit again so that GC won't be triggered.
- SetMemoryLimit(100);
- // Append data to fulfill seek.
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(30, 5));
- NewCodedFrameGroupAppend(15, 5, &kDataA);
- // Check to make sure all is well.
- CheckExpectedRanges("{ [15,19) [30,34) }");
- CheckExpectedBuffers(15, 19, &kDataA);
- Seek(30);
- CheckExpectedBuffers(30, 34, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_NeedsMoreData) {
- // Set memory limit to 15 buffers.
- SetMemoryLimit(15);
- // Append 10 buffers at positions 0 through 9.
- NewCodedFrameGroupAppend(0, 10, &kDataA);
- // Advance next buffer position to 10.
- Seek(0);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedBuffers(0, 9, &kDataA);
- CheckNoNextBuffer();
- // Append 20 buffers at positions 15 through 34.
- NewCodedFrameGroupAppend(15, 20, &kDataA);
- CheckExpectedRanges("{ [0,9) [15,34) }");
- // GC should save the keyframe before the next buffer position and the data
- // closest to the next buffer position. It will also save all buffers from
- // next buffer to the last GOP appended, which overflows limit and leads to
- // failure.
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(5, 0));
- CheckExpectedRanges("{ [5,9) [15,34) }");
- // Now fulfill the seek at position 10. This will make GC delete the data
- // before position 10 to keep it within cap.
- NewCodedFrameGroupAppend(10, 5, &kDataA);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(10, 0));
- CheckExpectedRanges("{ [10,24) }");
- CheckExpectedBuffers(10, 24, &kDataA);
- }
- // Using position based test API:
- // DTS : 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
- // PTS : 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3 5 9 6 7 8 0 4 1 2 3
- // old : A a a a a A a a a a A a a a a*A*a a
- // -- Garbage Collect --
- // after: A a a
- // -- Read one buffer --
- // after: A*a*a
- // new : B b b b b B b b b b B b b b b B b b b b
- // track: *a*a
- // -- Garbage Collect --
- // after: B b b b b
- // track: *a*a
- // -- Read 2 buffers -> exhausts track buffer
- // after: B b b b b
- // (awaiting next keyframe after GOP at position 15)
- // new : *B*b b b b
- // after: B b b b b*B*b b b b
- // -- Garbage Collect --
- // after: *B*b b b b
- TEST_F(SourceBufferStreamTest, GarbageCollection_TrackBuffer) {
- // Set memory limit to 3 buffers.
- SetMemoryLimit(3);
- // Seek to position 15.
- Seek(15);
- // Append 18 buffers at positions 0 through 17 (DTS), 0 through 19 (PTS) with
- // partial 4th GOP.
- NewCodedFrameGroupAppend(0, 18, &kDataA);
- EXPECT_TRUE(GarbageCollectWithPlaybackAtBuffer(15, 0));
- // GC should leave GOP containing seek position (15,16,17 DTS; 15,19,16 PTS).
- // Unlike the rest of the position based test API used in this case,
- // CheckExpectedRanges() uses expectation strings containing actual timestamps
- // (divided by frame_duration_).
- CheckExpectedRanges("{ [15,19) }");
- // Move next buffer position to 16.
- CheckExpectedBuffers(15, 15, &kDataA);
- // Completely overlap the existing buffers with 4 full GOPs (0-19, PTS and
- // DTS).
- NewCodedFrameGroupAppend(0, 20, &kDataB);
- // Final GOP [15,19) contains 5 buffers, which is more than memory limit of
- // 3 buffers set at the beginning of the test, so GC will fail.
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(15, 0));
- // Because buffers 16,17 (DTS), 19,16 (PTS) are not keyframes, they are moved
- // to the track buffer upon overlap. The source buffer (i.e. not the track
- // buffer) is now waiting for the next keyframe beyond GOP that survived GC.
- CheckExpectedRanges("{ [15,19) }"); // Source buffer
- CheckExpectedBuffers(16, 17, &kDataA); // Exhaust the track buffer
- CheckNoNextBuffer(); // Confirms the source buffer is awaiting next keyframe.
- // Now add a 5-frame GOP at position 20-24 (PTS and DTS).
- AppendBuffers(20, 5, &kDataB);
- // 5 buffers in final GOP, GC will fail
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(20, 0));
- // Should garbage collect such that there are 5 frames remaining, starting at
- // the keyframe.
- CheckExpectedRanges("{ [20,24) }");
- // The buffer at position 16 (PTS 19) in track buffer was adjacent
- // to the next keyframe (PTS=DTS=20), so no warning should be emitted on that
- // track buffer exhaustion even though the last frame read out of track buffer
- // before exhaustion was position 17 (PTS 16).
- CheckExpectedBuffers(20, 24, &kDataB);
- CheckNoNextBuffer();
- }
- // Test GC preserves data starting at first GOP containing playback position.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveDataAtPlaybackPosition) {
- // Set memory limit to 30 buffers = 1 second of data.
- SetMemoryLimit(30);
- // And append 300 buffers = 10 seconds of data.
- NewCodedFrameGroupAppend(0, 300, &kDataA);
- CheckExpectedRanges("{ [0,299) }");
- // Playback position at 0, all data must be preserved.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(0), 0));
- CheckExpectedRanges("{ [0,299) }");
- // Playback position at 1 sec, the first second of data [0,29) should be
- // collected, since we are way over memory limit.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(1000), 0));
- CheckExpectedRanges("{ [30,299) }");
- // Playback position at 1.1 sec, no new data can be collected, since the
- // playback position is still in the first GOP of buffered data.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(1100), 0));
- CheckExpectedRanges("{ [30,299) }");
- // Playback position at 5.166 sec, just at the very end of GOP corresponding
- // to buffer range 150-155, which should be preserved.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(5166), 0));
- CheckExpectedRanges("{ [150,299) }");
- // Playback position at 5.167 sec, just past the end of GOP corresponding to
- // buffer range 150-155, it should be garbage collected now.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(5167), 0));
- CheckExpectedRanges("{ [155,299) }");
- // Playback at 9.0 sec, we can now successfully collect all data except the
- // last second and we are back under memory limit of 30 buffers, so GCIfNeeded
- // should return true.
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(9000), 0));
- CheckExpectedRanges("{ [270,299) }");
- // Playback at 9.999 sec, GC succeeds, since we are under memory limit even
- // without removing any data.
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(9999), 0));
- CheckExpectedRanges("{ [270,299) }");
- // Playback at 15 sec, this should never happen during regular playback in
- // browser, since this position has no data buffered, but it should still
- // cause no problems to GC algorithm, so test it just in case.
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(15000), 0));
- CheckExpectedRanges("{ [270,299) }");
- }
- // Test saving the last GOP appended when this GOP is the only GOP in its range.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP) {
- // Set memory limit to 3 and make sure the 4-byte GOP is not garbage
- // collected.
- SetMemoryLimit(3);
- NewCodedFrameGroupAppend("0K 30 60 90");
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- // Make sure you can continue appending data to this GOP; again, GC should not
- // wipe out anything.
- AppendBuffers("120D30");
- EXPECT_FALSE(GarbageCollectWithPlaybackAtBuffer(0, 0));
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Append a 2nd range after this without triggering GC.
- NewCodedFrameGroupAppend("200K 230 260 290K 320 350");
- CheckExpectedRangesByTimestamp("{ [0,150) [200,380) }");
- // Seek to 290ms.
- SeekToTimestampMs(290);
- // Now append a GOP in a separate range after the selected range and trigger
- // GC. Because it is after 290ms, this tests that the GOP is saved when
- // deleting from the back.
- NewCodedFrameGroupAppend("500K 530 560 590");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(290), 0));
- // Should save GOPs between 290ms and the last GOP appended.
- CheckExpectedRangesByTimestamp("{ [290,380) [500,620) }");
- // Continue appending to this GOP after GC.
- AppendBuffers("620D30");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(290), 0));
- CheckExpectedRangesByTimestamp("{ [290,380) [500,650) }");
- }
- // Test saving the last GOP appended when this GOP is in the middle of a
- // non-selected range.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Middle) {
- // Append 3 GOPs starting at 0ms, 30ms apart.
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240");
- CheckExpectedRangesByTimestamp("{ [0,270) }");
- // Now set the memory limit to 1 and overlap the middle of the range with a
- // new GOP.
- SetMemoryLimit(1);
- NewCodedFrameGroupAppend("80K 110 140");
- // This whole GOP should be saved after GC, which will fail due to GOP being
- // larger than 1 buffer
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(80), 0));
- CheckExpectedRangesByTimestamp("{ [80,170) }");
- // We should still be able to continue appending data to GOP
- AppendBuffers("170D30");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(80), 0));
- CheckExpectedRangesByTimestamp("{ [80,200) }");
- // Append a 2nd range after this range, without triggering GC.
- NewCodedFrameGroupAppend("400K 430 460 490K 520 550 580K 610 640");
- CheckExpectedRangesByTimestamp("{ [80,200) [400,670) }");
- // Seek to 80ms to make the first range the selected range.
- SeekToTimestampMs(80);
- // Now append a GOP in the middle of the second range and trigger GC. Because
- // it is after the selected range, this tests that the GOP is saved when
- // deleting from the back.
- NewCodedFrameGroupAppend("500K 530 560 590");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(80), 0));
- // Should save the GOPs between the seek point and GOP that was last appended
- CheckExpectedRangesByTimestamp("{ [80,200) [400,620) }");
- // Continue appending to this GOP after GC.
- AppendBuffers("620D30");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(80), 0));
- CheckExpectedRangesByTimestamp("{ [80,200) [400,650) }");
- }
- // Test saving the last GOP appended when the GOP containing the next buffer is
- // adjacent to the last GOP appended.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected1) {
- // Append 3 GOPs at 0ms, 90ms, and 180ms.
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240");
- CheckExpectedRangesByTimestamp("{ [0,270) }");
- // Seek to the GOP at 90ms.
- SeekToTimestampMs(90);
- // Set the memory limit to 1, then overlap the GOP at 0.
- SetMemoryLimit(1);
- NewCodedFrameGroupAppend("0K 30 60");
- // GC should save the GOP at 0ms and 90ms, and will fail since GOP larger
- // than 1 buffer
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(90), 0));
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Seek to 0 and check all buffers.
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 30 60 90K 120 150");
- CheckNoNextBuffer();
- // Now seek back to 90ms and append a GOP at 180ms.
- SeekToTimestampMs(90);
- NewCodedFrameGroupAppend("180K 210 240");
- // Should save the GOP at 90ms and the GOP at 180ms.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(90), 0));
- CheckExpectedRangesByTimestamp("{ [90,270) }");
- CheckExpectedBuffers("90K 120 150 180K 210 240");
- CheckNoNextBuffer();
- }
- // Test saving the last GOP appended when it is at the beginning or end of the
- // selected range. This tests when the last GOP appended is before or after the
- // GOP containing the next buffer, but not directly adjacent to this GOP.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected2) {
- // Append 4 GOPs starting at positions 0ms, 90ms, 180ms, 270ms.
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- // Seek to the last GOP at 270ms.
- SeekToTimestampMs(270);
- // Set the memory limit to 1, then overlap the GOP at 90ms.
- SetMemoryLimit(1);
- NewCodedFrameGroupAppend("90K 120 150");
- // GC will save data in the range where the most recent append has happened
- // [0; 180) and the range where the next read position is [270;360)
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(270), 0));
- CheckExpectedRangesByTimestamp("{ [0,180) [270,360) }");
- // Add 3 GOPs to the end of the selected range at 360ms, 450ms, and 540ms.
- NewCodedFrameGroupAppend("360K 390 420 450K 480 510 540K 570 600");
- CheckExpectedRangesByTimestamp("{ [0,180) [270,630) }");
- // Overlap the GOP at 450ms and garbage collect to test deleting from the
- // back.
- NewCodedFrameGroupAppend("450K 480 510");
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(270), 0));
- // Should save GOPs from GOP at 270ms to GOP at 450ms.
- CheckExpectedRangesByTimestamp("{ [270,540) }");
- }
- // Test saving the last GOP appended when it is the same as the GOP containing
- // the next buffer.
- TEST_F(SourceBufferStreamTest, GarbageCollection_SaveAppendGOP_Selected3) {
- // Seek to start of stream.
- SeekToTimestampMs(0);
- // Append 3 GOPs starting at 0ms, 90ms, 180ms.
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240");
- CheckExpectedRangesByTimestamp("{ [0,270) }");
- // Set the memory limit to 1 then begin appending the start of a GOP starting
- // at 0ms.
- SetMemoryLimit(1);
- NewCodedFrameGroupAppend("0K 30");
- // GC should save the newly appended GOP, which is also the next GOP that
- // will be returned from the seek request.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(0), 0));
- CheckExpectedRangesByTimestamp("{ [0,60) }");
- // Check the buffers in the range.
- CheckExpectedBuffers("0K 30");
- CheckNoNextBuffer();
- // Continue appending to this buffer.
- AppendBuffers("60 90");
- // GC should still save the rest of this GOP and should be able to fulfill
- // the read.
- EXPECT_FALSE(GarbageCollect(base::Milliseconds(0), 0));
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- CheckExpectedBuffers("60 90");
- CheckNoNextBuffer();
- }
- // Test the performance of garbage collection.
- TEST_F(SourceBufferStreamTest, GarbageCollection_Performance) {
- // Force |keyframes_per_second_| to be equal to kDefaultFramesPerSecond.
- SetStreamInfo(kDefaultFramesPerSecond, kDefaultFramesPerSecond);
- const int kBuffersToKeep = 1000;
- SetMemoryLimit(kBuffersToKeep);
- int buffers_appended = 0;
- NewCodedFrameGroupAppend(0, kBuffersToKeep);
- buffers_appended += kBuffersToKeep;
- const int kBuffersToAppend = 1000;
- const int kGarbageCollections = 3;
- for (int i = 0; i < kGarbageCollections; ++i) {
- AppendBuffers(buffers_appended, kBuffersToAppend);
- buffers_appended += kBuffersToAppend;
- }
- }
- TEST_F(SourceBufferStreamTest, GarbageCollection_MediaTimeAfterLastAppendTime) {
- // Set memory limit to 10 buffers.
- SetMemoryLimit(10);
- // Append 12 buffers. The duration of the last buffer is 30
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150 180 210K 240 270 300K 330D30");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- // Do a garbage collection with the media time higher than the timestamp of
- // the last appended buffer (330), but still within buffered ranges, taking
- // into account the duration of the last frame (timestamp of the last frame is
- // 330, duration is 30, so the latest valid buffered position is 330+30=360).
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(360), 0));
- // GC should collect one GOP from the front to bring us back under memory
- // limit of 10 buffers.
- CheckExpectedRangesByTimestamp("{ [120,360) }");
- }
- TEST_F(SourceBufferStreamTest,
- GarbageCollection_MediaTimeOutsideOfStreamBufferedRange) {
- // Set memory limit to 10 buffers.
- SetMemoryLimit(10);
- // Append 12 buffers.
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150 180 210K 240 270 300K 330");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- // Seek in order to set the stream read position to 330 an ensure that the
- // stream selects the buffered range.
- SeekToTimestampMs(330);
- // Do a garbage collection with the media time outside the buffered ranges
- // (this might happen when there's both audio and video streams, audio stream
- // buffered range is longer than the video stream buffered range, since
- // media::Pipeline uses audio stream as a time source in that case, it might
- // return a media_time that is slightly outside of video buffered range). In
- // those cases the GC algorithm should clamp the media_time value to the
- // buffered ranges to work correctly (see crbug.com/563292).
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(361), 0));
- // GC should collect one GOP from the front to bring us back under memory
- // limit of 10 buffers.
- CheckExpectedRangesByTimestamp("{ [120,360) }");
- }
- TEST_F(SourceBufferStreamTest, GetRemovalRange_BytesToFree) {
- // Append 2 GOPs starting at 300ms, 30ms apart.
- NewCodedFrameGroupAppend("300K 330 360 390K 420 450");
- // Append 2 GOPs starting at 600ms, 30ms apart.
- NewCodedFrameGroupAppend("600K 630 660 690K 720 750");
- // Append 2 GOPs starting at 900ms, 30ms apart.
- NewCodedFrameGroupAppend("900K 930 960 990K 1020 1050");
- CheckExpectedRangesByTimestamp("{ [300,480) [600,780) [900,1080) }");
- int remove_range_end = -1;
- int bytes_removed = -1;
- // Size 0.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 0, &remove_range_end);
- EXPECT_EQ(-1, remove_range_end);
- EXPECT_EQ(0, bytes_removed);
- // Smaller than the size of GOP.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 1, &remove_range_end);
- EXPECT_EQ(390, remove_range_end);
- // Remove as the size of GOP.
- EXPECT_EQ(3, bytes_removed);
- // The same size with a GOP.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 3, &remove_range_end);
- EXPECT_EQ(390, remove_range_end);
- EXPECT_EQ(3, bytes_removed);
- // The same size with a range.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 6, &remove_range_end);
- EXPECT_EQ(480, remove_range_end);
- EXPECT_EQ(6, bytes_removed);
- // A frame larger than a range.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 7, &remove_range_end);
- EXPECT_EQ(690, remove_range_end);
- EXPECT_EQ(9, bytes_removed);
- // The same size with two ranges.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 12, &remove_range_end);
- EXPECT_EQ(780, remove_range_end);
- EXPECT_EQ(12, bytes_removed);
- // Larger than two ranges.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 14, &remove_range_end);
- EXPECT_EQ(990, remove_range_end);
- EXPECT_EQ(15, bytes_removed);
- // The same size with the whole ranges.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 18, &remove_range_end);
- EXPECT_EQ(1080, remove_range_end);
- EXPECT_EQ(18, bytes_removed);
- // Larger than the whole ranges.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end);
- EXPECT_EQ(1080, remove_range_end);
- EXPECT_EQ(18, bytes_removed);
- }
- TEST_F(SourceBufferStreamTest, GetRemovalRange_Range) {
- // Append 2 GOPs starting at 300ms, 30ms apart.
- NewCodedFrameGroupAppend("300K 330 360 390K 420 450");
- // Append 2 GOPs starting at 600ms, 30ms apart.
- NewCodedFrameGroupAppend("600K 630 660 690K 720 750");
- // Append 2 GOPs starting at 900ms, 30ms apart.
- NewCodedFrameGroupAppend("900K 930 960 990K 1020 1050");
- CheckExpectedRangesByTimestamp("{ [300,480) [600,780) [900,1080) }");
- int remove_range_end = -1;
- int bytes_removed = -1;
- // Within a GOP and no keyframe.
- bytes_removed = GetRemovalRangeInMs(630, 660, 20, &remove_range_end);
- EXPECT_EQ(-1, remove_range_end);
- EXPECT_EQ(0, bytes_removed);
- // Across a GOP and no keyframe.
- bytes_removed = GetRemovalRangeInMs(630, 750, 20, &remove_range_end);
- EXPECT_EQ(-1, remove_range_end);
- EXPECT_EQ(0, bytes_removed);
- // The same size with a range.
- bytes_removed = GetRemovalRangeInMs(600, 780, 20, &remove_range_end);
- EXPECT_EQ(780, remove_range_end);
- EXPECT_EQ(6, bytes_removed);
- // One frame larger than a range.
- bytes_removed = GetRemovalRangeInMs(570, 810, 20, &remove_range_end);
- EXPECT_EQ(780, remove_range_end);
- EXPECT_EQ(6, bytes_removed);
- // Facing the other ranges.
- bytes_removed = GetRemovalRangeInMs(480, 900, 20, &remove_range_end);
- EXPECT_EQ(780, remove_range_end);
- EXPECT_EQ(6, bytes_removed);
- // In the midle of the other ranges, but not including any GOP.
- bytes_removed = GetRemovalRangeInMs(420, 960, 20, &remove_range_end);
- EXPECT_EQ(780, remove_range_end);
- EXPECT_EQ(6, bytes_removed);
- // In the middle of the other ranges.
- bytes_removed = GetRemovalRangeInMs(390, 990, 20, &remove_range_end);
- EXPECT_EQ(990, remove_range_end);
- EXPECT_EQ(12, bytes_removed);
- // A frame smaller than the whole ranges.
- bytes_removed = GetRemovalRangeInMs(330, 1050, 20, &remove_range_end);
- EXPECT_EQ(990, remove_range_end);
- EXPECT_EQ(12, bytes_removed);
- // The same with the whole ranges.
- bytes_removed = GetRemovalRangeInMs(300, 1080, 20, &remove_range_end);
- EXPECT_EQ(1080, remove_range_end);
- EXPECT_EQ(18, bytes_removed);
- // Larger than the whole ranges.
- bytes_removed = GetRemovalRangeInMs(270, 1110, 20, &remove_range_end);
- EXPECT_EQ(1080, remove_range_end);
- EXPECT_EQ(18, bytes_removed);
- }
- TEST_F(SourceBufferStreamTest, ConfigChange_Basic) {
- VideoDecoderConfig new_config = TestVideoConfig::Large();
- ASSERT_FALSE(new_config.Matches(video_config_));
- Seek(0);
- CheckVideoConfig(video_config_);
- // Append 5 buffers at positions 0 through 4
- NewCodedFrameGroupAppend(0, 5, &kDataA);
- CheckVideoConfig(video_config_);
- // Signal a config change.
- stream_->UpdateVideoConfig(new_config, false);
- // Make sure updating the config doesn't change anything since new_config
- // should not be associated with the buffer GetNextBuffer() will return.
- CheckVideoConfig(video_config_);
- // Append 5 buffers at positions 5 through 9.
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Consume the buffers associated with the initial config.
- scoped_refptr<StreamParserBuffer> buffer;
- for (int i = 0; i < 5; i++) {
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- CheckVideoConfig(video_config_);
- }
- // Verify the next attempt to get a buffer will signal that a config change
- // has happened.
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- // Verify that the new config is now returned.
- CheckVideoConfig(new_config);
- // Consume the remaining buffers associated with the new config.
- for (int i = 0; i < 5; i++) {
- CheckVideoConfig(new_config);
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- }
- }
- TEST_F(SourceBufferStreamTest, ConfigChange_Seek) {
- scoped_refptr<StreamParserBuffer> buffer;
- VideoDecoderConfig new_config = TestVideoConfig::Large();
- Seek(0);
- NewCodedFrameGroupAppend(0, 5, &kDataA);
- stream_->UpdateVideoConfig(new_config, false);
- NewCodedFrameGroupAppend(5, 5, &kDataB);
- // Seek to the start of the buffers with the new config and make sure a
- // config change is signalled.
- CheckVideoConfig(video_config_);
- Seek(5);
- CheckVideoConfig(video_config_);
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- CheckVideoConfig(new_config);
- CheckExpectedBuffers(5, 9, &kDataB);
- // Seek to the start which has a different config. Don't fetch any buffers and
- // seek back to buffers with the current config. Make sure a config change
- // isn't signalled in this case.
- CheckVideoConfig(new_config);
- Seek(0);
- Seek(7);
- CheckExpectedBuffers(5, 9, &kDataB);
- // Seek to the start and make sure a config change is signalled.
- CheckVideoConfig(new_config);
- Seek(0);
- CheckVideoConfig(new_config);
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- CheckVideoConfig(video_config_);
- CheckExpectedBuffers(0, 4, &kDataA);
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration) {
- // Append 3 discontinuous partial GOPs.
- NewCodedFrameGroupAppend("50K 90|60");
- NewCodedFrameGroupAppend("150K 190|160");
- NewCodedFrameGroupAppend("250K 290|260");
- CheckExpectedRangesByTimestamp("{ [50,100) [150,200) [250,300) }");
- // Set duration to be 80ms. Truncates the buffered data after 80ms.
- stream_->OnSetDuration(base::Milliseconds(80));
- // The simulated P-frame at PTS 90ms should have been
- // removed by the duration truncation. Only the frame at PTS 50ms should
- // remain.
- CheckExpectedRangesByTimestamp("{ [50,60) }");
- // Adding data past the previous duration should still work.
- NewCodedFrameGroupAppend("0D50K 50 100K");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_EdgeCase) {
- // Append 10 buffers at positions 10 through 19.
- NewCodedFrameGroupAppend(10, 10);
- // Append 5 buffers at positions 25 through 29.
- NewCodedFrameGroupAppend(25, 5);
- // Check expected ranges.
- CheckExpectedRanges("{ [10,19) [25,29) }");
- // Set duration to be right before buffer 25.
- stream_->OnSetDuration(frame_duration() * 25);
- // Should truncate the last range.
- CheckExpectedRanges("{ [10,19) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_EdgeCase2) {
- // This test requires specific relative proportions for fudge room, append
- // size, and duration truncation amounts. See details at:
- // https://codereview.chromium.org/2385423002
- // Append buffers with first buffer establishing max_inter_buffer_distance
- // of 5 ms. This translates to a fudge room (2 x max_interbuffer_distance) of
- // 10 ms.
- NewCodedFrameGroupAppend("0K 5K 9D4K");
- CheckExpectedRangesByTimestamp("{ [0,13) }");
- // Trim off last 2 buffers, totaling 8 ms. Notably less than the current fudge
- // room of 10 ms.
- stream_->OnSetDuration(base::Milliseconds(5));
- // Verify truncation.
- CheckExpectedRangesByTimestamp("{ [0,5) }");
- // Append new buffers just beyond the fudge-room allowance of 10ms.
- AppendBuffers("11K 15K");
- // Verify new append creates a gap.
- CheckExpectedRangesByTimestamp("{ [0,5) [11,19) }");
- }
- TEST_F(SourceBufferStreamTest, RemoveWithinFudgeRoom) {
- // This test requires specific relative proportions for fudge room, append
- // size, and removal amounts. See details at:
- // https://codereview.chromium.org/2385423002
- // Append buffers with first buffer establishing max_inter_buffer_distance
- // of 5 ms. This translates to a fudge room (2 x max_interbuffer_distance) of
- // 10 ms.
- NewCodedFrameGroupAppend("0K 5K 9D4K");
- CheckExpectedRangesByTimestamp("{ [0,13) }");
- // Trim off last 2 buffers, totaling 8 ms. Notably less than the current fudge
- // room of 10 ms.
- RemoveInMs(5, 13, 13);
- // Verify removal.
- CheckExpectedRangesByTimestamp("{ [0,5) }");
- // Append new buffers just beyond the fudge-room allowance of 10ms.
- AppendBuffers("11K 15K");
- // Verify new append creates a gap.
- CheckExpectedRangesByTimestamp("{ [0,5) [11,19) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeletePartialRange) {
- // Append IPBBB GOPs into 3 discontinuous ranges.
- NewCodedFrameGroupAppend("0K 40|10 10|20 20|30 30|40");
- NewCodedFrameGroupAppend(
- "100K 140|110 110|120 120|130 130|140 "
- "150K 190|160 160|170 170|180 180|190");
- NewCodedFrameGroupAppend("250K 290|260 260|270 270|280 280|290");
- // Check expected ranges.
- CheckExpectedRangesByTimestamp("{ [0,50) [100,200) [250,300) }");
- stream_->OnSetDuration(base::Milliseconds(140));
- // The B-frames at PTS 110-130 were in the GOP in decode order after
- // the simulated P-frame at PTS 140 which was truncated, so those B-frames
- // are also removed.
- CheckExpectedRangesByTimestamp("{ [0,50) [100,110) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeleteSelectedRange) {
- // Append 3 discontinuous partial GOPs.
- NewCodedFrameGroupAppend("50K 90|60");
- NewCodedFrameGroupAppend("150K 190|160");
- NewCodedFrameGroupAppend("250K 290|260");
- CheckExpectedRangesByTimestamp("{ [50,100) [150,200) [250,300) }");
- SeekToTimestampMs(150);
- // Set duration to 50ms.
- stream_->OnSetDuration(base::Milliseconds(50));
- // Expect everything to be deleted, and should not have next buffer anymore.
- CheckNoNextBuffer();
- CheckExpectedRangesByTimestamp("{ }");
- // Appending data 0ms through 250ms should not fulfill the seek.
- // (If the duration is set to be something smaller than the current seek
- // point, which had been 150ms, then the seek point is reset and the
- // SourceBufferStream waits for a new seek request. Therefore even if the data
- // is re-appended, it should not fulfill the old seek.)
- NewCodedFrameGroupAppend("0K 50K 100K 150K 200K");
- CheckNoNextBuffer();
- CheckExpectedRangesByTimestamp("{ [0,250) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_DeletePartialSelectedRange) {
- // Append 5 buffers at positions 0 through 4.
- NewCodedFrameGroupAppend(0, 5);
- // Append 20 buffers at positions 10 through 29.
- NewCodedFrameGroupAppend(10, 20);
- // Check expected ranges.
- CheckExpectedRanges("{ [0,4) [10,29) }");
- // Seek to position 10.
- Seek(10);
- // Set duration to be between buffers 24 and 25.
- stream_->OnSetDuration(frame_duration() * 25);
- // Should truncate the data after 24.
- CheckExpectedRanges("{ [0,4) [10,24) }");
- // The seek position should not be lost.
- CheckExpectedBuffers(10, 10);
- // Now set the duration immediately after buffer 10.
- stream_->OnSetDuration(frame_duration() * 11);
- // Seek position should be reset.
- CheckNoNextBuffer();
- CheckExpectedRanges("{ [0,4) [10,10) }");
- }
- // Test the case where duration is set while the stream parser buffers
- // already start passing the data to decoding pipeline. Selected range,
- // when invalidated by getting truncated, should be updated to NULL
- // accordingly so that successive append operations keep working.
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_UpdateSelectedRange) {
- // Seek to start of stream.
- SeekToTimestampMs(0);
- NewCodedFrameGroupAppend("0K 30 60 90");
- // Read out the first few buffers.
- CheckExpectedBuffers("0K 30");
- // Set duration to be right before buffer 1.
- stream_->OnSetDuration(base::Milliseconds(60));
- // Verify that there is no next buffer.
- CheckNoNextBuffer();
- // We should be able to append new buffers at this point.
- NewCodedFrameGroupAppend("120K 150");
- CheckExpectedRangesByTimestamp("{ [0,60) [120,180) }");
- }
- TEST_F(SourceBufferStreamTest,
- SetExplicitDuration_AfterGroupTimestampAndBeforeFirstBufferTimestamp) {
- NewCodedFrameGroupAppend("0K 30K 60K");
- // Append a coded frame group with a start timestamp of 200, but the first
- // buffer starts at 230ms. This can happen in muxed content where the
- // audio starts before the first frame.
- NewCodedFrameGroupAppend(base::Milliseconds(200), "230K 260K 290K 320K");
- NewCodedFrameGroupAppend("400K 430K 460K");
- CheckExpectedRangesByTimestamp("{ [0,90) [200,350) [400,490) }");
- stream_->OnSetDuration(base::Milliseconds(120));
- // Verify that the buffered ranges are updated properly and we don't crash.
- CheckExpectedRangesByTimestamp("{ [0,90) }");
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_MarkEOS) {
- // Append 1 full and 1 partial GOP: IPBBBIPBB
- NewCodedFrameGroupAppend(
- "0K 40|10 10|20 20|30 30|40 "
- "50K 90|60 60|70 70|80");
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- SeekToTimestampMs(50);
- // Set duration to be before the seeked to position.
- // This will result in truncation of the selected range and a reset
- // of NextBufferPosition.
- stream_->OnSetDuration(base::Milliseconds(40));
- // The P-frame at PTS 40ms was removed, so its dependent B-frames at PTS 10-30
- // were also removed.
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- // Mark EOS reached.
- stream_->MarkEndOfStream();
- // Expect EOS to be reached.
- CheckEOSReached();
- }
- TEST_F(SourceBufferStreamTest, SetExplicitDuration_MarkEOS_IsSeekPending) {
- // Append 1 full and 1 partial GOP: IPBBBIPBB
- NewCodedFrameGroupAppend(
- "0K 40|10 10|20 20|30 30|40 "
- "50K 90|60 60|70 70|80");
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- // Seek to 100ms will result in a pending seek.
- SeekToTimestampMs(100);
- // Set duration to be before the seeked to position.
- // This will result in truncation of the selected range and a reset
- // of NextBufferPosition.
- stream_->OnSetDuration(base::Milliseconds(40));
- // The P-frame at PTS 40ms was removed, so its dependent B-frames at PTS 10-30
- // were also removed.
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- EXPECT_TRUE(stream_->IsSeekPending());
- // Mark EOS reached.
- stream_->MarkEndOfStream();
- EXPECT_FALSE(stream_->IsSeekPending());
- }
- // Test the case were the current playback position is at the end of the
- // buffered data and several overlaps occur.
- TEST_F(SourceBufferStreamTest, OverlapWhileWaitingForMoreData) {
- // Seek to start of stream.
- SeekToTimestampMs(0);
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Read all the buffered data.
- CheckExpectedBuffers("0K 30 60 90 120K 150");
- CheckNoNextBuffer();
- // Append data over the current GOP so that a keyframe is needed before
- // playback can continue from the current position.
- NewCodedFrameGroupAppend("120K 150");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Append buffers that replace the first GOP with a partial GOP.
- NewCodedFrameGroupAppend("0K 30");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Append buffers that complete that partial GOP.
- AppendBuffers("60 90");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Verify that we still don't have a next buffer.
- CheckNoNextBuffer();
- // Add more data to the end and verify that this new data is read correctly.
- NewCodedFrameGroupAppend("180K 210");
- CheckExpectedRangesByTimestamp("{ [0,240) }");
- CheckExpectedBuffers("180K 210");
- CheckNoNextBuffer();
- }
- // Verify that a single coded frame at the current read position unblocks the
- // read even if the frame is buffered after the previously read position is
- // removed.
- TEST_F(SourceBufferStreamTest, AfterRemove_SingleFrameRange_Unblocks_Read) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90D30");
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- CheckExpectedBuffers("0K 30 60 90");
- CheckNoNextBuffer();
- RemoveInMs(0, 120, 120);
- CheckExpectedRangesByTimestamp("{ }");
- NewCodedFrameGroupAppend("120D30K");
- CheckExpectedRangesByTimestamp("{ [120,150) }");
- CheckExpectedBuffers("120K");
- CheckNoNextBuffer();
- }
- // Verify that multiple short (relative to max-inter-buffer-distance * 2) coded
- // frames at the current read position unblock the read even if the frames are
- // buffered after the previously read position is removed.
- TEST_F(SourceBufferStreamTest, AfterRemove_TinyFrames_Unblock_Read_1) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90D30");
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- CheckExpectedBuffers("0K 30 60 90");
- CheckNoNextBuffer();
- RemoveInMs(0, 120, 120);
- CheckExpectedRangesByTimestamp("{ }");
- NewCodedFrameGroupAppend("120D1K 121D1");
- CheckExpectedRangesByTimestamp("{ [120,122) }");
- CheckExpectedBuffers("120K 121");
- CheckNoNextBuffer();
- }
- // Verify that multiple short (relative to max-inter-buffer-distance * 2) coded
- // frames starting at the fudge room boundary unblock the read even if the
- // frames are buffered after the previously read position is removed.
- TEST_F(SourceBufferStreamTest, AfterRemove_TinyFrames_Unblock_Read_2) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90D30");
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- CheckExpectedBuffers("0K 30 60 90");
- CheckNoNextBuffer();
- RemoveInMs(0, 120, 120);
- CheckExpectedRangesByTimestamp("{ }");
- NewCodedFrameGroupAppend("150D1K 151D1");
- CheckExpectedRangesByTimestamp("{ [150,152) }");
- CheckExpectedBuffers("150K 151");
- CheckNoNextBuffer();
- }
- // Verify that coded frames starting after the fudge room boundary do not
- // unblock the read when buffered after the previously read position is removed.
- TEST_F(SourceBufferStreamTest, AfterRemove_BeyondFudge_Stalled) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90D30");
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- CheckExpectedBuffers("0K 30 60 90");
- CheckNoNextBuffer();
- RemoveInMs(0, 120, 120);
- CheckExpectedRangesByTimestamp("{ }");
- NewCodedFrameGroupAppend("151D1K 152D1");
- CheckExpectedRangesByTimestamp("{ [151,153) }");
- CheckNoNextBuffer();
- }
- // Verify that non-keyframes with the same timestamp in the same
- // append are handled correctly.
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 30 60 90 120K 150");
- CheckExpectedBuffers("0K 30 30 60 90 120K 150");
- }
- // Verify that a non-keyframe followed by a keyframe with the same timestamp
- // is allowed.
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_SingleAppend2) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 30K 60");
- CheckExpectedBuffers("0K 30 30K 60");
- }
- // Verify that non-keyframes with the same timestamp can occur
- // in different appends.
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30D0");
- AppendBuffers("30 60 90 120K 150");
- CheckExpectedBuffers("0K 30 30 60 90 120K 150");
- }
- // Verify that a non-keyframe followed by a keyframe with the same timestamp
- // is allowed.
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_TwoAppends2) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30D0");
- AppendBuffers("30K 60");
- CheckExpectedBuffers("0K 30 30K 60");
- }
- // Verify that a keyframe followed by a non-keyframe with the same timestamp
- // is allowed.
- TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_TwoAppends) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30D0K");
- AppendBuffers("30 60");
- CheckExpectedBuffers("0K 30K 30 60");
- }
- TEST_F(SourceBufferStreamTest, SameTimestamp_VideoKeyFrame_SingleAppend) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30K 30 60");
- CheckExpectedBuffers("0K 30K 30 60");
- }
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_1) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150");
- NewCodedFrameGroupAppend("60K 91 121K 151");
- CheckExpectedBuffers("0K 30 60K 91 121K 151");
- }
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_2) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 60 90 120K 150");
- NewCodedFrameGroupAppend("0K 30 61");
- CheckExpectedBuffers("0K 30 61 120K 150");
- }
- TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 20 40 60 80 100K 101 102 103K");
- NewCodedFrameGroupAppend("0K 20 40 60 80 90D0");
- CheckExpectedBuffers("0K 20 40 60 80 90 100K 101 102 103K");
- AppendBuffers("90 110K 150");
- Seek(0);
- CheckExpectedBuffers("0K 20 40 60 80 90 90 110K 150");
- CheckNoNextBuffer();
- CheckExpectedRangesByTimestamp("{ [0,190) }");
- }
- // Test all the valid same timestamp cases for audio.
- TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) {
- AudioDecoderConfig config(AudioCodec::kMP3, kSampleFormatF32,
- CHANNEL_LAYOUT_STEREO, 44100, EmptyExtraData(),
- EncryptionScheme::kUnencrypted);
- ResetStream<>(config);
- Seek(0);
- NewCodedFrameGroupAppend("0K 0K 30K 30K");
- CheckExpectedBuffers("0K 0K 30K 30K");
- }
- // If seeking past any existing range and the seek is pending
- // because no data has been provided for that position,
- // the stream position can be considered as the end of stream.
- TEST_F(SourceBufferStreamTest, EndSelected_During_PendingSeek) {
- // Append 15 buffers at positions 0 through 14.
- NewCodedFrameGroupAppend(0, 15);
- Seek(20);
- EXPECT_TRUE(stream_->IsSeekPending());
- stream_->MarkEndOfStream();
- EXPECT_FALSE(stream_->IsSeekPending());
- }
- // If there is a pending seek between 2 existing ranges,
- // the end of the stream has not been reached.
- TEST_F(SourceBufferStreamTest, EndNotSelected_During_PendingSeek) {
- // Append:
- // - 10 buffers at positions 0 through 9.
- // - 10 buffers at positions 30 through 39
- NewCodedFrameGroupAppend(0, 10);
- NewCodedFrameGroupAppend(30, 10);
- Seek(20);
- EXPECT_TRUE(stream_->IsSeekPending());
- stream_->MarkEndOfStream();
- EXPECT_TRUE(stream_->IsSeekPending());
- }
- // Removing exact start & end of a range.
- TEST_F(SourceBufferStreamTest, Remove_WholeRange1) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- RemoveInMs(10, 160, 160);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Removal range starts before range and ends exactly at end.
- TEST_F(SourceBufferStreamTest, Remove_WholeRange2) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- RemoveInMs(0, 160, 160);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Removal range starts at the start of a range and ends beyond the
- // range end.
- TEST_F(SourceBufferStreamTest, Remove_WholeRange3) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- RemoveInMs(10, 200, 200);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Removal range starts before range start and ends after the range end.
- TEST_F(SourceBufferStreamTest, Remove_WholeRange4) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- CheckExpectedRangesByTimestamp("{ [10,160) }");
- RemoveInMs(0, 200, 200);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Removes multiple ranges.
- TEST_F(SourceBufferStreamTest, Remove_WholeRange5) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- NewCodedFrameGroupAppend("2000K 2030 2060K 2090 2120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
- RemoveInMs(10, 3000, 3000);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Verifies a [0-infinity) range removes everything.
- TEST_F(SourceBufferStreamTest, Remove_ZeroToInfinity) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- NewCodedFrameGroupAppend("2000K 2030 2060K 2090 2120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
- Remove(base::TimeDelta(), kInfiniteDuration, kInfiniteDuration);
- CheckExpectedRangesByTimestamp("{ }");
- }
- // Removal range starts at the beginning of the range and ends in the
- // middle of the range. This test verifies that full GOPs are removed.
- TEST_F(SourceBufferStreamTest, Remove_Partial1) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
- RemoveInMs(0, 80, 2200);
- CheckExpectedRangesByTimestamp("{ [130,160) [1000,1150) }");
- }
- // Removal range starts in the middle of a range and ends at the exact
- // end of the range.
- TEST_F(SourceBufferStreamTest, Remove_Partial2) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
- RemoveInMs(40, 160, 2200);
- CheckExpectedRangesByTimestamp("{ [10,40) [1000,1150) }");
- }
- // Removal range starts and ends within a range.
- TEST_F(SourceBufferStreamTest, Remove_Partial3) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) }");
- RemoveInMs(40, 120, 2200);
- CheckExpectedRangesByTimestamp("{ [10,40) [130,160) [1000,1150) }");
- }
- // Removal range starts in the middle of one range and ends in the
- // middle of another range.
- TEST_F(SourceBufferStreamTest, Remove_Partial4) {
- Seek(0);
- NewCodedFrameGroupAppend("10K 40 70K 100 130K");
- NewCodedFrameGroupAppend("1000K 1030 1060K 1090 1120K");
- NewCodedFrameGroupAppend("2000K 2030 2060K 2090 2120K");
- CheckExpectedRangesByTimestamp("{ [10,160) [1000,1150) [2000,2150) }");
- RemoveInMs(40, 2030, 2200);
- CheckExpectedRangesByTimestamp("{ [10,40) [2060,2150) }");
- }
- // Test behavior when the current position is removed and new buffers
- // are appended over the removal range.
- TEST_F(SourceBufferStreamTest, Remove_CurrentPosition) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- CheckExpectedBuffers("0K 30 60 90K 120");
- // Remove a range that includes the next buffer (i.e., 150).
- RemoveInMs(150, 210, 360);
- CheckExpectedRangesByTimestamp("{ [0,150) [270,360) }");
- // Verify that no next buffer is returned.
- CheckNoNextBuffer();
- // Append some buffers to fill the gap that was created.
- NewCodedFrameGroupAppend("120K 150 180 210K 240");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- // Verify that buffers resume at the next keyframe after the
- // current position.
- CheckExpectedBuffers("210K 240 270K 300 330");
- }
- // Test behavior when buffers in the selected range before the current position
- // are removed.
- TEST_F(SourceBufferStreamTest, Remove_BeforeCurrentPosition) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90K 120 150 180K 210 240 270K 300 330");
- CheckExpectedRangesByTimestamp("{ [0,360) }");
- CheckExpectedBuffers("0K 30 60 90K 120");
- // Remove a range that is before the current playback position.
- RemoveInMs(0, 90, 360);
- CheckExpectedRangesByTimestamp("{ [90,360) }");
- CheckExpectedBuffers("150 180K 210 240 270K 300 330");
- }
- // Test removing the preliminary portion for the current coded frame group being
- // appended.
- TEST_F(SourceBufferStreamTest, Remove_MidGroup) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150 180 210");
- CheckExpectedRangesByTimestamp("{ [0,240) }");
- // Partially replace the first GOP, then read its keyframe.
- NewCodedFrameGroupAppend("0K 30");
- CheckExpectedBuffers("0K");
- CheckExpectedRangesByTimestamp("{ [0,240) }");
- // Remove the partial GOP that we're in the middle of reading.
- RemoveInMs(0, 60, 240);
- // Verify that there is no next buffer since it was removed and the remaining
- // buffered range is beyond the current position.
- CheckNoNextBuffer();
- CheckExpectedRangesByTimestamp("{ [120,240) }");
- // Continue appending frames for the current GOP.
- AppendBuffers("60 90");
- // Verify that the non-keyframes are not added.
- CheckExpectedRangesByTimestamp("{ [120,240) }");
- // Finish the previous GOP and start the next one.
- AppendBuffers("120 150K 180");
- // Verify that new GOP replaces the existing GOP.
- CheckExpectedRangesByTimestamp("{ [150,210) }");
- SeekToTimestampMs(150);
- CheckExpectedBuffers("150K 180");
- CheckNoNextBuffer();
- }
- // Test removing the current GOP being appended, while not removing
- // the entire range the GOP belongs to.
- TEST_F(SourceBufferStreamTest, Remove_GOPBeingAppended) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 30 60 90 120K 150 180");
- CheckExpectedRangesByTimestamp("{ [0,210) }");
- // Remove the current GOP being appended.
- RemoveInMs(120, 150, 240);
- CheckExpectedRangesByTimestamp("{ [0,120) }");
- // Continue appending the current GOP and the next one.
- AppendBuffers("210 240K 270 300");
- // Verify that the non-keyframe in the previous GOP does
- // not effect any existing ranges and a new range is started at the
- // beginning of the next GOP.
- CheckExpectedRangesByTimestamp("{ [0,120) [240,330) }");
- // Verify the buffers in the ranges.
- CheckExpectedBuffers("0K 30 60 90");
- CheckNoNextBuffer();
- SeekToTimestampMs(240);
- CheckExpectedBuffers("240K 270 300");
- }
- TEST_F(SourceBufferStreamTest, Remove_WholeGOPBeingAppended) {
- SeekToTimestampMs(1000);
- NewCodedFrameGroupAppend("1000K 1030 1060 1090");
- CheckExpectedRangesByTimestamp("{ [1000,1120) }");
- // Remove the keyframe of the current GOP being appended.
- RemoveInMs(1000, 1030, 1120);
- CheckExpectedRangesByTimestamp("{ }");
- // Continue appending the current GOP.
- AppendBuffers("1210 1240");
- CheckExpectedRangesByTimestamp("{ }");
- // Append the beginning of the next GOP.
- AppendBuffers("1270K 1300");
- // Verify that the new range is started at the
- // beginning of the next GOP.
- CheckExpectedRangesByTimestamp("{ [1270,1330) }");
- // Verify the buffers in the ranges.
- CheckNoNextBuffer();
- SeekToTimestampMs(1270);
- CheckExpectedBuffers("1270K 1300");
- }
- TEST_F(SourceBufferStreamTest,
- Remove_PreviousAppendDestroyedAndOverwriteExistingRange) {
- SeekToTimestampMs(90);
- NewCodedFrameGroupAppend("90K 120 150");
- CheckExpectedRangesByTimestamp("{ [90,180) }");
- // Append a coded frame group before the previously appended data.
- NewCodedFrameGroupAppend("0K 30 60");
- // Verify that the ranges get merged.
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Remove the data from the last append.
- RemoveInMs(0, 90, 360);
- CheckExpectedRangesByTimestamp("{ [90,180) }");
- // Append a new coded frame group that follows the removed group and
- // starts at the beginning of the range left over from the
- // remove.
- NewCodedFrameGroupAppend("90K 121 151");
- CheckExpectedBuffers("90K 121 151");
- }
- TEST_F(SourceBufferStreamTest, Remove_GapAtBeginningOfGroup) {
- Seek(0);
- // Append a coded frame group that has a gap at the beginning of it.
- NewCodedFrameGroupAppend(base::Milliseconds(0), "30K 60 90 120K 150");
- CheckExpectedRangesByTimestamp("{ [0,180) }");
- // Remove the gap that doesn't contain any buffers.
- RemoveInMs(0, 10, 180);
- CheckExpectedRangesByTimestamp("{ [10,180) }");
- // Verify we still get the first buffer still since only part of
- // the gap was removed.
- // TODO(acolwell/wolenetz): Consider not returning a buffer at this
- // point since the current seek position has been explicitly
- // removed but didn't happen to remove any buffers.
- // http://crbug.com/384016
- CheckExpectedBuffers("30K");
- // Remove a range that includes the first GOP.
- RemoveInMs(0, 60, 180);
- // Verify that no buffer is returned because the current buffer
- // position has been removed.
- CheckNoNextBuffer();
- CheckExpectedRangesByTimestamp("{ [120,180) }");
- }
- TEST_F(SourceBufferStreamTest,
- OverlappingAppendRangeMembership_OneMicrosecond_Video) {
- NewCodedFrameGroupAppend("10D20K");
- CheckExpectedRangesByTimestamp("{ [10000,30000) }",
- TimeGranularity::kMicrosecond);
- // Append a buffer 1 microsecond earlier, with estimated duration.
- NewCodedFrameGroupAppend("9999uD20EK");
- CheckExpectedRangesByTimestamp("{ [9999,30000) }",
- TimeGranularity::kMicrosecond);
- // Append that same buffer again, but without any discontinuity signalled / no
- // new coded frame group.
- AppendBuffers("9999uD20EK");
- CheckExpectedRangesByTimestamp("{ [9999,30000) }",
- TimeGranularity::kMicrosecond);
- Seek(0);
- CheckExpectedBuffers("9999K 9999K 10000K", TimeGranularity::kMicrosecond);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- OverlappingAppendRangeMembership_TwoMicroseconds_Video) {
- NewCodedFrameGroupAppend("10D20K");
- CheckExpectedRangesByTimestamp("{ [10000,30000) }",
- TimeGranularity::kMicrosecond);
- // Append an exactly abutting buffer 2us earlier.
- NewCodedFrameGroupAppend("9998uD20EK");
- CheckExpectedRangesByTimestamp("{ [9998,30000) }",
- TimeGranularity::kMicrosecond);
- // Append that same buffer again, but without any discontinuity signalled / no
- // new coded frame group.
- AppendBuffers("9998uD20EK");
- CheckExpectedRangesByTimestamp("{ [9998,30000) }",
- TimeGranularity::kMicrosecond);
- Seek(0);
- CheckExpectedBuffers("9998K 9998K 10000K", TimeGranularity::kMicrosecond);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Text_Append_SingleRange) {
- SetTextStream();
- NewCodedFrameGroupAppend("0K 500K 1000K");
- CheckExpectedRangesByTimestamp("{ [0,1500) }");
- Seek(0);
- CheckExpectedBuffers("0K 500K 1000K");
- }
- TEST_F(SourceBufferStreamTest, Text_Append_DisjointAfter) {
- SetTextStream();
- NewCodedFrameGroupAppend("0K 500K 1000K");
- CheckExpectedRangesByTimestamp("{ [0,1500) }");
- NewCodedFrameGroupAppend("3000K 3500K 4000K");
- CheckExpectedRangesByTimestamp("{ [0,4500) }");
- Seek(0);
- CheckExpectedBuffers("0K 500K 1000K 3000K 3500K 4000K");
- }
- TEST_F(SourceBufferStreamTest, Text_Append_DisjointBefore) {
- SetTextStream();
- NewCodedFrameGroupAppend("3000K 3500K 4000K");
- CheckExpectedRangesByTimestamp("{ [3000,4500) }");
- NewCodedFrameGroupAppend("0K 500K 1000K");
- CheckExpectedRangesByTimestamp("{ [0,4500) }");
- Seek(0);
- CheckExpectedBuffers("0K 500K 1000K 3000K 3500K 4000K");
- }
- TEST_F(SourceBufferStreamTest, Text_CompleteOverlap) {
- SetTextStream();
- NewCodedFrameGroupAppend("3000K 3500K 4000K");
- CheckExpectedRangesByTimestamp("{ [3000,4500) }");
- NewCodedFrameGroupAppend(
- "0K 501K 1001K 1501K 2001K 2501K "
- "3001K 3501K 4001K 4501K 5001K");
- CheckExpectedRangesByTimestamp("{ [0,5501) }");
- Seek(0);
- CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 2501K "
- "3001K 3501K 4001K 4501K 5001K");
- }
- TEST_F(SourceBufferStreamTest, Text_OverlapAfter) {
- SetTextStream();
- NewCodedFrameGroupAppend("0K 500K 1000K 1500K 2000K");
- CheckExpectedRangesByTimestamp("{ [0,2500) }");
- NewCodedFrameGroupAppend("1499K 2001K 2501K 3001K");
- CheckExpectedRangesByTimestamp("{ [0,3501) }");
- Seek(0);
- CheckExpectedBuffers("0K 500K 1000K 1499K 2001K 2501K 3001K");
- }
- TEST_F(SourceBufferStreamTest, Text_OverlapBefore) {
- SetTextStream();
- NewCodedFrameGroupAppend("1500K 2000K 2500K 3000K 3500K");
- CheckExpectedRangesByTimestamp("{ [1500,4000) }");
- NewCodedFrameGroupAppend("0K 501K 1001K 1501K 2001K");
- CheckExpectedRangesByTimestamp("{ [0,4000) }");
- Seek(0);
- CheckExpectedBuffers("0K 501K 1001K 1501K 2001K 3000K 3500K");
- }
- TEST_F(SourceBufferStreamTest, Audio_SpliceTrimmingForOverlap) {
- SetAudioStream();
- Seek(0);
- NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K 12K");
- CheckExpectedRangesByTimestamp("{ [0,14) }");
- // Note that duration of frame at time 10 is verified to be 2 ms.
- CheckExpectedBuffers("0K 2K 4K 6K 8K 10D2K 12K");
- CheckNoNextBuffer();
- // Append new group with front slightly overlapping existing buffer at 10ms.
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(11000, 10000, 1000));
- NewCodedFrameGroupAppend("11K 13K 15K 17K");
- // Cross-fade splicing is no longer implemented. Instead we should expect
- // wholly overlapped buffers to be removed (12K). If a buffer is partially
- // overlapped (e.g. last millisecond of 10K), the existing buffer should be
- // trimmed to perfectly abut the newly appended buffers.
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,19) }");
- CheckExpectedBuffers("0K 2K 4K 6K 8K 10D1K 11D2K 13K 15K 17K");
- CheckNoNextBuffer();
- }
- // Test that a splice is not created if an end timestamp and start timestamp
- // perfectly overlap.
- TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) {
- SetAudioStream();
- Seek(0);
- // Add 10 frames across 2 *non-overlapping* appends.
- NewCodedFrameGroupAppend("0K 2K 4K 6K 8K 10K");
- NewCodedFrameGroupAppend("12K 14K 16K 18K");
- // Manually inspect the buffers at the no-splice boundary to verify duration
- // and lack of discard padding (set when splicing).
- scoped_refptr<StreamParserBuffer> buffer;
- const DecoderBuffer::DiscardPadding kEmptyDiscardPadding;
- for (int i = 0; i < 10; i++) {
- // Verify buffer timestamps and durations are preserved and no buffers have
- // discard padding (indicating no splice trimming).
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&buffer));
- EXPECT_EQ(base::Milliseconds(i * 2), buffer->timestamp());
- EXPECT_EQ(base::Milliseconds(2), buffer->duration());
- EXPECT_EQ(kEmptyDiscardPadding, buffer->discard_padding());
- }
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_NoSpliceForBadOverlap) {
- SetAudioStream();
- Seek(0);
- // Add 2 frames with matching PTS and ov, where the duration of the first
- // frame suggests that it overlaps the second frame. The overlap is within a
- // coded frame group (bad content), so no splicing is expected.
- NewCodedFrameGroupAppend("0D10K 0D10K");
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- CheckExpectedBuffers("0D10K 0D10K");
- CheckNoNextBuffer();
- Seek(0);
- // Add a new frame in a separate coded frame group that falls into the
- // overlap of the two existing frames. Splicing should not be performed since
- // the content is poorly muxed. We can't know which frame to splice when the
- // content is already messed up.
- EXPECT_MEDIA_LOG(NoSpliceForBadMux(2, 2000));
- NewCodedFrameGroupAppend("2D10K");
- CheckExpectedRangesByTimestamp("{ [0,12) }");
- CheckExpectedBuffers("0D10K 0D10K 2D10K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_NoSpliceForEstimatedDuration) {
- SetAudioStream();
- Seek(0);
- // Append two buffers, the latter having estimated duration.
- NewCodedFrameGroupAppend("0D10K 10D10EK");
- CheckExpectedRangesByTimestamp("{ [0,20) }");
- CheckExpectedBuffers("0D10K 10D10EK");
- CheckNoNextBuffer();
- Seek(0);
- // Add a new frame in a separate coded frame group that falls in the middle of
- // the second buffer. In spite of the overlap, no splice should be performed
- // due to the overlapped buffer having estimated duration.
- NewCodedFrameGroupAppend("15D10K");
- CheckExpectedRangesByTimestamp("{ [0,25) }");
- CheckExpectedBuffers("0D10K 10D10EK 15D10K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_SpliceTrimming_ExistingTrimming) {
- const base::TimeDelta kDuration = base::Milliseconds(4);
- const base::TimeDelta kNoDiscard = base::TimeDelta();
- const bool is_keyframe = true;
- SetAudioStream();
- Seek(0);
- // Make two BufferQueues with a mix of buffers containing start/end discard.
- // Buffer PTS and duration have been adjusted to reflect discard. A_buffers
- // will be appended first, then B_buffers. The start of B will overlap A
- // to generate a splice.
- BufferQueue A_buffers;
- BufferQueue B_buffers;
- // Buffer A1: PTS = 0, front discard = 2ms, duration = 2ms.
- scoped_refptr<StreamParserBuffer> bufferA1 = StreamParserBuffer::CopyFrom(
- &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
- bufferA1->set_timestamp(base::Milliseconds(0));
- bufferA1->set_duration(kDuration / 2);
- const DecoderBuffer::DiscardPadding discardA1 =
- std::make_pair(kDuration / 2, kNoDiscard);
- bufferA1->set_discard_padding(discardA1);
- A_buffers.push_back(bufferA1);
- // Buffer A2: PTS = 2, end discard = 2ms, duration = 2ms.
- scoped_refptr<StreamParserBuffer> bufferA2 = StreamParserBuffer::CopyFrom(
- &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
- bufferA2->set_timestamp(base::Milliseconds(2));
- bufferA2->set_duration(kDuration / 2);
- const DecoderBuffer::DiscardPadding discardA2 =
- std::make_pair(kNoDiscard, kDuration / 2);
- bufferA2->set_discard_padding(discardA2);
- A_buffers.push_back(bufferA2);
- // Buffer B1: PTS = 3, front discard = 2ms, duration = 2ms.
- scoped_refptr<StreamParserBuffer> bufferB1 = StreamParserBuffer::CopyFrom(
- &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
- bufferB1->set_timestamp(base::Milliseconds(3));
- bufferB1->set_duration(kDuration / 2);
- const DecoderBuffer::DiscardPadding discardB1 =
- std::make_pair(kDuration / 2, kNoDiscard);
- bufferB1->set_discard_padding(discardB1);
- B_buffers.push_back(bufferB1);
- // Buffer B2: PTS = 5, no discard padding, duration = 4ms.
- scoped_refptr<StreamParserBuffer> bufferB2 = StreamParserBuffer::CopyFrom(
- &kDataA, kDataSize, is_keyframe, DemuxerStream::AUDIO, 0);
- bufferB2->set_timestamp(base::Milliseconds(5));
- bufferB2->set_duration(kDuration);
- B_buffers.push_back(bufferB2);
- // Append buffers, trigger splice trimming.
- stream_->OnStartOfCodedFrameGroup(bufferA1->timestamp());
- stream_->Append(A_buffers);
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(3000, 2000, 1000));
- stream_->Append(B_buffers);
- // Verify buffers.
- scoped_refptr<StreamParserBuffer> read_buffer;
- // Buffer A1 was not spliced, should be unchanged.
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&read_buffer));
- EXPECT_EQ(base::Milliseconds(0), read_buffer->timestamp());
- EXPECT_EQ(kDuration / 2, read_buffer->duration());
- EXPECT_EQ(discardA1, read_buffer->discard_padding());
- // Buffer A2 was overlapped by buffer B1 1ms. Splice trimming should trim A2's
- // duration and increase its discard padding by 1ms.
- const base::TimeDelta overlap = base::Milliseconds(1);
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&read_buffer));
- EXPECT_EQ(base::Milliseconds(2), read_buffer->timestamp());
- EXPECT_EQ((kDuration / 2) - overlap, read_buffer->duration());
- const DecoderBuffer::DiscardPadding overlap_discard =
- std::make_pair(discardA2.first, discardA2.second + overlap);
- EXPECT_EQ(overlap_discard, read_buffer->discard_padding());
- // Buffer B1 is overlapping A2, but B1 should be unchanged - splice trimming
- // only modifies the earlier buffer (A1).
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&read_buffer));
- EXPECT_EQ(base::Milliseconds(3), read_buffer->timestamp());
- EXPECT_EQ(kDuration / 2, read_buffer->duration());
- EXPECT_EQ(discardB1, read_buffer->discard_padding());
- // Buffer B2 is not spliced, should be unchanged.
- EXPECT_STATUS_FOR_STREAM_OP(kSuccess, GetNextBuffer(&read_buffer));
- EXPECT_EQ(base::Milliseconds(5), read_buffer->timestamp());
- EXPECT_EQ(kDuration, read_buffer->duration());
- EXPECT_EQ(std::make_pair(kNoDiscard, kNoDiscard),
- read_buffer->discard_padding());
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) {
- EXPECT_MEDIA_LOG(SkippingSpliceTooLittleOverlap(1250, 250));
- video_config_ = TestVideoConfig::Invalid();
- audio_config_.Initialize(
- AudioCodec::kVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 4000,
- EmptyExtraData(), EncryptionScheme::kUnencrypted, base::TimeDelta(), 0);
- ResetStream<>(audio_config_);
- // Equivalent to 0.5ms per frame.
- SetStreamInfo(2000, 2000);
- Seek(0);
- // Append four buffers with a 0.5ms duration each.
- NewCodedFrameGroupAppend(0, 4);
- CheckExpectedRangesByTimestamp("{ [0,2) }");
- // Overlap the range [0, 2) with [1.25, 2); this results in an overlap of
- // 0.25ms between the original buffer at time 1.0 and the new buffer at time
- // 1.25.
- NewCodedFrameGroupAppend_OffsetFirstBuffer(2, 2, base::Milliseconds(0.25));
- CheckExpectedRangesByTimestamp("{ [0,2) }");
- // A splice frame should not be generated since it requires at least 1ms of
- // data to crossfade.
- CheckExpectedBuffers("0K 0K 1K 1K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_PrerollFrame) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 3P 6K");
- CheckExpectedBuffers("0K 3P 6K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_ConfigChangeWithPreroll) {
- AudioDecoderConfig new_config(AudioCodec::kVorbis, kSampleFormatPlanarF32,
- CHANNEL_LAYOUT_MONO, 2000, EmptyExtraData(),
- EncryptionScheme::kUnencrypted);
- SetAudioStream();
- Seek(0);
- // Append some audio using the default configuration.
- CheckAudioConfig(audio_config_);
- NewCodedFrameGroupAppend("0K 3K 6K");
- // Update the configuration.
- stream_->UpdateAudioConfig(new_config, false);
- // We haven't read any buffers at this point, so the config for the next
- // buffer at time 0 should still be the original config.
- CheckAudioConfig(audio_config_);
- // Append new audio containing preroll and using the new config.
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(7000, 6000, 2000));
- NewCodedFrameGroupAppend("7P 8K");
- // Check buffers from the first append.
- CheckExpectedBuffers("0K 3K 6K");
- // Verify the next attempt to get a buffer will signal that a config change
- // has happened.
- scoped_refptr<StreamParserBuffer> buffer;
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- // Verify upcoming buffers will use the new config.
- CheckAudioConfig(new_config);
- // Check buffers from the second append, including preroll.
- // CheckExpectedBuffers("6P 7K 8K");
- CheckExpectedBuffers("7P 8K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, Audio_Opus_SeekToJustBeforeRangeStart) {
- // Seek to a time within the fudge room of seekability to a buffered Opus
- // audio frame's range, but before the range's start. Use small seek_preroll
- // in case the associated logic to check same config in the preroll time
- // interval requires a nonzero seek_preroll value.
- video_config_ = TestVideoConfig::Invalid();
- audio_config_.Initialize(AudioCodec::kOpus, kSampleFormatPlanarF32,
- CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(),
- EncryptionScheme::kUnencrypted,
- base::Milliseconds(10), 0);
- ResetStream<>(audio_config_);
- // Equivalent to 1s per frame.
- SetStreamInfo(1, 1);
- Seek(0);
- // Append a buffer at 1.5 seconds, with duration 1 second, increasing the
- // fudge room to 2 * 1 seconds. The pending seek to time 0 should be satisfied
- // with this buffer's range, because that seek time is within the fudge room
- // of 2.
- NewCodedFrameGroupAppend("1500D1000K");
- CheckExpectedRangesByTimestamp("{ [1500,2500) }");
- CheckExpectedBuffers("1500K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, BFrames) {
- Seek(0);
- NewCodedFrameGroupAppend("0K 120|30 30|60 60|90 90|120");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- CheckExpectedBuffers("0K 120|30 30|60 60|90 90|120");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, RemoveShouldAlwaysExcludeEnd) {
- NewCodedFrameGroupAppend("10D2K 12D2 14D2");
- CheckExpectedRangesByTimestamp("{ [10,16) }");
- // Start new coded frame group, appending KF to abut the start of previous
- // group.
- NewCodedFrameGroupAppend("0D10K");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,16) }");
- CheckExpectedBuffers("0K 10K 12 14");
- CheckNoNextBuffer();
- // Append another buffer with the same timestamp as the last KF. This triggers
- // special logic that allows two buffers to have the same timestamp. When
- // preparing for this new append, there is no reason to remove the later GOP
- // starting at timestamp 10. This verifies the fix for http://crbug.com/469325
- // where the decision *not* to remove the start of the overlapped range was
- // erroneously triggering buffers with a timestamp matching the end
- // of the append (and any later dependent frames) to be removed.
- AppendBuffers("0D10");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,16) }");
- CheckExpectedBuffers("0K 0 10K 12 14");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_BackOverlap) {
- // Append a few buffers, the last one having estimated duration.
- NewCodedFrameGroupAppend("0K 5 10 20D10E");
- CheckExpectedRangesByTimestamp("{ [0,30) }");
- Seek(0);
- CheckExpectedBuffers("0K 5 10 20D10E");
- CheckNoNextBuffer();
- // Append a buffer to the end that overlaps the *back* of the existing range.
- // This should trigger the estimated duration to be recomputed as a timestamp
- // delta.
- AppendBuffers("25D10");
- CheckExpectedRangesByTimestamp("{ [0,35) }");
- Seek(0);
- // The duration of the buffer at time 20 has changed from 10ms to 5ms.
- CheckExpectedBuffers("0K 5 10 20D5E 25");
- CheckNoNextBuffer();
- // If the last buffer is removed, the adjusted duration should remain at 5ms.
- RemoveInMs(25, 35, 35);
- CheckExpectedRangesByTimestamp("{ [0,25) }");
- Seek(0);
- CheckExpectedBuffers("0K 5 10 20D5E");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, RefinedDurationEstimates_FrontOverlap) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("10K 15 20D5");
- CheckExpectedRangesByTimestamp("{ [10,25) }");
- SeekToTimestampMs(10);
- CheckExpectedBuffers("10K 15 20");
- CheckNoNextBuffer();
- // Append new buffers, where the last has estimated duration that overlaps the
- // *front* of the existing range. The overlap should trigger refinement of the
- // estimated duration from 7ms to 5ms.
- NewCodedFrameGroupAppend("0K 5D7E");
- CheckExpectedRangesByTimestamp("{ [0,25) }");
- Seek(0);
- CheckExpectedBuffers("0K 5D5E 10K 15 20");
- CheckNoNextBuffer();
- // If the overlapped buffer at timestamp 10 is removed, the adjusted duration
- // should remain adjusted.
- RemoveInMs(10, 20, 25);
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- Seek(0);
- CheckExpectedBuffers("0K 5D5E");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, SeekToStartSatisfiedUpToThreshold) {
- NewCodedFrameGroupAppend("999K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [999,1030) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("999K 1010 1020D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, SeekToStartUnsatisfiedBeyondThreshold) {
- NewCodedFrameGroupAppend("1000K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [1000,1030) }");
- SeekToTimestampMs(0);
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- ReSeekToStartSatisfiedUpToThreshold_SameTimestamps) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("999K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [999,1030) }");
- // Don't read any buffers between Seek and Remove.
- SeekToTimestampMs(0);
- RemoveInMs(999, 1030, 1030);
- CheckExpectedRangesByTimestamp("{ }");
- CheckNoNextBuffer();
- // Append buffers at the original timestamps and verify no stall.
- NewCodedFrameGroupAppend("999K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [999,1030) }");
- CheckExpectedBuffers("999K 1010 1020D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- ReSeekToStartSatisfiedUpToThreshold_EarlierTimestamps) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("999K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [999,1030) }");
- // Don't read any buffers between Seek and Remove.
- SeekToTimestampMs(0);
- RemoveInMs(999, 1030, 1030);
- CheckExpectedRangesByTimestamp("{ }");
- CheckNoNextBuffer();
- // Append buffers before the original timestamps and verify no stall (the
- // re-seek to time 0 should still be satisfied with the new buffers).
- NewCodedFrameGroupAppend("500K 510 520D10");
- CheckExpectedRangesByTimestamp("{ [500,530) }");
- CheckExpectedBuffers("500K 510 520D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- ReSeekToStartSatisfiedUpToThreshold_LaterTimestamps) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("500K 510 520D10");
- CheckExpectedRangesByTimestamp("{ [500,530) }");
- // Don't read any buffers between Seek and Remove.
- SeekToTimestampMs(0);
- RemoveInMs(500, 530, 530);
- CheckExpectedRangesByTimestamp("{ }");
- CheckNoNextBuffer();
- // Append buffers beginning after original timestamps, but still below the
- // start threshold, and verify no stall (the re-seek to time 0 should still be
- // satisfied with the new buffers).
- NewCodedFrameGroupAppend("999K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [999,1030) }");
- CheckExpectedBuffers("999K 1010 1020D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, ReSeekBeyondStartThreshold_SameTimestamps) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("1000K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [1000,1030) }");
- // Don't read any buffers between Seek and Remove.
- SeekToTimestampMs(1000);
- RemoveInMs(1000, 1030, 1030);
- CheckExpectedRangesByTimestamp("{ }");
- CheckNoNextBuffer();
- // Append buffers at the original timestamps and verify no stall.
- NewCodedFrameGroupAppend("1000K 1010 1020D10");
- CheckExpectedRangesByTimestamp("{ [1000,1030) }");
- CheckExpectedBuffers("1000K 1010 1020D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, ReSeekBeyondThreshold_EarlierTimestamps) {
- // Append a few buffers.
- NewCodedFrameGroupAppend("2000K 2010 2020D10");
- CheckExpectedRangesByTimestamp("{ [2000,2030) }");
- // Don't read any buffers between Seek and Remove.
- SeekToTimestampMs(2000);
- RemoveInMs(2000, 2030, 2030);
- CheckExpectedRangesByTimestamp("{ }");
- CheckNoNextBuffer();
- // Append buffers before the original timestamps and verify no stall (the
- // re-seek to time 2 seconds should still be satisfied with the new buffers
- // and should emit preroll from last keyframe).
- NewCodedFrameGroupAppend("1080K 1090 2000D10");
- CheckExpectedRangesByTimestamp("{ [1080,2010) }");
- CheckExpectedBuffers("1080K 1090 2000D10");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, ConfigChange_ReSeek) {
- // Append a few buffers, with a config change in the middle.
- VideoDecoderConfig new_config = TestVideoConfig::Large();
- NewCodedFrameGroupAppend("2000K 2010 2020D10");
- stream_->UpdateVideoConfig(new_config, false);
- NewCodedFrameGroupAppend("2030K 2040 2050D10");
- CheckExpectedRangesByTimestamp("{ [2000,2060) }");
- // Read the config change, but don't read any non-config-change buffer between
- // Seek and Remove.
- scoped_refptr<StreamParserBuffer> buffer;
- CheckVideoConfig(video_config_);
- SeekToTimestampMs(2030);
- CheckVideoConfig(video_config_);
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- CheckVideoConfig(new_config);
- // Trigger the re-seek.
- RemoveInMs(2030, 2060, 2060);
- CheckExpectedRangesByTimestamp("{ [2000,2030) }");
- CheckNoNextBuffer();
- // Append buffers at the original timestamps and verify no stall or redundant
- // signalling of config change.
- NewCodedFrameGroupAppend("2030K 2040 2050D10");
- CheckVideoConfig(new_config);
- CheckExpectedRangesByTimestamp("{ [2000,2060) }");
- CheckExpectedBuffers("2030K 2040 2050D10");
- CheckNoNextBuffer();
- CheckVideoConfig(new_config);
- // Seek to the start of buffered and verify config changes and buffers.
- SeekToTimestampMs(2000);
- CheckVideoConfig(new_config);
- ASSERT_FALSE(new_config.Matches(video_config_));
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- CheckVideoConfig(video_config_);
- CheckExpectedBuffers("2000K 2010 2020D10");
- CheckVideoConfig(video_config_);
- EXPECT_STATUS_FOR_STREAM_OP(kConfigChange, GetNextBuffer(&buffer));
- CheckVideoConfig(new_config);
- CheckExpectedBuffers("2030K 2040 2050D10");
- CheckNoNextBuffer();
- CheckVideoConfig(new_config);
- }
- TEST_F(SourceBufferStreamTest, TrackBuffer_ExhaustionWithSkipForward) {
- NewCodedFrameGroupAppend("0K 10 20 30 40");
- // Read the first 4 buffers, so next buffer is at time 40.
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,50) }");
- CheckExpectedBuffers("0K 10 20 30");
- // Overlap-append, populating track buffer with timestamp 40 from original
- // append. Confirm there could be a large jump in time until the next key
- // frame after exhausting the track buffer.
- NewCodedFrameGroupAppend(
- "31K 41 51 61 71 81 91 101 111 121 "
- "131K 141");
- CheckExpectedRangesByTimestamp("{ [0,151) }");
- // Confirm the large jump occurs and warning log is generated.
- // If this test is changed, update
- // TrackBufferExhaustion_ImmediateNewTrackBuffer accordingly.
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(91));
- CheckExpectedBuffers("40 131K 141");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- TrackBuffer_ExhaustionAndImmediateNewTrackBuffer) {
- NewCodedFrameGroupAppend("0K 10 20 30 40");
- // Read the first 4 buffers, so next buffer is at time 40.
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,50) }");
- CheckExpectedBuffers("0K 10 20 30");
- // Overlap-append
- NewCodedFrameGroupAppend(
- "31K 41 51 61 71 81 91 101 111 121 "
- "131K 141");
- CheckExpectedRangesByTimestamp("{ [0,151) }");
- // Exhaust the track buffer, but don't read any of the overlapping append yet.
- CheckExpectedBuffers("40");
- // Selected range's next buffer is now the 131K buffer from the overlapping
- // append. (See TrackBuffer_ExhaustionWithSkipForward for that verification.)
- // Do another overlap-append to immediately create another track buffer and
- // verify both track buffer exhaustions skip forward and emit log warnings.
- NewCodedFrameGroupAppend(
- "22K 32 42 52 62 72 82 92 102 112 122K 132 142 152K 162");
- CheckExpectedRangesByTimestamp("{ [0,172) }");
- InSequence s;
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(91));
- EXPECT_MEDIA_LOG(ContainsTrackBufferExhaustionSkipLog(11));
- CheckExpectedBuffers("131K 141 152K 162");
- CheckNoNextBuffer();
- }
- TEST_F(
- SourceBufferStreamTest,
- AdjacentCodedFrameGroupContinuation_NoGapCreatedByTinyGapInGroupContinuation) {
- NewCodedFrameGroupAppend("0K 10 20K 30 40K 50D10");
- CheckExpectedRangesByTimestamp("{ [0,60) }");
- // Continue appending to the previously started coded frame group, albeit with
- // a tiny (1ms) gap. This gap should *NOT* produce a buffered range gap.
- AppendBuffers("61K 71D10");
- CheckExpectedRangesByTimestamp("{ [0,81) }");
- }
- TEST_F(SourceBufferStreamTest,
- AdjacentCodedFrameGroupContinuation_NoGapCreatedPrefixRemoved) {
- NewCodedFrameGroupAppend("0K 10 20K 30 40K 50D10");
- CheckExpectedRangesByTimestamp("{ [0,60) }");
- RemoveInMs(0, 35, 60);
- CheckExpectedRangesByTimestamp("{ [40,60) }");
- // Continue appending to the previously started coded frame group, albeit with
- // a tiny (1ms) gap. This gap should *NOT* produce a buffered range gap.
- AppendBuffers("61K 71D10");
- CheckExpectedRangesByTimestamp("{ [40,81) }");
- }
- TEST_F(SourceBufferStreamTest,
- AdjacentNewCodedFrameGroupContinuation_NoGapCreatedPrefixRemoved) {
- NewCodedFrameGroupAppend("0K 10 20K 30 40K 50D10");
- CheckExpectedRangesByTimestamp("{ [0,60) }");
- RemoveInMs(0, 35, 60);
- CheckExpectedRangesByTimestamp("{ [40,60) }");
- // Continue appending, with a new coded frame group, albeit with
- // a tiny (1ms) gap. This gap should *NOT* produce a buffered range gap.
- // This test demonstrates the "pre-relaxation" behavior, where a new "media
- // segment" (now a new "coded frame group") was signaled at every media
- // segment boundary.
- NewCodedFrameGroupAppend("61K 71D10");
- CheckExpectedRangesByTimestamp("{ [40,81) }");
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_RemoveThenAppendMoreMuchLater) {
- NewCodedFrameGroupAppend("1000K 1010 1020 1030K 1040 1050 1060K 1070 1080");
- NewCodedFrameGroupAppend("0K 10 20");
- CheckExpectedRangesByTimestamp("{ [0,30) [1000,1090) }");
- SignalStartOfCodedFrameGroup(base::Milliseconds(1070));
- CheckExpectedRangesByTimestamp("{ [0,30) [1000,1090) }");
- RemoveInMs(1030, 1050, 1090);
- CheckExpectedRangesByTimestamp("{ [0,30) [1000,1030) [1060,1090) }");
- // We've signalled that we're about to do some appends to a coded frame group
- // which starts at time 1070ms. Note that the first frame, if any ever,
- // appended to this SourceBufferStream for that coded frame group must have a
- // decode timestamp >= 1070ms (it can be significantly in the future).
- // Regardless, that appended frame must be buffered into the same existing
- // range as current [1060,1090), since the new coded frame group's start of
- // 1070ms is within that range.
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,30) [1000,1030) [1060,2020) }");
- SeekToTimestampMs(1060);
- CheckExpectedBuffers("1060K 2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_InExisting_AppendMuchLater) {
- NewCodedFrameGroupAppend("0K 10 20 30K 40 50");
- SignalStartOfCodedFrameGroup(base::Milliseconds(45));
- CheckExpectedRangesByTimestamp("{ [0,60) }");
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,2020) }");
- Seek(0);
- CheckExpectedBuffers("0K 10 20 30K 40 2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_InExisting_RemoveGOP_ThenAppend_1) {
- NewCodedFrameGroupAppend("0K 10 20 30K 40 50");
- SignalStartOfCodedFrameGroup(base::Milliseconds(30));
- RemoveInMs(30, 60, 60);
- CheckExpectedRangesByTimestamp("{ [0,30) }");
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,2020) }");
- Seek(0);
- CheckExpectedBuffers("0K 10 20 2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_InExisting_RemoveGOP_ThenAppend_2) {
- NewCodedFrameGroupAppend("0K 10 20 30K 40 50");
- // Though we signal 45ms, it's adjusted internally (due to detected overlap)
- // to be 40.001ms (which is just beyond the highest buffered timestamp at or
- // before 45ms) to help prevent potential discontinuity across the front of
- // the overlapping append.
- SignalStartOfCodedFrameGroup(base::Milliseconds(45));
- RemoveInMs(30, 60, 60);
- CheckExpectedRangesByTimestamp("{ [0,30) }");
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,30) [40,2020) }");
- Seek(0);
- CheckExpectedBuffers("0K 10 20");
- CheckNoNextBuffer();
- SeekToTimestampMs(40);
- CheckExpectedBuffers("2000K 2010");
- CheckNoNextBuffer();
- SeekToTimestampMs(1000);
- CheckExpectedBuffers("2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_InExisting_RemoveMostRecentAppend_ThenAppend_1) {
- NewCodedFrameGroupAppend("0K 10 20 30K 40 50");
- SignalStartOfCodedFrameGroup(base::Milliseconds(45));
- RemoveInMs(50, 60, 60);
- CheckExpectedRangesByTimestamp("{ [0,50) }");
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,2020) }");
- Seek(0);
- CheckExpectedBuffers("0K 10 20 30K 40 2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- StartCodedFrameGroup_InExisting_RemoveMostRecentAppend_ThenAppend_2) {
- NewCodedFrameGroupAppend("0K 10 20 30K 40 50");
- SignalStartOfCodedFrameGroup(base::Milliseconds(50));
- RemoveInMs(50, 60, 60);
- CheckExpectedRangesByTimestamp("{ [0,50) }");
- AppendBuffers("2000K 2010");
- CheckExpectedRangesByTimestamp("{ [0,2020) }");
- Seek(0);
- CheckExpectedBuffers("0K 10 20 30K 40 2000K 2010");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, GetHighestPresentationTimestamp) {
- EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp());
- NewCodedFrameGroupAppend("0K 10K");
- EXPECT_EQ(base::Milliseconds(10), stream_->GetHighestPresentationTimestamp());
- RemoveInMs(0, 10, 20);
- EXPECT_EQ(base::Milliseconds(10), stream_->GetHighestPresentationTimestamp());
- RemoveInMs(10, 20, 20);
- EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp());
- NewCodedFrameGroupAppend("0K 10K");
- EXPECT_EQ(base::Milliseconds(10), stream_->GetHighestPresentationTimestamp());
- RemoveInMs(10, 20, 20);
- EXPECT_EQ(base::TimeDelta(), stream_->GetHighestPresentationTimestamp());
- }
- TEST_F(SourceBufferStreamTest, GarbageCollectionUnderMemoryPressure) {
- SetMemoryLimit(16);
- NewCodedFrameGroupAppend("0K 1 2 3K 4 5 6K 7 8 9K 10 11 12K 13 14 15K");
- CheckExpectedRangesByTimestamp("{ [0,16) }");
- // This feature is disabled by default, so by default memory pressure
- // notification takes no effect and the memory limits and won't remove
- // anything from buffered ranges, since we are under the limit of 20 bytes.
- stream_->OnMemoryPressure(
- base::Milliseconds(0),
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, false);
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(8), 0));
- CheckExpectedRangesByTimestamp("{ [0,16) }");
- // Now enable the feature (on top of any overrides already in
- // |scoped_feature_list_|.)
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kMemoryPressureBasedSourceBufferGC);
- // Verify that effective MSE memory limit is reduced under memory pressure.
- stream_->OnMemoryPressure(
- base::Milliseconds(0),
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, false);
- // Effective memory limit is now 8 buffers, but we still will not collect any
- // data between the current playback position 3 and last append position 15.
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(4), 0));
- CheckExpectedRangesByTimestamp("{ [3,16) }");
- // As playback proceeds further to time 9 we should be able to collect
- // enough data to bring us back under memory limit of 8 buffers.
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(9), 0));
- CheckExpectedRangesByTimestamp("{ [9,16) }");
- // If memory pressure becomes critical, the garbage collection algorithm
- // becomes even more aggressive and collects everything up to the current
- // playback position.
- stream_->OnMemoryPressure(
- base::Milliseconds(0),
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, false);
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(13), 0));
- CheckExpectedRangesByTimestamp("{ [12,16) }");
- // But even under critical memory pressure the MSE memory limit imposed by the
- // memory pressure is soft, i.e. we should be able to append more data
- // successfully up to the hard limit of 16 bytes.
- NewCodedFrameGroupAppend("16K 17 18 19 20 21 22 23 24 25 26 27");
- CheckExpectedRangesByTimestamp("{ [12,28) }");
- EXPECT_TRUE(GarbageCollect(base::Milliseconds(13), 0));
- CheckExpectedRangesByTimestamp("{ [12,28) }");
- }
- TEST_F(SourceBufferStreamTest, InstantGarbageCollectionUnderMemoryPressure) {
- SetMemoryLimit(16);
- NewCodedFrameGroupAppend("0K 1 2 3K 4 5 6K 7 8 9K 10 11 12K 13 14 15K");
- CheckExpectedRangesByTimestamp("{ [0,16) }");
- // Verify that garbage collection happens immediately on critical memory
- // pressure notification, even without explicit GarbageCollect invocation,
- // when the immediate GC is allowed.
- // First, enable the feature (on top of any overrides already in
- // |scoped_feature_list_|.)
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(kMemoryPressureBasedSourceBufferGC);
- stream_->OnMemoryPressure(
- base::Milliseconds(7),
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, true);
- CheckExpectedRangesByTimestamp("{ [6,16) }");
- stream_->OnMemoryPressure(
- base::Milliseconds(9),
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, true);
- CheckExpectedRangesByTimestamp("{ [9,16) }");
- }
- TEST_F(SourceBufferStreamTest, GCFromFrontThenExplicitRemoveFromMiddleToEnd) {
- // Attempts to exercise SourceBufferRange::GetBufferIndexAt() after its
- // |keyframe_map_index_base_| has been increased, and when there is a GOP
- // following the search timestamp. GC followed by an explicit remove may
- // trigger that code path.
- SetMemoryLimit(10);
- // Append 3 IBPPP GOPs in one continuous range.
- NewCodedFrameGroupAppend(
- "0K 40|10 10|20 20|30 30|40 "
- "50K 90|60 60|70 70|80 80|90 "
- "100K 140|110 110|120 120|130 130|140");
- CheckExpectedRangesByTimestamp("{ [0,150) }");
- // Seek to the second GOP's keyframe to allow GC to collect all of the first
- // GOP (ostensibly increasing SourceBufferRange's |keyframe_map_index_base_|).
- SeekToTimestampMs(50);
- GarbageCollect(base::Milliseconds(50), 0);
- CheckExpectedRangesByTimestamp("{ [50,150) }");
- // Remove from the middle of the first remaining GOP to the end of the range.
- RemoveInMs(60, 150, 150);
- CheckExpectedRangesByTimestamp("{ [50,60) }");
- }
- TEST_F(SourceBufferStreamTest, BFrames_WithoutEditList) {
- // Simulates B-frame content where MP4 edit lists are not used to shift PTS so
- // it matches DTS. From acolwell@chromium.org in https://crbug.com/398130
- Seek(0);
- NewCodedFrameGroupAppend(base::Milliseconds(60),
- "60|0K 180|30 90|60 120|90 150|120");
- CheckExpectedRangesByTimestamp("{ [60,210) }");
- CheckExpectedBuffers("60|0K 180|30 90|60 120|90 150|120");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, OverlapSameTimestampWithinSameGOP) {
- // We use distinct appends here to make sure the intended frame durations
- // are respected by the test helpers (which the OneByOne helper doesn't
- // respect always). We need granular appends of this GOP for at least the
- // append of PTS=DTS=30, below.
- NewCodedFrameGroupAppend("0|0D10K");
- AppendBuffers("30|10D0");
- AppendBuffers("20|20D10");
- // The following should *not* remove the PTS frame 30, above.
- AppendBuffers("30|30 40|40");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,50) }");
- CheckExpectedBuffers("0K 30|10 20 30 40");
- }
- struct VideoEndTimeCase {
- // Times in Milliseconds
- int64_t new_frame_pts;
- int64_t new_frame_duration;
- int64_t expected_highest_pts;
- int64_t expected_end_time;
- };
- TEST_F(SourceBufferStreamTest, VideoRangeEndTimeCases) {
- // With a basic range containing just a single keyframe [10,20), verify
- // various keyframe overlap append cases' results on the range end time.
- const VideoEndTimeCase kCases[] = {
- {0, 10, 10, 20},
- {20, 1, 20, 21},
- {15, 3, 15, 18},
- {15, 5, 15, 20},
- {15, 8, 15, 23},
- // Cases where the new frame removes the previous frame:
- {10, 3, 10, 13},
- {10, 10, 10, 20},
- {10, 13, 10, 23},
- {5, 8, 5, 13},
- {5, 15, 5, 20},
- {5, 20, 5, 25}};
- for (const auto& c : kCases) {
- RemoveInMs(0, 100, 100);
- NewCodedFrameGroupAppend("10D10K");
- CheckExpectedRangesByTimestamp("{ [10,20) }");
- CheckExpectedRangeEndTimes("{ <10,20> }");
- std::stringstream ss;
- ss << c.new_frame_pts << "D" << c.new_frame_duration << "K";
- DVLOG(1) << "Appending " << ss.str();
- NewCodedFrameGroupAppend(ss.str());
- std::stringstream expected;
- expected << "{ <" << c.expected_highest_pts << "," << c.expected_end_time
- << "> }";
- CheckExpectedRangeEndTimes(expected.str());
- }
- }
- struct AudioEndTimeCase {
- // Times in Milliseconds
- int64_t new_frame_pts;
- int64_t new_frame_duration;
- int64_t expected_highest_pts;
- int64_t expected_end_time;
- bool expect_splice;
- };
- TEST_F(SourceBufferStreamTest, AudioRangeEndTimeCases) {
- // With a basic range containing just a single keyframe [10,20), verify
- // various keyframe overlap append cases' results on the range end time.
- const AudioEndTimeCase kCases[] = {
- {0, 10, 10, 20, false},
- {20, 1, 20, 21, false},
- {15, 3, 15, 18, true},
- {15, 5, 15, 20, true},
- {15, 8, 15, 23, true},
- // Cases where the new frame removes the previous frame:
- {10, 3, 10, 13, false},
- {10, 10, 10, 20, false},
- {10, 13, 10, 23, false},
- {5, 8, 5, 13, false},
- {5, 15, 5, 20, false},
- {5, 20, 5, 25, false}};
- SetAudioStream();
- for (const auto& c : kCases) {
- InSequence s;
- RemoveInMs(0, 100, 100);
- NewCodedFrameGroupAppend("10D10K");
- CheckExpectedRangesByTimestamp("{ [10,20) }");
- CheckExpectedRangeEndTimes("{ <10,20> }");
- std::stringstream ss;
- ss << c.new_frame_pts << "D" << c.new_frame_duration << "K";
- if (c.expect_splice) {
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(c.new_frame_pts * 1000, 10000,
- (20 - c.new_frame_pts) * 1000));
- }
- DVLOG(1) << "Appending " << ss.str();
- NewCodedFrameGroupAppend(ss.str());
- std::stringstream expected;
- expected << "{ <" << c.expected_highest_pts << "," << c.expected_end_time
- << "> }";
- CheckExpectedRangeEndTimes(expected.str());
- }
- }
- TEST_F(SourceBufferStreamTest, SameTimestampEstimatedDurations_Video) {
- // Start a coded frame group with a frame having a non-estimated duration.
- NewCodedFrameGroupAppend("10D10K");
- // In the same coded frame group, append a same-timestamp frame with estimated
- // duration smaller than the first frame. (This can happen at least if there
- // was an intervening init segment resetting the estimation logic.) This
- // second frame need not be a keyframe. We use a non-keyframe here to
- // differentiate the buffers in CheckExpectedBuffers(), below.
- AppendBuffers("10D9E");
- // The next append, which triggered https://crbug.com/761567, didn't need to
- // be with same timestamp as the earlier ones; it just needs to be in the same
- // buffered range. Also, it doesn't need to be a keyframe, have an estimated
- // duration, nor be in the same coded frame group to trigger that issue.
- NewCodedFrameGroupAppend("11D10K");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [10,21) }");
- CheckExpectedRangeEndTimes("{ <11,21> }");
- CheckExpectedBuffers("10K 10 11K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, RangeIsNextInPTS_Simple) {
- // Append a simple GOP where DTS==PTS, perform basic PTS continuity checks.
- NewCodedFrameGroupAppend("10D10K");
- CheckIsNextInPTSSequenceWithFirstRange(9, false);
- CheckIsNextInPTSSequenceWithFirstRange(10, true);
- CheckIsNextInPTSSequenceWithFirstRange(20, true);
- CheckIsNextInPTSSequenceWithFirstRange(30, true);
- CheckIsNextInPTSSequenceWithFirstRange(31, false);
- }
- TEST_F(SourceBufferStreamTest, RangeIsNextInPTS_OutOfOrder) {
- // Append a GOP where DTS != PTS such that a timestamp used as DTS would not
- // be continuous, but used as PTS is, and verify PTS continuity.
- NewCodedFrameGroupAppend("1000|0K 1120|30 1030|60 1060|90 1090|120");
- CheckIsNextInPTSSequenceWithFirstRange(0, false);
- CheckIsNextInPTSSequenceWithFirstRange(30, false);
- CheckIsNextInPTSSequenceWithFirstRange(60, false);
- CheckIsNextInPTSSequenceWithFirstRange(90, false);
- CheckIsNextInPTSSequenceWithFirstRange(120, false);
- CheckIsNextInPTSSequenceWithFirstRange(150, false);
- CheckIsNextInPTSSequenceWithFirstRange(1000, false);
- CheckIsNextInPTSSequenceWithFirstRange(1030, false);
- CheckIsNextInPTSSequenceWithFirstRange(1060, false);
- CheckIsNextInPTSSequenceWithFirstRange(1090, false);
- CheckIsNextInPTSSequenceWithFirstRange(1119, false);
- CheckIsNextInPTSSequenceWithFirstRange(1120, true);
- CheckIsNextInPTSSequenceWithFirstRange(1150, true);
- CheckIsNextInPTSSequenceWithFirstRange(1180, true);
- CheckIsNextInPTSSequenceWithFirstRange(1181, false);
- }
- TEST_F(SourceBufferStreamTest, RangeCoalescenceOnFudgeRoomIncrease_1) {
- // Change the fudge room (by increasing frame duration) and verify coalescence
- // behavior.
- NewCodedFrameGroupAppend("0K 10K");
- NewCodedFrameGroupAppend("100K 110K");
- NewCodedFrameGroupAppend("500K 510K");
- CheckExpectedRangesByTimestamp("{ [0,20) [100,120) [500,520) }");
- // Increase the fudge room almost enough to merge the first two buffered
- // ranges.
- NewCodedFrameGroupAppend("1000D44K");
- CheckExpectedRangesByTimestamp("{ [0,20) [100,120) [500,520) [1000,1044) }");
- // Increase the fudge room again to merge the first two buffered ranges.
- NewCodedFrameGroupAppend("2000D45K");
- CheckExpectedRangesByTimestamp(
- "{ [0,120) [500,520) [1000,1044) [2000,2045) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 10K 100K 110K");
- CheckNoNextBuffer();
- SeekToTimestampMs(500);
- CheckExpectedBuffers("500K 510K");
- CheckNoNextBuffer();
- SeekToTimestampMs(1000);
- CheckExpectedBuffers("1000K");
- CheckNoNextBuffer();
- SeekToTimestampMs(2000);
- CheckExpectedBuffers("2000K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, RangeCoalescenceOnFudgeRoomIncrease_2) {
- // Change the fudge room (by increasing frame duration) and verify coalescence
- // behavior.
- NewCodedFrameGroupAppend("0K 10K");
- NewCodedFrameGroupAppend("40K 50K 60K");
- CheckExpectedRangesByTimestamp("{ [0,20) [40,70) }");
- // Increase the fudge room to merge the first two buffered ranges.
- NewCodedFrameGroupAppend("1000D20K");
- CheckExpectedRangesByTimestamp("{ [0,70) [1000,1020) }");
- // Try to trigger unsorted ranges, as might occur if the first two buffered
- // ranges were not correctly coalesced.
- NewCodedFrameGroupAppend("45D10K");
- CheckExpectedRangesByTimestamp("{ [0,70) [1000,1020) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 10K 40K 45K 60K");
- CheckNoNextBuffer();
- SeekToTimestampMs(1000);
- CheckExpectedBuffers("1000K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, NoRangeGapWhenIncrementallyOverlapped) {
- // Append 2 SAP-Type-1 GOPs continuous in DTS and PTS interval and with frame
- // durations and number of frames per GOP such that the first keyframe by
- // itself would not be considered "adjacent" to the second GOP by our fudge
- // room logic alone, but we now adjust the range start times occurring during
- // an overlap to enable overlap appends to remain continuous with the
- // remainder of the overlapped range, if any. Then incrementally reappend
- // each frame of the first GOP.
- NewCodedFrameGroupAppend("0K 10 20 30 40 50K 60 70 80 90");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <90,100> }");
- CheckExpectedBuffers("0K 10 20 30 40 50K 60 70 80 90");
- CheckNoNextBuffer();
- NewCodedFrameGroupAppend("0D10K"); // Replaces first GOP with 1 frame.
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <90,100> }");
- CheckExpectedBuffers("0K 50K 60 70 80 90");
- CheckNoNextBuffer();
- // Add more of the replacement GOP.
- AppendBuffers("10 20");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <90,100> }");
- CheckExpectedBuffers("0K 10 20 50K 60 70 80 90");
- CheckNoNextBuffer();
- // Add more of the replacement GOP.
- AppendBuffers("30D10");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <90,100> }");
- CheckExpectedBuffers("0K 10 20 30 50K 60 70 80 90");
- CheckNoNextBuffer();
- // Complete the replacement GOP.
- AppendBuffers("40D10");
- Seek(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <90,100> }");
- CheckExpectedBuffers("0K 10 20 30 40 50K 60 70 80 90");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, AllowIncrementalAppendsToCoalesceRangeGap) {
- // Append a SAP-Type-1 GOP with a coded frame group start time far before the
- // timestamp of the first GOP (beyond any fudge room possible in this test).
- // This simulates one of multiple muxed tracks with jagged start times
- // following a discontinuity.
- // Then incrementally append a preceding SAP-Type-1 GOP with frames that
- // eventually are adjacent within fudge room of the first appended GOP's group
- // start time and observe the buffered range and demux gap coalesces. Finally,
- // incrementally append more frames of that preceding GOP to fill in the
- // timeline to abut the first appended GOP's keyframe timestamp and observe no
- // further buffered range change or discontinuity.
- NewCodedFrameGroupAppend(base::Milliseconds(100), "150K 160");
- SeekToTimestampMs(100);
- CheckExpectedRangesByTimestamp("{ [100,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("150K 160");
- CheckNoNextBuffer();
- NewCodedFrameGroupAppend("70D10K");
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,80) [100,170) }");
- CheckExpectedRangeEndTimes("{ <70,80> <160,170> }");
- CheckExpectedBuffers("70K");
- CheckNoNextBuffer();
- SeekToTimestampMs(100);
- CheckExpectedBuffers("150K 160");
- CheckNoNextBuffer();
- AppendBuffers("80D10"); // 80ms is just close enough to 100ms to coalesce.
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("70K 80 150K 160");
- CheckNoNextBuffer();
- AppendBuffers("90D10");
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("70K 80 90 150K 160");
- CheckNoNextBuffer();
- AppendBuffers("100 110 120");
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("70K 80 90 100 110 120 150K 160");
- CheckNoNextBuffer();
- AppendBuffers("130D10");
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("70K 80 90 100 110 120 130 150K 160");
- CheckNoNextBuffer();
- AppendBuffers("140D10");
- SeekToTimestampMs(70);
- CheckExpectedRangesByTimestamp("{ [70,170) }");
- CheckExpectedRangeEndTimes("{ <160,170> }");
- CheckExpectedBuffers("70K 80 90 100 110 120 130 140 150K 160");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, PreciselyOverlapLastAudioFrameAppended_1) {
- // Appends an audio frame, A, which is then immediately followed by a
- // subsequent frame, B. Then appends a new frame, C, which precisely overlaps
- // frame B, and verifies that there is exactly 1 buffered range resulting.
- SetAudioStream();
- // Frame A
- NewCodedFrameGroupAppend("0D10K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- CheckExpectedRangeEndTimes("{ <0,10> }");
- CheckExpectedBuffers("0K");
- CheckNoNextBuffer();
- // Frame B
- NewCodedFrameGroupAppend("10D10K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,20) }");
- CheckExpectedRangeEndTimes("{ <10,20> }");
- CheckExpectedBuffers("0K 10K");
- CheckNoNextBuffer();
- // Frame C.
- // Though DTS is continuous per MSE spec, FrameProcessor signals new CFG more
- // granularly, including in this case.
- NewCodedFrameGroupAppend("10D10K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,20) }");
- CheckExpectedRangeEndTimes("{ <10,20> }");
- CheckExpectedBuffers("0K 10K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, PreciselyOverlapLastAudioFrameAppended_2) {
- // Appends an audio frame, A, which is then splice-trim-truncated by a
- // subsequent frame, B. Then appends a new frame, C, which precisely overlaps
- // frame B, and verifies that there is exactly 1 buffered range resulting.
- SetAudioStream();
- // Frame A
- NewCodedFrameGroupAppend("0D100K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,100) }");
- CheckExpectedRangeEndTimes("{ <0,100> }");
- CheckExpectedBuffers("0K");
- CheckNoNextBuffer();
- // Frame B
- EXPECT_MEDIA_LOG(TrimmedSpliceOverlap(60000, 0, 40000));
- NewCodedFrameGroupAppend("60D10K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,70) }");
- CheckExpectedRangeEndTimes("{ <60,70> }");
- CheckExpectedBuffers("0K 60K");
- CheckNoNextBuffer();
- // Frame C.
- // Though DTS is continuous per MSE spec, FrameProcessor signals new CFG more
- // granularly, including in this case.
- NewCodedFrameGroupAppend("60D10K");
- SeekToTimestampMs(0);
- CheckExpectedRangesByTimestamp("{ [0,70) }");
- CheckExpectedRangeEndTimes("{ <60,70> }");
- CheckExpectedBuffers("0K 60K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, ZeroDurationBuffersThenIncreasingFudgeRoom) {
- // Appends some zero duration buffers to result in disjoint buffered ranges.
- // Verifies that increasing the fudge room allows those that become within
- // adjacency threshold to merge, including those for which the new fudge room
- // is well more than sufficient to let them be adjacent.
- SetAudioStream();
- NewCodedFrameGroupAppend("0uD0K");
- CheckExpectedRangesByTimestamp("{ [0,1) }", TimeGranularity::kMicrosecond);
- NewCodedFrameGroupAppend("1uD0K");
- CheckExpectedRangesByTimestamp("{ [0,2) }", TimeGranularity::kMicrosecond);
- // Initial fudge room allows for up to 2ms gap to coalesce.
- NewCodedFrameGroupAppend("5000uD0K");
- CheckExpectedRangesByTimestamp("{ [0,2) [5000,5001) }",
- TimeGranularity::kMicrosecond);
- NewCodedFrameGroupAppend("2002uD0K");
- CheckExpectedRangesByTimestamp("{ [0,2) [2002,2003) [5000,5001) }",
- TimeGranularity::kMicrosecond);
- // Grow the fudge room enough to coalesce the first two ranges.
- NewCodedFrameGroupAppend("8000uD1001uK");
- CheckExpectedRangesByTimestamp("{ [0,2003) [5000,5001) [8000,9001) }",
- TimeGranularity::kMicrosecond);
- // Append a buffer with duration 4ms, much larger than previous buffers. This
- // grows the fudge room to 8ms (2 * 4ms). Expect that the first three ranges
- // are retroactively merged due to being adjacent per the new, larger fudge
- // room.
- NewCodedFrameGroupAppend("100D4K");
- CheckExpectedRangesByTimestamp("{ [0,9001) [100000,104000) }",
- TimeGranularity::kMicrosecond);
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 1K 2002K 5000K 8000K",
- TimeGranularity::kMicrosecond);
- CheckNoNextBuffer();
- SeekToTimestampMs(100);
- CheckExpectedBuffers("100K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, NonZeroDurationBuffersThenIncreasingFudgeRoom) {
- // Verifies that a single fudge room increase which merges more than 2
- // previously disjoint ranges in a row performs the merging correctly.
- NewCodedFrameGroupAppend("0D10K");
- NewCodedFrameGroupAppend("50D10K");
- NewCodedFrameGroupAppend("100D10K");
- NewCodedFrameGroupAppend("150D10K");
- NewCodedFrameGroupAppend("500D10K");
- CheckExpectedRangesByTimestamp(
- "{ [0,10) [50,60) [100,110) [150,160) [500,510) }");
- NewCodedFrameGroupAppend("600D30K");
- CheckExpectedRangesByTimestamp("{ [0,160) [500,510) [600,630) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K 50K 100K 150K");
- CheckNoNextBuffer();
- SeekToTimestampMs(500);
- CheckExpectedBuffers("500K");
- CheckNoNextBuffer();
- SeekToTimestampMs(600);
- CheckExpectedBuffers("600K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest, SapType2WithNonkeyframePtsInEarlierRange) {
- // Buffer a standalone GOP [0,10).
- NewCodedFrameGroupAppend("0D10K");
- CheckExpectedRangesByTimestamp("{ [0,10) }");
- // Following discontinuity (simulated by DTS gap, signalled by new coded frame
- // group with time beyond fudge room of [0,10)), buffer 2 new GOPs in a later
- // range: a SAP-2 GOP with a nonkeyframe with PTS belonging to the first
- // range, and a subsequent minimal GOP.
- NewCodedFrameGroupAppend("30D10K 1|40D10");
- CheckExpectedRangesByTimestamp("{ [0,10) [30,40) }");
- NewCodedFrameGroupAppend("40|50D10K");
- // Verify that there are two distinct ranges, and that the SAP-2 nonkeyframe
- // is buffered as part of the second range's first GOP.
- CheckExpectedRangesByTimestamp("{ [0,10) [30,50) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0K");
- CheckNoNextBuffer();
- SeekToTimestampMs(30);
- CheckExpectedBuffers("30K 1|40 40|50K");
- CheckNoNextBuffer();
- }
- TEST_F(SourceBufferStreamTest,
- MergeAllowedIfRangeEndTimeWithEstimatedDurationMatchesNextRangeStart) {
- // Tests the edge case where fudge room is not increased when an estimated
- // duration is increased due to overlap appends, causing two ranges to not be
- // within fudge room of each other (nor merged), yet abutting each other.
- // Append a GOP that has fudge room as its interval (e.g. 2 frames of same
- // duration >= minimum 1ms).
- NewCodedFrameGroupAppend("0D10K 10D10");
- CheckExpectedRangesByTimestamp("{ [0,20) }");
- // Trigger a DTS discontinuity so later 21ms append also is discontinuous and
- // retains 10ms*2 fudge room.
- NewCodedFrameGroupAppend("100D10K");
- CheckExpectedRangesByTimestamp("{ [0,20) [100,110) }");
- // Append another keyframe that starts within fudge room distance of the
- // non-keyframe in the GOP appended, above.
- NewCodedFrameGroupAppend("21D10K");
- CheckExpectedRangesByTimestamp("{ [0,31) [100,110) }");
- // Overlap-append the original GOP with a single estimated-duration keyframe.
- // Though its timestamp is not within fudge room of the next keyframe, that
- // next keyframe at time 21ms was in the overlapped range and is retained in
- // the result of the overlap append's range.
- NewCodedFrameGroupAppend("0D10EK");
- CheckExpectedRangesByTimestamp("{ [0,31) [100,110) }");
- // That new keyframe at time 0 now has derived estimated duration 21ms. That
- // increased estimated duration did *not* increase the fudge room (which is
- // still 2 * 10ms = 20ms.) So the next line, which splices in a new frame at
- // time 21 causes the estimated keyframe at time 0 to not have a timestamp
- // within fudge room of the new range that starts right at 21ms, the same time
- // that ends the first buffered range, requiring CanAppendBuffersToEnd to
- // handle this scenario specifically.
- NewCodedFrameGroupAppend("21D10K");
- CheckExpectedRangesByTimestamp("{ [0,31) [100,110) }");
- SeekToTimestampMs(0);
- CheckExpectedBuffers("0D21EK 21D10K");
- CheckNoNextBuffer();
- SeekToTimestampMs(100);
- CheckExpectedBuffers("100D10K");
- CheckNoNextBuffer();
- }
- } // namespace media
|