1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include "cbs.h"
20cabdff1aSopenharmony_ci#include "cbs_internal.h"
21cabdff1aSopenharmony_ci#include "cbs_h264.h"
22cabdff1aSopenharmony_ci#include "cbs_h265.h"
23cabdff1aSopenharmony_ci#include "cbs_sei.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_cistatic void cbs_free_user_data_registered(void *opaque, uint8_t *data)
26cabdff1aSopenharmony_ci{
27cabdff1aSopenharmony_ci    SEIRawUserDataRegistered *udr = (SEIRawUserDataRegistered*)data;
28cabdff1aSopenharmony_ci    av_buffer_unref(&udr->data_ref);
29cabdff1aSopenharmony_ci    av_free(udr);
30cabdff1aSopenharmony_ci}
31cabdff1aSopenharmony_ci
32cabdff1aSopenharmony_cistatic void cbs_free_user_data_unregistered(void *opaque, uint8_t *data)
33cabdff1aSopenharmony_ci{
34cabdff1aSopenharmony_ci    SEIRawUserDataUnregistered *udu = (SEIRawUserDataUnregistered*)data;
35cabdff1aSopenharmony_ci    av_buffer_unref(&udu->data_ref);
36cabdff1aSopenharmony_ci    av_free(udu);
37cabdff1aSopenharmony_ci}
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ciint ff_cbs_sei_alloc_message_payload(SEIRawMessage *message,
40cabdff1aSopenharmony_ci                                     const SEIMessageTypeDescriptor *desc)
41cabdff1aSopenharmony_ci{
42cabdff1aSopenharmony_ci    void (*free_func)(void*, uint8_t*);
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci    av_assert0(message->payload     == NULL &&
45cabdff1aSopenharmony_ci               message->payload_ref == NULL);
46cabdff1aSopenharmony_ci    message->payload_type = desc->type;
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci    if (desc->type == SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35)
49cabdff1aSopenharmony_ci        free_func = &cbs_free_user_data_registered;
50cabdff1aSopenharmony_ci    else if (desc->type == SEI_TYPE_USER_DATA_UNREGISTERED)
51cabdff1aSopenharmony_ci        free_func = &cbs_free_user_data_unregistered;
52cabdff1aSopenharmony_ci    else
53cabdff1aSopenharmony_ci        free_func = NULL;
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci    if (free_func) {
56cabdff1aSopenharmony_ci        message->payload = av_mallocz(desc->size);
57cabdff1aSopenharmony_ci        if (!message->payload)
58cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
59cabdff1aSopenharmony_ci        message->payload_ref =
60cabdff1aSopenharmony_ci            av_buffer_create(message->payload, desc->size,
61cabdff1aSopenharmony_ci                             free_func, NULL, 0);
62cabdff1aSopenharmony_ci    } else {
63cabdff1aSopenharmony_ci        message->payload_ref = av_buffer_alloc(desc->size);
64cabdff1aSopenharmony_ci    }
65cabdff1aSopenharmony_ci    if (!message->payload_ref) {
66cabdff1aSopenharmony_ci        av_freep(&message->payload);
67cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
68cabdff1aSopenharmony_ci    }
69cabdff1aSopenharmony_ci    message->payload = message->payload_ref->data;
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci    return 0;
72cabdff1aSopenharmony_ci}
73cabdff1aSopenharmony_ci
74cabdff1aSopenharmony_ciint ff_cbs_sei_list_add(SEIRawMessageList *list)
75cabdff1aSopenharmony_ci{
76cabdff1aSopenharmony_ci    void *ptr;
77cabdff1aSopenharmony_ci    int old_count = list->nb_messages_allocated;
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    av_assert0(list->nb_messages <= old_count);
80cabdff1aSopenharmony_ci    if (list->nb_messages + 1 > old_count) {
81cabdff1aSopenharmony_ci        int new_count = 2 * old_count + 1;
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci        ptr = av_realloc_array(list->messages,
84cabdff1aSopenharmony_ci                               new_count, sizeof(*list->messages));
85cabdff1aSopenharmony_ci        if (!ptr)
86cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci        list->messages = ptr;
89cabdff1aSopenharmony_ci        list->nb_messages_allocated = new_count;
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci        // Zero the newly-added entries.
92cabdff1aSopenharmony_ci        memset(list->messages + old_count, 0,
93cabdff1aSopenharmony_ci               (new_count - old_count) * sizeof(*list->messages));
94cabdff1aSopenharmony_ci    }
95cabdff1aSopenharmony_ci    ++list->nb_messages;
96cabdff1aSopenharmony_ci    return 0;
97cabdff1aSopenharmony_ci}
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_civoid ff_cbs_sei_free_message_list(SEIRawMessageList *list)
100cabdff1aSopenharmony_ci{
101cabdff1aSopenharmony_ci    for (int i = 0; i < list->nb_messages; i++) {
102cabdff1aSopenharmony_ci        SEIRawMessage *message = &list->messages[i];
103cabdff1aSopenharmony_ci        av_buffer_unref(&message->payload_ref);
104cabdff1aSopenharmony_ci        av_buffer_unref(&message->extension_data_ref);
105cabdff1aSopenharmony_ci    }
106cabdff1aSopenharmony_ci    av_free(list->messages);
107cabdff1aSopenharmony_ci}
108cabdff1aSopenharmony_ci
109cabdff1aSopenharmony_cistatic int cbs_sei_get_unit(CodedBitstreamContext *ctx,
110cabdff1aSopenharmony_ci                            CodedBitstreamFragment *au,
111cabdff1aSopenharmony_ci                            int prefix,
112cabdff1aSopenharmony_ci                            CodedBitstreamUnit **sei_unit)
113cabdff1aSopenharmony_ci{
114cabdff1aSopenharmony_ci    CodedBitstreamUnit *unit;
115cabdff1aSopenharmony_ci    int sei_type, highest_vcl_type, err, i, position;
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_ci    switch (ctx->codec->codec_id) {
118cabdff1aSopenharmony_ci    case AV_CODEC_ID_H264:
119cabdff1aSopenharmony_ci        // (We can ignore auxiliary slices because we only have prefix
120cabdff1aSopenharmony_ci        // SEI in H.264 and an auxiliary picture must always follow a
121cabdff1aSopenharmony_ci        // primary picture.)
122cabdff1aSopenharmony_ci        highest_vcl_type = H264_NAL_IDR_SLICE;
123cabdff1aSopenharmony_ci        if (prefix)
124cabdff1aSopenharmony_ci            sei_type = H264_NAL_SEI;
125cabdff1aSopenharmony_ci        else
126cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
127cabdff1aSopenharmony_ci        break;
128cabdff1aSopenharmony_ci    case AV_CODEC_ID_H265:
129cabdff1aSopenharmony_ci        highest_vcl_type = HEVC_NAL_RSV_VCL31;
130cabdff1aSopenharmony_ci        if (prefix)
131cabdff1aSopenharmony_ci            sei_type = HEVC_NAL_SEI_PREFIX;
132cabdff1aSopenharmony_ci        else
133cabdff1aSopenharmony_ci            sei_type = HEVC_NAL_SEI_SUFFIX;
134cabdff1aSopenharmony_ci        break;
135cabdff1aSopenharmony_ci    default:
136cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
137cabdff1aSopenharmony_ci    }
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci    // Find an existing SEI NAL unit of the right type.
140cabdff1aSopenharmony_ci    unit = NULL;
141cabdff1aSopenharmony_ci    for (i = 0; i < au->nb_units; i++) {
142cabdff1aSopenharmony_ci        if (au->units[i].type == sei_type) {
143cabdff1aSopenharmony_ci            unit = &au->units[i];
144cabdff1aSopenharmony_ci            break;
145cabdff1aSopenharmony_ci        }
146cabdff1aSopenharmony_ci    }
147cabdff1aSopenharmony_ci
148cabdff1aSopenharmony_ci    if (unit) {
149cabdff1aSopenharmony_ci        *sei_unit = unit;
150cabdff1aSopenharmony_ci        return 0;
151cabdff1aSopenharmony_ci    }
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_ci    // Need to add a new SEI NAL unit ...
154cabdff1aSopenharmony_ci    if (prefix) {
155cabdff1aSopenharmony_ci        // ... before the first VCL NAL unit.
156cabdff1aSopenharmony_ci        for (i = 0; i < au->nb_units; i++) {
157cabdff1aSopenharmony_ci            if (au->units[i].type < highest_vcl_type)
158cabdff1aSopenharmony_ci                break;
159cabdff1aSopenharmony_ci        }
160cabdff1aSopenharmony_ci        position = i;
161cabdff1aSopenharmony_ci    } else {
162cabdff1aSopenharmony_ci        // ... after the last VCL NAL unit.
163cabdff1aSopenharmony_ci        for (i = au->nb_units - 1; i >= 0; i--) {
164cabdff1aSopenharmony_ci            if (au->units[i].type < highest_vcl_type)
165cabdff1aSopenharmony_ci                break;
166cabdff1aSopenharmony_ci        }
167cabdff1aSopenharmony_ci        if (i < 0) {
168cabdff1aSopenharmony_ci            // No VCL units; just put it at the end.
169cabdff1aSopenharmony_ci            position = au->nb_units;
170cabdff1aSopenharmony_ci        } else {
171cabdff1aSopenharmony_ci            position = i + 1;
172cabdff1aSopenharmony_ci        }
173cabdff1aSopenharmony_ci    }
174cabdff1aSopenharmony_ci
175cabdff1aSopenharmony_ci    err = ff_cbs_insert_unit_content(au, position, sei_type,
176cabdff1aSopenharmony_ci                                     NULL, NULL);
177cabdff1aSopenharmony_ci    if (err < 0)
178cabdff1aSopenharmony_ci        return err;
179cabdff1aSopenharmony_ci    unit = &au->units[position];
180cabdff1aSopenharmony_ci    unit->type = sei_type;
181cabdff1aSopenharmony_ci
182cabdff1aSopenharmony_ci    err = ff_cbs_alloc_unit_content2(ctx, unit);
183cabdff1aSopenharmony_ci    if (err < 0)
184cabdff1aSopenharmony_ci        return err;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci    switch (ctx->codec->codec_id) {
187cabdff1aSopenharmony_ci    case AV_CODEC_ID_H264:
188cabdff1aSopenharmony_ci        {
189cabdff1aSopenharmony_ci            H264RawSEI sei = {
190cabdff1aSopenharmony_ci                .nal_unit_header = {
191cabdff1aSopenharmony_ci                    .nal_ref_idc   = 0,
192cabdff1aSopenharmony_ci                    .nal_unit_type = sei_type,
193cabdff1aSopenharmony_ci                },
194cabdff1aSopenharmony_ci            };
195cabdff1aSopenharmony_ci            memcpy(unit->content, &sei, sizeof(sei));
196cabdff1aSopenharmony_ci        }
197cabdff1aSopenharmony_ci        break;
198cabdff1aSopenharmony_ci    case AV_CODEC_ID_H265:
199cabdff1aSopenharmony_ci        {
200cabdff1aSopenharmony_ci            H265RawSEI sei = {
201cabdff1aSopenharmony_ci                .nal_unit_header = {
202cabdff1aSopenharmony_ci                    .nal_unit_type         = sei_type,
203cabdff1aSopenharmony_ci                    .nuh_layer_id          = 0,
204cabdff1aSopenharmony_ci                    .nuh_temporal_id_plus1 = 1,
205cabdff1aSopenharmony_ci                },
206cabdff1aSopenharmony_ci            };
207cabdff1aSopenharmony_ci            memcpy(unit->content, &sei, sizeof(sei));
208cabdff1aSopenharmony_ci        }
209cabdff1aSopenharmony_ci        break;
210cabdff1aSopenharmony_ci    default:
211cabdff1aSopenharmony_ci        av_assert0(0);
212cabdff1aSopenharmony_ci    }
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci    *sei_unit = unit;
215cabdff1aSopenharmony_ci    return 0;
216cabdff1aSopenharmony_ci}
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_cistatic int cbs_sei_get_message_list(CodedBitstreamContext *ctx,
219cabdff1aSopenharmony_ci                                    CodedBitstreamUnit *unit,
220cabdff1aSopenharmony_ci                                    SEIRawMessageList **list)
221cabdff1aSopenharmony_ci{
222cabdff1aSopenharmony_ci    switch (ctx->codec->codec_id) {
223cabdff1aSopenharmony_ci    case AV_CODEC_ID_H264:
224cabdff1aSopenharmony_ci        {
225cabdff1aSopenharmony_ci            H264RawSEI *sei = unit->content;
226cabdff1aSopenharmony_ci            if (unit->type != H264_NAL_SEI)
227cabdff1aSopenharmony_ci                return AVERROR(EINVAL);
228cabdff1aSopenharmony_ci            *list = &sei->message_list;
229cabdff1aSopenharmony_ci        }
230cabdff1aSopenharmony_ci        break;
231cabdff1aSopenharmony_ci    case AV_CODEC_ID_H265:
232cabdff1aSopenharmony_ci        {
233cabdff1aSopenharmony_ci            H265RawSEI *sei = unit->content;
234cabdff1aSopenharmony_ci            if (unit->type != HEVC_NAL_SEI_PREFIX &&
235cabdff1aSopenharmony_ci                unit->type != HEVC_NAL_SEI_SUFFIX)
236cabdff1aSopenharmony_ci                return AVERROR(EINVAL);
237cabdff1aSopenharmony_ci            *list = &sei->message_list;
238cabdff1aSopenharmony_ci        }
239cabdff1aSopenharmony_ci        break;
240cabdff1aSopenharmony_ci    default:
241cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
242cabdff1aSopenharmony_ci    }
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_ci    return 0;
245cabdff1aSopenharmony_ci}
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_ciint ff_cbs_sei_add_message(CodedBitstreamContext *ctx,
248cabdff1aSopenharmony_ci                           CodedBitstreamFragment *au,
249cabdff1aSopenharmony_ci                           int prefix,
250cabdff1aSopenharmony_ci                           uint32_t     payload_type,
251cabdff1aSopenharmony_ci                           void        *payload_data,
252cabdff1aSopenharmony_ci                           AVBufferRef *payload_buf)
253cabdff1aSopenharmony_ci{
254cabdff1aSopenharmony_ci    const SEIMessageTypeDescriptor *desc;
255cabdff1aSopenharmony_ci    CodedBitstreamUnit *unit;
256cabdff1aSopenharmony_ci    SEIRawMessageList *list;
257cabdff1aSopenharmony_ci    SEIRawMessage *message;
258cabdff1aSopenharmony_ci    AVBufferRef *payload_ref;
259cabdff1aSopenharmony_ci    int err;
260cabdff1aSopenharmony_ci
261cabdff1aSopenharmony_ci    desc = ff_cbs_sei_find_type(ctx, payload_type);
262cabdff1aSopenharmony_ci    if (!desc)
263cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
264cabdff1aSopenharmony_ci
265cabdff1aSopenharmony_ci    // Find an existing SEI unit or make a new one to add to.
266cabdff1aSopenharmony_ci    err = cbs_sei_get_unit(ctx, au, prefix, &unit);
267cabdff1aSopenharmony_ci    if (err < 0)
268cabdff1aSopenharmony_ci        return err;
269cabdff1aSopenharmony_ci
270cabdff1aSopenharmony_ci    // Find the message list inside the codec-dependent unit.
271cabdff1aSopenharmony_ci    err = cbs_sei_get_message_list(ctx, unit, &list);
272cabdff1aSopenharmony_ci    if (err < 0)
273cabdff1aSopenharmony_ci        return err;
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci    // Add a new message to the message list.
276cabdff1aSopenharmony_ci    err = ff_cbs_sei_list_add(list);
277cabdff1aSopenharmony_ci    if (err < 0)
278cabdff1aSopenharmony_ci        return err;
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ci    if (payload_buf) {
281cabdff1aSopenharmony_ci        payload_ref = av_buffer_ref(payload_buf);
282cabdff1aSopenharmony_ci        if (!payload_ref)
283cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
284cabdff1aSopenharmony_ci    } else {
285cabdff1aSopenharmony_ci        payload_ref = NULL;
286cabdff1aSopenharmony_ci    }
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci    message = &list->messages[list->nb_messages - 1];
289cabdff1aSopenharmony_ci
290cabdff1aSopenharmony_ci    message->payload_type = payload_type;
291cabdff1aSopenharmony_ci    message->payload      = payload_data;
292cabdff1aSopenharmony_ci    message->payload_ref  = payload_ref;
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ci    return 0;
295cabdff1aSopenharmony_ci}
296cabdff1aSopenharmony_ci
297cabdff1aSopenharmony_ciint ff_cbs_sei_find_message(CodedBitstreamContext *ctx,
298cabdff1aSopenharmony_ci                            CodedBitstreamFragment *au,
299cabdff1aSopenharmony_ci                            uint32_t payload_type,
300cabdff1aSopenharmony_ci                            SEIRawMessage **iter)
301cabdff1aSopenharmony_ci{
302cabdff1aSopenharmony_ci    int err, i, j, found;
303cabdff1aSopenharmony_ci
304cabdff1aSopenharmony_ci    found = 0;
305cabdff1aSopenharmony_ci    for (i = 0; i < au->nb_units; i++) {
306cabdff1aSopenharmony_ci        CodedBitstreamUnit *unit = &au->units[i];
307cabdff1aSopenharmony_ci        SEIRawMessageList *list;
308cabdff1aSopenharmony_ci
309cabdff1aSopenharmony_ci        err = cbs_sei_get_message_list(ctx, unit, &list);
310cabdff1aSopenharmony_ci        if (err < 0)
311cabdff1aSopenharmony_ci            continue;
312cabdff1aSopenharmony_ci
313cabdff1aSopenharmony_ci        for (j = 0; j < list->nb_messages; j++) {
314cabdff1aSopenharmony_ci            SEIRawMessage *message = &list->messages[j];
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci            if (message->payload_type == payload_type) {
317cabdff1aSopenharmony_ci                if (!*iter || found) {
318cabdff1aSopenharmony_ci                    *iter = message;
319cabdff1aSopenharmony_ci                    return 0;
320cabdff1aSopenharmony_ci                }
321cabdff1aSopenharmony_ci                if (message == *iter)
322cabdff1aSopenharmony_ci                    found = 1;
323cabdff1aSopenharmony_ci            }
324cabdff1aSopenharmony_ci        }
325cabdff1aSopenharmony_ci    }
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci    return AVERROR(ENOENT);
328cabdff1aSopenharmony_ci}
329cabdff1aSopenharmony_ci
330cabdff1aSopenharmony_cistatic void cbs_sei_delete_message(SEIRawMessageList *list,
331cabdff1aSopenharmony_ci                                   int position)
332cabdff1aSopenharmony_ci{
333cabdff1aSopenharmony_ci    SEIRawMessage *message;
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_ci    av_assert0(0 <= position && position < list->nb_messages);
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci    message = &list->messages[position];
338cabdff1aSopenharmony_ci    av_buffer_unref(&message->payload_ref);
339cabdff1aSopenharmony_ci    av_buffer_unref(&message->extension_data_ref);
340cabdff1aSopenharmony_ci
341cabdff1aSopenharmony_ci    --list->nb_messages;
342cabdff1aSopenharmony_ci
343cabdff1aSopenharmony_ci    if (list->nb_messages > 0) {
344cabdff1aSopenharmony_ci        memmove(list->messages + position,
345cabdff1aSopenharmony_ci                list->messages + position + 1,
346cabdff1aSopenharmony_ci                (list->nb_messages - position) * sizeof(*list->messages));
347cabdff1aSopenharmony_ci    }
348cabdff1aSopenharmony_ci}
349cabdff1aSopenharmony_ci
350cabdff1aSopenharmony_civoid ff_cbs_sei_delete_message_type(CodedBitstreamContext *ctx,
351cabdff1aSopenharmony_ci                                    CodedBitstreamFragment *au,
352cabdff1aSopenharmony_ci                                    uint32_t payload_type)
353cabdff1aSopenharmony_ci{
354cabdff1aSopenharmony_ci    int err, i, j;
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci    for (i = 0; i < au->nb_units; i++) {
357cabdff1aSopenharmony_ci        CodedBitstreamUnit *unit = &au->units[i];
358cabdff1aSopenharmony_ci        SEIRawMessageList *list;
359cabdff1aSopenharmony_ci
360cabdff1aSopenharmony_ci        err = cbs_sei_get_message_list(ctx, unit, &list);
361cabdff1aSopenharmony_ci        if (err < 0)
362cabdff1aSopenharmony_ci            continue;
363cabdff1aSopenharmony_ci
364cabdff1aSopenharmony_ci        for (j = list->nb_messages - 1; j >= 0; j--) {
365cabdff1aSopenharmony_ci            if (list->messages[j].payload_type == payload_type)
366cabdff1aSopenharmony_ci                cbs_sei_delete_message(list, j);
367cabdff1aSopenharmony_ci        }
368cabdff1aSopenharmony_ci    }
369cabdff1aSopenharmony_ci}
370