Coverage Report

Created: 2026-03-31 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavc/common/ih264_buf_mgr.c
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Copyright (C) 2015 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
*/
20
21
/**
22
*******************************************************************************
23
* @file
24
*  ih264_buf_mgr.c
25
*
26
* @brief
27
*  Contains function definitions for buffer management
28
*
29
* @author
30
*  ittiam
31
*
32
* @par List of Functions:
33
*  - ih264_buf_mgr_size
34
*  - ih264_buf_mgr_lock
35
*  - ih264_buf_mgr_unlock
36
*  - ih264_buf_mgr_yield
37
*  - ih264_buf_mgr_free
38
*  - ih264_buf_mgr_init
39
*  - ih264_buf_mgr_add
40
*  - ih264_buf_mgr_get_next_free
41
*  - ih264_buf_mgr_check_free
42
*  - ih264_buf_mgr_release
43
*  - ih264_buf_mgr_set_status
44
*  - ih264_buf_mgr_get_status
45
*  - ih264_buf_mgr_get_buf
46
*  - ih264_buf_mgr_get_bufid
47
*  - ih264_buf_mgr_get_num_active_buf
48
*
49
* @remarks
50
*  none
51
*
52
*******************************************************************************
53
*/
54
55
/*****************************************************************************/
56
/* File Includes                                                             */
57
/*****************************************************************************/
58
59
/* System Include Files */
60
#include <stdio.h>
61
#include <stdlib.h>
62
63
/* User Include Files */
64
#include "ih264_typedefs.h"
65
#include "ithread.h"
66
#include "ih264_macros.h"
67
#include "ih264_error.h"
68
#include "ih264_defs.h"
69
#include "ih264_buf_mgr.h"
70
71
72
/*****************************************************************************/
73
/* Function Definitions                                                      */
74
/*****************************************************************************/
75
76
/**
77
*******************************************************************************
78
*
79
* @brief Returns size for buffer queue context. Does not include the size of the
80
*  actual buffers that are stored here.
81
*
82
* @par Description
83
*  Returns size for buf queue context. Does not include the size of the
84
*  actual buffers that are stored here.
85
*
86
* @returns Size of the buf queue context
87
*
88
* @remarks none
89
*
90
*******************************************************************************
91
*/
92
WORD32 ih264_buf_mgr_size(void)
93
399k
{
94
399k
    WORD32 size;
95
96
399k
    size = sizeof(buf_mgr_t);
97
399k
    size += ithread_get_mutex_lock_size();
98
99
399k
    return size;
100
399k
}
101
102
/**
103
*******************************************************************************
104
*
105
* @brief Locks the buffer manager context
106
*
107
* @par Description
108
*  Locks the buffer manager context by calling ithread_mutex_lock()
109
*
110
* @param[in] ps_buf_mgr
111
*  Pointer to the buffer manager
112
*
113
* @returns IH264_FAIL if mutex lock fails else IH264_SUCCESS
114
*
115
* @remarks none
116
*
117
*******************************************************************************
118
*/
119
IH264_ERROR_T ih264_buf_mgr_lock(buf_mgr_t *ps_buf_mgr)
120
3.58M
{
121
3.58M
    WORD32 retval;
122
123
3.58M
    retval = ithread_mutex_lock(ps_buf_mgr->pv_mutex);
124
3.58M
    if(retval)
125
0
        return IH264_FAIL;
126
3.58M
    return IH264_SUCCESS;
127
3.58M
}
128
129
/**
130
*******************************************************************************
131
*
132
* @brief Unlocks the buffer manager context
133
*
134
* @par Description
135
*  Unlocks the buffer manager context by calling ithread_mutex_unlock()
136
*
137
* @param[in] ps_buf_mgr
138
*  Pointer to the buffer manager
139
*
140
* @returns IH264_FAIL if mutex unlock fails else IH264_SUCCESS
141
*
142
* @remarks
143
*
144
*******************************************************************************
145
*/
146
IH264_ERROR_T ih264_buf_mgr_unlock(buf_mgr_t *ps_buf_mgr)
147
3.58M
{
148
3.58M
    WORD32 retval;
149
150
3.58M
    retval = ithread_mutex_unlock(ps_buf_mgr->pv_mutex);
151
3.58M
    if(retval)
152
0
        return IH264_FAIL;
153
3.58M
    return IH264_SUCCESS;
154
3.58M
}
155
156
/**
157
*******************************************************************************
158
*
159
* @brief Yields the thread
160
*
161
* @par Description
162
*  Unlocks the buf_mgr context by calling ih264_buf_mgr_unlock(),
163
*  ithread_yield() and then ih264_buf_mgr_lock(). buf_mgr is unlocked before to
164
*  ensure the buf_mgr can be accessed by other threads. If unlock is not done
165
*  before calling yield then no other thread can access the buf_mgr functions
166
*  and update buf_mgr.
167
*
168
* @param[in] ps_buf_mgr
169
*  Pointer to the buffer manager
170
*
171
* @returns IH264_FAIL if mutex lock unlock or yield fails else IH264_SUCCESS
172
*
173
* @remarks
174
*
175
*******************************************************************************
176
*/
177
IH264_ERROR_T ih264_buf_mgr_yield(buf_mgr_t *ps_buf_mgr)
178
0
{
179
0
    IH264_ERROR_T ret;
180
181
0
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
182
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
183
184
    //ithread_usleep(10);
185
0
    ithread_yield();
186
187
0
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
188
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
189
0
    return IH264_SUCCESS;
190
0
}
191
192
/**
193
*******************************************************************************
194
*
195
* @brief frees the buffer manager context
196
*
197
* @par Description
198
*  Frees the buffer manager context
199
*
200
* @param[in] ps_buf_mgr
201
*  Pointer to the buffer manager
202
*
203
* @returns IH264_FAIL if mutex destory fails else IH264_SUCCESS
204
*
205
* @remarks
206
*  Since it will be called only once by master thread this is not thread safe.
207
*
208
*******************************************************************************
209
*/
210
IH264_ERROR_T ih264_buf_mgr_free(buf_mgr_t *ps_buf_mgr)
211
73.3k
{
212
73.3k
    WORD32 ret;
213
214
73.3k
    ret = ithread_mutex_destroy(ps_buf_mgr->pv_mutex);
215
73.3k
    if(0 == ret)
216
73.3k
        return IH264_SUCCESS;
217
0
    return IH264_FAIL;
218
73.3k
}
219
220
/**
221
*******************************************************************************
222
*
223
* @brief Buffer manager context initialization.
224
*
225
* @par Description:
226
*  Initializes the buffer manager structure
227
*
228
* @param[in] pv_buf
229
*  Pointer to the buffer manager
230
*
231
* @returns none
232
*
233
* @remarks none
234
*
235
*******************************************************************************
236
*/
237
void* ih264_buf_mgr_init(void *pv_buf)
238
93.6k
{
239
93.6k
    WORD32 id;
240
93.6k
    UWORD8 *pu1_buf = (UWORD8 *)pv_buf;
241
93.6k
    buf_mgr_t *ps_buf_mgr = (buf_mgr_t *)pu1_buf;
242
243
93.6k
    pu1_buf += sizeof(buf_mgr_t);
244
93.6k
    ps_buf_mgr->pv_mutex = pu1_buf;
245
246
93.6k
    pu1_buf += ithread_get_mutex_lock_size();
247
93.6k
    ithread_mutex_init(ps_buf_mgr->pv_mutex);
248
249
93.6k
    ps_buf_mgr->i4_max_buf_cnt = BUF_MGR_MAX_CNT;
250
93.6k
    ps_buf_mgr->i4_active_buf_cnt = 0;
251
6.09M
    for(id = 0; id < BUF_MGR_MAX_CNT; id++)
252
5.99M
    {
253
5.99M
        ps_buf_mgr->au4_status[id] = 0;
254
5.99M
        ps_buf_mgr->apv_ptr[id] = NULL;
255
5.99M
    }
256
257
93.6k
    return ps_buf_mgr;
258
93.6k
}
259
260
/**
261
*******************************************************************************
262
*
263
* @brief Buffer manager reset function.
264
*
265
* @par Description:
266
*  resets the buffer manager structure
267
*
268
* @param[in] pv_buf
269
*  Pointer to the buffer manager
270
*
271
* @returns none
272
*
273
* @remarks none
274
*
275
*******************************************************************************
276
*/
277
void ih264_buf_mgr_reset(void *pv_buf_mgr)
278
153k
{
279
153k
    WORD32 id;
280
153k
    buf_mgr_t *ps_buf_mgr;
281
282
153k
    ps_buf_mgr = (buf_mgr_t *) pv_buf_mgr;
283
284
9.96M
    for(id = 0; id < BUF_MGR_MAX_CNT; id++)
285
9.80M
    {
286
9.80M
        ps_buf_mgr->au4_status[id] = 0;
287
9.80M
    }
288
289
153k
    return;
290
153k
}
291
292
/**
293
*******************************************************************************
294
*
295
* @brief Adds and increments the buffer and buffer count.
296
*
297
* @par Description:
298
*  Adds a buffer to the buffer manager if it is not already present and
299
*  increments the active buffer count
300
*
301
* @param[in] ps_buf_mgr
302
*  Pointer to the buffer manager
303
*
304
* @param[in] pv_ptr
305
*  Pointer to the buffer to be added
306
*
307
* @param[in] buf_id
308
*  buffer id
309
*
310
* @returns  Returns 0 on success, -1 otherwise
311
*
312
* @remarks
313
*  none
314
*
315
*******************************************************************************
316
*/
317
IH264_ERROR_T ih264_buf_mgr_add(buf_mgr_t *ps_buf_mgr,
318
                                void *pv_ptr,
319
                                WORD32 buf_id)
