package Ġcom . se ang hay . studio example . core ĊĊ Ċ import Ġandroid . media .* Ċ import Ġandroid . util . Sparse Array Ċ import Ġcom . se ang hay . studio . utils . is Audio Format Ċ import Ġcom . se ang hay . studio . utils . is Video Format Ċ import Ġjava . nio . ByteBuffer Ċ import Ġjava . util .* Ċ Ċ class ĠAudio Mixer ( ĊĠĠĠ Ġprivate Ġval Ġvideo Path : ĠString , ĊĠĠĠ Ġprivate Ġval Ġaudio Path : ĠString , ĊĠĠĠ Ġprivate Ġval Ġoutput Path : ĠString Ċ ) Ġ{ ĊĊĠĠĠ Ġprivate Ġval Ġencoder : ĠMedia Codec Ġ= ĠMedia Codec . create Encoder ByType (" video / av c ") ĊĠĠĠ Ġprivate Ġval Ġmux er : ĠMedia Mux er Ġ= ĊĠĠĠĠĠĠĠ ĠMedia Mux er ( output Path , ĠMedia Mux er . Output Format . MUX ER _ OUTPUT _ M PEG _ 4 ) ĊĠĠĠ Ġprivate Ġval Ġtrack Queue : ĠQueue < Int > Ġ= ĠArray Deque () ĊĠĠĠ Ġprivate Ġval Ġtrack Map : ĠSparse Array < Media Extractor > Ġ= ĠSparse Array () ĊĠĠĠ Ġprivate Ġval Ġtrack Formats Ġ= Ġarray ListOf < Media Format >() ĊĊĠĠĠ Ġprivate Ġvar Ġis Started Ġ= Ġfalse ĊĠĠĠ Ġprivate Ġvar ĠbufferSize : ĠInt Ġ= Ġ- 1 ĊĊĠĠĠ Ġprivate Ġvar Ġmax Us : ĠLong Ġ= Ġ- 1 L ĊĊĊĠĠĠ Ġ@ Suppress (" unused ") ĊĠĠĠ Ġprivate Ġval Ġvideo Extractor : ĠMedia Extractor Ġ= ĠMedia Extractor (). also Ġ{ ĊĠĠĠĠĠĠĠ Ġit . set DataSource ( video Path ) ĊĠĠĠĠĠĠĠ Ġval Ġvideo Format Ġ= Ġit . select Track Of Ġ{ Ġis Video Format () Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġtrack Id Ġ= Ġmux er . add Track ( video Format ) ĊĠĠĠĠĠĠĠ Ġtrack Queue . add ( track Id ) ĊĠĠĠĠĠĠĠ Ġtrack Map . put ( track Id , Ġit ) ĊĠĠĠĠĠĠĠ Ġtrack Formats . add ( video Format ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Suppress (" unused ") ĊĠĠĠ Ġprivate Ġval Ġaudio Extractor : ĠMedia Extractor Ġ= ĠMedia Extractor (). also Ġ{ ĊĠĠĠĠĠĠĠ Ġit . set DataSource ( audio Path ) ĊĠĠĠĠĠĠĠ Ġval Ġaudio Format Ġ= Ġit . select Track Of Ġ{ Ġis Audio Format () Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġtrack Id Ġ= Ġmux er . add Track ( audio Format ) ĊĠĠĠĠĠĠĠ Ġtrack Queue . add ( track Id ) ĊĠĠĠĠĠĠĠ Ġtrack Map . put ( track Id , Ġit ) ĊĠĠĠĠĠĠĠ Ġtrack Formats . add ( audio Format ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġbuffer Info : ĠMedia Codec . Buffer Info Ġ= ĠMedia Codec . Buffer Info () ĊĊĠĠĠ Ġfun Ġbegin () Ġ{ ĊĊĠĠĠĠĠĠĠ Ġtrack Formats . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . containsKey ( Media Format . KEY _ MAX _ INPUT _ SIZE )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmax Input Size Ġ= Ġit . getInteger ( Media Format . KEY _ MAX _ INPUT _ SIZE ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( max Input Size Ġ> ĠbufferSize ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠbufferSize Ġ= Ġmax Input Size ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġduration Ġ= Ġit . getLong ( Media Format . KEY _ DURATION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( duration Ġ> Ġmax Us ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmax Us Ġ= Ġduration ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġset Orientation Hint () ĊĊĠĠĠĠĠĠĠ Ġif Ġ( buffer Size Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠbufferSize Ġ= ĠBUFFER _ SIZE ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġmux er . start () ĊĊĠĠĠĠĠĠĠ Ġval Ġdst Buf Ġ= ĠByteBuffer . allocate ( buffer Size ) ĊĠĠĠĠĠĠĠ Ġval Ġoffset Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġis Started Ġ= Ġtrue ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ(! track Queue . isEmpty ()) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtrack Id Ġ= Ġtrack Queue . poll () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġextractor Ġ= Ġtrack Map . get ( track Id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġextractor . seek To ( 0 , ĠMedia Extractor . SEEK _ TO _ CLOSE ST _ SYNC ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġtime Offset Ġ= Ġ 0 L ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlast Time Ġ= Ġ 0 L ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer Info . offset Ġ= Ġoffset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer Info . size Ġ= Ġextractor . read Sample Data ( dst Buf , Ġoffset ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( buffer Info . size Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextractor . seek To ( 0 , ĠMedia Extractor . SEEK _ TO _ CLOSE ST _ SYNC ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtime Offset Ġ+= Ġlast Time ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcontinue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer Info . presentation Time Us Ġ= Ġextractor . sample Time Ġ+ Ġtime Offset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Time Ġ= Ġextractor . sample Time ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( max Us Ġ!= Ġ- 1 L Ġ&& Ġbuffer Info . presentation Time Us Ġ> Ġmax Us ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuffer Info . flags Ġ= Ġextractor . sample Flags ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmux er . write Sample Data ( track Id , Ġdst Buf , Ġbuffer Info ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġextractor . advance () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġis Started Ġ= Ġfalse ĊĠĠĠĠĠĠĠ Ġmux er . stop () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġset Orientation Hint () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġretrie ver Ġ= ĠMedia Metadata Retriever () ĊĠĠĠĠĠĠĠ Ġretrie ver . use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . set DataSource ( video Path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġorientation String : ĠString ? Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . extract Metadata ( Media Metadata Retriever . METADATA _ KEY _ VIDEO _ ROT ATION ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġorientation String ?. toInt ()?. let Ġ{ Ġif Ġ( it Ġ>= Ġ 0 ) Ġmux er . set Orientation Hint ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġflush () Ġ{ ĊĠĠĠĠĠĠĠ Ġencoder . flush () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġconst Ġval ĠBUFFER _ SIZE Ġ= Ġ 1 Ġ* Ġ 1 0 2 4 Ġ* Ġ 1 0 2 4 Ġ// ĠMagic Ġnumber ĊĠĠĠĠĠĠĠ Ġprivate Ġfun ĠMedia Extractor . select Track Of ( block : ĠMedia Format . () Ġ-> ĠBoolean ): ĠMedia Format Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( track Index Ġin Ġ 0 Ġuntil Ġtrack Count ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġformat Ġ= Ġget Track Format ( track Index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( block ( format )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġselect Track ( track Index ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġformat ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠRuntimeException (" Couldn 't Ġfind Ġthe Ġpreferred ĠMedia Format Ġtrack Ġindex !") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġ} Ċ }