一、简介

RTMP(Real Time Message Protocol 实时信息传输协议)是由Adobe公司提出的一种应用层网络协议,用来解决多媒体数据传输流的多路复用和分包的问题。OpenHarmony-5.0 之前的版本播放器AVPlayer使用gstreamer引擎实现播放能力,目前不支持rtmp网络协议。本篇文章介绍如何基于gstreamer框架扩展支持rtmp协议。

二、前言

版本信息:OpenHarmony-4.0-Release 和 OpenHarmony-4.1-Release 标准系统
备注:下面代码中“+”代表新增行,“-”代表删除行,“增加”代表以下代码均需添加,“...”代表省略n行代码

三、扩展方法

1、gio

gio是glib下的一个库,实现了通用 I/O、网络、IPC、设置等基础功能,与网络协议相关的插件库基本会依赖该库提供的基本能力。
third_party/glib/BUILD.gn 增加

config("gio_config") {
  visibility = [ ":*" ]
  include_dirs = [
    ".",
    "glib",
    "gobject",
    "gio",
    "gmodule",
    "//third_party/libffi/include",
    "//third_party/zlib/",
  ]
  cflags = [
    "-DG_LOG_DOMAIN=\"GIO\"",
    "-Wno-sign-compare",
    "-Wno-unused-function",
    "-Wno-int-conversion",
    "-DGIO_COMPILATION",
    "-DGIO_MODULE_DIR=\"system/lib/gio/modules\"",
    "-DHAVE_NETLINK",
    "-DLOCALSTATEDIR=\"system\"",
    "-DXDG_PREFIX=_gio_xdg",
   ]
}

ohos_source_set("gio_source") {
  source = [
    gio/xxx.c...
    gio/inotify/xxx.c,
    ...,
    gio/xdgmime/xxx.c,
    需要编译的C文件
  ]

  config = [ ":gio_config" ]
}

ohos_shared_library("gio") {
  deps = [
    ":gio_source",
    "glib"
    "gobject",
    "gmodule"
    "//third_party/libffi:ffi",
    "//third_party/zlib:shared_libz",
  ]

  part_name = "glib"
  subsystem_name = "thirdparty"
}

编译生成libgio.z.so,安装到/system/lib/ 目录

2、rtmpsrc

目前gstreamer官方提供了2个rtmp插件,其中第一次rtmp需要依赖三方库 librtmp,源码位于third_party/gstreamer/gstplugins_bad/ext/rtmp/ 目录,rtmp2不依赖外部库,源码位于third_party/gstreamer/gstplugins_bad/gst/rtmp2/ 目录。

注:如果熟悉librtmp三方库或者想支持rtmpt、rtmps等协议可以编译第一个rtmp插件库。

下面以rtmp2为例,库名必须为libgstrtmp2.z.so,不可修改

third_party/gstreamer/gstplugins_bad/BUILD.gn 增加

ohos_source_set("rtmp2_source") {
  sources = [
    "gst/rtmp2/xxx.c",
    ...
    ”gst/rtmp2/rtmp/xxx.c",
    ...
  ]

  configs = [ ":gst_plugins_config" ]
}

ohos_shared_library("gstrtmp2") {
  deps = [
    ":rtmp2_source",
    "//third_party/glib:glib",
    "//third_party/glib:gobject",
    "//third_party/glib:gio",
    "//third_party/gstreamer/gstreamer:gstbase",
    "//third_party/gstreamer/gstreamer:gstreamer",
  ]

  relative_install_dir = "media/plugins"
  part_name = "gstreamer"
  subsystem_name = "thirdparty"
}

third_party/gstreamer/gstplugins_bad/BUILD.gn 修改

group("gstplugins_bad_packages") {
  deps = [
    ":gstcurl",
    ":gstdrmdec",
    ":gsthls",
    ":gstmpegtsdemux",
    ":gstvideoparsersbad",
+   ":gstrtmp2",
  ]
}

编译生成libgstrtmp2.z.so,安装到/system/lib/media/plugins 目录

3、flv demux

rtmp协议传输的一般是flv数据,需要扩展flv解封装插件。
下面以gstreamer提供的flvdemux插件为例,库名必须为libgstflv.z.so,不可修改。

third_party/gstreamer/gstplugins_good/BUILD.gn 增加

ohos_source_set("gstflv_source") {
  sources = [
    "gst/flv/gstflvdemux.c",
    "gst/flv/gstflvmux.c",
    "gst/flv/gstflvplugin.c",
    "gst/flv/gstflvelement.c",
  ]

  configs = [ ":gst_plugins_config" ]
}

ohos_shared_library("gstflv") {
  deps = [
    ":gstflv_source",
    "//third_party/glib:glib",
    "//third_party/glib:gobject",
    "//third_party/gstreamer/gstreamer:gstbase",
    "//third_party/gstreamer/gstreamer:gstreamer",
    "//third_party/gstreamer/gstplugins_base:gstvideo",
    "//third_party/gstreamer/gstplugins_base:gstaudio",
    "//third_party/gstreamer/gstplugins_base:gsttag",
    "//third_party/gstreamer/gstplugins_base:gstpbutils",
  ]

  relative_install_dir = "media/plugins"
  part_name = "gstreamer"
  subsystem_name = "thirdparty"
}

third_party/gstreamer/gstplugins_good/BUILD.gn 修改

group("gstplugins_good_packages") {
  deps = [
    ":gstaudiofx",
    ":gstaudioparsers",
    ":gstisomp4",
    ":gstmatroska",
    ":gstmultifile",
    ":gstwavparse",
+   ":gstflv",
  ]
}

编译生成libgstflv.z.so,安装到/system/lib/media/plugins 目录

注:如果熟悉ffmpeg的flv解封装,也可以添加libav插件,修改third_party/gstreamer/gst_libav/ext/libav/gstavdemux.c和third_party/ffmpeg编译ff_flv_demuxer,详情可看后续文章。

4、AVPlayer NAPI

在AVPlayer的NAPI代码中限制只能设置http前缀的网络url,需要解除限制
/foundation/multimedia/player_framework/frameworks/js/avplayer/avplayer_napi.cpp 修改

void AVPlayerNapi::SetSource(std::string url)
{
    MEDIA_LOGI("input url is %{public}s!", url.c_str());
    bool isFd = (url.find("fd://") != std::string::npos) ? true : false;
-   bool isNetwork = (url.find("http") != std::string::npos) ? true : false;
+   bool isNetwork = ((url.find("http") != std::string::npos) || (url.find("rtsp") != std::string::npos)) ? true : false;
    if (isNetwork) {
        auto task = std::make_shared<TaskHandler<void>>([this, url]() {
        MEDIA_LOGI("SetNetworkSource Task");
        std::unique_lock<std::mutex> lock(taskMutex_);
        auto state = GetCurrentState();
        ...
    }
}

5、运行

编译上面新增加的动态库后,替换到板子上,播放器应用设置rtmp url给AVPlayer即可播放rtmp网络流。

四、管道运行图

img

img

img

后续解码渲染流程同本地播放

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