在播放同一个m3u8视频时,分别使用AVCodec硬件视频解码器和ffmpeg软件解码器播放,发现使用硬件解码器时的CPU使用率要比软件的高很多。在进行视频解码的过程中,硬解码过程的CPU使用率预期比软解码过程要低。在使用ijkplayer进行测试时,CPU的使用率出现相反的情况。
CPU测试结果如下图:
硬解码:

ffmpeg软解码:

从CPU测试结果图来看硬件视频解码CPU使用率维持在7%到8%左右,使用ffmpeg软件解码播放时平均维持在3%左右。这与硬解码和软解码的CPU占用不符合。硬解码调用设备相关硬件进行解码,软解码调用软件(调用CPU)进行解码,预期结果应当为硬解码占用更少的CPU。
解码代码中AVCodecOnNeedInputBuffer的代码段:
void AVCodecOnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
{
OHOSVDecoder *decoder = static_cast<OHOSVDecoder *>(userData);
if (decoder == nullptr) {
return;
}
decoder->OnNeedInputBuffer(codec, index, buffer);
} void OHOSVDecoder::OnNeedInputBuffer(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer)
{
if (codec == nullptr) {
return;
}
std::shared_ptr<Frame> frame;
{
std::unique_lock<std::mutex> auto_lock(_frame_mutex);
if (_input_frames.size() > 0) {
frame = _input_frames.front();
_input_frames.pop_front();
}
}
if (frame == nullptr) {
OH_AVCodecBufferAttr info;
info.pts = 0;
info.size = 0;
info.offset = 0;
info.flags = AVCODEC_BUFFER_FLAGS_DISCARD;
OH_AVBuffer_SetBufferAttr(buffer, &info);
OH_VideoDecoder_PushInputBuffer(codec, index);
return;
}
std::shared_ptr<VideoFrame> video_frame = std::dynamic_pointer_cast<VideoFrame>(frame);
OH_AVCodecBufferAttr info;
info.pts = video_frame->pts();
info.size = frame->Size();
info.offset = 0;
info.flags = AVCODEC_BUFFER_FLAGS_NONE;
int32_t ret = OH_AVBuffer_SetBufferAttr(buffer, &info);
if (ret != AV_ERR_OK) {
return;
}
uint8_t *data = OH_AVBuffer_GetAddr(buffer);
if (data == nullptr) {
return;
}
memcpy(data, frame->Data(), frame->Size());
ret = OH_VideoDecoder_PushInputBuffer(codec, index);
if (ret != AV_ERR_OK) {
return;
}
} 可以看见OnNeedInputBuffer函数实现中由自定义类型Frame去存储相关数据,在后续读取其中的信息到结构体OH_AVBuffer和OH_AVCodecBufferAttr中以调用函数PushInputBuffer往视频解码队列输入数据,等待解码器解码,但在最后使用OH_AVBuffer_GetAddr获取的是AVBuffer的地址,使用memcpy拷贝的是地址而非实际数据,且在使用PushInputBuffer填充数据时只传入了解码器和索引,Buffer的数据没有被传递。
在视频Buffer和音频Buffer都为nullptr时,在视频源有数据不断传入时,解码器会保持空载。


当传入解码队列的音频Buffer不为空,视频Buffer为nullptr时,解码器运行,只有音频输出。
