1# 创建视频解码器和NativeWindow初始化并行 2 3## 场景介绍 4 5为了解码Surface模式的正常创建,在XComponent尚未创建或OpenGL后处理(NativeImage)尚未初始化的情况下, 6可以创建一个空的surface,以确保视频解码器能够正常创建和运行。 7 8 9## 开发步骤 10 11以下步骤描述了在surface的消费端没有创建之前,如何并行创建视频解码器和NativeWindow,让视频解码器正常创建执行。 12 13**添加动态链接库** 14 15``` cmake 16target_link_libraries(sample PUBLIC libnative_image.so) 17target_link_libraries(sample PUBLIC libnative_window.so) 18target_link_libraries(sample PUBLIC libnative_buffer.so) 19target_link_libraries(sample PUBLIC libnative_media_vdec.so) 20``` 21 22> **说明:** 23> 24> 上述'sample'字样仅为示例,此处由调用者根据实际工程目录自定义。 25> 26 27**头文件** 28 29```c++ 30#include <iostream> 31#include <string> 32#include <native_image/native_image.h> 33#include <native_window/external_window.h> 34#include <native_buffer/native_buffer.h> 35#include <multimedia/player_framework/native_avcodec_videodecoder.h> 36``` 37 381. 创建OH_NativeImage实例。 39 40 ```c++ 41 // 创建NativeImage实例,作为surface的消费者 42 OH_NativeImage* image = OH_ConsumerSurface_Create(); 43 ``` 44 452. 获取对应的数据生产者端NativeWindow。 46 47 ```c++ 48 // 获取生产者NativeWindow 49 OHNativeWindow* nativeImageWindow = OH_NativeImage_AcquireNativeWindow(image); 50 ``` 51 523. 设置NativeWindow的宽高。 53 54 ```c++ 55 int code = SET_BUFFER_GEOMETRY; 56 int32_t width = 800; 57 int32_t height = 600; 58 int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeImageWindow, code, width, height); 59 if (ret != AV_ERR_OK) { 60 // 异常处理 61 } 62 ``` 63 644. 注册NativeImage的回调函数。 65 66 注册OH_NativeImage的监听者OH_OnFrameAvailableListener,包括: 67 68 - context 用户自定义的上下文信息; 69 - onFrameAvailable 有buffer可获取触发时的回调函数。 70 71 ```c++ 72 // onFrameAvailable实现 73 static void onFrameAvailable() 74 { 75 OHNativeWindowBuffer *buffer = nullptr; 76 int fenceFd; 77 // 通过消费端的OH_NativeImage获取一个OHNativeWindowBuffer 78 OH_NativeImage_AcquireNativeWindowBuffer(image, &buffer, &fenceFd); 79 // 通过OH_NativeImage实例将OHNativeWindowBuffer归还到buffer队列中 80 OH_NativeImage_ReleaseNativeWindowBuffer(image, &buffer, &fenceFd); 81 } 82 83 static void context() 84 { 85 // 调用者自定义的上下文信息 86 } 87 88 // 设置回调监听者 89 OH_OnFrameAvailableListener listener = {&onFrameAvailable, &context}; 90 // 设置帧可用回调 91 ret = OH_NativeImage_SetOnFrameAvailableListener(image, listener); 92 if (ret != AV_ERR_OK) { 93 // 异常处理 94 } 95 ``` 96 97 > **说明:** 98 > 99 > 在此示例中,回调函数的实现仅仅是将buffer取出来并释放,调用者可以根据业务需求自行拓展。 100 > 101 1025. 配置解码器。 103 104 具体开发指导请参考[视频解码Surface模式](video-decoding.md#surface模式)“步骤-5:调用OH_VideoDecoder_Configure()配置解码器”。 105 1066. 设置surface。 107 108 在应用业务真正的surface消费端创建成功之前,可以先使用上面临时创建的消费端连接解码器。 109 110 示例中的变量说明如下: 111 - videoDec:视频解码器实例的指针。创建方式可参考[视频解码Surface模式](video-decoding.md#surface模式)“步骤-2:创建解码器实例对象”。 112 113 ```c++ 114 115 ret = OH_VideoDecoder_SetSurface(videoDec, nativeImageWindow); 116 if (ret != AV_ERR_OK) { 117 // 异常处理 118 } 119 ``` 120 1217. 启动解码器。 122 123 具体开发指导请参考[视频解码Surface模式](video-decoding.md#surface模式)“步骤-9:调用OH_VideoDecoder_Start()启动解码器”。 124 125 1268. 设置surface。 127 128 在应用业务真正的surface消费端创建成功后,可以调用OH_VideoDecoder_SetSurface接口,将解码输出重定向到新的surface上。 129 130 本例中的nativeWindow,有两种方式获取: 131 1. 如果解码后直接显示,则从XComponent组件获取,获取方式请参考 [XComponent](../../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md); 132 2. 如果解码后接OpenGL后处理,则从NativeImage获取,获取方式请参考 [NativeImage](../../graphics/native-image-guidelines.md)。 133 134 ```c++ 135 136 ret = OH_VideoDecoder_SetSurface(videoDec, nativeWindow); 137 if (ret != AV_ERR_OK) { 138 // 异常处理 139 } 140 ``` 141 1429. 销毁OH_NativeImage实例。 143 144 在调用OH_VideoDecoder_Destroy接口后,调用OH_NativeImage_Destroy接口销毁OH_NativeImage实例 145 ```c++ 146 // 销毁OH_NativeImage实例 147 OH_NativeImage_Destroy(&image); 148 ```