Project Overview
Project Purpose and Objectives
This project implements a modular, extensible media player system primarily targeting Android platforms. Its core purpose is to provide a robust video playback experience with advanced ad integration capabilities, including support for VPAID ads, cue points, and adaptive streaming. The system leverages a finite state machine (FSM) architecture to manage media playback states, including content playback, ad retrieval, and ad playing states, ensuring smooth transitions and consistent user experience.
The project objectives include:
Media Playback with Ads: Seamlessly integrate video ads with content playback, supporting preroll, midroll, and postroll ads managed via cue points.
Finite State Machine (FSM) Driven Playback: Use an FSM to control playback logic, state transitions, and error handling for both content and advertisement media.
Dependency Injection and Modularity: Employ Dagger 2 for dependency injection to improve modularity, testability, and scalability.
Rich User Interface: Provide customizable, data-binding-enabled UI components for user interaction such as play/pause toggling, seeking, subtitle toggling, and ad interaction.
VPAID Ad Support: Integrate VPAID-compliant ads through a WebView interface, managing JS communication, errors, and lifecycle.
Adaptive Streaming: Use ExoPlayer with adaptive track selection to optimize playback quality based on bandwidth.
Extensive Logging and Testing: Include detailed logging utilities and unit/instrumentation tests covering FSM states and playback flows.
Major Functionalities and Implementation Details
Finite State Machine Player (
FsmPlayer,FsmPlayerImperial)
Implements the core playback state machine managing the lifecycle of media content and ads. It handles transitions using input events (Inputenum) and state classes such asMoviePlayingState,MakingAdCallState,AdPlayingState, and VpaidState. The FSM interacts with ad retrieval interfaces and UI controllers to update playback and UI accordingly.Ad and Cue Point Management
Classes likeAdRetriever,CuePointsRetriever, and listeners likeAdPlayingMonitorandCuePointMonitorcoordinate fetching ads and cue points and trigger state transitions in the FSM based on playback progress.Dependency Injection Modules (
PlayerModuleDefault,FSMModuleReal) and Components (FsmComonent,FsmComonentReal)
Provide scoped injection of the FSM player, controllers, monitors, and ad interfaces using Dagger 2, supporting testability and separation of concerns.Media Playback Activities
DoubleViewTubiPlayerActivityextends a base player activity to provide dual ExoPlayer instances for content and ad playback, integrating FSM and UI controllers.DemoActivityandRealActivityprovide example implementations of media playback with different UI and dependency injection configurations.SelectionActivityoffers a media selection interface to launch playback with different configurations.WebviewActivitymanages WebView-based VPAID ad playback.
User Interface Components and Bindings
PlayerControllerUIandUIControllerViewprovide customizable playback control UIs with data binding toUserController.UserControllermanages user input, playback status observables, and ExoPlayer event callbacks.TubiExoPlayerViewis a custom player view hosting ExoPlayer, subtitle rendering, and controller integration.
VPAID Integration (
TubiVPAID,Vastxml)
Implements a WebView-based VPAID client that communicates with JavaScript to control ad playback, report errors, and notify video end events.Core Utilities
Helpers for media source construction, logging (ExoPlayerLogger,EventLogger), device detection (PlayerDeviceUtils), and UI utilities (Utils,SeekCalculator).
Example Workflows and Use Cases
Playback with Ads and FSM Transitions
Initialization
The player activity initializes the FSM player (FsmPlayerImperial) and injects dependencies using Dagger modules (FSMModuleRealorPlayerModuleDefault).Media Loading
The content media (MediaModel) is loaded into the FSM player. The FSM starts in theFetchCuePointStateto retrieve cue points from the ad server.Cue Points and Pre-roll Ads
If preroll ads are present (detected via cue points), the FSM transitions to MakingPrerollAdCallState to fetch preroll ads.Ad Playback
Ads are played within theAdPlayingStateor VpaidState (for VPAID ads). Ad playback is managed on a dedicated ExoPlayer instance or via WebView for VPAID.Content Playback
After ads, the FSM transitions toMoviePlayingStatewhere the main content plays. Cue points are monitored to trigger midroll ads.User Interaction
TheUserControllerupdates UI elements such as play/pause, seek bar, subtitles toggle, and ad-related UI components.Error Handling
Playback errors or ad retrieval errors trigger FSM transitions to FinishState or error states, enabling graceful recovery or termination.
Example: Playing a Video with Cue Points and Ads
User selects a video in
SelectionActivity.DoubleViewTubiPlayerActivityreceives the media model and prepares the FSM.FSM retrieves cue points (
FetchCuePointState), finds preroll ads, transitions to fetch ads (MakingPrerollAdCallState).Ads are played (
AdPlayingState), with the UI showing ad metadata and a "Learn More" button.After ads, content plays (
MoviePlayingState).During playback, cue point monitor triggers midroll ad network calls and ad playback.
User controls playback using
PlayerControllerUIorUIControllerView.
Example: VPAID Ad Playback in WebView
WebviewActivityinitializes a WebView andTubiVPAIDclient.VPAID ad XML is loaded either from hardcoded
Vastxmlor via network.JavaScript interface methods notify the FSM player on ad completion or errors.
FSM transitions accordingly to resume or finish playback.
Stack and Technologies
Technologies
Android Platform: Targeted for Android devices, supports TV devices and various screen sizes.
Java: Core language for implementation.
ExoPlayer: Google's media playback library used for content and ad playback with support for DASH, HLS, and SmoothStreaming.
Dagger 2: Dependency injection framework used for managing object graph and lifecycle scopes.
Fabric Crashlytics and Answers: For crash reporting and analytics integration.
Android Architecture Components (Lifecycle): For lifecycle-aware components.
Data Binding Library: For UI binding between XML layouts and Java code.
JUnit and Mockito: For unit and instrumentation testing.
WebView: For VPAID ad playback and JavaScript communication.
Key Libraries and Frameworks
ExoPlayer: Enables adaptive streaming, multiple media sources, and track selection.
Dagger 2: Provides scoped injection with custom annotations like
@ActicityScope.Fabric SDK: Integrated via DemoApplication for app analytics and crash reporting.
Material Dialogs and Picasso: Included in dependencies for UI dialogs and image loading (in lib).
Custom Views: Includes
TubiExoPlayerView,PlayerControllerUI,UIControllerView, and custom widgets likeStateImageButton.
Rationale for Technology Choices
ExoPlayer was chosen for its flexibility, adaptive streaming support, and open-source community.
FSM Architecture ensures clear, maintainable state transitions for complex ad and content playback scenarios.
Dagger 2 improves modularity and testability, reducing boilerplate code.
Data Binding simplifies UI updates and reduces coupling between UI and logic.
WebView Integration allows for complex VPAID ad interactions with JavaScript.
High-Level Architecture
The project is structured primarily into two modules:
app Module: Contains demo applications and UI implementations.
lib Module: Contains core media playback logic, FSM implementation, controllers, models, utilities, and UI components.
Major Components
Frontend / UI Layer
Activities such asDoubleViewTubiPlayerActivity,DemoActivity,RealActivity, andSelectionActivityprovide user interaction and media playback interfaces.
Custom views likeTubiExoPlayerView,PlayerControllerUI, andUIControllerViewhandle media display and user controls.Finite State Machine (FSM) Layer
Core playback logic handled byFsmPlayerImperialextendingFsmPlayer, managing states like fetching cue points, making ad calls, playing ads, and playing content.
State classes (FetchCuePointState,AdPlayingState, VpaidState, etc.) encapsulate state-specific behavior.StateFactorycreates and caches state instances.Ad and Cue Point Management
AdRetrieverandCuePointsRetrieverfetch ad and cue point data.AdPlayingMonitorandCuePointMonitorlisten to ExoPlayer events and playback progress to trigger FSM transitions.Dependency Injection
Dagger components (FsmComonent,FsmComonentReal) and modules (PlayerModuleDefault,FSMModuleReal) provide scoped instances of FSM player, controllers, monitors, and ad interfaces.Media Playback and Control
Uses ExoPlayer instances for content and ad playback, managed viaPlayerUIControllerandPlayerAdLogicController.
VPAID ads are handled byTubiVPAIDvia a WebView interface.Utilities and Helpers
Logging utilities (ExoPlayerLogger,EventLogger), media helpers (MediaHelper), and device utilities (PlayerDeviceUtils) support core functionality.
Interactions Among Components
Activities initialize and inject FSM player and controllers.
FSM player manages playback state, interacting with controllers to update UI and player instances.
Ad and cue point retrievers fetch data asynchronously, notifying FSM via callbacks.
FSM states invoke ad interfaces to fetch ads, then transition to ad playback states.
UserController binds UI controls to player, reflecting playback state and responding to user input.
VPAID client manages ad playback inside a WebView, communicating with FSM via JS interface callbacks.
ExoPlayer instances play media content and ads separately or combined, coordinated by controllers.
Mermaid Component Diagram
graph TB
UI[Activities & UI Components] -->|injects| DI[Dagger Components & Modules]
DI --> FSM[FsmPlayer & States]
FSM -->|controls| PlayerUI[PlayerUIController]
FSM -->|controls| PlayerAd[PlayerAdLogicController]
FSM -->|fetches| AdInterface[AdInterface Implementation]
FSM -->|fetches| CuePointInterface[CuePointsRetriever]
PlayerUI --> ExoPlayerContent[ExoPlayer Content Player]
PlayerAd --> ExoPlayerAd[ExoPlayer Ad Player]
PlayerAd --> VPAID[TubiVPAID WebView]
UI --> UserCtrl[UserController]
UserCtrl --> PlayerUI
UserCtrl --> FSM
Developer Navigation
To facilitate efficient exploration and contribution, the following developer roles and starting points are suggested:
Frontend Developers
Start with UI components:
PlayerControllerUI.javafor media control UI implementation.UIControllerView.javafor media control visibility and interaction management.TubiExoPlayerView.javafor the main video player view integrating ExoPlayer and subtitles.
Explore activities providing playback UI:
DoubleViewTubiPlayerActivity.javafor dual player and FSM integration.DemoActivity.java,RealActivity.java, andSelectionActivity.javafor example usage.
Review XML layout resources in
app/src/main/res/layout/for UI structure.
Backend / Core Developers
Explore the FSM implementation:
FsmPlayer.javaandFsmPlayerImperial.javafor core FSM player logic.State classes under
fsm/concrete/such asAdPlayingState.java,MoviePlayingState.java,FetchCuePointState.java.StateFactory.javafor state instance creation and overriding.
Ad and cue point control:
AdRetriever.java,CuePointsRetriever.java,AdInterface.java,RetrieveAdCallback.javafor ad fetching logic.AdPlayingMonitor.javaandCuePointMonitor.javafor playback progress monitoring.
Dependency injection setup:
PlayerModuleDefault.javaandFSMModuleReal.javafor module provisioning.FsmComonent.javaandFsmComonentReal.javafor component interfaces.
Ad Integration Developers
VPAID integration:
TubiVPAID.javafor WebView-based VPAID ad client.Vastxml.javafor VAST XML ad data.WebviewActivity.javafor VPAID WebView lifecycle.
Testing and Utilities
Unit and instrumentation tests in
lib/src/test/javaandapp/src/androidTest/javafolders.Logging utilities:
ExoPlayerLogger.java,EventLogger.java.Utility classes:
PlayerDeviceUtils.java,Utils.java,SeekCalculator.java.
Visual Diagrams
FSM Playback Workflow Flowchart
flowchart TD
Start[Initialize Player]
Start --> FetchCuePoints[Fetch Cue Points]
FetchCuePoints -->|Has Preroll Ad| MakePrerollAdCall[Make Preroll Ad Call]
FetchCuePoints -->|No Preroll Ad| MoviePlaying[Play Movie]
MakePrerollAdCall --> ReceivePrerollAd[Receive Preroll Ad]
ReceivePrerollAd --> PlayPrerollAd[Play Preroll Ad]
PlayPrerollAd --> MoviePlaying
MoviePlaying --> CheckCuePoints[Check Cue Points During Playback]
CheckCuePoints -->|Cue Point Reached| MakeAdCall[Make Midroll Ad Call]
MakeAdCall --> ReceiveAd[Receive Ad]
ReceiveAd --> PlayAd[Play Ad]
PlayAd --> MoviePlaying
MoviePlaying --> End[Movie Finished]
PlayAd -->|Ad Finished| MoviePlaying
PlayPrerollAd -->|Ad Finished| MoviePlaying
MakeAdCall -->|No Ad| MoviePlaying
FetchCuePoints -->|Error| ErrorState[Error Handling]
MakePrerollAdCall -->|Error| ErrorState
MakeAdCall -->|Error| ErrorState
ErrorState --> End
High-Level Component Interaction Sequence
sequenceDiagram
participant UI as UI/Activities
participant DI as Dagger DI
participant FSM as FsmPlayer
participant AdSvc as Ad Server Interface
participant PlayerUI as PlayerUIController
participant PlayerAd as PlayerAdLogicController
participant ExoContent as ExoPlayer Content
participant ExoAd as ExoPlayer Ad
participant VPAID as VPAID WebView
UI->>DI: Request FSM and Controllers
DI->>FSM: Provide FsmPlayer instance
UI->>FSM: Load MediaModel
FSM->>AdSvc: Fetch Cue Points
AdSvc-->>FSM: Cue Points Data
FSM->>FSM: Transition States (e.g. preroll ad)
FSM->>AdSvc: Fetch Ads
AdSvc-->>FSM: Ads Data
FSM->>PlayerAd: Control Ad Playback
PlayerAd->>ExoAd: Play Ad Media
FSM->>PlayerUI: Update Playback UI
UI->>PlayerUI: User Controls Interaction
PlayerUI->>FSM: Control Playback (play/pause/seek)
FSM->>ExoContent: Play Content Media
FSM->>VPAID: Play VPAID Ad via WebView
VPAID-->>FSM: Notify Ad Events (end/error)
This overview provides a clear roadmap for developers to understand the software architecture, key components, workflows, and technology stack. It facilitates quick onboarding and effective contribution across frontend, backend, ad integration, and testing domains.