OpenHarmony AVPlayer扩展RTMP协议

一、简介

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网络流。

四、管道运行图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
后续解码渲染流程同本地播放

一直以来, 在多媒体播放器这块, 即使目前有许多开源的播放器项目, 但要写一个播放器仍然是件非常困难的事, 如果在windows上你有可能需要熟悉DShow, 另外的话, 你需要学习一堆开源项目(比如FFmpeg, MPC, VLC, Mplayer), 而且多数都是基于linux, 在windows上学习起来很不容易, 然而这些开源项目对于一些希望快速实现自己播放器, 就显得很困难. 因此, 我创建了这个项目, 致力于以最简单的方法实现自己的播放器, 并提供一个可以很方便使用的接口. 目前, 在这个代码中, 主要链接到FFmpeg来进行解码, 并将其改造成一个通用的播放器框架. 在这个框架中能够接受各种数据的读入, 可以很方便的封装自己的数据读取模块, 也可以很方便的定制自己的视频渲染模块和音频播放模块, 你只需要参考其中的实现即可. 另外在当前的实现中, 因为个人精力实在有限, 所以借鉴了一些开源项目的代码(如Mplayer), 并且该代码主要基于windows平台, 有移植到linux等其它平台的打算. 所以, 我希望有朋友能参与到这个项目中一起研究和学习, 并完成这个目标. 在 https://github.com/Jackarain/avplayer/downloads 中有已经编译好的exe可供测试, 测试命令如下: avplayer.exe test.mp4 或者 avplayer.exe http://edstream.googlecode.com/files/stream.m3u8 或者 avplayer.exe gq.flv.torrent gq.flv.torrent 是从优酷找的一个超清视频文件做的种子. 整个项目分为几个模块: 1. avcore 这只是一个包装类, 实现windows上的窗口创建以及消息响应, 比如: 右击暂停/开始, 单击按屏幕宽百分比seek, F2全屏切换. 在这个模块中, avplayer类是外部接口类, 具体实现在player_impl类中. 在player_impl类中, 初始化各模块结构指针由下面几个函数实现, void init_file_source(media_source *ms); void init_audio(audio_render *ao); void init_video(video_render *vo); 你可以根据自己的需求来修改这些函数实现. media_source是一个提供数据访问的结构, 包含一些函数指针, 如果你需要重新从其它地方读取数据进来提供给播放器, 那么你可以参照这个结构体, 实现这些函数并指向它, 就可以获得从你指定的地方读取数据来进行播放, 这里实现了一个从文件读取数据播放的dll. audio_render是用于播放音频的结构, 同样包含了一些函数指针, 只要实现这些函数指针, 就可以改变音频输出, 比如把音频数据写到文件, 这里实现了2种方式输出音频, 一种是使用dsound来输出音频, 另一种是使用waveout来输出音频. video_render是用于渲染视频的结构, 原理同上, 需要注意的是render_one_frame的data是YUV420格式. 2. libav 这是一个基于ffmpeg的播放框架, 该框架不包含视频渲染和音频播放以及数据读取, 若需要可以实现上述结构体各函数即可, 这个框架中主要完成了使用ffmpeg解码, 以及音视频同步, seek操作处理, 并提供一些基本的控制播放器的函数(在avplay.h中定义). 3. audio 是一个音频播放输出模块实现, 主要实现了audio_render中那几个函数指针. 在这个模块中实现了2套音频输出dsound和waveout. 4. video 是一个视频渲染模块的实现, 实现了video_render中的那几个函数指针. 在这个模块中, 实现了3套视频渲染输出d3d, ddraw, opengl这些方式(还有gdi方式渲染没有添加到video_out.h中). 5. avplayer 是一个使用avcore实现一个简单播放器的示范, 如果要创建一个播放器, 只需要avplayer.h, 然后使用创建一个avplayer对象, 就可以创建一个播放器, 关于如何使用avcore的具体细节可以参考avplayer/main.cpp. 最后, 任何方式(包括商业或非商业)修改或引用该项目的全部或部分源码(或dll), 请在你的软件中或产品文档中必须清楚的声明引用了该项目, 并注明url(https://github.com/Jackarain/avplayer), 你可以偷偷的不这样做, 但这样做是令人欣赏的做法. 最后本程序作者不承担使用该程序所带来的任何问题并拥有一切解释权. mail: jack.wgm@gmail.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值