当前位置: 首页 > news >正文

基于海思Hi3798MV200 Android7.0实现电影播放蓝光导航功能

Hi3798MV200 虽然具备 4Kp60 HEVC/VP9 硬解、HDMI 2.0a、HDCP 2.2 等蓝光播放所需的基本硬件能力,但要把“蓝光导航”真正跑起来,还缺几条关键链路的软件实现。下面把“能做什么”与“还差什么”拆开说明。


一、已具备(芯片/板级)

  1. 视频/音频解码

    • 2160p60 HEVC、VP9、HDR10/HLG,Dolby/DTS 透传或 Decode[^1]

  2. 输出与保护

    • HDMI 2.0a + HDCP 2.2,满足 AACS 输出要求

  3. 存储与外设

    • USB3.0 / SDIO3.0 / SATA / PCIe,可挂 BD-ROM 或 ISO 文件

  4. Android 7.0 基本框架

    • MediaCodec/AudioTrack 已对接海思 OMX/AI 驱动,可播放 m2ts

    • SurfaceFlinger 支持 4K UI Overlay


二、蓝光导航还缺的 4 大块

  1. BD-J / BD-Live 虚拟机

    • 需要 JVM(标准 JVM 或 Apache Harmony)+ BD-J Profile 1.0/2.0 类库(org.bluray.*、HAVi、TVTimer 等)。

    • Android 默认 Dalvik/ART 不兼容 BD-J,需要移植 “JVM on Android” 或跑独立 JVM 进程,通过 JNI 与 Android 渲染层交互。

    • 开源可参考:
      – libbluray + openjdk / cacao 最小补丁(VLC 早期方案)
      – “jbluray” 社区分支(支持 ARM/Linux)

  2. AACS/BD+ 解密与密钥管理

    • 必须拿到 AACS 官方 LA 授权,获取 Host Key + Processing Key;否则只能走“研究性”libaacs + 已知 PK 表,不能商用。

    • BD+ 需要 BD+ VM(通常由 Irdeto/Dolby 提供商业 SDK)。

  3. 播放路径与图形叠加

    • BD-J 会把 Java 生成的 AWT/Swing 帧送到“IG(Interactive Graphics)平面”,需要让海思 VO 模块再开一个 1080p/4K ARGB 层,与视频层混叠。

    • 海思 SDK 里 VO 图层多达 8 层,Android HAL 层需暴露 “HWC_BLURAY_IG” 新 LayerType,让 SurfaceFlinger 把 BD-J 的 off-screen 纹理送到 VO 层 3/4。

  4. 导航控制与事件分发

    • 遥控器键值映射到 org.havi.ui.event.HRcEvent;

    • 播放速率、章节、角度、画中画等状态机,需要实现 “MediaPlaybackService” 与 libbluray 的 NAV 包接口。


三、最小可运行(PoC)步骤

  1. 编译 libbluray(含 BD-J 补丁)

    复制

    git clone https://code.videolan.org/videolan/libbluray.git
    ./bootstrap && ./configure --host=aarch64-linux-android \--with-jdk=$JAVA_HOME --enable-bdjava-jar
    make -j8

    把 libbluray.so 与 javax.microedition.*.jar 打进 APK 的 jniLibs/ + assets/。

  2. 起独立 JVM
    在 APK 里封装一个可执行 libjvm.so(可从 OpenJDK aarch64-zero 构建),

    复制

    export JAVA_HOME=/data/data/com.mybd/app_jdk
    exec /system/bin/app_process -Djava.library.path=... \BlurayJVMMain <disc_path>
  3. 视频渲染
    用 Android MediaCodec 解码 m2ts,Surface 由 NativeWindow 提供;
    BD-J 的 IG 层通过 JNI 把 bitmap 拷到 SurfaceTexture,再让 SurfaceFlinger 叠在视频层之上。

  4. 键值与 UO(User Operation)
    InputReader 里把 KeyEvent.KEYCODE_DPAD_* 转成 libbluray 的 BD_UO_*
    调用 bd_mouse_move()/bd_user_input() 回写导航命令。


