前一篇文章已经把捕获屏幕的功能实现,现在我们要把捕获的视频数据编码成264为后面保存成文件,或者通过流媒体的形式分发做准备
鸿蒙avcodec kit编码的关系图如下
编码调用关系官方图
下面实现整个编码过程
1,在CMake脚本中链接动态库
target_link_libraries(entry PUBLIC libace_napi.z.so
libnative_avscreen_capture.so
libhilog_ndk.z.so
libnative_media_core.so
libnative_buffer.so
libnative_media_codecbase.so
libnative_media_venc.so
libnative_media_acodec.so)
2,新建video_encoder类,并实现相关函数
视频编码器类中包括创建编码器,配置编码器,启动编码器,停止二号释放编码器
int32_t Create(const std::string &videoCodecMime);
int32_t Config(VideoSampleInfo &sampleInfo, AVCodecUserData *codecUserData);
int32_t Start();
int32_t Stop();
int32_t Release();
1,根据mine type创建编码器,这里我们用的mine type是OH_AVCODEC_MIMETYPE_VIDEO_AVC就是h264
int32_t VideoEncoder::Create(const std::string &videoCodecMime)
{
// 通过 MIME TYPE 创建编码器,系统会根据MIME创建最合适的编码器。
// OH_AVCapability *capability = OH_AVCodec_GetCapability(OH_AVCODEC_MIMETYPE_VIDEO_AVC, true);
// const char *codecName = OH_AVCapability_GetName(capability);
// codec = OH_VideoEncoder_CreateByName(codecName);
encoder_ = OH_VideoEncoder_CreateByMime(videoCodecMime.c_str());
CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Create failed");
return AVCODEC_SAMPLE_ERR_OK;
}
2,配置编码器,主要包括色彩格式,视频宽度,视频高度,视频帧率,关键帧间隔,和编码回调等
int32_t VideoEncoder::Config(VideoSampleInfo &sampleInfo, AVCodecUserData *codecUserData)
{
CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
CHECK_AND_RETURN_RET_LOG(codecUserData != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Invalid param: codecUserData");
// Configure video encoder
int32_t ret = Configure(sampleInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Configure failed");
// GetSurface from video encoder
ret = GetSurface(sampleInfo);
CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Get surface failed");
// SetCallback for video encoder
ret = SetCallback(codecUserData);
CHECK_AND_RETURN_RET_LOG(ret == AVCODEC_SAMPLE_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR,
"Set callback failed, ret: %{public}d", ret);
// Prepare video encoder
ret = OH_VideoEncoder_Prepare(encoder_);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Prepare failed, ret: %{public}d", ret);
return AVCODEC_SAMPLE_ERR_OK;
}
这里写了两个辅助函数,
创建surface模式对应的窗口
int32_t VideoEncoder::GetSurface(VideoSampleInfo &sampleInfo)
{
int32_t ret = OH_VideoEncoder_GetSurface(encoder_, &sampleInfo.window);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK && sampleInfo.window, AVCODEC_SAMPLE_ERR_ERROR,
"Get surface failed, ret: %{public}d", ret);
(void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_BUFFER_GEOMETRY, sampleInfo.videoWidth,
sampleInfo.videoHeight);
(void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_USAGE, 16425); // 16425: Window usage
(void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_FORMAT,
ToGraphicPixelFormat(sampleInfo.pixelFormat, sampleInfo.isHDRVivid));
return AVCODEC_SAMPLE_ERR_OK;
}
配置编码器的相关回调:编码错误回调,编码格式更新回调,编码输入缓存回调(这是surface模式,未使用),编码输出缓存回调
int32_t VideoEncoder::SetCallback(AVCodecUserData *codecUserData)
{
int32_t ret = OH_VideoEncoder_RegisterCallback(encoder_,
{VideoSampleCallback::OnCodecError, VideoSampleCallback::OnCodecFormatChange,
VideoSampleCallback::OnNeedInputBuffer, VideoSampleCallback::OnNewOutputBuffer},
codecUserData);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Set callback failed, ret: %{public}d", ret);
return AVCODEC_SAMPLE_ERR_OK;
}
3,启动编码器
int32_t VideoEncoder::Start()
{
CHECK_AND_RETURN_RET_LOG(encoder_ != nullptr, AVCODEC_SAMPLE_ERR_ERROR, "Encoder is null");
int ret = OH_VideoEncoder_Start(encoder_);
CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "Start failed, ret: %{public}d", ret);
return AVCODEC_SAMPLE_ERR_OK;
}
然后改造screen_capture
引入视频编码类,额外启动一个线程用来接受编码后的数据,并写入文件
在CreateAndInitWithSurfaceMode函数中实例化视频编码器
在StartWithSurfaceMode函数中加入
在StopAndReleaseWithSurfaceMode添加停止编码相关逻辑
这里我们把视频保存成h264文件了,文件地址如下
运行测后会在手机报名目录下生成文件
用ffplay播放文件显示如下信息
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,一年会员只需98元,全站资源免费下载 点击查看详情
站 长 微 信: lzxmw777
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。