Slide 1

Slide 1 text

I’ve spent a year building Picasso for Video and here is it Tokyo Android Meetup・2019/07/23 Nam Nguyen (eneim)

Slide 2

Slide 2 text

Picasso? A powerful image downloading and caching library for Android https://square.github.io/picasso/

Slide 3

Slide 3 text

Picasso? Picasso.get() .load(photoUrl) .into(imageView) source: https://square.github.io/picasso/

Slide 4

Slide 4 text

Picasso for Video? HOW?

Slide 5

Slide 5 text

Picasso for Video? A powerful image downloading and caching video playback library for Android

Slide 6

Slide 6 text

Picasso for Video? OKAY...

Slide 7

Slide 7 text

MediaPlayer, ExoPlayer, ffmpeg, etc exist. Why do we need another Video playback library?

Slide 8

Slide 8 text

Scenario: cloning YouTube client

Slide 9

Slide 9 text

YouTube clone sprint 1 - List of thumbnail - Click item thumbnail → open Player - One Video in one screen at one time!

Slide 10

Slide 10 text

Sprint 1 approach - 1 Activity for list & 1 Activity for player - Click → Parcelize Video information and start PlayerActivity - MediaPlayer or ExoPlayer for playback

Slide 11

Slide 11 text

YouTube clone sprint 2 - List of thumbnail Videos - Fully visible Video on top: plays automatically - Click an item → open Player - Many Videos in one screen at one time! - At most one to play

Slide 12

Slide 12 text

Sprint 2 approach - 1 Activity for list & 1 Activity for player - List: RecyclerView with OnScrollListener - onScrolled: - LinearLayoutManager’s findFirstCompletelyVisibleItemPosition() - Start and Pause item properly - MediaPlayer or ExoPlayer for playback

Slide 13

Slide 13 text

YouTube clone sprint 3 - Single player UX ⇆ Orientation: - Portrait: Player + Video detail - Landscape: Fullscreen player - Background playback (to replicate YouTube Premium) - Playback continuity - No reloading/re-buffering

Slide 14

Slide 14 text

Sprint 3 approach - Manifest flag: configChanges + Orientation Detector and/or onConfigurationChanged + if/else 祭り - Background playback: foreground Service - No re-creation → No re-buffering

Slide 15

Slide 15 text

Sprint 3 challenges - Manifest flag: configChanges ← How many flags you will need? - Background playback: foreground Service ← How? - Foreground Service should be alive even if no Activity is

Slide 16

Slide 16 text

Not done yet ! https://github.com/google/ExoPlayer/issues/867

Slide 17

Slide 17 text

Need more power!

Slide 18

Slide 18 text

‘Picasso for Video’ is a powerful Video playback library for Android Named it Kohii

Slide 19

Slide 19 text

DEMO

Slide 20

Slide 20 text

// fragment_main.xml // // // // // // override fun onActivityCreated(state: Bundle?) { super.onActivityCreated(state) kohii = Kohii[this@MyFragment].also { it.register(this, this.scrollView) } kohii.setUp(videoUrl).bind(playerView) } Easy to start

Slide 21

Slide 21 text

// fragment_main.xml // // // // // // // // override fun onActivityCreated(state: Bundle?) { super.onActivityCreated(state) kohii = Kohii[this@MyFragment].also { it.register(this, this.scrollView) } kohii.setUp(videoUrl).bind(firstPlayerView) kohii.setUp(otherVideoUrl).bind(secondPlayerView) } Many videos scenario is supported out of the box

Slide 22

Slide 22 text

Reusability: Unlimited items using only one PlayerView!

Slide 23

Slide 23 text

Summary: what Kohii offers? - Works out of the box - Implement Video playback as quick as possible - Single Video or many Videos - Safe and resource friendly - Cache and reuse playback resource - All cached resources are torn down at reasonable timing - Flexible & Extensible - Powerful abstraction & default impl using ExoPlayer - DIY on top of Kohii’s abstraction

Slide 24

Slide 24 text

Under the hood

Slide 25

Slide 25 text

