Skip to content

Latest commit

 

History

History
239 lines (178 loc) · 6.98 KB

File metadata and controls

239 lines (178 loc) · 6.98 KB

AtomicPlayer for Android

A lightweight, atomic live-streaming player SDK — fast start, seamless switching, easy to extend.

English | 简体中文 | 日本語 · ⬅ Back to overview

Platform minSdk

AtomicPlayer targets low-latency live streaming (LEB / RTMP) and CDN pull-stream scenarios. It does one thing well: play a live stream fast and stable.

  • 🚀 Fast start — first frame under 600ms
  • 🎞️ Premium visual quality — opt-in AI super-resolution and HDR
  • 🔄 Seamless switch — quality switch is smooth
  • 🌐 Consistent across platforms — all platforms share the same unified flow

✨ Features

Capability API
Playback control startPlay / stopPlay / pause / resume
Seamless switch switchStream
Render control setRenderView / setRenderRotation / setRenderFillMode
Snapshot snapshot
Volume setVolume
SEI messages enableReceiveSeiMessage
Event callbacks AtomicPlayerObserver
Advanced features enableAdvancedFeature (AI super-resolution / HDR)

🚀 5-Minute Quick Start

1. Requirements

  • Android minSdk 21+ (Android 5.0)
  • ABIs: armeabi-v7a / arm64-v8a / x86_64

2. Add Maven dependency

In your project-level settings.gradle (or build.gradle), add the Maven repository:

dependencyResolutionManagement {
    repositories {
        maven { url "" } // TODO: fill in AtomicPlayer Maven repository URL
    }
}

In your module-level build.gradle, add the dependency:

dependencies {
    implementation "" // TODO: fill in AtomicPlayer Maven coordinate, e.g. "io.trtc:atomic-player:x.y.z"
}

3. Permissions

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

4. Add an AtomicView in your layout

<io.trtc.tuikit.atomicxcore.api.view.AtomicView
    android:id="@+id/atomic_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

5. Three lines to play

val player = AtomicPlayerImpl()
player.setRenderView(findViewById(R.id.atomic_view))
player.startPlay("https://your-cdn.com/live/stream.m3u8")

6. Full sample

class PlayerActivity : AppCompatActivity() {

    private lateinit var player: AtomicPlayer

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_player)

        player = AtomicPlayerImpl()
        player.setRenderView(findViewById(R.id.atomic_view))

        player.setObserver(object : AtomicPlayerObserver() {
            override fun didRenderFirstVideoFrame(player: AtomicPlayer, elapsedMs: Int) {
                Log.i("AtomicPlayer", "First frame: ${elapsedMs}ms")
            }
            override fun didFailWithCode(
                player: AtomicPlayer,
                code: AtomicPlayerCode,
                message: String
            ) {
                Log.e("AtomicPlayer", "Failed: $code, $message")
            }
        })

        player.startPlay("https://your-cdn.com/live/stream.m3u8")
    }

    override fun onDestroy() {
        super.onDestroy()
        player.stopPlay()
        player.setObserver(null)
    }
}

Supported protocols: FLV / HLS (http(s)://…) · LEB (webrtc://) · RTMP (rtmp://)


📖 Common Scenarios

▶ Seamless quality switch (no black frame)
// ✅ Recommended: seamless, no black frame
player.switchStream("webrtc://.../stream_1080p")

// ❌ Not recommended: visible black frame + re-first-frame
player.stopPlay()
player.startPlay("webrtc://.../stream_1080p")

The result is delivered asynchronously via didSwitchStream(player, url, code).

▶ Render fill mode
import com.tencent.cloud.tuikit.engine.common.TUICommonDefine.VideoRenderParams.FillMode

player.setRenderFillMode(FillMode.Fill)       // fill container, crop overflow (default)
player.setRenderFillMode(FillMode.Fit)        // aspect-fit, may have letterbox
player.setRenderFillMode(FillMode.ScaleFill)  // stretch to fill, may distort
▶ Snapshot
player.snapshot()

override fun didTakeSnapshot(player: AtomicPlayer, image: Bitmap) {
    // save / share / display
}
▶ Receive SEI messages (danmaku sync, co-hosting signals, timestamp alignment)
player.enableReceiveSeiMessage(enable = true, payloadType = 243)

override fun didReceiveSEI(player: AtomicPlayer, data: ByteArray) {
    Log.i(TAG, "SEI: ${String(data, Charsets.UTF_8)}")
}

Supported payloadType: 5 / 100 / 242 / 243.

▶ HEVC fallback to H.264
override fun didFailWithCode(
    player: AtomicPlayer,
    code: AtomicPlayerCode,
    message: String
) {
    if (code == AtomicPlayerCode.ERROR_NO_AVAILABLE_HEVC_DECODERS) {
        player.stopPlay()
        player.startPlay(h264FallbackUrl)
    }
}
▶ Advanced features (AI super-resolution / HDR)
player.enableAdvancedFeature("setVideoSuperResolutionEnableMode", 1)             // AI super-resolution
player.enableAdvancedFeature("enableHdrEnhancement", "{\"enable\": 1}") // HDR

📡 Callbacks

All methods on AtomicPlayerObserver have a default no-op implementation — override only what you care about:

Category Callback Description
Playback didRenderFirstVideoFrame(player, elapsedMs) First frame rendered; elapsed since startPlay
didStartBuffering(player) / didEndBuffering(player, elapsedMs) Buffering start / end
didChangeVideoSize(player, width, height) Resolution changed
Connection didConnect(player) / didDisconnect(player) Connected / disconnected
didFailWithCode(player, code, message) Playback failed
Data didUpdateStatistics(player, stats) Stats every 2s (resolution / bitrate / fps)
didSwitchStream(player, url, code) Stream switch finished
didTakeSnapshot(player, image) Snapshot ready
didReceiveSEI(player, data) SEI received

⚠️ All callbacks are dispatched on the main thread. Update UI directly; move heavy work to a background thread yourself.


❗ Error Codes

Enum Value Description
OK 0 Success
ERROR_FAILED -1 Uncategorized failure
ERROR_INVALID_PARAMETER -1001 Invalid parameter
ERROR_INSTANCE_NOT_EXIST -1002 Instance disposed
ERROR_NO_AVAILABLE_HEVC_DECODERS -2304 No HEVC decoder available on the device