低分辨率刷视频看了个寂寞?华为HMS Core超分辨率功能助您一招提升用户体验

“社畜”的手机视频体验

作为一名社畜,白天要把时间献给代码,晚上要把时间献给家庭,真正属于自己的时间,算来算去也只有每天搭乘公共交通的通勤时间能够自由支配。不过,因为身处车厢哪也去不了,这种自由也仅限于掏出手机刷哪部剧,看哪个直播而已。

但即便是这仅有的一点休闲,我们也只能看超低分辨率、超卡顿的视频。原因无他,地铁信号实在、实在太差了!

就拿我现在都没看全的几个奥运大项决赛来说,在信号不好的公交或地铁上看比赛,开低分辨率是保持流畅的唯一方法。但在低分辨率下看比赛,你既看不见球在哪,也分不清谁是谁;基本等于看了个寂寞。

如果分辨率太低,在乒乓球、网球这样的小球比赛里,两个运动员就像在隔空做广播体操,完全看不见球在哪;在足球、排球、网球这样的团队竞技中,也完全看不出来同一个队里谁是谁;而在跳水这样的项目中,每个人入水都没什么水花,都是9.5水平……

那么,面对此起彼伏的视频内容风口,除了指望运营商能多建几个基站之外,作为开发者,我们有什么能做的吗?

答案很简单,视频超分辨率!


超分辨率,过去很复杂,现在很简单

在GitHub上随手一搜,我们就能看到数千个与超分辨率相关的项目,其中还有不少经常维护的技术合集,可以说是百花齐放。不过真到了实践阶段,你就会发现,这些开源项目不仅需要很多DL方面的框架知识,集成到项目中也是非常麻烦的事情。缺少相关技术大牛的小团队想要搞定视频超分,别说赶眼前的内容风口了,能赶下半年的内容风口就不错了。

不过最近,华为HMS Core 6.0全球上线,其新推出的多媒体管线服务(AV Pipeline Kit,简称AV Pipeline)中,提供了视频超分插件。开发者只需将AV Pipeline的SDK集成到自己的视频播放器应用中并完成UI的适配便可实现视频超分功能。

image
image.gif

AV Pipeline框架支持在播放过程中进行视频的逐帧超分。而除视频播放Pipeline的插件外,还包含视频超分插件CVFilter。编排关系如上图所示。

话不多说,我们来实战:


1开发准备

1.1 新建Android Studio工程,修改工程级build.gradle文件,在“allprojects > repositories”里面增加华为的Maven仓地址。

allprojects {
    repositories {
        google()
        jcenter()
        maven {url 'https://developer.huawei.com/repo/'}
    }
}
image.gif

1.2 打开项目中应用级的“build.gradle”文件。在dependencies中添加编译依赖。

dependencies {

    ...

    implementation 'com.huawei.hms:avpipelinesdk:6.0.0.302'
    implementation 'com.huawei.hms:avpipeline-aidl:6.0.0.302'
    implementation 'com.huawei.hms:avpipeline-fallback-base:6.0.0.302'
    implementation 'com.huawei.hms:avpipeline-fallback-cvfoundry:6.0.0.302'

}
image.gif

1.3 在完成以上的配置后,点击工具栏中的gradle同步图标,完成“build.gradle”文件的
同步,将相关依赖下载到本地。

image
image.gif

2 开发步骤

2.1 动态申请存储权限

private void handlePermission() {
    String[] permissionLists = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.ACCESS_NETWORK_STATE
    };
    int requestPermissionCode = 1;
    for (String permission : permissionLists) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissionLists, requestPermissionCode);
        }
    }
}

image.gif

2.2 初始化AV Pipeline框架。

private void initFwk() {
    if (AVPLoader.isInit()) {
        Log.d(TAG, "avp framework already inited");
        return;
    }
    boolean ret = AVPLoader.initFwk(getApplicationContext());
    if (ret) {
        makeToastAndRecordLog(Log.INFO, "avp framework load succ");
    } else {
        makeToastAndRecordLog(Log.ERROR, "avp framework load failed");
    }
}

image.gif

2.3 创建MediaPlayer实例。播放过程的控制由该实例来完成。

//创建MediaPlayer实例
mPlayer = MediaPlayer.create(MediaPlayer.PLAYER_TYPE_AV);

image.gif

2.4 设置graph配置文件。AV Pipeline框架依赖于该配置文件来编排各个插件。此外还需要将MEDIA_ENABLE_CV的值设置为1,激活视频超分插件。

protected void setGraph() {
    String path = getExternalFilesDir(null).getPath() + "/PlayerGraphCV.xml";
    MediaMeta meta = new MediaMeta();
    meta.setString(MediaMeta.MEDIA_GRAPH_PATH, path);
    meta.setInt32(MediaMeta.MEDIA_ENABLE_CV, 1);
    mPlayer.setParameter(meta);
}

image.gif

2.5 以下为视频超分Pipeline的graph配置文件PlayerGraphCV.xml。