320
803k
{
321
803k
    IH264_ERROR_T ret = IH264_SUCCESS;
322
323
803k
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
324
803k
    RETURN_IF((ret != IH264_SUCCESS), ret);
325
326
    /* Check if buffer ID is within allowed range */
327
803k
    if(buf_id >= ps_buf_mgr->i4_max_buf_cnt)
328
0
    {
329
0
        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
330
0
        RETURN_IF((ret != IH264_SUCCESS), ret);
331
0
        return IH264_FAIL;
332
0
    }
333
334
    /* Check if the current ID is being used to hold some other buffer */
335
803k
    if((ps_buf_mgr->apv_ptr[buf_id] != NULL) &&
336
84.2k
       (ps_buf_mgr->apv_ptr[buf_id] != pv_ptr))
337
0
    {
338
0
        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
339
0
        RETURN_IF((ret != IH264_SUCCESS), ret);
340
0
        return IH264_FAIL;
341
0
    }
342
803k
    ps_buf_mgr->apv_ptr[buf_id] = pv_ptr;
343
803k
    ps_buf_mgr->i4_active_buf_cnt++;
344
345
803k
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
346
803k
    RETURN_IF((ret != IH264_SUCCESS), ret);
347
348
803k
    return ret;
349
803k
}
350
351
/**
352
*******************************************************************************
353
*
354
* @brief Gets the next free buffer.
355
*
356
* @par Description:
357
*  Returns the next free buffer available and sets the corresponding status
358
*  to Busy
359
*
360
* @param[in] ps_buf_mgr
361
*  Pointer to the buffer manager
362
*
363
* @param[in] pi4_buf_id
364
*  Pointer to the id of the free buffer
365
*
366
* @returns  Pointer to the free buffer
367
*
368
* @remarks
369
*  none
370
*
371
*******************************************************************************
372
*/
373
void* ih264_buf_mgr_get_next_free(buf_mgr_t *ps_buf_mgr, WORD32 *pi4_buf_id)
374
605k
{
375
605k
    WORD32 id;
376
605k
    void *pv_ret_ptr = NULL;
377
605k
    IH264_ERROR_T ret = IH264_SUCCESS;
378
379
605k
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
380
605k
    RETURN_IF((ret != IH264_SUCCESS), NULL);
381
382
1.84M
    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
383
1.84M
    {
384
        /* Check if the buffer is non-null and status is zero */
385
1.84M
        if((ps_buf_mgr->au4_status[id] == 0) && (ps_buf_mgr->apv_ptr[id]))
386
602k
        {
387
602k
            *pi4_buf_id = id;
388
            /* mark buffer as busy before returning */
389
602k
            ps_buf_mgr->au4_status[id] = 1;
390
602k
            pv_ret_ptr = ps_buf_mgr->apv_ptr[id];
391
602k
            break;
392
602k
        }
393
1.84M
    }
394
605k
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
395
605k
    RETURN_IF((ret != IH264_SUCCESS), NULL);
396
397
605k
    return pv_ret_ptr;
398
605k
}
399
400
/**
401
*******************************************************************************
402
*
403
* @brief Checks the buffer manager for free buffers available.
404
*
405
* @par Description:
406
*  Checks if there are any free buffers available
407
*
408
* @param[in] ps_buf_mgr
409
*  Pointer to the buffer manager
410
*
411
* @returns  Returns IH264_SUCCESS if available, IH264_FAIL otherwise
412
*
413
* @remarks
414
*  none
415
*
416
*******************************************************************************
417
*/
418
IH264_ERROR_T ih264_buf_mgr_check_free(buf_mgr_t *ps_buf_mgr)
419
0
{
420
0
    WORD32 id;
421
0
    IH264_ERROR_T ret = IH264_FAIL;
422
0
    IH264_ERROR_T rettmp = IH264_SUCCESS;
423
424
0
    rettmp = ih264_buf_mgr_lock(ps_buf_mgr);
425
0
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
426
427
0
    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
428
0
    {
429
0
        if((ps_buf_mgr->au4_status[id] == 0) &&
430
0
           (ps_buf_mgr->apv_ptr[id]))
431
0
        {
432
0
            ret = IH264_SUCCESS;
433
0
            break;
434
0
        }
435
0
    }
436
0
    rettmp = ih264_buf_mgr_unlock(ps_buf_mgr);
437
0
    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
438
439
0
    return ret;
440
0
}
441
442
/**
443
*******************************************************************************
444
*
445
* @brief Release buffer to buffer manager
446
*
447
* @par Description:
448
*  Clear the status bit basing on the mask. If the buffer is no longer used by
449
*  the codec then release back to the pool
450
*
451
* @param[in] ps_buf_mgr
452
*  Pointer to the buffer manager
453
*
454
* @param[in] buf_id
455
*  ID of the buffer status to be released
456
*
457
* @param[in] mask
458
*  Contains the bits that are to be reset
459
*
460
* @returns  IH264_SUCCESS if success, IH264_FAIL otherwise
461
*
462
* @remarks
463
*  none
464
*
465
*******************************************************************************
466
*/
467
IH264_ERROR_T ih264_buf_mgr_release(buf_mgr_t *ps_buf_mgr,
468
                                    WORD32 buf_id,
469
                                    UWORD32 mask)
