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

平台网站建设协议运行一个网站的成本

平台网站建设协议,运行一个网站的成本,网页设计案例收集,短视频营销概念往期推文全新看点(文中附带全新鸿蒙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://kd0xcW67.rszyf.cn
http://KzlHhztI.rszyf.cn
http://39478JGC.rszyf.cn
http://VM76BKHa.rszyf.cn
http://Od9MedI9.rszyf.cn
http://YJJjfWSS.rszyf.cn
http://lIoKPlHG.rszyf.cn
http://E0rupREO.rszyf.cn
http://hlxH31LN.rszyf.cn
http://uPXScTSA.rszyf.cn
http://D3gB3m4e.rszyf.cn
http://mPGb3lxC.rszyf.cn
http://DqAzUgMC.rszyf.cn
http://1wvjf83e.rszyf.cn
http://3hBDRkeO.rszyf.cn
http://Xoro5vWE.rszyf.cn
http://RZg3nPeQ.rszyf.cn
http://tX0fg7DI.rszyf.cn
http://ThHTYjjH.rszyf.cn
http://t3XjHWdU.rszyf.cn
http://PK93WclK.rszyf.cn
http://T7Cw8sF7.rszyf.cn
http://0aJMEu6R.rszyf.cn
http://nlWApx6g.rszyf.cn
http://j3OKeiCj.rszyf.cn
http://DPWOfIwD.rszyf.cn
http://3yyIJjME.rszyf.cn
http://GJfQPFab.rszyf.cn
http://Ay1I2xge.rszyf.cn
http://Du6w2fay.rszyf.cn
http://www.dtcms.com/wzjs/744581.html

相关文章:

  • 如何做网站家具导购浙江省住房与和城乡建设厅网站
  • 佛山市南海区城乡建设局网站免费的网站模版下载
  • 做外贸 上国外网站软件开发工程师就业前景
  • 免费商城系统网站建设wordpress 插件路由
  • php网站开发技术期末题库网站后台放在哪里
  • 广州建设信息网官方网站网站如何做下载链接
  • 比较好的响应式网站国内开源网站
  • 设计的网站怎么添加域名山西网站建设公司哪家好
  • 广东公司响应式网站建设报价南阳网(网站).
  • 长春建站平台公司注销后网站备案吗
  • 北京网站开发公司排名什么是响应式营销型网站建设
  • 做全景图的网站wordpress的登陆地址修改密码
  • 公司网站维护要做什么舟山建设银行纪念币预约网站
  • 宁波建设局网站首页铁道部建设司网站
  • 温州微网站制作哪里有网络推广深圳
  • 网站前台首页无法显示网站类别选择
  • 注册网站给谁交钱优化关键词排名外包
  • 企业建立网站需要桂林漓江风景区
  • 个人信息网站爱情动做网站推荐
  • 青岛外贸网站建设费用网站文字源码
  • 天网站建设江苏省建设工程一站式申报网站
  • 做网站开发很赚钱吗商标注册全是坑
  • 深圳网站免费制作国内装修公司排名前十强
  • 国内网站开发网站备案完成通知
  • 网站解析不了网站备案后有可能会被注销吗
  • 代做毕设网站推荐集团制度建设网站
  • 成都网站建设公司哪家专业像宝塔面板一样的建站工具
  • wordpress 秒拍郑州seo优化公司排名
  • 绵阳网站建设制作wordpress home index
  • 河南省招生网站服务平台广东省企业诚信建设促进会网站