Flutter OHOS 外接纹理适配简介 - 视频播放
Flutter OHOS 外接纹理适配简介-视频播放
Flutter 在 OHOS 平台使用外接纹理,视频播在注册纹理时,flutter engine 返回 surfaceId。
注:1. 一般而言,为了方便复用,会将 ohos 对接 flutter 外接纹理的功能代码作为一个 module 模块组件单独写一个插件注册到 Flutter engine
外接纹理背景色为白色,暂不支持修改
视频播放
实现说明
在 video_player_ohos 插件中实现 ohos 原生播放器:AVplayer。
实现插件,在 onAttachedToEngine 中,从入参 FlutterPluginBinding 中获取 TextureRegistry(此处放入 FlutterState 中封装)。
export class VideoPlayerPlugin implements FlutterPlugin, AbilityAware { private pluginBinding: FlutterPluginBinding | null = null; private videoPlayerApi: VideoPlayerApiImpl | null = null; private flutterState: FlutterState | null = null; getUniqueClassName(): string { return TAG; } onAttachedToEngine(binding: FlutterPluginBinding): void { this.pluginBinding = binding; Log.i(TAG, "VideoPlayer onAttachedToEngine"); this.flutterState = new FlutterState(this.pluginBinding.getBinaryMessenger(), this.pluginBinding.getTextureRegistry()); }
在创建视频播放器的方法中,(先从 FlutterState 拿出 TextureRegistry)同样的先获取 textureId,再注册纹理到 engine,得到 surfaceId(surfaceId 在返回的 SurfaceTextureEntry 对象中):
let flutterRenderer = this.flutterState.getTextureRegistry(); let uri: string = arg.getUri(); let asset: string = arg.getAsset(); let header: Record<string, string= {}; arg.getHttpHeaders().forEach((value, key) ={ header[key.toString()] = value.toString(); }) let textureId: number = flutterRenderer.getTextureId(); Log.i(TAG, "enter getRawFd, textureId=" + textureId); let surfaceTextureEntry: SurfaceTextureEntry = flutterRenderer.registerTexture(textureId); if (asset != null) { let avImageGenerator = await media.createAVImageGenerator(); avImageGenerator.fdSrc = await this.getContext().resourceManager.getRawFd("flutter_assets/" + asset); let pixelMap = await avImageGenerator.fetchFrameByTime(0, media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC, { width: -1, height: -1 }); this.pixelMaps.set(JSON.stringify(arg), pixelMap); avImageGenerator.release(); flutterRenderer.setTextureBackGroundPixelMap(textureId, this.pixelMaps.get(JSON.stringify(arg))); } else if (uri != null && uri.startsWith("fd://")) { let avImageGenerator = await media.createAVImageGenerator(); avImageGenerator.fdSrc = { fd: Number.parseInt(uri.replace("fd://", "")) }; let pixelMap = await avImageGenerator.fetchFrameByTime(0, media.AVImageQueryOptions.AV_IMAGE_QUERY_NEXT_SYNC, { width: -1, height: -1 }); this.pixelMaps.set(JSON.stringify(arg), pixelMap); avImageGenerator.release(); flutterRenderer.setTextureBackGroundPixelMap(textureId, this.pixelMaps.get(JSON.stringify(arg))); } let eventChannel: EventChannel = new EventChannel(this.flutterState.getBinaryMessenger(), "flutter.io/videoPlayer/videoEvents" + textureId.toString()); if (asset != null) { let rawFileDescriptor: resourceManager.RawFileDescriptor = await this.getContext().resourceManager.getRawFd("flutter_assets/" + asset); let videoPlayer = new VideoPlayer(playerModel, surfaceTextureEntry, rawFileDescriptor, null, eventChannel, this.AudioFocus, null); await videoPlayer.createAVPlayer(); this.videoPlayers.set(textureId.toString(), videoPlayer); } else if (uri != null) { let videoPlayer = new VideoPlayer(playerModel, surfaceTextureEntry, null, uri, eventChannel, this.AudioFocus, header); await videoPlayer.createAVPlayer(); this.videoPlayers.set(textureId.toString(), videoPlayer); }
Videoplaye 构造方法中取出 surfaceId:
constructor(playerModel: PlayerModel, textureEntry: SurfaceTextureEntry, url: resourceManager.RawFileDescriptor | null, iUrl: string | null, eventChannel: EventChannel, AudioFocus: Boolean, headers: Record<string, string| null) { this.playerModel = playerModel; this.textureEntry = textureEntry; this.surfaceId = textureEntry.getSurfaceId().toString(); this.url = url; this.iUrl = iUrl; this.eventChannel = eventChannel; this.headers = headers; if (AudioFocus == true) { this.interruptMode = audio.InterruptMode.SHARE_MODE; Log.i(TAG, "set interruptMode : " + this.interruptMode); } Log.i(TAG, "surfaceId : " + this.surfaceId); }
在 AVplayer 是 AvplayerStatus.INITIALIZED 状态时,把 surfaceId 赋给 AVplayer
case AvplayerStatus.INITIALIZED: this.avPlayer.surfaceId = this.surfaceId; this.avPlayer.prepare();
第三步创建 AVplayer 时,需要把 textureId 返回给 dart 层,dart 层得到该值,可以在 texture Widget 中使用该外接纹理完成渲染。
评论