470
938k
{
471
938k
    IH264_ERROR_T ret = IH264_SUCCESS;
472
473
938k
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
474
938k
    RETURN_IF((ret != IH264_SUCCESS), ret);
475
476
    /* If the given id is pointing to an id which is not yet added */
477
938k
    if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
478
94.4k
    {
479
94.4k
        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
480
94.4k
        RETURN_IF((ret != IH264_SUCCESS), ret);
481
94.4k
        return IH264_FAIL;
482
94.4k
    }
483
484
844k
    ps_buf_mgr->au4_status[buf_id] &= ~mask;
485
486
    /* If both the REF and DISP are zero, DEC is set to zero */
487
844k
    if(ps_buf_mgr->au4_status[buf_id] == 1)
488
433k
    {
489
433k
        ps_buf_mgr->au4_status[buf_id] = 0;
490
433k
    }
491
492
844k
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
493
844k
    RETURN_IF((ret != IH264_SUCCESS), ret);
494
495
844k
    return ret;
496
844k
}
497
498
/**
499
*******************************************************************************
500
*
501
* @brief Sets the status bit.
502
*
503
* @par Description:
504
*  sets the status bits that the mask contains (status corresponding to the id)
505
*
506
* @param[in] ps_buf_mgr
507
*  Pointer to the buffer manager
508
*
509
* @param[in] buf_id
510
*  ID of the buffer whose status needs to be modified
511
*
512
* @param[in] mask
513
*  Contains the bits that are to be set
514
*
515
* @returns  IH264_SUCCESS if success, IH264_FAIL otherwise
516
*
517
* @remarks
518
*  none
519
*
520
*******************************************************************************
521
*/
522
IH264_ERROR_T ih264_buf_mgr_set_status(buf_mgr_t *ps_buf_mgr,
523
                                       WORD32 buf_id,
524
                                       UWORD32 mask)
