1# Using AVPlayer to Play Video (C/C++)
2
3The [AVPlayer](../../reference/apis-media-kit/_a_v_player.md#avplayer) is used to play raw media assets in an end-to-end manner. In this topic, you will learn how to use the AVPlayer to play a complete video.
4
5
6The full playback process includes creating an AVPlayer instance, setting callback functions, setting the media asset to play, setting playback parameters (volume, speed, and focus mode), setting the playback window, controlling playback (play, pause, seek, and stop), resetting the playback configuration, and releasing the AVPlayer instance.
7
8
9During application development, you can obtain the playback process information through the callbacks [OH_AVPlayerOnInfoCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeroninfocallback) and [OH_AVPlayerOnErrorCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeronerrorcallback) of the AVPlayer. If the application performs an operation when the AVPlayer is not in the given state, the system may throw an exception or generate other undefined behavior.
10
11**Figure 1** Playback state transition
12
13![Playback status change](figures/playback-status-change-ndk.png)
14
15For details about the states, see [AVPlayerState](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1). When the AVPlayer is in the **prepared**, **playing**, **paused**, or **completed** state, the playback engine is working and a large amount of RAM is occupied. If your application does not need to use the AVPlayer, call **OH_AVPlayer_Reset()** or **OH_AVPlayer_Release()** to release the instance.
16
17## Development Tips
18
19This topic describes only how to implement the playback of a media asset. In practice, background playback and playback conflicts may be involved. You can refer to the following description to handle the situation based on your service requirements.
20
21- If you want the application to continue playing the media asset in the background or when the screen is off, use the [AVSession](../avsession/avsession-access-scene.md) and [continuous task](../../task-management/continuous-task.md) to prevent the playback from being forcibly interrupted by the system. Only ArkTS APIs are provided.
22- If the media asset being played involves audio, the playback may be interrupted by other applications based on the system audio management policy. (For details, see [Processing Audio Interruption Events](../audio/audio-playback-concurrency.md).) It is recommended that the player application proactively listen for audio interruption events [AV_INFO_TYPE_INTERRUPT_EVENT](../../reference/apis-media-kit/_a_v_player.md#avplayeroninfotype-1) through [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and handle the events accordingly to avoid the inconsistency between the application status and the expected effect.
23- When a device is connected to multiple audio output devices, the application can listen for audio output device changes [AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE](../../reference/apis-media-kit/_a_v_player.md#avplayeroninfotype-1) through [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and perform the processing accordingly.
24- During the playback, an internal error may occur, for example, network data download failure or media service unavailability. You are advised to set an error callback through [OH_AVPlayer_SetOnErrorCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setonerrorcallback) and handle the error based on the error type.
25- Use [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and [OH_AVPlayer_SetOnErrorCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setonerrorcallback) to set the information callback [OH_AVPlayerOnInfoCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeroninfocallback) and error callback [OH_AVPlayerOnErrorCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeronerrorcallback), respectively. After [OH_AVPlayerOnInfoCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeroninfocallback) is set, the callback [OH_AVPlayerOnInfo](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeroninfo) set through [OH_AVPlayer_SetPlayerCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setplayercallback) is not executed. After [OH_AVPlayerOnErrorCallback](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeronerrorcallback) is set, the callback [OH_AVPlayerOnError](../../reference/apis-media-kit/_a_v_player.md#oh_avplayeronerror) set through [OH_AVPlayer_SetPlayerCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setplayercallback) is not executed.
26
27## How to Develop
28Link the dynamic library in the CMake script.
29```
30target_link_libraries(sample PUBLIC libavplayer.so)
31```
32
33To use [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and [OH_AVPlayer_SetOnErrorCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setonerrorcallback) to set the information callback and error callback, link the following dynamic link library in the CMake script:
34```
35target_link_libraries(sample PUBLIC libnative_media_core.so)
36```
37
38To use system logging, include the following header file:
39```
40#include <hilog/log.h>
41```
42
43In addition, link the following dynamic link library in the CMake script:
44```
45target_link_libraries(sample PUBLIC libhilog_ndk.z.so)
46```
47
48You can use C/C++ APIs related to video playback by including the header files [avplayer.h](../../reference/apis-media-kit/avplayer_8h.md), [avpalyer_base.h](../../reference/apis-media-kit/avplayer__base_8h.md), and [native_averrors.h](../../reference/apis-avcodec-kit/native__averrors_8h.md).
49Read [AVPlayer](../../reference/apis-media-kit/_a_v_player.md) for the API reference.
50
511. Create an AVPlayer instance by calling [OH_AVPlayer_Create()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_create). The AVPlayer is initialized to the [AV_IDLE](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1) state.
52
532. Set callbacks to listen for events. Specifically, call [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and [OH_AVPlayer_SetOnErrorCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setonerrorcallback) to set the information callback and error callback, which are used in the entire process scenario. The table below lists the supported events.
54   | Event Type| Description|
55   | -------- | -------- |
56   | OH_AVPlayerOnInfoCallback | Mandatory; used to listen for AVPlayer process information.|
57   | OH_AVPlayerOnErrorCallback | Mandatory; used to listen for AVPlayer errors.|
58
59    The application can obtain more information from the callbacks set by calling [OH_AVPlayer_SetOnInfoCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setoninfocallback) and [OH_AVPlayer_SetOnErrorCallback()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setonerrorcallback). In addition, it can set **userData** to distinguish different AVPlayer instances.
60
613. Set the media asset. Specifically, call [OH_AVPlayer_SetURLSource()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_seturlsource) to set the URL of the media asset. The AVPlayer enters the [AV_INITIALIZED](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1) state.
62
634. (Optional) Set the audio stream type by calling [OH_AVPlayer_SetAudioRendererInfo()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setaudiorendererinfo).
64
655. (Optional) Set the audio interruption mode by calling [OH_AVPlayer_SetAudioInterruptMode()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setaudiointerruptmode).
66
676. Set the playback window by calling [OH_AVPlayer_SetVideoSurface()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setvideosurface). This function must be called after **SetSource** and before **Prepare**.
68
697. Prepare for the playback by calling [OH_AVPlayer_Prepare()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_prepare). The AVPlayer enters the [AV_PREPARED](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1) state. In this case, you can obtain the duration and set the volume.
70
718. (Optional) Set the audio effect mode of the AVPlayer by calling [OH_AVPlayer_SetAudioEffectMode()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_setaudioeffectmode).
72
739. Control the playback. You can call [OH_AVPlayer_Play()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_play), [OH_AVPlayer_Pause()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_pause), [OH_AVPlayer_Seek()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_seek), and [OH_AVPlayer_Stop()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_stop) to trigger different control operations.
74
7510. (Optional) Reset the media asset by calling [OH_AVPlayer_Reset()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_reset). The AVPlayer enters the [AV_IDLE](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1) state again and you can change the media asset URL.
76
7711. Exit the playback. Specifically, call [OH_AVPlayer_Release()](../../reference/apis-media-kit/_a_v_player.md#oh_avplayer_release) to destroy the instance. The AVPlayer enters the [AV_RELEASED](../../reference/apis-media-kit/_a_v_player.md#avplayerstate-1) state and exits the playback. Further actions on the AVPlayer instance may lead to undefined behavior, such as the process crashing or the application terminating unexpectedly.
78
79## Sample Code
80
81```c++
82#include "napi/native_api.h"
83
84#include <ace/xcomponent/native_interface_xcomponent.h>
85#include <multimedia/player_framework/avplayer.h>
86#include <multimedia/player_framework/avplayer_base.h>
87#include <multimedia/player_framework/native_averrors.h>
88
89#include <hilog/log.h>
90
91#define LOG_MSG_TAG "AVPlayerNdk"
92#define LOG(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
93#define LOGE(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
94
95typedef struct DemoNdkPlayer {
96    OH_AVPlayer *player = nullptr;
97    char *url = nullptr;
98    int32_t errorCode = AV_ERR_UNKNOWN;
99
100    int32_t value = -1;
101    int32_t state = -1;
102    int32_t stateChangeReason = -1;
103    AVPlayerState avState = AV_IDLE;
104    AVPlaybackSpeed speed = AV_SPEED_FORWARD_1_00_X;
105
106    float volume = 0.0;
107    int64_t duration = -1;
108
109    int32_t width = -1;
110    int32_t height = -1;
111
112    static OHNativeWindow *nativeWindow;
113
114    AVPlayerBufferingType bufferType = AVPLAYER_BUFFERING_START;
115    int32_t bufferValue = -1;
116
117    uint32_t *bitRates = nullptr;
118    size_t bitRatesSize = 0;
119    uint32_t bitRate = 0;
120
121    int32_t interruptType = -1;
122    int32_t interruptForce = -1;
123    int32_t interruptHint = -1;
124} DemoNdkPlayer;
125
126OHNativeWindow *DemoNdkPlayer::nativeWindow = nullptr;
127
128void HandleStateChange(OH_AVPlayer *player, AVPlayerState state) {
129    OH_AVErrCode ret;
130    switch (state) {
131        case AV_IDLE: // This state is reported upon a successful callback of OH_AVPlayer_Reset().
132//            ret = OH_AVPlayer_SetURLSource(player, url); // Set the URL.
133//            if (ret != AV_ERR_OK) {
134//            // Handle the exception.
135//        }
136            break;
137        case AV_INITIALIZED:
138            ret = OH_AVPlayer_SetVideoSurface(player, DemoNdkPlayer::nativeWindow); // Set the video playback surface.
139            LOG("OH_AVPlayer_SetVideoSurface ret:%d", ret);
140            ret = OH_AVPlayer_Prepare(player); // This state is reported when the AVPlayer sets the playback source.
141            if (ret != AV_ERR_OK) {
142            // Handle the exception.
143            }
144            break;
145        case AV_PREPARED:
146//            ret = OH_AVPlayer_SetAudioEffectMode(player, EFFECT_NONE); // Set the audio effect mode.
147//            if (ret != AV_ERR_OK) {
148//            // Handle the exception.
149//            }
150            ret = OH_AVPlayer_Play(player); // Call OH_AVPlayer_Play() to start playback.
151            if (ret != AV_ERR_OK) {
152            // Handle the exception.
153            }
154            break;
155        case AV_PLAYING:
156//            ret = OH_AVPlayer_Pause(player); // Call OH_AVPlayer_Pause() to pause the playback.
157//            if (ret != AV_ERR_OK) {
158//            // Handle the exception.
159//            }
160            break;
161        case AV_PAUSED:
162//            ret = OH_AVPlayer_Play(player); // Call OH_AVPlayer_Play() again to start playback.
163//            if (ret != AV_ERR_OK) {
164//            // Handle the exception.
165//            }
166           break;
167        case AV_STOPPED:
168            ret = OH_AVPlayer_Release(player); // Call OH_AVPlayer_Reset() to reset the AVPlayer state.
169            if (ret != AV_ERR_OK) {
170            // Handle the exception.
171            }
172            break;
173        case AV_COMPLETED:
174            ret = OH_AVPlayer_Stop(player);// Call OH_AVPlayer_Stop() to stop the playback.
175            if (ret != AV_ERR_OK) {
176            // Handle the exception.
177            }
178            break;
179        default:
180            break;
181    }
182}
183
184void OHAVPlayerOnInfoCallback(OH_AVPlayer *player, AVPlayerOnInfoType type, OH_AVFormat *infoBody, void *userData) {
185    OH_AVErrCode ret;
186    int32_t value = -1;
187
188    DemoNdkPlayer *demoNdkPlayer = reinterpret_cast<DemoNdkPlayer *>(userData);
189    if (demoNdkPlayer == nullptr || player == nullptr) {
190        LOGE("OHAVPlayerOnInfoCallback demoNdkPlayer is nullptr");
191        return;
192    }
193    switch (type) {
194    case AV_INFO_TYPE_STATE_CHANGE:
195        LOG("AVPlayerOnInfoType AV_INFO_TYPE_STATE_CHANGE");
196        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_STATE, &demoNdkPlayer->state);
197        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_STATE_CHANGE_REASON, &demoNdkPlayer->stateChangeReason);
198        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_STATE_CHANGE  state: %d ,stateChangeReason: %d",
199            demoNdkPlayer->state, demoNdkPlayer->stateChangeReason);
200        demoNdkPlayer->avState = static_cast<AVPlayerState>(demoNdkPlayer->state);
201        HandleStateChange(player, demoNdkPlayer->avState);
202        break;
203    case AV_INFO_TYPE_SEEKDONE:
204        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_SEEK_POSITION, &value);
205        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SEEKDONE value: %d", value);
206        break;
207    case AV_INFO_TYPE_SPEEDDONE:
208        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_PLAYBACK_SPEED, &value);
209        demoNdkPlayer->speed = static_cast<AVPlaybackSpeed>(value);
210        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SPEEDDONE value: %d", value);
211        break;
212    case AV_INFO_TYPE_BITRATEDONE:
213        // Currently, OH_AVFormat does not support storage of data of the uint32_t type or custom type.
214        // Obtain the data of the int32_t type and forcibly convert the data to the corresponding type.
215        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BITRATE, &value);
216        demoNdkPlayer->bitRate = static_cast<uint32_t>(value);
217        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATEDONE value: %d", value);
218        break;
219    case AV_INFO_TYPE_EOS:
220        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_EOS");
221        break;
222    case AV_INFO_TYPE_POSITION_UPDATE:
223        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_CURRENT_POSITION, &value);
224        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_POSITION_UPDATE value: %d", value);
225        break;
226    case AV_INFO_TYPE_MESSAGE:
227        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_MESSAGE_TYPE, &value);
228        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_MESSAGE value: %d", value);
229        break;
230    case AV_INFO_TYPE_VOLUME_CHANGE:
231        OH_AVFormat_GetFloatValue(infoBody, OH_PLAYER_VOLUME, &demoNdkPlayer->volume);
232        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_VOLUME_CHANGE value: %f", demoNdkPlayer->volume);
233        break;
234    case AV_INFO_TYPE_RESOLUTION_CHANGE:
235        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_VIDEO_WIDTH, &demoNdkPlayer->width);
236        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_VIDEO_HEIGHT, &demoNdkPlayer->height);
237        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_RESOLUTION_CHANGE width: %d, height: %d",
238            demoNdkPlayer->width, demoNdkPlayer->height);
239        break;
240    case AV_INFO_TYPE_BUFFERING_UPDATE:
241        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BUFFERING_TYPE, &value);
242        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BUFFERING_VALUE, &demoNdkPlayer->bufferValue);
243        demoNdkPlayer->bufferType = static_cast<AVPlayerBufferingType>(value);
244        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BUFFERING_UPDATE bufferType: %d, bufferValue: %d",
245            value, demoNdkPlayer->bufferValue);
246        break;
247    case AV_INFO_TYPE_BITRATE_COLLECT: {
248        uint8_t *bitRates = nullptr;
249        size_t size = 0;
250        OH_AVFormat_GetBuffer(infoBody, OH_PLAYER_BITRATE_ARRAY, &bitRates, &size);
251        demoNdkPlayer->bitRatesSize = size / sizeof(uint32_t);
252        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bytes size: %zu, size: %zu",
253            size, demoNdkPlayer->bitRatesSize );
254        if (demoNdkPlayer->bitRatesSize <= 0) {
255            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT invalid bitRatesSize");
256            return;
257        }
258        demoNdkPlayer->bitRates = new uint32_t[demoNdkPlayer->bitRatesSize];
259        if (demoNdkPlayer->bitRates == nullptr || bitRates == nullptr) {
260            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bitRates is nullptr");
261            return;
262        }
263        memcpy((void *)(demoNdkPlayer->bitRates), (void *)bitRates, demoNdkPlayer->bitRatesSize * sizeof(uint32_t));
264        for (size_t i = 0; i < demoNdkPlayer->bitRatesSize; i++) {
265            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bitRates[%zu]: %zu",
266                i, *(demoNdkPlayer->bitRates + i));
267        }
268        break;
269    }
270    case AV_INFO_TYPE_INTERRUPT_EVENT:
271        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_TYPE, &demoNdkPlayer->interruptType);
272        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_FORCE, &demoNdkPlayer->interruptForce);
273        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_HINT, &demoNdkPlayer->interruptHint);
274        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_INTERRUPT_EVENT interruptType: %d, interruptForce: %d"
275            ", interruptHint: %d", demoNdkPlayer->interruptType, demoNdkPlayer->interruptForce,
276            demoNdkPlayer->interruptHint);
277        break;
278    case AV_INFO_TYPE_DURATION_UPDATE:
279        OH_AVFormat_GetLongValue(infoBody, OH_PLAYER_DURATION, &demoNdkPlayer->duration);
280        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_DURATION_UPDATE value: %lld", demoNdkPlayer->duration);
281        break;
282    case AV_INFO_TYPE_IS_LIVE_STREAM:
283        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_IS_LIVE_STREAM, &value);
284        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_IS_LIVE_STREAM value: %d", value);
285        break;
286    case AV_INFO_TYPE_TRACKCHANGE:
287        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_TRACKCHANGE value: %d", value);
288        break;
289    case AV_INFO_TYPE_TRACK_INFO_UPDATE:
290        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_TRACK_INFO_UPDATE value: %d", value);
291        break;
292    case AV_INFO_TYPE_SUBTITLE_UPDATE:
293        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SUBTITLE_UPDATE value: %d", value);
294        break;
295    case AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE:
296        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_DEVICE_CHANGE_REASON, &value);
297        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE value: %d", value);
298        break;
299    default:
300        break;
301    }
302}
303
304void OHAVPlayerOnErrorCallback(OH_AVPlayer *player, int32_t errorCode, const char *errorMsg, void *userData) {
305    LOG("OHAVPlayerOnError errorCode: %d ,errorMsg: %s", errorCode, errorMsg == nullptr ? "unknown" : errorMsg);
306    DemoNdkPlayer *demoNdkPlayer = reinterpret_cast<DemoNdkPlayer *>(userData);
307    if (demoNdkPlayer == nullptr || player == nullptr) {
308        LOGE("OHAVPlayerOnErrorCallback demoNdkPlayer or player is nullptr");
309        return;
310    }
311    demoNdkPlayer->errorCode = errorCode;
312    // do something
313}
314
315// Describe the mapped play method in the index.d.ts file and pass in a parameter of the string type.
316// When calling the player method in the .ets file, pass in the file path testNapi.play("/data/test/test.mp4").
317static napi_value Play(napi_env env, napi_callback_info info)
318{
319    OH_AVErrCode ret;
320    size_t argc = 1;
321    napi_value args[1] = {nullptr};
322
323    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
324
325    // Obtain the parameter type.
326    napi_valuetype stringType;
327    if (napi_ok != napi_typeof(env, args[0], &stringType)) {
328        // Handle the exception.
329        return nullptr;
330    }
331
332    // Verify the parameter.
333    if (napi_null == stringType) {
334        // Handle the exception.
335        return nullptr;
336    }
337
338    // Obtain the length of the passed-in string.
339    size_t length = 0;
340    if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {
341        // Handle the exception.
342        return nullptr;
343    }
344
345    // If "" is passed in, the result is directly returned.
346    if (length == 0) {
347        // Handle the exception.
348        return nullptr;
349    }
350
351    // Read the passed-in string and place it in the buffer.
352    char *url = new char[length + 1];
353    if (napi_ok != napi_get_value_string_utf8(env, args[0], url, length + 1, &length)) {
354        delete[] url;
355        url = nullptr;
356        // Handle the exception.
357        return nullptr;
358    }
359
360    // Use the new function to set the information callback and error callback. Do not use OH_AVPlayer_SetPlayerCallback.
361    // Release the object when it is no longer needed.
362    OH_AVPlayer *player = OH_AVPlayer_Create();
363    DemoNdkPlayer *demoNdkPlayer = new DemoNdkPlayer({
364        .player = player,
365        .url = url,
366    });
367    LOG("call OH_AVPlayer_SetPlayerOnInfoCallback");
368    ret = OH_AVPlayer_SetOnInfoCallback(player, OHAVPlayerOnInfoCallback, demoNdkPlayer);
369    LOG("OH_AVPlayer_SetPlayerOnInfoCallback ret:%d", ret);
370    LOG("call OH_AVPlayer_SetPlayerOnErrorCallback");
371    ret = OH_AVPlayer_SetOnErrorCallback(player, OHAVPlayerOnErrorCallback, demoNdkPlayer);
372    LOG("OH_AVPlayer_SetPlayerOnErrorCallback ret:%d", ret);
373
374    if (ret != AV_ERR_OK) {
375    // Handle the exception.
376    }
377    ret = OH_AVPlayer_SetURLSource(player, url); // Set the URL.
378    if (ret != AV_ERR_OK) {
379    // Handle the exception.
380    }
381    // Set the audio stream type.
382    OH_AudioStream_Usage streamUsage = OH_AudioStream_Usage::AUDIOSTREAM_USAGE_UNKNOWN;
383    ret = OH_AVPlayer_SetAudioRendererInfo(player, streamUsage);
384    if (ret != AV_ERR_OK) {
385    // Handle the exception.
386    }
387    // Set the audio interruption mode.
388    OH_AudioInterrupt_Mode interruptMode = OH_AudioInterrupt_Mode::AUDIOSTREAM_INTERRUPT_MODE_INDEPENDENT;
389    ret = OH_AVPlayer_SetAudioInterruptMode(player, interruptMode);
390    if (ret != AV_ERR_OK) {
391    // Handle the exception.
392    }
393    napi_value value;
394    napi_create_int32(env, 0, &value);
395    return value;
396}
397
398// Define the surface callback.
399void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
400    LOG("OnSurfaceCreatedCB...");
401    // Obtain an OHNativeWindow instance.
402    OHNativeWindow * nativeWindow = static_cast<OHNativeWindow *>(window);
403    DemoNdkPlayer::nativeWindow = nativeWindow;
404    // ...
405}
406
407void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {
408    LOG("OnSurfaceDestroyedCB...");
409    // Obtain an OHNativeWindow instance.
410    OHNativeWindow * nativeWindow = static_cast<OHNativeWindow *>(window);
411    // ...
412}
413
414void Export(napi_env env, napi_value exports) {
415    if ((env == nullptr) || (exports == nullptr)) {
416        LOG("Export: env or exports is null");
417        return;
418    }
419    napi_value exportInstance = nullptr;
420    if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
421        LOG("Export: napi_get_named_property fail");
422        return;
423    }
424    OH_NativeXComponent *nativeXComponent = nullptr;
425    if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
426        LOG("Export: napi_unwrap fail");
427        return;
428    }
429    char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
430    uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
431    if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
432        LOG("OH_NativeXComponent_GetXComponentId fail");
433        return;
434    }
435    LOG("call Export surfaceID=%s", idStr);
436}
437
438EXTERN_C_START
439static napi_value Init(napi_env env, napi_value exports)
440{
441    napi_property_descriptor desc[] = {
442        { "Play", nullptr, Play, nullptr, nullptr, nullptr, napi_default, nullptr }
443    };
444    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
445
446    Export(env, exports);
447    return exports;
448}
449EXTERN_C_END
450
451static napi_module demoModule = {
452    .nm_version =1,
453    .nm_flags = 0,
454    .nm_filename = nullptr,
455    .nm_register_func = Init,
456    .nm_modname = "entry",
457    .nm_priv = ((void*)0),
458    .reserved = { 0 },
459};
460
461extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
462{
463    napi_module_register(&demoModule);
464}
465```
466