Skip to content

Commit 7a31acc

Browse files
committed
Add keep last frame documentation
1 parent b754805 commit 7a31acc

8 files changed

Lines changed: 148 additions & 6 deletions

doc/KEEP_LAST_FRAME.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# 完成后保留最后一帧 Demo
2+
3+
`KeepLastFrameVideo` 是一个 Demo 级播放器,用来验证“自然播放完成后停留在最后一帧”的交互语义。它不会改变基础播放器的默认完成态,也不会全局影响其他播放器页面。
4+
5+
## 目标
6+
7+
- 播放自然结束时,可以选择保留当前 render view 画面,不立刻显示封面。
8+
- 通过 flag 控制行为,业务可以在同一个页面里对比“保留最后一帧”和“默认封面态”。
9+
- 播放失败、主动释放、退出页面等非自然完成场景仍走原有释放流程。
10+
- 全屏和非全屏切换时同步该 flag。
11+
12+
## Demo 入口
13+
14+
主页面入口:`完成保留最后一帧`
15+
16+
主要类:
17+
18+
- `app/src/main/java/com/example/gsyvideoplayer/KeepLastFrameDemoActivity.java`
19+
- `app/src/main/java/com/example/gsyvideoplayer/video/KeepLastFrameVideo.java`
20+
- `app/src/main/res/layout/activity_keep_last_frame_demo.xml`
21+
22+
## 基本用法
23+
24+
```java
25+
keepLastFrameVideo.setKeepLastFrameWhenComplete(true);
26+
```
27+
28+
关闭后恢复默认完成态:
29+
30+
```java
31+
keepLastFrameVideo.setKeepLastFrameWhenComplete(false);
32+
```
33+
34+
Demo 内部通过 `isLastAutoCompleteRetainedSurface()` 判断本次自然完成时是否确实保留了 render view。
35+
36+
## 实现说明
37+
38+
`KeepLastFrameVideo#onAutoCompletion()` 在开启 flag 时不会调用基础类默认的完成释放逻辑,而是:
39+
40+
- 设置状态为 `CURRENT_STATE_AUTO_COMPLETE`
41+
- 保留当前 render view。
42+
- 隐藏封面层,显示完成态控制 UI。
43+
- 释放音频焦点、网络监听和屏幕常亮 flag。
44+
- 触发 `onAutoComplete` 回调。
45+
46+
`onCompletion()`、重新播放和页面销毁仍走原释放逻辑,避免资源长期残留。
47+
48+
## 注意事项
49+
50+
- 这是 Demo 级能力,适合先验证业务交互,不建议直接理解为全局播放器默认行为。
51+
- 是否能保留画面取决于当前 render view 是否仍存在,以及业务是否主动释放 Surface。
52+
- 如果业务完成后必须展示封面、广告或推荐位,应保持默认完成态。
53+
- 如果要下沉到基础库,需要同时设计 Surface 生命周期、封面层、重播、全屏复制、小窗等场景。
54+
55+
## 回归建议
56+
57+
```bash
58+
./gradlew :app:assembleDebug
59+
adb install -r app/build/outputs/apk/debug/app-debug.apk
60+
adb shell am start -n com.example.gsyvideoplayer/.MainActivity
61+
```
62+
63+
真机检查:
64+
65+
- 进入 `完成保留最后一帧`
66+
- 开启“保留最后一帧”,播放到自然结束,确认停留在最后一帧且不显示封面。
67+
- 关闭“保留最后一帧”,重新播放到结束,确认回到默认封面态。
68+
- 播放结束后点击重播,确认能重新开始。
69+
- 播放中进入全屏、退出全屏,再等播放结束,确认 flag 仍生效。
70+
- 退出页面后扫 logcat,确认没有 `FATAL EXCEPTION``IllegalStateException` 或 Surface 相关 crash。