Kohii manages playbacks like managing an organization

Slide 26

Slide 26 text

Application FragmentActivity Fragment Fragment RecyclerView RecyclerView PlayerViews

Slide 27

Slide 27 text

Application FragmentActivity Fragment Fragment RecyclerView RecyclerView Kohii (BOSS) PlaybackManagerGroup PlaybackManager TargetHost Target(s) PlayerView

Slide 28

Slide 28 text

Kohii PlaybackManagerGroup PlaybackManager_A PlaybackManager_B TargetHost_A TargetHost_B Target_A0 Target_A2 Target_A1 Target_B0 Target_B2 Target_B1 Target_B3 Target_B5 Target_4 Target’s attach/detach/layout events PlaybackManager requests update TargetHost’s scroll/layout event PlaybackManagerGroup talks to all PlaybackManagers: collect all Targets to play and to pause

Slide 29

Slide 29 text

Kohii PlaybackManagerGroup PlaybackManager_A PlaybackManager_B TargetHost_A TargetHost_B Target_A0 Target_A2 Target_A1 Target_B0 Target_B2 Target_B1 Target_B3 Target_B5 Target_4 Each PlaybackManager talks to its TargetHosts: select the Target to play, others will be paused. PlaybackManagerGroup then decide the final Target to play and pause all others React to user interaction. Using Handler/Messenger to prevent aggressive update requests.

Slide 30

Slide 30 text

Limited resource for unlimited demand: Caching

Slide 31

Slide 31 text

ExoPlayer pool and PlayerView pool

Slide 32

Slide 32 text

TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text Video: not playable

Slide 33

Slide 33 text

TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text Video: playable Player provider Pool Creator Player #1 Give me a Player Here you are

Slide 34

Slide 34 text

TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text Video: playable Player provider Pool Creator Player #1 TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text TEXT Text text text text text text text text text text text text text text text text text text text text I’m done, thanks!

Slide 35

Slide 35 text

TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text Video: playable Player provider Pool Creator Player #1 Give me a Player Here you are TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text

Slide 36

Slide 36 text

Player provider Pool Creator TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text TEXT Text text text text text text text text text text text text text text text text text text text text text text text text text Lifecycle.Event.ON_DESTROY Player #1 I’m done, thanks!

Slide 37

Slide 37 text

Non-blocking playback experience (a.k.a Playback continuity)

Slide 38

Slide 38 text

By passing the same resource around, we can switch the Player without reloading the content

Slide 39

Slide 39 text

This mechanism learns from how ExoPLayer works

Slide 40

Slide 40 text

How ExoPlayer works ExoPlayer PlayerView MediaSource // playerView: PlayerView instance // player: ExoPlayer instance // mediaSource: MediaSource instance playerView.setPlayer(player) player.prepare(videoSource) player.playWhenReady = true // to play, or false to pause

Slide 41

Slide 41 text

Target Playable ExoPlayer, MediaSource PlayerView

Slide 42

Slide 42 text

Target Playable Screen A Screen B Target

Slide 43

Slide 43 text

Target Playable PlayerView ExoPlayer, MediaSource Playback play/pause/etc

Slide 44

Slide 44 text

Target Playable Playback Application scope Activity scope Activity scope Target Playback

Slide 45

Slide 45 text

Target Playable Playback Application List Fullscreen Player Target Playback

Slide 46

Slide 46 text

One Playable (= one ExoPlayer) Video in List Overlay Player Background Player

Slide 47

Slide 47 text

Q: Looks good. But I don’t want to use ExoPlayer.

Slide 48

Slide 48 text

A: Kohii is extensible. i.e You can support other playback API on top of Kohii’s abstraction

Slide 49

Slide 49 text

Abstraction: Playable, Playback, Pool, etc Default impl using ExoPlayer DIY* using your own playback API (eg: androidx Media2, YouTube Player API) *Not all API support easy switching Target, eg: YouTube Player API

Slide 50

Slide 50 text

Source code https://github.com/eneim/kohii

Slide 51

Slide 51 text

Thanks