<?xml version="1.0"?>
<Nodes>
    <node id="0" name="AVDemuxer" mime="media/demuxer" type="source">
        <!-- 数据流从这里开始分两路,一路到视频解码节点node 1,一路到音频解码节点node 2 -->
        <next id="1"/>
        <next id="2"/>
    </node>
    <!-- 视频解码节点将解码后的图像送到下一个节点,即next id号对应的3号CVFilter节点 -->
    <node id="1" name="MediaCodecDecoder" mime="video/avc" type="filter">
        <next id="3"/>
    </node>
    <!-- 音频解码节点将解码后的音频送到下一个节点,即next id号对应的4号AudioSinkOpenSL节点 -->
    <node id="2" name="FFmpegNode" mime="audio/aac" type="filter">
        <next id="4"/>
    </node>
    <!-- node的name、mime、type参考示例中的定义。node id应当唯一,建议为上一个node id加1即可 -->
    <node id="3" name="CVFilter" mime="video/cv-filter" type="filter">
        <!-- next id为视频流从本节点出去后需要到达的下一个节点,本示例中为送显节点 -->
        <next id="5" />
    </node>
    <node id="4" name="AudioSinkOpenSL" mime="audio/sink" type="sink">
    </node>
    <node id="5" name="VideoSinkBasic" mime="video/sink" type="sink">
    </node>
</Nodes>

image.gif

2.6 设置以下参数后调用prepare接口,启动MediaPlayer准备工作。

//创建MediaPlayer实例
mPlayer = MediaPlayer.create(MediaPlayer.PLAYER_TYPE_AV);
if (mPlayer == null) {
    return;
}
//设置graph配置文件
setGraph();
if (getPlayerType() == MediaPlayer.PLAYER_TYPE_AV) {
    // 设置视频渲染的surface
    SurfaceView mSurfaceVideo = findViewById(R.id.surfaceViewup);
    SurfaceHolder mVideoHolder = mSurfaceVideo.getHolder();
    int ret = mPlayer.setVideoDisplay(mVideoHolder.getSurface());
    if (ret != 0) {
        makeToastAndRecordLog(Log.ERROR, "setVideoDisplay failed, ret=" + ret);
        return;
    }
}
// 设置待播放媒体文件的路径
int ret = mPlayer.setDataSource(mFilePath);
if (ret != 0) {
    makeToastAndRecordLog(Log.ERROR, "setDataSource failed, ret=" + ret);
    return;
}
//启动MediaPlayer准备工作
mPlayer.prepare();

image.gif

2.7 调用start开始播放

mPlayer.start();
image.gif

2.8 停止播放和销毁播放器

mPlayer.stop();
mPlayer.reset();
mPlayer.release();
mPlayer = null;

image.gif

视频超分辨率效果对比

image
image.gif

在AV Pipeline的demo中我们可以看到,在开启超分辨率后,画质、色彩和亮度均获得了不同程度的提升,观看体验提升还是比较明显的。而最重要的是,相对于其他超分辨率实现手段,通过调用HMS Core的方法实现超分非常简单。这相当于以很低的开发成本给你的视频应用带来体验的大幅升级;何乐而不为?


HMS Core 与未来

HMS Core是华为软硬件开放能力的合集,其目的在于帮助应用开发者简化开发流程,让APP能够以更简单、更高效、更低成本的方式完成功能开发,为尽可能多的最终用户提供优秀且一致的应用体验。

从最初的帐号、支付、推送服务一路走来,目前的HMS Core 6.0已经能够提供应用服务、AI、媒体、智能设备连接、图形、安全和连接通信等七大类、几十种开放能力和数百种功能。从用户登录、广告推送,到图形渲染、机器学习、音视频编辑,再到5G、网络聚合、NFC……HMS Core用庞大的代码库为开发者提供了构建APP所需的各类功能模块。利用HMS Core,开发者要做的便是展开想象力,用无数块“积木”搭建出属于自己的App城堡并开始运营。可以说HMS Core不仅降低了移动App开发的门槛,也提升了开发的敏捷性和上限。

华为不仅维护了全球数百万开发者参与的社区,更在gitee、GitHub上有海量的代码库和demo可供参考。无论大团队、小团队还是个人都可以通过调用HMS Core获得开发上的便利。

另一方面,面向手机、智能终端和物联网设备的HarmonyOS在上线后的短短一个多月时间内便迅速在全球迅速积累了数千万用户和设备,并拥有数十家重量级设备合作伙伴。在这一全新OS生态中的布局是App提供新体验、获得新用户的重要途径。而HMS生态是运行在操作系统之上的应用和服务生态,可运行在HarmonyOS上。现有Android应用已经使用了HMS Core的能力可在HarmonyOS可以继续使用,这很大降低了开发者进入HarmonyOS生态的门槛,并让多版本App的维护变得异常简单。

更简便的开发、更全面的功能、更好的体验,外加更庞大的生态……好东西分享完了,我去给儿子当家教去了ToT

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容