当前位置: 首页 > wzjs >正文

职业教育网站平台建设长沙有实力seo优化公司

职业教育网站平台建设,长沙有实力seo优化公司,苏州那家公司做网站比较好,网站开发怎样转h5页面往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录) ✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~ ✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ ✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景&#…

往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)

✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~

✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~

✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✏️ 记录一场鸿蒙开发岗位面试经历~

✏️ 持续更新中……


1:场景描述

场景:基于VideoCoder的音视频解码及二次处理播放。

首先导入选择器picker模块,使用PhotoViewPicker方法拉起图库选择视频文件,将视频文件传递到native侧使用Demuxer解封装器进行解封装,再使用OH_VideoDecoder进行解码(surface模式)送显播放

使用的核心API:

  • picker :提供拉起图库选择视频的功能接口。
  • AVDemuxer :音视频解封装,用于获取视频等媒体帧数据。
  • VideoDecoder:视频解码,将视频数据解码后送显播放。

2:方案描述

Step1:导入picker模块(仅代表选择一个视频路径,还有其它获取媒体文件的方式), 拉起图库选择视频文件保存到自定义路径。

Step2:将文件传递到native侧进行交互。

Step3:使用AVDemuxer接口对文件进行解封装获取视频流数据。

Step4:使用VideoDecoder接口将视频数据解码,结合Xcomponent送显播放。

效果图如下:

具体步骤如下:

步骤一:导入picker模块, 拉起图库选择视频文件自定义保存。

import { picker } from '@kit.CoreFileKit';
let photoSelectOptions = new picker.PhotoSelectOptions();
photoSelectOptions.MIMEType = picker.PhotoViewMIMETypes.VIDEO_TYPE;
photoSelectOptions.maxSelectNumber = 1;
let photoPicker = new picker.PhotoViewPicker();
photoPicker.select(photoSelectOptions).then((PhotoSelectResult: picker.PhotoSelectResult) => {hilog.info(0x0000, TAG, 'PhotoViewPicker.select successfully, PhotoSelectResult uri: ' + JSON.stringify(PhotoSelectResult));this.selectFilePath = PhotoSelectResult.photoUris[0];hilog.info(0x0000, TAG, 'Get selectFilePath successfully: ' + JSON.stringify(this.selectFilePath));
}).catch((err: BusinessError) => {hilog.error(0x0000, TAG, 'PhotoViewPicker.select failed with err: ' + JSON.stringify(err));
})
}

步骤二:将文件传递到native侧进行交互。

import player from 'libplayer.so';
export const playNative: (inputFileFd: number,inputFileOffset: number,inputFileSize: number,cbFn: () => void
) => void;
static napi_value Init(napi_env env, napi_value exports) {napi_property_descriptor classProp[] = {{"playNative", nullptr, Play, nullptr, nullptr, nullptr, napi_default, nullptr},
};
napi_value PlayerNative = nullptr;
const char *classBindName = "playerNative";
napi_define_class(env, classBindName, strlen(classBindName), nullptr, nullptr, 1, classProp, &PlayerNative);
PluginManager::GetInstance()->Export(env, exports);
napi_define_properties(env, exports, sizeof(classProp) / sizeof(classProp[0]), classProp);
return exports;
}

步骤三:使用Demuxer接口对文件进行解封装获取视频流数据。

Step1:创建解封装器,传入媒体文件格式信息。

int32_t Demuxer::CreateDemuxer(SampleInfo &info) {source = OH_AVSource_CreateWithFD(info.inputFd, info.inputFileOffset, info.inputFileSize);demuxer = OH_AVDemuxer_CreateWithSource(source);auto sourceFormat = std::shared_ptr<OH_AVFormat>(OH_AVSource_GetSourceFormat(source), OH_AVFormat_Destroy);int32_t ret = GetTrackInfo(sourceFormat, info);return AV_ERR_OK;
}

Step2:添加解封装轨道,获取文件轨道信息。

