• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   ```