doc/KEEP_LAST_FRAME_EN.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Keep Last Frame Demo
2+
3+
`KeepLastFrameVideo` is a demo-level player for validating the behavior of keeping the last rendered frame after natural playback completion. It does not change the base player's default completion state and does not affect other player pages globally.
4+
5+
## Goals
6+
7+
- After natural completion, optionally keep the current render view instead of showing the cover immediately.
8+
- Use a flag so the same page can compare keep-last-frame behavior with the default cover state.
9+
- Playback errors, manual release, and page exit still follow the normal release path.
10+
- Fullscreen and normal players copy the flag consistently.
11+
12+
## Demo Entry
13+
14+
Main page entry: `Keep last frame`
15+
16+
Main classes:
17+
18+
- `app/src/main/java/com/example/gsyvideoplayer/KeepLastFrameDemoActivity.java`
19+
- `app/src/main/java/com/example/gsyvideoplayer/video/KeepLastFrameVideo.java`
20+
- `app/src/main/res/layout/activity_keep_last_frame_demo.xml`
21+
22+
## Basic Usage
23+
24+
```java
25+
keepLastFrameVideo.setKeepLastFrameWhenComplete(true);
26+
```
27+
28+
Disable it to restore the default completion state:
29+
30+
```java
31+
keepLastFrameVideo.setKeepLastFrameWhenComplete(false);
32+
```
33+
34+
The demo uses `isLastAutoCompleteRetainedSurface()` to check whether the render view was actually retained for the latest natural completion.
35+
36+
## Implementation Notes
37+
38+
When the flag is enabled, `KeepLastFrameVideo#onAutoCompletion()` does not call the base default completion release flow. It:
39+
40+
- Sets state to `CURRENT_STATE_AUTO_COMPLETE`.
41+
- Keeps the current render view.
42+
- Hides the cover layer and shows completion controls.
43+
- Releases audio focus, network listener, and keep-screen-on flag.
44+
- Dispatches `onAutoComplete`.
45+
46+
`onCompletion()`, replay, and page destroy still use the normal release flow to avoid long-lived resources.
47+
48+
## Notes
49+
50+
- This is a demo-level capability for validating business behavior, not a global default.
51+
- Whether the frame can be kept depends on the current render view and whether the app releases the Surface manually.
52+
- If the business must show cover, ads, or recommendations after completion, keep the default completion state.
53+
- Moving this into base components needs a full design for Surface lifecycle, cover visibility, replay, fullscreen cloning, and small-window behavior.
54+
55+
## Regression Checklist
56+
57+
```bash
58+
./gradlew :app:assembleDebug
59+
adb install -r app/build/outputs/apk/debug/app-debug.apk
60+
adb shell am start -n com.example.gsyvideoplayer/.MainActivity
61+
```
62+
63+
Manual checks:
64+
65+
- Enter `Keep last frame`.
66+
- Enable keep-last-frame, play to natural completion, and confirm the last frame remains visible without showing the cover.
67+
- Disable keep-last-frame, replay to completion, and confirm the default cover state returns.
68+
- Replay after completion and confirm playback starts again.
69+
- Enter and exit fullscreen during playback, then wait for completion and confirm the flag still works.
70+
- Check logcat for no `FATAL EXCEPTION`, `IllegalStateException`, or Surface-related crash.

doc/RECENT_FEATURES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
- `doc/ARCHITECTURE.md`:播放能力在 UI、Manager、Render、Exo manager 等层级上的设计归属。
4343
- `doc/GSYVIDEO_PLAYER_PROJECT_INFO.md` / `doc/GSYVIDEO_PLAYER_PROJECT_INFO_EN.md`:项目结构说明里的近期能力层级映射。
4444
- `doc/SUBTITLE_CN.md`:通用字幕专题说明。
45+
- `doc/KEEP_LAST_FRAME.md` / `doc/KEEP_LAST_FRAME_EN.md`:完成后保留最后一帧专题说明。
4546
- `doc/RECENT_FEATURES.md` / `doc/RECENT_FEATURES_EN.md`:近期能力总览、API 和回归清单。
4647

4748
构建、依赖、SO、发布、解码器、FAQ 类文档没有强行加入本次播放能力说明,因为它们的主题不是 Demo 功能入口或播放架构。
@@ -88,7 +89,7 @@ videoPlayer.setSubtitleEnabled(true);
8889

8990
## 完成后保留最后一帧
9091

91-
`KeepLastFrameVideo` 是 Demo 级实现,核心是覆写自然播放完成后的 UI 状态切换,在不主动释放 render view 的情况下保留画面。
92+
`KeepLastFrameVideo` 是 Demo 级实现,核心是覆写自然播放完成后的 UI 状态切换,在不主动释放 render view 的情况下保留画面。详细说明见 [KEEP_LAST_FRAME.md](KEEP_LAST_FRAME.md)
9293

9394
```java
9495
keepLastFrameVideo.setKeepLastFrameWhenComplete(true);

doc/RECENT_FEATURES_EN.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Recent playback feature notes are covered in:
4242
- `doc/ARCHITECTURE.md`: layer ownership across UI, Manager, Render, and Exo manager.
4343
- `doc/GSYVIDEO_PLAYER_PROJECT_INFO.md` / `doc/GSYVIDEO_PLAYER_PROJECT_INFO_EN.md`: recent feature mapping in the project structure guide.
4444
- `doc/SUBTITLE_CN.md`: unified subtitle guide.
45+
- `doc/KEEP_LAST_FRAME.md` / `doc/KEEP_LAST_FRAME_EN.md`: keep-last-frame guide.
4546
- `doc/RECENT_FEATURES.md` / `doc/RECENT_FEATURES_EN.md`: full recent feature overview, APIs, and regression checklist.
4647

4748
Build, dependency, SO, publishing, decoder, and FAQ documents are not forced to repeat these playback feature notes because their scope is not demo entry points or playback architecture.
@@ -88,7 +89,7 @@ See [SUBTITLE_CN.md](SUBTITLE_CN.md) for the detailed Chinese subtitle guide.
8889

8990
## Keep Last Frame
9091

91-
`KeepLastFrameVideo` is a demo-level implementation. It overrides the natural completion UI transition and keeps the render view instead of returning to the cover immediately.
92+
`KeepLastFrameVideo` is a demo-level implementation. It overrides the natural completion UI transition and keeps the render view instead of returning to the cover immediately. See [KEEP_LAST_FRAME_EN.md](KEEP_LAST_FRAME_EN.md) for details.
9293

9394
```java
9495
keepLastFrameVideo.setKeepLastFrameWhenComplete(true);