int32_t Demuxer::GetTrackInfo(std::shared_ptr<OH_AVFormat> sourceFormat, SampleInfo &info) {int32_t trackCount = 0;OH_AVFormat_GetIntValue(sourceFormat.get(), OH_MD_KEY_TRACK_COUNT, &trackCount);for (int32_t index = 0; index < trackCount; index++) {int trackType = -1;auto trackFormat = std::shared_ptr<OH_AVFormat>(OH_AVSource_GetTrackFormat(source, index), OH_AVFormat_Destroy);OH_AVFormat_GetIntValue(trackFormat.get(), OH_MD_KEY_TRACK_TYPE, &trackType);if (trackType == MEDIA_TYPE_VID) {OH_AVDemuxer_SelectTrackByID(demuxer, index);OH_AVFormat_GetIntValue(trackFormat.get(), OH_MD_KEY_WIDTH, &info.videoWidth);OH_AVFormat_GetIntValue(trackFormat.get(), OH_MD_KEY_HEIGHT, &info.videoHeight);OH_AVFormat_GetDoubleValue(trackFormat.get(), OH_MD_KEY_FRAME_RATE, &info.frameRate);OH_AVFormat_GetLongValue(trackFormat.get(), OH_MD_KEY_BITRATE, &info.bitrate);OH_AVFormat_GetIntValue(trackFormat.get(), "video_is_hdr_vivid", &info.isHDRVivid);OH_AVFormat_GetIntValue(trackFormat.get(), OH_MD_KEY_ROTATION, &info.rotation);char *codecMime;OH_AVFormat_GetStringValue(trackFormat.get(), OH_MD_KEY_CODEC_MIME, const_cast<char const **>(&codecMime));info.codecMime = codecMime;OH_AVFormat_GetIntValue(trackFormat.get(), OH_MD_KEY_PROFILE, &info.hevcProfile);videoTrackId_ = index;OH_LOG_ERROR(LOG_APP, "Demuxer config: %{public}d*%{public}d, %{public}.1ffps, %{public}ld" "kbps",info.videoWidth, info.videoHeight, info.frameRate, info.bitrate / 1024);}}return AV_ERR_OK;
}

Step3:开始解封装,循环获取视频帧数据。

int32_t Demuxer::ReadSample(OH_AVBuffer *buffer, OH_AVCodecBufferAttr &attr) {int32_t ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, videoTrackId_, buffer);ret = OH_AVBuffer_GetBufferAttr(buffer, &attr);return AV_ERR_OK;
}

解封装支持的文件格式:

步骤四:使用VideoDecoder接口将视频数据解码,结合Xcomponent送显播放。

Step1:将解封装后的数据送去解码器进行解码

void Player::DecInputThread() {while (true) {std::unique_lock<std::mutex> lock(signal->inputMutex_);bool condRet = signal->inputCond_.wait_for(lock, 5s, [this]() { return !isStarted_ || !signal->inputBufferInfoQueue_.empty(); });if (!isStarted_) {OH_LOG_ERROR(LOG_APP, "Work done, thread out");break;}if (signal->inputBufferInfoQueue_.empty()) {OH_LOG_ERROR(LOG_APP, "Buffer queue is empty, continue, cond ret: %{public}d", condRet);}CodecBufferInfo bufferInfo = signal->inputBufferInfoQueue_.front();signal->inputBufferInfoQueue_.pop();signal->inputFrameCount_++;lock.unlock();demuxer_->ReadSample(reinterpret_cast<OH_AVBuffer *>(bufferInfo.buffer), bufferInfo.attr);int32_t ret = videoDecoder_->PushInputData(bufferInfo);
}
StartRelease();
}

Step2:获取解码后的数据