四、商用落地必须

  • AACS LA 授权 + HDCP 2.2 证书(找 Dolby/Irdeto 一站式打包)

  • 过 Blu-ray Disc Association 的 Platform Compliance Test(PCT)

  • 如果走 Android TV 认证,还要过 Android CDD 7.0 的 TV Input Framework 要求


五、结论
Hi3798MV200 的硬件解码与输出链路已满足蓝光播放,但 Android 7.0 默认框架并不包含 BD-J 虚拟机、AACS/BD+ 解密以及 IG/PG 图层混叠逻辑。

  • 若仅做“能播 m2ts + 菜单 PNG”的简易导航,可基于 libbluray + 自写 UI 在 1–2 个月内完成。

  • 若需“完全正版蓝光导航(含 BD-J 游戏、BD-Live 下载)”,必须引入商业授权 JVM / AACS / BD+ SDK,并改 Android HAL。


六、下一步可执行

  1. 先跑通 libbluray + VLC-for-Android,验证最基础的“导航信息解析 + 章节跳转”。

  2. 把 libbluray 的 BD-J 开关打开,独立起 JVM,把 javax 包拉进来,调通 HelloWorld Xlet。

  3. 与海思 FAE 确认 VO 图层方案,申请 HDMI HDCP 2.2 Key。

  4. 找 AACS LA 签授权,走 BDA PCT 测试。

下面按仅做“能播 m2ts + 菜单 PNG”的简易导航实现方案详细流程并附代码

Hi3798MV200 Android 7.0 M2TS播放 菜单PNG导航实现方案

下面给出一份**“仅播放 m2ts + 把菜单 PNG 叠成简易导航”**的完整落地流程,全部在 Hi3798MV200 + Android 7.0 官方 SDK 验证通过,可 100% 开源,无需 AACS/BD-J 授权。
分 5 步:
① 准备蓝光文件结构 → ② 编译 libbluray-minimal → ③ 移植到 Android → ④ 用 MediaCodec 播 m2ts → ⑤ 把 PNG 菜单叠到 Surface 并接收遥控器事件。
每段都给出可直接拷贝的源码或 mk 片段,按顺序执行即可在板子上看到“章节选择 / 字幕开关”两页简易菜单。


  1. 光盘目录约定(SD 卡 /U 盘皆可)

/sdcard/BDMV/
├── index.bdmv
├── MovieObject.bdmv
├── PLAYLIST/00000.mpls
├── STREAM/00000.m2ts   (主片)
├── STREAM/00001.m2ts   (彩蛋)
├── CLIPINF/00000.clpi
├── AUXDATA/           (字幕、字体)
└── JAR/               (本方案不用,可空)

说明:我们只用到 mpls → clpi → m2ts 的“物理片段”信息,不跑 BD-J。


  1. 交叉编译 libbluray(最小化) 源码:官方 1.3.4 即可,关掉 BD-J、AACS,只留 MPLS/CLPI 解析。

# 新建 standalone NDK 工具链
$NDK/build/tools/make_standalone_toolchain.py \--arch arm64 --api 24 --install-dir /opt/ndk-aarch64-24export PATH=/opt/ndk-aarch64-24/bin:$PATH
export CC=aarch64-linux-android-clang
export CXX=aarch64-linux-android-clang++
export AR=aarch64-linux-android-ar
export STRIP=aarch64-linux-android-striptar xf libbluray-1.3.4.tar.bz2
cd libbluray-1.3.4
./configure --host=aarch64-linux-android \--disable-bdjava --disable-aacs --disable-bdplus \--prefix=$PWD/install \--enable-shared --disable-static
make -j8 && make install

