package Ġcom . mar co ub ert i . video . playground . ui . extract images Ċ Ċ import Ġandroid . media . Media Codec Ċ import Ġandroid . media . Media Extractor Ċ import Ġandroid . media . Media Format Ċ import Ġandroid . os . Bundle Ċ import Ġandroid . view . View Ċ import Ġandroidx . annotation . Raw Res Ċ import Ġandroidx . fragment . app . Fragment Ċ import Ġcom . mar co ub ert i . video . R Ċ import Ġcom . mar co ub ert i . video . playground . find Decoder For Format Ċ import Ġcom . mar co ub ert i . video . playground . log Ċ import Ġjava . io . File Ċ Ċ /** Ċ Ġ* ĠDe codes Ġa Ġmp 4 Ġfile Ġand Ġrenders Ġit Ġon Ġa ĠSurface Texture Ġ( no ĠUI / View ), Ġreads Ġeach Ġframe Ċ Ġ* Ġ[ Image ] Ġand Ġconverts Ġit Ġto Ġa Ġ[ Bitmap ]. Ċ Ġ* Ċ Ġ* ĠThen Ġsave Ġthe Ġframes Ġas ĠPNG s Ġ( slow ). Ċ Ġ*/ Ċ class ĠExtract Images Fragment Ġ: ĠFragment ( R . layout . extract _ images _ fragment ) Ġ{ ĊĊĠĠĠ Ġlateinit Ġvar Ġextractor : ĠMedia Extractor ĊĠĠĠ Ġlateinit Ġvar Ġdecoder : ĠMedia Codec ĊĠĠĠ Ġprivate Ġvar Ġextractor Done Ġ= Ġfalse ĊĠĠĠ Ġlateinit Ġvar Ġoutput Surface : ĠCodec Output Surface ĊĊĠĠĠ Ġval ĠMAX _ FRAME Ġ= Ġ 1 0 ĊĠĠĠ Ġvar Ġcounter Ġ= Ġ 0 ĊĊĠĠĠ Ġoverride Ġfun Ġon Destroy View () Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on Destroy View () ĊĠĠĠĠĠĠĠ Ġrelease () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġon View Created ( view : ĠView , ĠsavedInstanceState : ĠBundle ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġsuper . on View Created ( view , ĠsavedInstanceState ) ĊĠĠĠĠĠĠĠ Ġval Ġformat Ġ= Ġcreate Decoder From Video Source ( R . raw . par is _ 0 1 _ 1 0 8 0 p ) ĊĠĠĠĠĠĠĠ Ġsetup Decoder Callback () ĊĠĠĠĠĠĠĠ Ġsetup Output Surface () ĊĠĠĠĠĠĠĠ Ġconfigure Decoder ( format ) ĊĠĠĠĠĠĠĠ Ġstart Decoder () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Output Surface () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠCould Ġuse Ġwidth / height Ġfrom Ġthe ĠMedia Format Ġto Ġget Ġfull - size Ġframes . ĊĠĠĠĠĠĠĠ Ġoutput Surface Ġ= ĠCodec Output Surface ( 6 4 0 , Ġ 4 8 0 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġstart Decoder () Ġ{ ĊĠĠĠĠĠĠĠ Ġdecoder . start () ĊĠĠĠĠĠĠĠ Ġlog (" start Decoder ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsetup Decoder Callback () Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠUse Ġnull Ġto Ġclear Ġa Ġpreviously Ġset Ġcallback Ġbefore Ġconfigure ĊĠĠĠĠĠĠĠ Ġdecoder . set Callback ( null ) ĊĠĠĠĠĠĠĠ Ġdecoder . set Callback ( object Ġ: ĠMedia Codec . Callback () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Input Buffer Available ( codec : ĠMedia Codec , Ġindex : ĠInt ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" on Input Buffer Available Ġindex : Ġ$ index ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( extractor Done ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbuffer Ġ= Ġcodec . getInput Buffer ( index ) Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġsize : ĠInt Ġ= Ġextractor . read Sample Data ( buffer , Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġpts : ĠLong Ġ= Ġextractor . sample Time ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextractor Done Ġ= Ġ! extractor . advance () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( size Ġ>= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġflags Ġ= Ġextractor . sample Flags ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( extractor Done ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" extractor Ġdone ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġflags Ġ= ĠMedia Codec . BUFFER _ FLAG _ END _ OF _ STREAM ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcodec . queue Input Buffer ( index , Ġ 0 , Ġsize , Ġpts , Ġflags ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Output Buffer Available ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcodec : ĠMedia Codec , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġindex : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġinfo : ĠMedia Codec . Buffer Info ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" on Output Buffer Available Ġindex : Ġ$ index , Ġinfo : Ġ$ info ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( extractor Done ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// val Ġimage Ġ= Ġcodec . getOutput Image ( index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// log (" Image Ġdata : Ġ${ image ?. width } Ġx Ġ${ image ?. height }") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( info . flags Ġand ĠMedia Codec . BUFFER _ FLAG _ CODEC _ CONFIG Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcodec . release Output Buffer ( index , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrender Ġ= Ġinfo . size Ġ!= Ġ 0 ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠAs Ġsoon Ġas Ġwe Ġcall Ġrelease Output Buffer , Ġthe Ġbuffer Ġwill Ġbe Ġforwarded ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġto ĠSurface Texture Ġto Ġconvert Ġto Ġa Ġtexture . Ġ ĠThe ĠAPI Ġdoesn 't Ġguarantee ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġthat Ġthe Ġtexture Ġwill Ġbe Ġavailable Ġbefore Ġthe Ġcall Ġreturns , Ġso Ġwe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġneed Ġto Ġwait Ġfor Ġthe Ġon Frame Available Ġcallback Ġto Ġfire . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcodec . release Output Buffer ( index , Ġrender ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġextract Ġframe Ġpixels ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( render ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" await ing Ġdecode Ġof Ġframe Ġ$ index ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Surface . await New Image () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠThrowable ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Surface . drawImage ( true ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( counter Ġ< ĠMAX _ FRAME ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfilename Ġ= ĠString . format (" frame -% 0 2 d . png ", Ġcounter ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠoutputFile : ĠFile Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠFile ( require Context (). cacheDir , Ġfilename ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput Surface . save Frame ( outputFile . toString ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" saved Ġframe Ġ$ filename ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcounter ++ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( info . flags Ġand ĠMedia Codec . BUFFER _ FLAG _ END _ OF _ STREAM Ġ!= Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" received ĠBUFFER _ FLAG _ END _ OF _ STREAM ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrelease () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun ĠonError ( codec : ĠMedia Codec , Ġe : ĠMedia Codec . Codec Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" onError Ġerror : Ġ$ e ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġon Output Format Changed ( codec : ĠMedia Codec , Ġformat : ĠMedia Format ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlog (" on Output Format Changed Ġformat : Ġ$ format ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcreate Decoder From Video Source (@ Raw Res Ġvideo Res Id : ĠInt ): ĠMedia Format Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġformat Ġ= ĠMedia Format () ĊĠĠĠĠĠĠĠ Ġvar ĠmimeType Ġ= Ġ"" ĊĊĠĠĠĠĠĠĠ Ġextractor Ġ= ĠMedia Extractor () ĊĊĠĠĠĠĠĠĠ Ġ// ĠLoad Ġfile Ġfrom Ġraw Ġdirectory ĊĠĠĠĠĠĠĠ Ġval Ġvideo Fd Ġ= Ġthis . resources . open Raw Resource Fd ( video Res Id ) ĊĠĠĠĠĠĠĠ Ġextractor . set DataSource ( video Fd . file Descriptor , Ġvideo Fd . start Offset , Ġvideo Fd . length ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠFind Ġthe ĠMIME Ġtype Ġfrom Ġthe Ġraw Ġvideo Ġfile ĊĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġextractor . track Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġformat Ġ= Ġextractor . get Track Format ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUse Ġthis Ġin ĠAPI Ġ 2 1 + Ġas Ġstated Ġby Ġthe Ġdocumentation , Ġbut Ġcrashes Ġthe Ġapp ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġformat . setString ( Media Format . KEY _ FRAME _ RATE , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠmimeType Ġ= Ġformat . getString ( Media Format . KEY _ MIME ) Ġ?: Ġ"" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( mime Type . startsWith (" video / ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextractor . select Track ( i ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ// extractor . release () ĊĠĠĠĠĠĠĠ Ġvideo Fd . close () ĊĊĠĠĠĠĠĠĠ Ġval Ġdecoder Name Ġ= Ġfind Decoder For Format ( format ) ĊĠĠĠĠĠĠĠ Ġdecoder Ġ= ĠMedia Codec . create By Codec Name ( decoder Name ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġformat ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrelease () Ġ{ ĊĠĠĠĠĠĠĠ Ġlog (" release Ġsurface ") ĊĠĠĠĠĠĠĠ Ġoutput Surface . release () ĊĠĠĠĠĠĠĠ Ġlog (" release Ġextractor ") ĊĠĠĠĠĠĠĠ Ġextractor . release () ĊĠĠĠĠĠĠĠ Ġlog (" release Ġdecoder ") ĊĠĠĠĠĠĠĠ Ġdecoder . release () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġconfigure Decoder ( format : ĠMedia Format ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠConfigure Ġthe Ġdecoder ĊĠĠĠĠĠĠĠ Ġ// Ġflags Ġto Ġ 0 Ġfor Ġdecoding , ĠCONFIG URE _ FLAG _ ENCODE Ġfor Ġencoding ĊĠĠĠĠĠĠĠ Ġdecoder . configure ( format , Ġoutput Surface . surface , Ġnull , Ġ 0 ) ĊĊĠĠĠĠĠĠĠ Ġlog (" Input Ġformat : Ġ${ decoder . input Format }") ĊĠĠĠĠĠĠĠ Ġlog (" Output Ġformat : Ġ${ decoder . output Format }") ĊĠĠĠ Ġ} Ċ } Ċ