doc/UPDATE_VERSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- 截图能力补齐 SurfaceView、TextureView、GLSurfaceView 回调,并新增包含播放器 UI 的组合截图 API。
1212
- GL 渲染 Demo 增加多种效果场景,强化 GL renderer 生命周期、截图和释放安全性。
1313
- 多 URL 清晰度切换优化位置同步、超时、失败回退和临时 manager 释放,降低切换回 0 的风险。
14-
- 新增完成后保留最后一帧 Demo,方便验证自然播放完成后的封面和 Surface 保留策略。
14+
- 新增完成后保留最后一帧 Demo 和专题文档,方便验证自然播放完成后的封面和 Surface 保留策略。
1515
- 播放器内核创建和初始化失败时走错误回调与资源清理,降低直接 crash 风险。
1616
- 优化 Exo cache 生命周期处理和 GIF 生成结束/失败后的清理流程。
1717

doc/UPDATE_VERSION_EN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- Screenshot handling now reports SurfaceView, TextureView, and GLSurfaceView failure paths and adds composed player screenshot APIs including UI.
1212
- GL demos include more effect scenes and safer renderer lifecycle, screenshot, and release behavior.
1313
- Multi-URL quality switching improves position sync, timeout handling, failure fallback, and temporary manager release to reduce jump-back-to-0 risk.
14-
- Add a keep-last-frame demo for validating cover and Surface retention behavior after natural completion.
14+
- Add a keep-last-frame demo and guide for validating cover and Surface retention behavior after natural completion.
1515
- Player core creation and initialization failures now route through error callbacks and cleanup to reduce direct crash risk.
1616
- Improve Exo cache lifecycle handling and cleanup after GIF creation finishes or fails.
1717

doc/USE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ GSYVideoType.setRenderType(GSYVideoType.GLSURFACE);
539539

540540
- `打开VIDEO`:WebVTT 进度条预览,使用 `PreViewGSYVideoPlayer#setPreviewVttUrl(String)`
541541
- `自定义EXO支持字幕``通用字幕非EXO`:通用外挂字幕,支持 SRT/WebVTT 和多内核复用。
542-
- `完成保留最后一帧`:完成后保留最后一帧 Demo,通过 `KeepLastFrameVideo#setKeepLastFrameWhenComplete(boolean)` 控制。
542+
- `完成保留最后一帧`:完成后保留最后一帧 Demo,通过 `KeepLastFrameVideo#setKeepLastFrameWhenComplete(boolean)` 控制,详见 [KEEP_LAST_FRAME.md](KEEP_LAST_FRAME.md)
543543
- `滤镜`:GLSurfaceView 滤镜和多种 GL 效果场景。
544544
- `无缝切换`:多 URL 清晰度切换 Demo,适合多个独立 URL 的切换。
545545
- `EXO自适应清晰度`:HLS master / DASH MPD 自适应清晰度 Demo,适合服务端提供标准多码率流的场景。

doc/USE_EN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ Common entry points:
504504

505505
- `Open VIDEO`: WebVTT seek preview via `PreViewGSYVideoPlayer#setPreviewVttUrl(String)`.
506506
- `Custom EXO subtitles`, `Common subtitles non-EXO`: unified external SRT/WebVTT subtitles across player cores.
507-
- `Keep last frame`: keep-last-frame demo controlled by `KeepLastFrameVideo#setKeepLastFrameWhenComplete(boolean)`.
507+
- `Keep last frame`: keep-last-frame demo controlled by `KeepLastFrameVideo#setKeepLastFrameWhenComplete(boolean)`, see [KEEP_LAST_FRAME_EN.md](KEEP_LAST_FRAME_EN.md).
508508
- `Filter`: GLSurfaceView filters and GL effect scenes.
509509
- `Seamless switch`: multi-URL quality switching for separate URLs.
510510
- `EXO adaptive quality`: HLS master / DASH MPD adaptive quality demo for standard multi-bitrate streams.

0 commit comments

Comments
 (0)