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