播放器为什么设计硬解码
好多开发者跟我们反馈,到底用硬解码好还是软解好,本文以大牛直播SDK的Windows平台RTMP|RTSP播放器为例,探讨下实现硬解码具有以下诸多必要性:
提升性能
减轻 CPU 负担
软解码主要依靠 CPU 来处理视频数据。当播放高分辨率(如 4K、8K)或高帧率(如 120Hz、240Hz)的视频时,软解码会使 CPU 占用率急剧上升。例如,播放一个 4K H.265 编码的视频,或者Windows场景下,需要同时播放多路1080p或720p的流时,软解码可能会使 CPU 占用率达到80%-90% 甚至更高。而硬解码利用显卡(GPU)中的专用解码模块,如NVIDIA的NVDE,能够将大部分解码工作从 CPU 转移到 GPU。这样,CPU占用率可能会降低到一个相对接受的比例,从而使计算机在播放视频的同时还能流畅地进行其他多任务处理。
提高播放流畅度
对于一些码率很高的视频流,软解码可能会因为CPU处理速度跟不上视频数据的传输速度而出现卡顿、掉帧的现象。以超高清视频为例,码率通常较高,软解码可能无法保证稳定的帧率。而硬解码由于GPU的强大并行处理能力,能够更高效地对视频数据进行解码,按照视频的原始帧率进行播放,提供更流畅的观看体验,不会出现画面撕裂或卡顿的情况。
支持更高分辨率和格式
随着视频技术的不断发展,新的视频格式和更高的分辨率不断涌现。例如,H.266(VVC)等新一代视频编码标准以及8K超高清视频。这些新格式和高分辨率视频的数据量巨大,软解码对于这样复杂的视频解码可能会力不从心。硬解码则可以通过更新显卡驱动来支持这些新的视频编码格式和高分辨率,确保播放器能够顺利播放最新的视频内容。
能源效率方面
降低功耗
当CPU长时间处于高负载的软解码状态时,计算机的整体功耗会增加。例如,在软解码一个复杂视频时,CPU 功耗可能会比闲置状态高出 30 - 50 瓦。而硬解码将解码任务交给 GPU 后,由于 GPU 在处理视频解码任务时更加节能高效,能够在保证视频播放质量的同时降低计算机的整体功耗,对于笔记本电脑等依靠电池供电的设备来说,可以延长电池续航时间。
画质和功能增强
优化画质
一些显卡的硬解码功能可以提供额外的画质增强技术。例如,NVIDIA的PureVideo技术和 AMD 的 Video Enhance 等。这些技术可以在硬解码过程中对视频进行色彩校正、降噪、锐化等处理,提升视频的视觉质量。以播放低质量视频为例,通过硬解码中的画质增强功能,可以减少画面中的噪点,使色彩更加鲜艳和准确。
如何设计硬解码接口
以大牛直播SDK的Windows平台RTMP|RTSP播放器为例,我们通常的做法是,先检测、再设置,先检测设备是不是支持H.264、H.265硬解码,返回检测结果,针对H.264和H.265,分别设置,是否需要开启硬解码。
接口设计如下:
/*
* smart_player_sdk.h
* Created by daniusdk.com (C) All rights reserved.
*/
...
/*
* 检查是否支持H264硬解码
* 如果支持的话返回NT_ERC_OK
*/
NT_UINT32(NT_API *IsSupportH264HardwareDecoder)();
/*
* 检查是否支持H265硬解码
* 如果支持的话返回NT_ERC_OK
*/
NT_UINT32(NT_API *IsSupportH265HardwareDecoder)();
...
设置H.264、H.265硬解码:
/*
* smart_player_sdk.h
* Created by daniusdk.com (C) All rights reserved.
*/
...
/*
* 设置H264硬解
* is_hardware_decoder: 1:表示硬解, 0:表示不用硬解
* reserve: 保留参数, 当前传0就好
* 成功返回NT_ERC_OK
*/
NT_UINT32(NT_API *SetH264HardwareDecoder)(NT_HANDLE handle, NT_INT32 is_hardware_decoder, NT_INT32 reserve);
/*
* 设置H265硬解
* is_hardware_decoder: 1:表示硬解, 0:表示不用硬解
* reserve: 保留参数, 当前传0就好
* 成功返回NT_ERC_OK
*/
NT_UINT32(NT_API *SetH265HardwareDecoder)(NT_HANDLE handle, NT_INT32 is_hardware_decoder, NT_INT32 reserve);
...
demo调用示例如下:
我们在页面添加了个“硬解码”选项,如果需要设置硬解码,只要在播放前检测并设置即可。
/*
* SmartPlayerDlg.cpp
* Created by daniusdk.com (C) All rights reserved.
*/
...
is_support_h264_hardware_decoder_ = NT_ERC_OK == player_api_.IsSupportH264HardwareDecoder();
is_support_h265_hardware_decoder_ = NT_ERC_OK == player_api_.IsSupportH265HardwareDecoder();
...
if (is_support_h264_hardware_decoder_ || is_support_h265_hardware_decoder_)
{
btn_check_hardware_decoder_.EnableWindow(TRUE);
}
...
if ( BST_CHECKED == btn_check_hardware_decoder_.GetCheck() )
{
player_api_.SetH264HardwareDecoder(player_handle_, is_support_h264_hardware_decoder_?1:0, 0);
player_api_.SetH265HardwareDecoder(player_handle_, is_support_h265_hardware_decoder_?1:0, 0);
}
else
{
player_api_.SetH264HardwareDecoder(player_handle_, 0, 0);
player_api_.SetH265HardwareDecoder(player_handle_, 0, 0);
}
...