HarmonyOS 鸿蒙Next 使用硬编码264数据问题:1280*720可正常编码,720*1280编码后出现画屏
HarmonyOS 鸿蒙Next 使用硬编码264数据问题:1280720可正常编码,7201280编码后出现画屏
如题,使用下面代码初始化编码器
this->capability = OH_AVCodec_GetCapability( OH_AVCODEC_MIMETYPE_VIDEO_AVC, true );
ExecFuncRet( WEBRTC_VIDEO_CODEC_ENCODER_FAILURE, OH_AVCapability_GetEncoderBitrateRange, capability, &supportBitrateRange_ );
codec_.startBitrate = std::max(std::min((int32_t)codec_.startBitrate,supportBitrateRange_.maxVal),supportBitrateRange_.minVal);
codec_.minBitrate = std::max(std::min((int32_t)codec_.minBitrate,supportBitrateRange_.maxVal),supportBitrateRange_.minVal);
codec_.maxBitrate = std::max(std::min((int32_t)codec_.maxBitrate,supportBitrateRange_.maxVal),supportBitrateRange_.minVal);
const char* codecName = OH_AVCapability_GetName( capability );
encoder_ = OH_VideoEncoder_CreateByName( codecName );
if ( encoder_ == nullptr ) {
RTC_LOG( LS_ERROR ) << TAG “OH_VideoEncoder_CreateByName fail”;
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
}
// 1. 确认视频宽高是否支持
bool isSupported = OH_AVCapability_IsVideoSizeSupported(this->capability, codec_.width, codec_.height);
if ( !isSupported ) {
int32_t widthAlignment = 0;
ExecFunc(OH_AVCapability_GetVideoWidthAlignment,capability, &widthAlignment);
// 3. 确认视频宽处在可支持宽范围内
OH_AVRange widthRange = {-1, -1};
ExecFunc(OH_AVCapability_GetVideoWidthRange,capability, &widthRange);
// 5. 基于视频宽,获取可选视频高的范围
OH_AVRange heightRange = {-1, -1};
ExecFunc( OH_AVCapability_GetVideoHeightRangeForWidth, capability, codec_.width, &heightRange );
RTC_LOG( LS_ERROR ) << TAG “OH_AVCapability_IsVideoSizeSupported fail:” << codec_.width << “x” << codec_.height << " WidthAlignment:" << widthAlignment
<< " WidthRange:" << widthRange.minVal << “-” << widthRange.maxVal << " HeightRange:" << heightRange.minVal << “-” << heightRange.maxVal;
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
}
OH_AVFormat* format = OH_AVFormat_Create();
if ( format == nullptr ) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_Create fail”;
return WEBRTC_VIDEO_CODEC_ENCODER_FAILURE;
}
// 写入format
if ( !OH_AVFormat_SetIntValue( format, OH_MD_KEY_WIDTH, codec_.width ) ) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_WIDTH fail”;
}
if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_HEIGHT, codec_.height )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_HEIGHT fail”;
}
if (!OH_AVFormat_SetDoubleValue( format, OH_MD_KEY_FRAME_RATE, codec_.maxFramerate )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_FRAME_RATE fail”;
}
if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_YUVI420 )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_PIXEL_FORMAT fail”;
}
if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_RANGE_FLAG, 1 )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_RANGE_FLAG fail”;
}
if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_VIDEO_ENABLE_LOW_LATENCY, 1 )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_VIDEO_ENABLE_LOW_LATENCY fail”;
}
if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, OH_VideoEncodeBitrateMode::CBR )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE CBR fail”;
}
if (!OH_AVFormat_SetLongValue( format, OH_MD_KEY_BITRATE, 500000 )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_BITRATE fail:” << codec_.startBitrate;
}
uint32_t key_frame_interval = 3000;
std::string key_frame_interval_str = jrtc_sdk_get_config_by_key( “key_frame_interval” );
if ( key_frame_interval_str.length() > 0 ) {
key_frame_interval = atoi( key_frame_interval_str.c_str() );
}
if(!OH_AVFormat_SetIntValue( format, OH_MD_KEY_I_FRAME_INTERVAL, key_frame_interval )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_I_FRAME_INTERVAL fail:” << key_frame_interval;
}
if(!OH_AVFormat_SetIntValue( format, OH_MD_KEY_PROFILE, static_cast< int32_t >( OH_AVCProfile::AVC_PROFILE_BASELINE ) )) {
RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_PROFILE fail:” << key_frame_interval;
}
//TODO 设置QP
// if (!OH_AVFormat_SetIntValue( format, OH_MD_KEY_VIDEO_ENCODER_QP_MAX, codec_.qpMax )) {
// RTC_LOG( LS_ERROR ) << TAG “OH_AVFormat_SetIntValue OH_MD_KEY_VIDEO_ENCODER_QP_MAX fail:” << codec_.qpMax;
// }
RTC_LOG( LS_INFO ) << TAG “Init OHOS HardWare Codec:”<< encoder_ << " " << codec_.width << “x” << codec_.height << " " << codec_.maxFramerate << "fps " << codec_.startBitrate
<< "bps " << codec_.qpMax << “qpMax EncoderSupport:” << supportBitrateRange_.minVal << " - " << supportBitrateRange_.maxVal << “bps KeyFrameInterval:” << key_frame_interval;
// OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS,
// static_cast<int32_t>(OH_TransferCharacteristic::TRANSFER_CHARACTERISTIC_BT709));
// OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES,
// static_cast<int32_t>(OH_ColorPrimary::COLOR_PRIMARY_BT709));
ExecFuncRet( WEBRTC_VIDEO_CODEC_ENCODER_FAILURE, OH_VideoEncoder_Configure, encoder_, format );
OH_AVFormat_Destroy( format );
看日志初始化也没有报错,而且也在编码前dump下来YUV数据是没有问题的,但是就是如果是7201280的数据就是花的,1280720就没有问题
7201280的数据是采集来1280720(鸿蒙摄像头采集参数没有7201280,只有1280720的格式)进行旋转的到的,旋转时将采集的nv21数据转成I420格式的,所以使用AV_PIXEL_FORMAT_YUVI420
更多关于HarmonyOS 鸿蒙Next 使用硬编码264数据问题:1280*720可正常编码,720*1280编码后出现画屏的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
获取跨距,然后按行拷贝
1.获取跨距
API 12 新增以下方式获取跨距:
// 解码场景,收到输出 Buffer 后
OH_AVFormat *format = OH_VideoDecoder_GetOutputDescription(decoder);
int widthStride = 0;
int32_t heightStride = 0;
bool ret = OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, widthStride);
if (ret) {
// Error
}
bool ret = OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_SLICE_HEIGHT, heightStride);
if (ret) {
// Error
}
OH_AVFormat_Destroy(format);
// 编码场景,收到输入 Buffer 后
OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(encoder);
int widthStride = 0;
bool ret = OH_AVFormat_GetIntValue(format, OH_MD_KEY_VIDEO_STRIDE, widthStride);
if (ret) {
// Error
}
OH_AVFormat_Destroy(format);
2.按行拷贝:
参考实现:
int32_t ReadYUV420P(std::shared_ptr<VideoEncSignal> &signal, uint8_t *addr, int32_t width, int32_t height, int32_t stride){
if (width == 0) {
return 0;
}
int32_t pixelSize = int32_t(stride / width);
width *= pixelSize;
// Y
for (int32_t i = 0; i < height; ++i) {
signal->inFile_->read(reinterpret_cast<char *>(addr), width);
addr += stride;
}
width >>= 1;
stride >>= 1;
// UV
for (int32_t i = 0; i < height; ++i) {
signal->inFile_->read(reinterpret_cast<char *>(addr), width);
addr += stride;
}
return stride * height * 3 / 2; // 3: nom, 2: denom
}
更多关于HarmonyOS 鸿蒙Next 使用硬编码264数据问题:1280*720可正常编码,720*1280编码后出现画屏的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
使用VLC播放编码的264数据长这样
在HarmonyOS鸿蒙Next系统中,使用硬编码H.264数据时,若遇到1280720分辨率正常而7201280分辨率编码后出现画屏的问题,通常可能由以下几个原因引起:
-
编码器支持限制:部分硬件编码器对特定分辨率支持有限,尤其是非标准或非常见分辨率。720*1280可能不在编码器的原生支持列表中。
-
内存对齐问题:编码过程中,图像数据需要按照特定对齐要求处理。720*1280可能不满足这些对齐条件,导致数据访问异常。
-
编码参数配置:编码参数如比特率、帧率、GOP结构等,对于不同分辨率需调整优化。未正确配置可能导致编码异常。
-
驱动或固件问题:硬件驱动或固件可能存在缺陷,不支持或错误处理某些分辨率。
解决方法:
- 尝试使用标准分辨率如1280720或19201080进行编码。
- 检查并调整编码参数,确保符合硬件要求。
- 更新硬件驱动或固件至最新版本。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html