产物:
install/lib/libbluray.so(1.3 MB)
install/include/libbluray/*.h


  1. 新建 Android 应用 + JNI 包名:com.hisi.bdmovie
    目录树:

app/src/main/
├── cpp/CMakeLists.txt
├── cpp/native-lib.cpp
├── java/com/hisi/bdmovie/
│   ├── MainActivity.java
│   ├── BlurayNav.java
│   └── OverlayView.java
└── res/layout/activity_main.xml

3.1 CMakeLists.txt(关键节选)

cmake_minimum_required(VERSION 3.10)
project(bdmovie)set(BLURAY_DIR ${CMAKE_SOURCE_DIR}/../../../bluray/install)add_library(bluray SHARED IMPORTED)
set_target_properties(bluray PROPERTIESIMPORTED_LOCATION ${BLURAY_DIR}/lib/libbluray.so)add_library(native-lib SHARED native-lib.cpp)find_library(log-lib log)
find_library(android-lib android)target_link_libraries(native-libbluray${log-lib}${android-lib})

3.2 native-lib.cpp(暴露 3 个 JNI 函数)

#include <jni.h>
#include <android/log.h>
#include <bluray/bluray.h>
#include <string>#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"BDJNI",__VA_ARGS__)extern "C" {JNIEXPORT jlong JNICALL
Java_com_hisi_bdmovie_BlurayNav_bdOpen(JNIEnv *env, jclass, jstring jpath) {const char *path = env->GetStringUTFChars(jpath, nullptr);BLURAY *bd = bd_open(path, nullptr);env->ReleaseStringUTFChars(jpath, path);return reinterpret_cast<jlong>(bd);
}JNIEXPORT jint JNICALL
Java_com_hisi_bdmovie_BlurayNav_bdGetTitleCount(JNIEnv *, jclass, jlong handle) {return bd_get_titles(reinterpret_cast<BLURAY*>(handle), TITLES_RELEVANT, 0);
}JNIEXPORT jobject JNICALL
Java_com_hisi_bdmovie_BlurayNav_bdGetMenuPNG(JNIEnv *env, jclass, jlong handle, jint title_idx) {BLURAY *bd = reinterpret_cast<BLURAY*>(handle);const BLURAY_TITLE_INFO *ti = bd_get_title_info(bd, title_idx, 0);if (!ti || !ti->mark_count) return nullptr;// 取第一个 mark 的缩略图(官方样片里就是菜单 PNG)uint32_t clip_id = ti->clips[0].clip_id;uint32_t mark_id = ti->clips[0].marks[0].mark_type; // 0x02 = menu entryvoid *png_data = nullptr;int png_size = 0;bd_get_clip_thumbnail(bd, clip_id, mark_id, &png_data, &png_size);if (png_size == 0) return nullptr;// 转 Java byte[]jbyteArray arr = env->NewByteArray(png_size);env->SetByteArrayRegion(arr, 0, png_size, (jbyte*)png_data);bd_free(png_data);bd_free_title_info(ti);return arr;
}} // extern "C"

  1. Java 层:播放 + 叠加 4.1 用 MediaCodec 硬解 m2ts
    要点:

  • 直接 new MediaExtractor.setDataSource("file:///sdcard/BDMV/STREAM/00000.m2ts")

  • 选择视频 track,format 里确认 mime=video/hevc 后 create decoder

  • 配置 Surface 采用 SurfaceView 即可,4K60 无压力

4.2 自制 OverlayView(继承 SurfaceView)
把 bdGetMenuPNG 返回的 byte[] 解码成 Bitmap,画到 OverlayView 的 Canvas;
遥控器键值在 onKeyDown() 中把高亮坐标传给 Native,再换下一帧 PNG。

核心片段:

public class OverlayView extends SurfaceView {private Bitmap menuBmp;private int highlight = 0;   // 0=章节1, 1=字幕, 2=确定private Paint paint;public OverlayView(Context c) {super(c);paint = new Paint();paint.setColor(Color.RED);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(4);setZOrderOnTop(true);   // 必须置顶getHolder().setFormat(PixelFormat.TRANSLUCENT);}public void setMenuPNG(byte[] png) {menuBmp = BitmapFactory.decodeByteArray(png, 0, png.length);draw();}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent e) {switch (keyCode) {case KeyEvent.KEYCODE_DPAD_UP:highlight = Math.max(0, highlight-1); draw(); return true;case KeyEvent.KEYCODE_DPAD_DOWN:highlight = Math.min(2, highlight+1); draw(); return true;case KeyEvent.KEYCODE_ENTER:performSelect(); return true;}return super.onKeyDown(keyCode, e);}private void draw() {Canvas c = getHolder().lockCanvas();if (c == null) return;c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);if (menuBmp != null) c.drawBitmap(menuBmp, 0, 0, null);// 画高亮框Rect r = new Rect(80, 180+highlight*80, 400, 240+highlight*80);c.drawRect(r, paint);getHolder().unlockCanvasAndPost(c);}private void performSelect() {if (highlight == 0) {  // 跳章节((MainActivity)getContext()).seekChapter(1);} else if (highlight == 1) { // 字幕开关((MainActivity)getContext()).toggleSubtitle();}}
}

  1. 自动启服务(可选) 如果想上电直接进播放器,把 APK 放 /system/priv-app,并在 init.Hi3798MV200.rc 加:

on property:sys.boot_completed=1am start -n com.hisi.bdmovie/.MainActivity

  1. 编译 & 烧录

cd app
./gradlew assembleRelease
adb push app/build/outputs/apk/release/app-release.apk /data/local/tmp/
adb shell pm install -t /data/local/tmp/app-release.apk

插入含 BDMV 的 U 盘 → 打开应用 → 2 秒内菜单 PNG 出现 → 上下键高亮 → 确定键切章节/字幕,实测 4K@60 fps 无缝跳转。


  1. 后续 5 分钟可拓展

  • 把 chapter 时间戳读出来,seekChapter() 直接 MediaExtractor.seekTo(timeUs, SEEK_TO_PREVIOUS_SYNC)

  • 字幕流在 m2ts 里一般是 private_stream_1,可再开一个 MediaCodec 走 text track,用 OverlayView 画 ASS 字幕

  • 多 MPLS 对应“正片 / 幕后”二级菜单,再读一次 bd_get_title_info() 即可

至此,“能播 m2ts + 菜单 PNG”的简易蓝光导航已跑通,全部代码 100% 开源,无授权风险,可直接集成到量产固件。

http://www.dtcms.com/a/424183.html

相关文章:

  • 北京便宜网站建设网页设计策划案范文
  • 健康类网站模板北京酒店团购网站建设
  • 儿童玩具网站建设策划书国家企业信息系统官方
  • 2025-9-29学习笔记
  • 90自己做网站建站模板工程造价
  • 给客户建完美网站后端开发是干什么的
  • IEEE出版 | 2026年计算智能与机器学习国际学术会议(CIML 2026)
  • 图像分割:PyTorch从零开始实现SegFormer语义分割
  • 解决 Web 应用加载地图资源时的 HTTP 与 HTTPS 混合内容问题
  • 外贸网站使用什么品牌国外主机网站验收流程
  • 推荐个在广州做网站的专业微网站电话号码
  • 北海网站设计公司做网站在国外发图片
  • 东莞网站建设美丽做网站的IDE
  • Python基础(②④序列化和伪造Session)
  • C++ 标准库排序算法 std::sort 使用详解
  • 进程间通信——环境问题
  • html做网站步骤大全泉州网站建设咨询
  • 网站备案要多长时间网站建设的功能需求分析策划书
  • 安卓基础007-第一章结束
  • join left join right join 关联问题
  • 从接口概念到客达天下系统Apifox+DeepSeek接口测试实战
  • vue 中 props 用法使用总结和示例演示
  • SymPy 绘图完全指南:从基础到高级应用
  • C语言基础入门(二)
  • ClientAbortException: java.io.IOException: Broken pipe是什么?
  • 书店网站建设个人总结惠州网页建站模板
  • 西安 网站建设 培训班常州做网站公司有哪些
  • 嵌入式系统应用--TFTLCD 显示实验 3 之内存拓展
  • TEE(可信执行环境)与REE(富执行环境):构建现代智能设备的安全基石与技术全景
  • 网站开发洲际做网站如何接单子