525
884k
{
526
884k
    IH264_ERROR_T ret = IH264_SUCCESS;
527
528
884k
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
529
884k
    RETURN_IF((ret != IH264_SUCCESS), ret);
530
531
884k
    if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
532
0
    {
533
0
        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
534
0
        RETURN_IF((ret != IH264_SUCCESS), ret);
535
0
        return IH264_FAIL;
536
0
    }
537
538
884k
    if((ps_buf_mgr->au4_status[buf_id] & mask) != 0)
539
226k
    {
540
226k
        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
541
226k
        RETURN_IF((ret != IH264_SUCCESS), ret);
542
226k
        return IH264_FAIL;
543
226k
    }
544
545
658k
    ps_buf_mgr->au4_status[buf_id] |= mask;
546
658k
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
547
658k
    RETURN_IF((ret != IH264_SUCCESS), ret);
548
549
658k
    return ret;
550
658k
}
551
552
/**
553
*******************************************************************************
554
*
555
* @brief Returns the status of the buffer.
556
*
557
* @par Description:
558
*  Returns the status of the buffer corresponding to the id
559
*
560
* @param[in] ps_buf_mgr
561
*  Pointer to the buffer manager
562
*
563
* @param[in] buf_id
564
*  ID of the buffer status required
565
*
566
* @returns  Status of the buffer corresponding to the id
567
*
568
* @remarks
569
*  none
570
*
571
*******************************************************************************
572
*/
573
WORD32 ih264_buf_mgr_get_status(buf_mgr_t *ps_buf_mgr, WORD32 buf_id)
574
353k
{
575
353k
    IH264_ERROR_T ret = IH264_SUCCESS;
576
353k
    UWORD32 status;
577
578
353k
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
579
353k
    RETURN_IF((ret != IH264_SUCCESS), ret);
580
581
353k
    status = ps_buf_mgr->au4_status[buf_id];
582
583
353k
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
584
353k
    RETURN_IF((ret != IH264_SUCCESS), ret);
585
586
353k
    return status;
587
353k
}
588
589
/**
590
*******************************************************************************
591
*
592
* @brief Gets the buffer from the buffer manager
593
*
594
* @par Description:
595
*  Returns the pointer to the buffer corresponding to the id
596
*
597
* @param[in] ps_buf_mgr
598
*  Pointer to the buffer manager
599
*
600
* @param[in] buf_id
601
*  ID of the buffer required
602
*
603
* @returns  Pointer to the buffer required
604
*
605
* @remarks
606
*  none
607
*
608
*******************************************************************************
609
*/
610
void* ih264_buf_mgr_get_buf(buf_mgr_t *ps_buf_mgr, WORD32 buf_id)
611
0
{
612
0
    IH264_ERROR_T ret = IH264_SUCCESS;
613
0
    void *pv_buf;
614
615
0
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
616
0
    RETURN_IF((ret != IH264_SUCCESS), NULL);
617
618
0
    pv_buf = ps_buf_mgr->apv_ptr[buf_id];
619
620
0
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
621
0
    RETURN_IF((ret != IH264_SUCCESS), NULL);
622
623
0
    return pv_buf;
624
0
}
625
626
/**
627
*******************************************************************************
628
*
629
* @brief Gets the buffer id from the buffer manager if the buffer is added to
630
*  the buffer manager
631
*
632
* @par Description:
633
*  Returns the buffer id corresponding to the given buffer if it exists
634
*
635
* @param[in] ps_buf_mgr
636
*  Pointer to the buffer manager
637
*
638
* @param[in] pv_buf
639
*  Pointer to the buffer
640
*
641
* @returns  Buffer id if exists, else -1
642
*
643
* @remarks
644
*  none
645
*
646
*******************************************************************************
647
*/
648
WORD32 ih264_buf_mgr_get_bufid(buf_mgr_t *ps_buf_mgr, void *pv_buf)
649
0
{
650
0
    WORD32 id;
651
0
    WORD32 buf_id = -1;
652
0
    IH264_ERROR_T ret = IH264_SUCCESS;
653
654
0
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
655
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
656
657
0
    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
658
0
    {
659
0
        if(ps_buf_mgr->apv_ptr[id] == pv_buf)
660
0
        {
661
0
            buf_id = id;
662
0
            break;
663
0
        }
664
0
    }
665
0
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
666
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
667
668
0
    return buf_id;
669
0
}
670
671
/**
672
*******************************************************************************
673
*
674
* @brief Gets the no.of active buffer
675
*
676
* @par Description:
677
*  Return the number of active buffers in the buffer manager
678
*
679
* @param[in] ps_buf_mgr
680
*  Pointer to the buffer manager
681
*
682
* @returns  number of active buffers
683
*
684
* @remarks
685
*  none
686
*
687
*******************************************************************************
688
*/
689
UWORD32 ih264_buf_mgr_get_num_active_buf(buf_mgr_t *ps_buf_mgr)
690
0
{
691
0
    UWORD32 u4_buf_cnt = 0;
692
0
    IH264_ERROR_T ret = IH264_SUCCESS;
693
694
0
    ret = ih264_buf_mgr_lock(ps_buf_mgr);
695
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
696
697
0
    u4_buf_cnt = ps_buf_mgr->i4_active_buf_cnt;
698
699
0
    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
700
0
    RETURN_IF((ret != IH264_SUCCESS), ret);
701
702
0
    return u4_buf_cnt;
703
0
}