【张大伟】视频的可插拔播放框架

犹思菱

2017/12/31 发布于 技术 分类

2017年,droidcon 第2次来到中国,并将于2017年11月在北京盛大开幕。参会人群包括业界领袖、技术大咖、技术开发者、大众创业者及领域从业者。大会将邀请来自Google、微软、Facebook、Ebay、Intel、Telenav、阿里巴巴、腾讯、小米、乐视、联想等国内外安卓技术与应用领域的大咖,沿袭历年国际大会特色,聚焦行业最前沿技术,碰撞切磋技术火花。

文字内容
1. A Pluggable Player Business Framework Zhang Dawei
2. Outline Introduction of the background Design of the framework Choices
3. Introduction of the background Too many playback related businesses exists in a single activity, and most businesses are logically independent. Video Advertisement Cross device interaction Subtitles QR Code Resolution auto adjustment Danmaku Scoring Motion control Payment Tip messages Floating Advertisement Trail playback Settings Playback statistic reporting Error handling 0s playback startup 3D Playback Multiple audio track Play list Panoramic playback Live steaming Tip messages Resolution switching Voice control Gifts Auto-skipping Clocks Message pushing Playback controlling
4. Introduction of the background Some businesses are different in presentation only, and lots of playback activities contains the same businesses.
5. Introduction of the background It’s hard to manage the Z-order and interactions between views from different controller. void showViewOfA() { dismissViewOfB(); dismissViewOfC(); dismissViewOfD(); … viewOfA.setVisibility(View.VISIBLE); } void showViewOfB() { ... }
6. Introduction of the background According the the factor above, we want our new architecture can archive the following goals: • All businesses is isolated both in logics and storage, and insensitive to other businesses. • Has a linear increment of complexity when business grows • Separate views and logics as much as possible. • Find a way to manage the Z-order and the interaction of views easily. • Businesses can be easily reused in other playback activities.
7. Outline Introduction of the background Design of the framework Choices
8. Design of the framework Runtime Container of Businesses Video Advertisement Subtitles Danmaku Play list Playback statistic reporting Trail playback Voice control … Video Player Implementation View Management Implementation Activity Life Cycle & Event Dispatching Business Related Dependencies
9. Design of the framework Each business exists as an implementation of IController interface. << interface >> IController + onInit() + onRelease() + onPrepared() … + onActivityResuming() … + onViewDismissed() … + onDispatchKeyEvent() … Lifecycle of a controller it self. Event callbacks from the player. Lifecycle callbacks from the host activity or fragment. Event callbacks from view management. Key input event handling.
10. Design of the framework The runtime container of controllers is called ControllerManager. Activity Player Controller Manager View management Controller A Dependencies of Controller A Controller B Dependencies of Controller C
11. Design of the framework To build a new playback activity, just add all controllers you need into ControllerManager, and then, everything is started. void onCreate() { controllerManager.addControllers(new IController[] { new ControllerA(), new ControllerB(), … new ControllerZ() }); controllerManager.start(); }
12. Design of the framework Controllers still can sense the existence of other controllers. For example, playing an video advertisement is done by a controller, and then other controllers can receive the playback callbacks belongs to the advertisement. So they are confused! ControllerManager (A movie is now playing) (Now an AD is started) Go start the Ad AD Controller What? The movie restarted?? onPrepared() received Innocent Controller A
13. Design of the framework There is a lot of way to prevent this issue, better than checking if a AD is playing or a movie is playing. Callbacks Stack Callbacks Callbacks Hub Bad Controller Controller A Controller B Controller C
14. Design of the framework How a callback stack solves this issue? Callbacks Stack Callbacks Bad Controller Callbacks Hub Controller A Controller B Controller C
15. Design of the framework View of a controller exists as an implementation of IControllerView interface << interface >> IControllerView + getView(): View + getType(): int • getView(): To obtain the actual view to be displayed. • getType(): To indicate the type of this view. << interface >> IPlayInfoView + setVideoInfo(info: VideoInfo) + updateProgress(int progress) … AbsUserActionView + setActionListener(l:UserActionListener) + triggerAction(actionCode: int, T params) …
16. Design of the framework Controller can get an instance of IControllerView and display it via ViewManager. // To get an instance which implements the given interface <T extends IControllerView> T getView(IController controller, Class<T> clazzName); // To display an IControllerView boolean showView(IController controller, Class viewClass, IControllerView view); Controller only knows the interface of the view but don’t know what the view actually is. For showing a view, controller do not care where the view is displayed, nor who is the parent of the view, nor what happed to other views if this view is shown.
17. Design of the framework IViewFactory will take care of the creation of IControllerView. << interface >> IViewFactory + create(ctx: Context, className: Class<T>, parent: ViewGroup) DefaultViewFactory MyViewFactory
18. Design of the framework Different implementation of IViewFactory brings different feeling for the same controller TopicFactory TimeLineTopicFactory
19. Design of the framework IViewPolicy manages the Z-Order of the views, and what will happen to other views if certain view is just displayed. IViewPolicy do this according to the view type. • FLOATING_AD = 25 • CLOCK = 125 • COUNT_DOWN_TIMER = 175 • DEFUALT = 250 BACKGROUND = Integer.MIN_VALUE VIDEO = 0 DANMAKU = 100 CONTROLLER = 200 MENU = 300
20. Design of the framework What happened if a view is requesting to be displayed by a controller? • Refuse the request - AddViewStrategy.REFUSE • Dismiss one or more other views - AddViewStrategy.REMOVE_EXISTING • Just display - AddViewStrategy.KEEP_BOTH // To get an instance which implements the given interface AddViewStrategy getAddViewStrategy(IControllerView adding, IControllerView existing) Adding View (type 0) Existing View (type 1) Existing View (type 2) Existing View (type 3)
21. Design of the framework Strategies of the return value of getAddViewStrategy(): • AddViewStrategy.REFUSE: Stop the traversal and refuse the view to be added. • AddViewStrategy.REMOVE_EXISTING: Existing views with this strategy will be collected, and they will be removed later. • AddViewStrategy.KEEP_BOTH: No effects for existing views with this strategy.
22. Design of the framework Overview of ViewManager, IViewFactory & IViewPolicy. IViewFactory createView() ViewManager IViewPolicy getAddViewStrategy() getViewLayer() getView() showView()
23. Design of the framework How a controller to communicate with other controllers? ControllerManager registerLocalService Controller who provide local service to others Local Service Map <Class, Object> << interface >> ServiceInterface + foo1(): void + foo2(): int getLocalService Controller who depends on the local service
24. Design of the framework Thank to the local service, we can provide lots of common functionalities by providing certain controllers. • Playback statistics reporting • Video time line management • Heartbeat scheduler • Settings framework • Play list • Trail playback •… We can also provide Extension Packs which contains a set of controllers that is suitable for certain business domain. • VOD extension packs • Live streaming extension packs
25. Design of the framework Overview of this framework: • How a business nested in: IController • ControllerManager • Various callbacks • How a business presents it self to the user: IControllerView • ViewManager • ViewFactory & ViewPolicy • Communications between controllers: Local Service
27. Outline Introduction of the background Design of the framework Choices
28. Choices Shell we supports hot-plugging of controllers, which means we can add or remove controllers at runtime? NO. Who has the rights to add or remove the controller? Effort is needed for ensure the stability. There are lots of alternative ways to support enable/disable a controller during runtime.
29. Choices Is Message better than LocalService? Message is lightweight than callbacks, and is very easy to use for events. It also provide the weakest dependency between sender and receiver. But it is a disaster for complex communications, but usually abused because it is too easy to send or receive a message (cause we are lazy). We provided a controller named MessageCenter for message delivery.
30. Choices What about to provide a layout template? Just like BoarderLayout in Swing? So showing a view could be like this: // To get an instance which implements the given interface // To display an IControllerView boolean showView(IController controller, Class viewClass, IControllerView view, int constract); NO. We don’t want the controller knows any thing about how the view layout is arranged. But doing this in the implementation of IViewFactory sounds good. Dock Top Dock Left Center Dock Right Dock Bottom
31. Choices Using an matrix to determine the strategies when adding a view seems simpler than using an method of IViewPolicy. This matrix works well for most cases, but it does not contains enough information for solving complexed cases. This is why we didn’t include this matrix into our framework. But it is good implement IViewPolicy based on this matrix, and write extra code to solve complexed cases. Adding existing ABCD A 0 -1 0 1 B1011 C1101 D 1 -1 1 0
32. Thank you!