1# Using AVPlayer to Play Audio (C/C++)
2
3The [AVPlayer](media-kit-intro.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 piece of music.
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), 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 following 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 audio 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. 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.
68
697. (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).
70
718. 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.
72
739. (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.
74
7510. 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.
76
77## Sample Code
78
79```c
80#include "napi/native_api.h"
81
82#include <multimedia/player_framework/avplayer.h>
83#include <multimedia/player_framework/avplayer_base.h>
84#include <multimedia/player_framework/native_averrors.h>
85
86#include <hilog/log.h>
87
88#define LOG_MSG_TAG "AVPlayerNdk"
89#define LOG(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
90#define LOGE(format, ...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, LOG_MSG_TAG, format, ##__VA_ARGS__))
91
92typedef struct DemoNdkPlayer {
93    OH_AVPlayer *player = nullptr;
94    char *url = nullptr;
95    int32_t errorCode = AV_ERR_UNKNOWN;
96
97    int32_t value = -1;
98    int32_t state = -1;
99    int32_t stateChangeReason = -1;
100    AVPlayerState avState = AV_IDLE;
101    AVPlaybackSpeed speed = AV_SPEED_FORWARD_1_00_X;
102
103    float volume = 0.0;
104    int64_t duration = -1;
105
106    int32_t width = -1;
107    int32_t height = -1;
108
109    AVPlayerBufferingType bufferType = AVPLAYER_BUFFERING_START;
110    int32_t bufferValue = -1;
111
112    uint32_t *bitRates = nullptr;
113    size_t bitRatesSize = 0;
114    uint32_t bitRate = 0;
115
116    int32_t interruptType = -1;
117    int32_t interruptForce = -1;
118    int32_t interruptHint = -1;
119} DemoNdkPlayer;
120
121void HandleStateChange(OH_AVPlayer *player, AVPlayerState state) {
122    switch (state) {
123        case AV_IDLE: // This state is reported upon a successful callback of OH_AVPlayer_Reset().
124//            ret = OH_AVPlayer_SetURLSource(player, url); // Set the URL.
125//            if (ret != AV_ERR_OK) {
126//            // Handle the exception.
127//        }
128            break;
129        case AV_INITIALIZED:
130            ret = OH_AVPlayer_Prepare(player); // This state is reported when the AVPlayer sets the playback source.
131            if (ret != AV_ERR_OK) {
132            // Exception processing.
133            }
134            break;
135        case AV_PREPARED:
136//            ret = OH_AVPlayer_SetAudioEffectMode(player, EFFECT_NONE); // Set the audio effect mode.
137//            if (ret != AV_ERR_OK) {
138//            // Handle the exception.
139//            }
140            ret = OH_AVPlayer_Play(player); // Call OH_AVPlayer_Play() to start playback.
141            if (ret != AV_ERR_OK) {
142            // Exception processing.
143            }
144            break;
145        case AV_PLAYING:
146//            ret = OH_AVPlayer_Pause(player); // Call OH_AVPlayer_Pause() to pause the playback.
147//            if (ret != AV_ERR_OK) {
148//            // Handle the exception.
149//            }
150            break;
151        case AV_PAUSED:
152//            ret = OH_AVPlayer_Play(player); // Call OH_AVPlayer_Play() again to start playback.
153//            if (ret != AV_ERR_OK) {
154//            // Handle the exception.
155//            }
156           break;
157        case AV_STOPPED:
158            ret = OH_AVPlayer_Release(player); // Call OH_AVPlayer_Reset() to reset the AVPlayer state.
159            if (ret != AV_ERR_OK) {
160            // Exception processing.
161            }
162            break;
163        case AV_COMPLETED:
164            ret = OH_AVPlayer_Stop(player);// Call OH_AVPlayer_Stop() to stop the playback.
165            if (ret != AV_ERR_OK) {
166            // Exception processing.
167            }
168            break;
169        default:
170            break;
171    }
172}
173
174void OHAVPlayerOnInfoCallback(OH_AVPlayer *player, AVPlayerOnInfoType type, OH_AVFormat *infoBody, void *userData) {
175    int32_t ret;
176    int32_t value = -1;
177
178    DemoNdkPlayer *demoNdkPlayer = reinterpret_cast<DemoNdkPlayer *>(userData);
179    if (demoNdkPlayer == nullptr || player == nullptr) {
180        LOGE("OHAVPlayerOnInfoCallback demoNdkPlayer is nullptr");
181        return;
182    }
183    switch (type) {
184    case AV_INFO_TYPE_STATE_CHANGE:
185        LOG("AVPlayerOnInfoType AV_INFO_TYPE_STATE_CHANGE");
186        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_STATE, &demoNdkPlayer->state);
187        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_STATE_CHANGE_REASON, &demoNdkPlayer->stateChangeReason);
188        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_STATE_CHANGE  state: %d ,stateChangeReason: %d",
189            demoNdkPlayer->state, demoNdkPlayer->stateChangeReason);
190        demoNdkPlayer->avState = static_cast<AVPlayerState>(demoNdkPlayer->state);
191        HandleStateChange(player, demoNdkPlayer->avState);
192        break;
193    case AV_INFO_TYPE_SEEKDONE:
194        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_SEEK_POSITION, &value);
195        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SEEKDONE value: %d", value);
196        break;
197    case AV_INFO_TYPE_SPEEDDONE:
198        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_PLAYBACK_SPEED, &value);
199        demoNdkPlayer->speed = static_cast<AVPlaybackSpeed>(value);
200        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SPEEDDONE value: %d", value);
201        break;
202    case AV_INFO_TYPE_BITRATEDONE:
203        // Currently, OH_AVFormat does not support storage of data of the uint32_t type or custom type.
204        // Obtain the data of the int32_t type and forcibly convert the data to the corresponding type.
205        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BITRATE, &value);
206        demoNdkPlayer->bitRate = static_cast<uint32_t>(value);
207        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATEDONE value: %d", value);
208        break;
209    case AV_INFO_TYPE_EOS:
210        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_EOS");
211        break;
212    case AV_INFO_TYPE_POSITION_UPDATE:
213        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_CURRENT_POSITION, &value);
214        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_POSITION_UPDATE value: %d", value);
215        break;
216    case AV_INFO_TYPE_MESSAGE:
217        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_MESSAGE_TYPE, &value);
218        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_MESSAGE value: %d", value);
219        break;
220    case AV_INFO_TYPE_VOLUME_CHANGE:
221        OH_AVFormat_GetFloatValue(infoBody, OH_PLAYER_VOLUME, &demoNdkPlayer->volume);
222        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_VOLUME_CHANGE value: %f", demoNdkPlayer->volume);
223        break;
224    case AV_INFO_TYPE_RESOLUTION_CHANGE:
225        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_VIDEO_WIDTH, &demoNdkPlayer->width);
226        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_VIDEO_HEIGHT, &demoNdkPlayer->height);
227        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_RESOLUTION_CHANGE width: %d, height: %d",
228            demoNdkPlayer->width, demoNdkPlayer->height);
229        break;
230    case AV_INFO_TYPE_BUFFERING_UPDATE:
231        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BUFFERING_TYPE, &value);
232        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_BUFFERING_VALUE, &demoNdkPlayer->bufferValue);
233        demoNdkPlayer->bufferType = static_cast<AVPlayerBufferingType>(value);
234        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BUFFERING_UPDATE bufferType: %d, bufferValue: %d",
235            value, demoNdkPlayer->bufferValue);
236        break;
237    case AV_INFO_TYPE_BITRATE_COLLECT: {
238        uint8_t *bitRates = nullptr;
239        size_t size = 0;
240        OH_AVFormat_GetBuffer(infoBody, OH_PLAYER_BITRATE_ARRAY, &bitRates, &size);
241        demoNdkPlayer->bitRatesSize = size / sizeof(uint32_t);
242        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bytes size: %zu, size: %zu",
243            size, demoNdkPlayer->bitRatesSize );
244        if (demoNdkPlayer->bitRatesSize <= 0) {
245            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT invalid bitRatesSize");
246            return;
247        }
248        demoNdkPlayer->bitRates = new uint32_t[demoNdkPlayer->bitRatesSize];
249        if (demoNdkPlayer->bitRates == nullptr || bitRates == nullptr) {
250            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bitRates is nullptr");
251            return;
252        }
253        memcpy((void *)(demoNdkPlayer->bitRates), (void *)bitRates, demoNdkPlayer->bitRatesSize * sizeof(uint32_t));
254        for (size_t i = 0; i < demoNdkPlayer->bitRatesSize; i++) {
255            LOGE("OHAVPlayerOnInfoCallback AV_INFO_TYPE_BITRATE_COLLECT bitRates[%zu]: %zu",
256                i, *(demoNdkPlayer->bitRates + i));
257        }
258        break;
259    }
260    case AV_INFO_TYPE_INTERRUPT_EVENT:
261        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_TYPE, &demoNdkPlayer->interruptType);
262        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_FORCE, &demoNdkPlayer->interruptForce);
263        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_INTERRUPT_HINT, &demoNdkPlayer->interruptHint);
264        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_INTERRUPT_EVENT interruptType: %d, interruptForce: %d"
265            ", interruptHint: %d", demoNdkPlayer->interruptType, demoNdkPlayer->interruptForce,
266            demoNdkPlayer->interruptHint);
267        break;
268    case AV_INFO_TYPE_DURATION_UPDATE:
269        OH_AVFormat_GetLongValue(infoBody, OH_PLAYER_DURATION, &demoNdkPlayer->duration);
270        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_DURATION_UPDATE value: %lld", demoNdkPlayer->duration);
271        break;
272    case AV_INFO_TYPE_IS_LIVE_STREAM:
273        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_IS_LIVE_STREAM, &value);
274        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_IS_LIVE_STREAM value: %d", value);
275        break;
276    case AV_INFO_TYPE_TRACKCHANGE:
277        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_TRACKCHANGE value: %d", value);
278        break;
279    case AV_INFO_TYPE_TRACK_INFO_UPDATE:
280        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_TRACK_INFO_UPDATE value: %d", value);
281        break;
282    case AV_INFO_TYPE_SUBTITLE_UPDATE:
283        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_SUBTITLE_UPDATE value: %d", value);
284        break;
285    case AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE:
286        OH_AVFormat_GetIntValue(infoBody, OH_PLAYER_AUDIO_DEVICE_CHANGE_REASON, &value);
287        LOG("OHAVPlayerOnInfoCallback AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE value: %d", value);
288        break;
289    default:
290        break;
291    }
292}
293
294void OHAVPlayerOnErrorCallback(OH_AVPlayer *player, int32_t errorCode, const char *errorMsg, void *userData) {
295    LOG("OHAVPlayerOnError errorCode: %d ,errorMsg: %s", errorCode, errorMsg == nullptr ? "unknown" : errorMsg);
296    DemoNdkPlayer *demoNdkPlayer = reinterpret_cast<DemoNdkPlayer *>(userData);
297    if (demoNdkPlayer == nullptr || player == nullptr) {
298        LOGE("OHAVPlayerOnErrorCallback demoNdkPlayer or player is nullptr");
299        return;
300    }
301    demoNdkPlayer->errorCode = errorCode;
302    // do something
303}
304
305// Describe the mapped play method in the index.d.ts file and pass in a parameter of the string type.
306// When calling the player method in the .ets file, pass in the file path testNapi.play("/data/test/test.mp3").
307static napi_value Play(napi_env env, napi_callback_info info)
308{
309    size_t argc = 1;
310    napi_value args[1] = {nullptr};
311
312    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
313
314    // Obtain the parameter type.
315    napi_valuetype stringType;
316    if (napi_ok != napi_typeof(env, args[0], &stringType)) {
317        // Exception processing.
318        return nullptr;
319    }
320
321    // Verify the parameter.
322    if (napi_null == stringType) {
323        // Exception processing.
324        return nullptr;
325    }
326
327    // Obtain the length of the passed-in string.
328    size_t length = 0;
329    if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {
330        // Exception processing.
331        return nullptr;
332    }
333
334    // If "" is passed in, the result is directly returned.
335    if (length == 0) {
336        // Exception processing.
337        return nullptr;
338    }
339
340    // Read the passed-in string and place it in the buffer.
341    char *url = new char[length + 1];
342    if (napi_ok != napi_get_value_string_utf8(env, args[0], url, length + 1, &length)) {
343        delete[] url;
344        url = nullptr;
345        // Exception processing.
346        return nullptr;
347    }
348
349    // Use the new function to set the information callback and error callback. Do not use OH_AVPlayer_SetPlayerCallback.
350    // Release the object when it is no longer needed.
351    DemoNdkPlayer *demoNdkPlayer = new DemoNdkPlayer({
352        .player = player,
353        .url = url,
354    });
355    LOG("call OH_AVPlayer_SetPlayerOnInfoCallback");
356    ret = OH_AVPlayer_SetOnInfoCallback(player, OHAVPlayerOnInfoCallback, demoNdkPlayer);
357    LOG("OH_AVPlayer_SetPlayerOnInfoCallback ret:%d", ret);
358    LOG("call OH_AVPlayer_SetPlayerOnErrorCallback");
359    ret = OH_AVPlayer_SetOnErrorCallback(player, OHAVPlayerOnErrorCallback, demoNdkPlayer);
360    LOG("OH_AVPlayer_SetPlayerOnErrorCallback ret:%d", ret);
361
362    if (ret != AV_ERR_OK) {
363    // Exception processing.
364    }
365    ret = OH_AVPlayer_SetURLSource(player, url); // Set the URL.
366    if (ret != AV_ERR_OK) {
367    // Exception processing.
368    }
369    // Set the audio stream type.
370    OH_AudioStream_Usage streamUsage = OH_AudioStream_Usage::AUDIOSTREAM_USAGE_UNKNOWN;
371    ret = OH_AVPlayer_SetAudioRendererInfo(player, streamUsage);
372    if (ret != AV_ERR_OK) {
373    // Handle the exception.
374    }
375    // Set the audio interruption mode.
376    OH_AudioInterrupt_Mode interruptMode = OH_AudioInterrupt_Mode::AUDIOSTREAM_INTERRUPT_MODE_INDEPENDENT;
377    ret = OH_AVPlayer_SetAudioInterruptMode(player, interruptMode);
378    if (ret != AV_ERR_OK) {
379    // Handle the exception.
380    }
381    napi_value value;
382    napi_create_int32(env, 0, &value);
383    return value;
384}
385
386EXTERN_C_START
387static napi_value Init(napi_env env, napi_value exports)
388{
389    napi_property_descriptor desc[] = {
390        { "play", nullptr, Play, nullptr, nullptr, nullptr, napi_default, nullptr }
391    };
392    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
393    return exports;
394}
395EXTERN_C_END
396
397static napi_module demoModule = {
398    .nm_version =1,
399    .nm_flags = 0,
400    .nm_filename = nullptr,
401    .nm_register_func = Init,
402    .nm_modname = "entry",
403    .nm_priv = ((void*)0),
404    .reserved = { 0 },
405};
406
407extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
408{
409    napi_module_register(&demoModule);
410}
411```
412