void Player::DecOutputThread() {sampleInfo_.frameInterval = MICROSECOND / sampleInfo_.frameRate;while (true) {thread_local auto lastPushTime = std::chrono::system_clock::now();if (!isStarted_) {OH_LOG_ERROR(LOG_APP, "Decoder output thread out");break;}std::unique_lock<std::mutex> lock(signal->outputMutex_);bool condRet = signal->outputCond_.wait_for(lock, 5s, [this]() { return !isStarted_ || !signal->outputBufferInfoQueue_.empty(); });if (!isStarted_) {OH_LOG_ERROR(LOG_APP, "Decoder output thread out");break;}if (signal->outputBufferInfoQueue_.empty()) {OH_LOG_ERROR(LOG_APP, "Buffer queue is empty, continue, cond ret: %{public}d", condRet);}CodecBufferInfo bufferInfo = signal->outputBufferInfoQueue_.front();signal->outputBufferInfoQueue_.pop();if (bufferInfo.attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {OH_LOG_ERROR(LOG_APP, "Catch EOS, thread out");break;}signal->outputFrameCount_++;OH_LOG_ERROR(LOG_APP, "Out buffer count: %{public}u, size: %{public}d, flag: %{public}u, pts: %{public}ld",signal->outputFrameCount_, bufferInfo.attr.size, bufferInfo.attr.flags, bufferInfo.attr.pts);lock.unlock();int32_t ret = videoDecoder_->FreeOutputData(bufferInfo.bufferIndex, true);if (ret != AV_ERR_OK) {OH_LOG_ERROR(LOG_APP, "Decoder output thread out");break;}std::this_thread::sleep_until(lastPushTime + std::chrono::microseconds(sampleInfo_.frameInterval));lastPushTime = std::chrono::system_clock::now();
}
OH_LOG_ERROR(LOG_APP, "Exit, frame count: %{public}u", signal->outputFrameCount_);
StartRelease();
}

Step3:使用OH_VideoDecoder_SetSurface设置surface数据和window绑定

int32_t VideoDecoder::Config(const SampleInfo &sampleInfo, VDecSignal *signal) {// Configure video decoderint32_t ret = ConfigureVideoDecoder(sampleInfo);// SetSurface from video decoderif (sampleInfo.window != nullptr) {int ret = OH_VideoDecoder_SetSurface(decoder, sampleInfo.window);if (ret != AV_ERR_OK || sampleInfo.window == nullptr) {OH_LOG_ERROR(LOG_APP, "Set surface failed, ret: %{public}d", ret);return AV_ERR_UNKNOWN;}}// SetCallback for video decoderret = SetCallback(signal);if (ret != AV_ERR_OK) {OH_LOG_ERROR(LOG_APP, "Set callback failed, ret: %{public}d", ret);return AV_ERR_UNKNOWN;}// Prepare video decoder{int ret = OH_VideoDecoder_Prepare(decoder);if (ret != AV_ERR_OK) {OH_LOG_ERROR(LOG_APP, "Prepare failed, ret: %{public}d", ret);return AV_ERR_UNKNOWN;}}return AV_ERR_OK;
}

Step4: native层获取 NativeXComponent

void PluginManager::Export(napi_env env, napi_value exports) {napi_value exportInstance = nullptr;if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "PluginManager", "Export: napi_get_named_property fail");return;}OH_NativeXComponent *nativeXComponent = nullptr;if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "PluginManager", "Export: napi_unwrap fail");return;}char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "PluginManager", "Export: OH_NativeXComponent_GetXComponentId fail");return;}std::string id(idStr);auto context = PluginManager::GetInstance();if ((context != nullptr) && (nativeXComponent != nullptr)) {context->SetNativeXComponent(id, nativeXComponent);auto render = context->GetRender(id);OH_NativeXComponent_RegisterCallback(nativeXComponent, &PluginRender::m_callback);}
}

step5:通过回调将window渲染播放

void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, "Callback", "OnSurfaceCreatedCB");auto context = PluginManager::GetInstance();context->m_window = (OHNativeWindow *)window;
}
http://www.dtcms.com/wzjs/425068.html

相关文章:

  • 广州网络公司人气排名百度推广seo自学
  • 南京专业网站建设软文营销的三个层面
  • 在什么平台可以发布信息seo搜索优化费用
  • 网站做流量的论坛贴吧苏州百度代理公司
  • 做网站导航用什么开元程序seo公司推荐推广平台
  • html怎么做网站设计免费推广网址
  • 霞浦网站建设长尾关键词查询工具
  • 中国工程建设造价信息网站网络科技公司
  • 网站建设有名的公司网络营销专业技能
  • 微信头像在线制作免费南京seo优化公司
  • 南京汽车 企业 网站建设郑州网站优化推广
  • 怎么建设一个社交网站seo页面代码优化
  • 福州定制网站开发制作google搜索app下载
  • 杭州 网站建设公司排名百度助手安卓版下载
  • 做高级电工题的网站seo排名优化
  • 潍坊制作网站软件灰色词排名上首页
  • 杭州建设网通知公告栏湖北seo诊断
  • 抵押网站建设方案网站seo入门基础教程
  • 烟台网站制作网站百度外链查询工具
  • 提升学历咨询优化公司怎么优化网站的
  • 做网站哪家强百度开户资质
  • 关于建立企业网站的方案内容螺蛳粉的软文推广
  • 用服务器做网站需要购买域名吗今日新闻摘抄50字
  • 大型网站技术架构:核心原理与案例分析安年软文网
  • 做平面设计一般上哪个网站参考百度app官网下载
  • b2c电子商务模式seo快速排名的方法
  • 南通政府网站建设合肥百度竞价推广代理公司
  • 贵阳企业网站设计与建设成都网站优化seo
  • 网站建设的素材百度关键词推广怎么做
  • 杭州建设网站制作免费网站在线观看人数在哪